1 | |
2 | // |
3 | // This source file is part of appleseed. |
4 | // Visit http://appleseedhq.net/ for additional information and resources. |
5 | // |
6 | // This software is released under the MIT license. |
7 | // |
8 | // Copyright (c) 2012-2013 Esteban Tovagliari, Jupiter Jazz Limited |
9 | // Copyright (c) 2014-2017 Esteban Tovagliari, The appleseedhq Organization |
10 | // |
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
12 | // of this software and associated documentation files (the "Software"), to deal |
13 | // in the Software without restriction, including without limitation the rights |
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
15 | // copies of the Software, and to permit persons to whom the Software is |
16 | // furnished to do so, subject to the following conditions: |
17 | // |
18 | // The above copyright notice and this permission notice shall be included in |
19 | // all copies or substantial portions of the Software. |
20 | // |
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
27 | // THE SOFTWARE. |
28 | // |
29 | |
30 | // appleseed.python headers. |
31 | #include "pyseed.h" // has to be first, to avoid redefinition warnings |
32 | #include "dict2dict.h" |
33 | #include "gillocks.h" |
34 | |
35 | // appleseed.renderer headers. |
36 | #include "renderer/api/project.h" |
37 | #include "renderer/api/rendering.h" |
38 | |
39 | // Standard headers. |
40 | #include <memory> |
41 | |
42 | namespace bpy = boost::python; |
43 | using namespace foundation; |
44 | using namespace renderer; |
45 | |
46 | namespace |
47 | { |
48 | // A class that wraps MasterRenderer and keeps a Python |
49 | // reference to the project object to prevent it being |
50 | // destroyed by Python before the MasterRenderer is destroyed. |
51 | struct MasterRendererWrapper |
52 | { |
53 | MasterRendererWrapper( |
54 | bpy::object project, |
55 | const ParamArray& params, |
56 | IRendererController* renderer_controller, |
57 | ITileCallbackFactory* tile_callback_factory = 0) |
58 | : m_project(project) |
59 | { |
60 | Project* proj = bpy::extract<Project*>(project); |
61 | m_renderer.reset( |
62 | new MasterRenderer( |
63 | *proj, |
64 | params, |
65 | renderer_controller, |
66 | tile_callback_factory)); |
67 | } |
68 | |
69 | MasterRendererWrapper( |
70 | bpy::object project, |
71 | const ParamArray& params, |
72 | IRendererController* renderer_controller, |
73 | ITileCallback* tile_callback) |
74 | : m_project(project) |
75 | { |
76 | Project* proj = bpy::extract<Project*>(project); |
77 | m_renderer.reset( |
78 | new MasterRenderer( |
79 | *proj, |
80 | params, |
81 | renderer_controller, |
82 | tile_callback)); |
83 | } |
84 | |
85 | bpy::object m_project; |
86 | std::auto_ptr<MasterRenderer> m_renderer; |
87 | }; |
88 | |
89 | std::auto_ptr<MasterRendererWrapper> create_master_renderer( |
90 | bpy::object project, |
91 | const bpy::dict& params, |
92 | IRendererController* renderer_controller) |
93 | { |
94 | return |
95 | std::auto_ptr<MasterRendererWrapper>( |
96 | new MasterRendererWrapper( |
97 | *project, |
98 | bpy_dict_to_param_array(params), |
99 | renderer_controller)); |
100 | } |
101 | |
102 | std::auto_ptr<MasterRendererWrapper> create_master_renderer_with_tile_callback( |
103 | bpy::object project, |
104 | const bpy::dict& params, |
105 | IRendererController* renderer_controller, |
106 | ITileCallback* tile_callback) |
107 | { |
108 | return |
109 | std::auto_ptr<MasterRendererWrapper>( |
110 | new MasterRendererWrapper( |
111 | *project, |
112 | bpy_dict_to_param_array(params), |
113 | renderer_controller, |
114 | tile_callback)); |
115 | } |
116 | |
117 | bpy::dict master_renderer_get_parameters(const MasterRendererWrapper* m) |
118 | { |
119 | return param_array_to_bpy_dict(m->m_renderer->get_parameters()); |
120 | } |
121 | |
122 | void master_renderer_set_parameters( |
123 | MasterRendererWrapper* m, |
124 | const bpy::dict& params) |
125 | { |
126 | m->m_renderer->get_parameters() = bpy_dict_to_param_array(params); |
127 | } |
128 | |
129 | bool master_renderer_render(MasterRendererWrapper* m) |
130 | { |
131 | // Unlock Python's global interpreter lock (GIL) while we do lenghty C++ computations. |
132 | // The GIL is locked again when unlock goes out of scope. |
133 | ScopedGILUnlock unlock; |
134 | |
135 | return m->m_renderer->render(); |
136 | } |
137 | } |
138 | |
139 | void bind_master_renderer() |
140 | { |
141 | bpy::class_<MasterRendererWrapper, std::auto_ptr<MasterRendererWrapper>, boost::noncopyable>("MasterRenderer" , bpy::no_init) |
142 | .def("__init__" , bpy::make_constructor(create_master_renderer)) |
143 | .def("__init__" , bpy::make_constructor(create_master_renderer_with_tile_callback)) |
144 | .def("get_parameters" , master_renderer_get_parameters) |
145 | .def("set_parameters" , master_renderer_set_parameters) |
146 | .def("render" , master_renderer_render) |
147 | ; |
148 | } |
149 | |