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
42namespace bpy = boost::python;
43using namespace foundation;
44using namespace renderer;
45
46namespace
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
139void 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