Blender V5.0
python.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "final_engine.hh"
6#include "preview_engine.hh"
7#include "viewport_engine.hh"
8
9#include <Python.h>
10
11#include "RE_engine.h"
12
13#include "../generic/py_capi_utils.hh"
14#include "bpy_rna.hh"
15
16#include "BKE_context.hh"
17
18#include "RNA_prototypes.hh"
19
20#include "hydra/image.hh"
21
22namespace blender::render::hydra {
23
24template<typename T> T *pyrna_to_pointer(PyObject *pyobject, const StructRNA *rnatype)
25{
26 const PointerRNA *ptr = pyrna_struct_as_ptr_or_null(pyobject, rnatype);
27 return (ptr) ? static_cast<T *>(ptr->data) : nullptr;
28}
29
30static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
31{
32 PyObject *pyengine;
33 char *engine_type, *render_delegate_id;
34 if (!PyArg_ParseTuple(args, "Oss", &pyengine, &engine_type, &render_delegate_id)) {
35 return nullptr;
36 }
37
38 RenderEngine *bl_engine = pyrna_to_pointer<RenderEngine>(pyengine, &RNA_RenderEngine);
39
40 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %s", engine_type);
41 Engine *engine = nullptr;
42 try {
43 if (STREQ(engine_type, "VIEWPORT")) {
44 engine = new ViewportEngine(bl_engine, render_delegate_id);
45 }
46 else if (STREQ(engine_type, "PREVIEW")) {
47 engine = new PreviewEngine(bl_engine, render_delegate_id);
48 }
49 else {
50 engine = new FinalEngine(bl_engine, render_delegate_id);
51 }
52 }
53 catch (std::runtime_error &e) {
54 CLOG_ERROR(LOG_HYDRA_RENDER, "%s", e.what());
55 }
56
57 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %p", engine);
58 return PyLong_FromVoidPtr(engine);
59}
60
61static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
62{
63 PyObject *pyengine;
64 if (!PyArg_ParseTuple(args, "O", &pyengine)) {
65 return nullptr;
66 }
67
68 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
69 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %p", engine);
70 delete engine;
71
72 Py_RETURN_NONE;
73}
74
75static PyObject *engine_update_func(PyObject * /*self*/, PyObject *args)
76{
77 PyObject *pyengine, *pydepsgraph, *pycontext;
78 if (!PyArg_ParseTuple(args, "OOO", &pyengine, &pydepsgraph, &pycontext)) {
79 return nullptr;
80 }
81
82 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
83 Depsgraph *depsgraph = pyrna_to_pointer<Depsgraph>(pydepsgraph, &RNA_Depsgraph);
84 bContext *context = pyrna_to_pointer<bContext>(pycontext, &RNA_Context);
85
86 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %p", engine);
87 engine->sync(depsgraph, context);
88
89 Py_RETURN_NONE;
90}
91
92static PyObject *engine_render_func(PyObject * /*self*/, PyObject *args)
93{
94 PyObject *pyengine;
95 if (!PyArg_ParseTuple(args, "O", &pyengine)) {
96 return nullptr;
97 }
98
99 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
100
101 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %p", engine);
102
103 /* Allow Blender to execute other Python scripts. */
104 Py_BEGIN_ALLOW_THREADS;
105 engine->render();
106 Py_END_ALLOW_THREADS;
107
108 Py_RETURN_NONE;
109}
110
111static PyObject *engine_view_draw_func(PyObject * /*self*/, PyObject *args)
112{
113 PyObject *pyengine, *pycontext;
114 if (!PyArg_ParseTuple(args, "OO", &pyengine, &pycontext)) {
115 return nullptr;
116 }
117
118 ViewportEngine *engine = static_cast<ViewportEngine *>(PyLong_AsVoidPtr(pyengine));
119 bContext *context = pyrna_to_pointer<bContext>(pycontext, &RNA_Context);
120
121 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %p", engine);
122
123 /* Allow Blender to execute other Python scripts. */
124 Py_BEGIN_ALLOW_THREADS;
125 engine->render(context);
126 Py_END_ALLOW_THREADS;
127
128 Py_RETURN_NONE;
129}
130
131static pxr::VtValue get_setting_val(PyObject *pyval)
132{
133 pxr::VtValue val;
134 if (PyBool_Check(pyval)) {
135 val = Py_IsTrue(pyval);
136 }
137 else if (PyLong_Check(pyval)) {
138 val = PyLong_AsLong(pyval);
139 }
140 else if (PyFloat_Check(pyval)) {
141 val = PyFloat_AsDouble(pyval);
142 }
143 else if (PyUnicode_Check(pyval)) {
144 val = std::string(PyUnicode_AsUTF8(pyval));
145 }
146 return val;
147}
148
149static PyObject *engine_set_render_setting_func(PyObject * /*self*/, PyObject *args)
150{
151 PyObject *pyengine, *pyval;
152 char *key;
153 if (!PyArg_ParseTuple(args, "OsO", &pyengine, &key, &pyval)) {
154 return nullptr;
155 }
156
157 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
158
159 CLOG_DEBUG(LOG_HYDRA_RENDER, "Engine %p: %s", engine, key);
160 engine->set_render_setting(key, get_setting_val(pyval));
161
162 Py_RETURN_NONE;
163}
164
165static PyObject *cache_or_get_image_file_func(PyObject * /*self*/, PyObject *args)
166{
167 PyObject *pycontext, *pyimage;
168 if (!PyArg_ParseTuple(args, "OO", &pycontext, &pyimage)) {
169 return nullptr;
170 }
171
172 bContext *context = static_cast<bContext *>(PyLong_AsVoidPtr(pycontext));
173 Image *image = static_cast<Image *>(PyLong_AsVoidPtr(pyimage));
174
175 std::string image_path = io::hydra::cache_or_get_image_file(
176 CTX_data_main(context), CTX_data_scene(context), image, nullptr);
177 return PyC_UnicodeFromStdStr(image_path);
178}
179
180static PyMethodDef methods[] = {
181 {"engine_create", engine_create_func, METH_VARARGS, ""},
182 {"engine_free", engine_free_func, METH_VARARGS, ""},
183 {"engine_update", engine_update_func, METH_VARARGS, ""},
184 {"engine_render", engine_render_func, METH_VARARGS, ""},
185 {"engine_view_draw", engine_view_draw_func, METH_VARARGS, ""},
186 {"engine_set_render_setting", engine_set_render_setting_func, METH_VARARGS, ""},
187
188 {"cache_or_get_image_file", cache_or_get_image_file_func, METH_VARARGS, ""},
189
190 {nullptr, nullptr, 0, nullptr},
191};
192
193static PyModuleDef module = {
195 "_bpy_hydra",
196 "Hydra render API",
197 -1,
198 methods,
199 nullptr,
200 nullptr,
201 nullptr,
202 nullptr,
203};
204
205} // namespace blender::render::hydra
206
207PyObject *BPyInit_hydra();
208
209PyObject *BPyInit_hydra()
210{
211 PyObject *mod = PyModule_Create(&blender::render::hydra::module);
212 return mod;
213}
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
#define STREQ(a, b)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
BPy_StructRNA * depsgraph
const PointerRNA * pyrna_struct_as_ptr_or_null(PyObject *py_obj, const StructRNA *srna)
Definition bpy_rna.cc:9026
void sync(Depsgraph *depsgraph, bContext *context)
virtual void set_render_setting(const std::string &key, const pxr::VtValue &val)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
#define T
std::string cache_or_get_image_file(Main *bmain, Scene *scene, Image *image, ImageUser *iuser)
static pxr::VtValue get_setting_val(PyObject *pyval)
Definition python.cc:131
static PyObject * engine_view_draw_func(PyObject *, PyObject *args)
Definition python.cc:111
static PyObject * engine_set_render_setting_func(PyObject *, PyObject *args)
Definition python.cc:149
static PyObject * engine_free_func(PyObject *, PyObject *args)
Definition python.cc:61
static PyObject * engine_render_func(PyObject *, PyObject *args)
Definition python.cc:92
static PyObject * engine_update_func(PyObject *, PyObject *args)
Definition python.cc:75
static PyObject * cache_or_get_image_file_func(PyObject *, PyObject *args)
Definition python.cc:165
static PyObject * engine_create_func(PyObject *, PyObject *args)
Definition python.cc:30
struct CLG_LogRef * LOG_HYDRA_RENDER
T * pyrna_to_pointer(PyObject *pyobject, const StructRNA *rnatype)
Definition python.cc:24
static PyMethodDef methods[]
Definition python.cc:180
PyObject * PyC_UnicodeFromStdStr(const std::string &str)
PyObject * BPyInit_hydra()
Definition python.cc:209
static struct PyModuleDef module
Definition python.cpp:796
static PyMethodDef methods[]
Definition python.cpp:752
PointerRNA * ptr
Definition wm_files.cc:4238