Blender V5.0
bpy_inline_shader_nodes.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BKE_idtype.hh"
10#include "BKE_lib_id.hh"
11#include "BKE_node.hh"
12
13#include "DNA_light_types.h"
14#include "DNA_material_types.h"
15#include "DNA_node_types.h"
16
17#include "DNA_world_types.h"
19
21#include "bpy_rna.hh"
22
24
25extern PyTypeObject bpy_inline_shader_nodes_Type;
26
28 PyObject_HEAD
30};
31
33{
36 if (!self) {
37 return nullptr;
38 }
39 self->inline_node_tree = blender::bke::node_tree_add_tree(
40 nullptr, (blender::StringRef(tree.id.name) + " Inlined").c_str(), tree.idname);
43 return self;
44}
45
47 /* Wrap. */
48 bpy_inline_shader_nodes_from_material_doc,
49 ".. staticmethod:: from_material(material)\n"
50 "\n"
51 " Create an inlined shader node tree from a material.\n"
52 "\n"
53 " :arg material: The material to inline the node tree of.\n"
54 " :type material: bpy.types.Material\n");
56 PyObject *args,
57 PyObject *kwds)
58{
59 static const char *kwlist[] = {"material", nullptr};
60 PyObject *py_material;
61 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", const_cast<char **>(kwlist), &py_material)) {
62 return nullptr;
63 }
64 ID *material_id = nullptr;
65 if (!pyrna_id_FromPyObject(py_material, &material_id)) {
66 PyErr_Format(
67 PyExc_TypeError, "Expected a Material, not %.200s", Py_TYPE(py_material)->tp_name);
68 return nullptr;
69 }
70 if (GS(material_id->name) != ID_MA) {
71 PyErr_Format(PyExc_TypeError,
72 "Expected a Material, not %.200s",
73 BKE_idtype_idcode_to_name(GS(material_id->name)));
74 return nullptr;
75 }
76 Material *material = blender::id_cast<Material *>(material_id);
77 if (!material->nodetree) {
78 PyErr_Format(PyExc_TypeError, "Material '%s' has no node tree", BKE_id_name(*material_id));
79 return nullptr;
80 }
81 return create_from_shader_node_tree(*material->nodetree);
82}
83
85 /* Wrap. */
86 bpy_inline_shader_nodes_from_light_doc,
87 ".. staticmethod:: from_light(light)\n"
88 "\n"
89 " Create an inlined shader node tree from a light.\n"
90 "\n"
91 " :arg light: The light to online the node tree of.\n"
92 " :type light: bpy.types.Light\n");
94 PyObject *args,
95 PyObject *kwds)
96{
97 static const char *kwlist[] = {"light", nullptr};
98 PyObject *py_light;
99 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", const_cast<char **>(kwlist), &py_light)) {
100 return nullptr;
101 }
102 ID *light_id = nullptr;
103 if (!pyrna_id_FromPyObject(py_light, &light_id)) {
104 PyErr_Format(PyExc_TypeError, "Expected a Light, not %.200s", Py_TYPE(py_light)->tp_name);
105 return nullptr;
106 }
107 if (GS(light_id->name) != ID_LA) {
108 PyErr_Format(PyExc_TypeError,
109 "Expected a Light, not %.200s",
110 BKE_idtype_idcode_to_name(GS(light_id->name)));
111 return nullptr;
112 }
113 Light *light = blender::id_cast<Light *>(light_id);
114 if (!light->nodetree) {
115 PyErr_Format(PyExc_TypeError, "Light '%s' has no node tree", BKE_id_name(*light_id));
116 return nullptr;
117 }
119}
120
122 /* Wrap. */
123 bpy_inline_shader_nodes_from_world_doc,
124 ".. staticmethod:: from_world(world)\n"
125 "\n"
126 " Create an inlined shader node tree from a world.\n"
127 "\n"
128 " :arg world: The world to inline the node tree of.\n"
129 " :type world: bpy.types.World\n");
131 PyObject *args,
132 PyObject *kwds)
133{
134 static const char *kwlist[] = {"world", nullptr};
135 PyObject *py_world;
136 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", const_cast<char **>(kwlist), &py_world)) {
137 return nullptr;
138 }
139 ID *world_id = nullptr;
140 if (!pyrna_id_FromPyObject(py_world, &world_id)) {
141 PyErr_Format(PyExc_TypeError, "Expected a World, not %.200s", Py_TYPE(py_world)->tp_name);
142 return nullptr;
143 }
144 if (GS(world_id->name) != ID_WO) {
145 PyErr_Format(PyExc_TypeError,
146 "Expected a World, not %.200s",
147 BKE_idtype_idcode_to_name(GS(world_id->name)));
148 return nullptr;
149 }
150 World *world = blender::id_cast<World *>(world_id);
151 if (!world->nodetree) {
152 PyErr_Format(PyExc_TypeError, "World '%s' has no node tree", BKE_id_name(*world_id));
153 return nullptr;
154 }
156}
157
159{
160 BKE_id_free(nullptr, self->inline_node_tree);
161 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject *>(self));
162}
163
165 /* Wrap. */
166 bpy_inline_shader_nodes_node_tree_doc,
167 "The inlined node tree.\n"
168 "\n"
169 ":type: :class:`bpy.types.NodeTree`\n");
171 void * /*closure*/)
172{
173 return pyrna_id_CreatePyObject(blender::id_cast<ID *>(self->inline_node_tree));
174}
175
176static PyGetSetDef BPy_InlineShaderNodes_getseters[] = {
177 {"node_tree",
179 nullptr,
180 bpy_inline_shader_nodes_node_tree_doc,
181 nullptr},
182 {nullptr},
183};
184
185#ifdef __GNUC__
186# ifdef __clang__
187# pragma clang diagnostic push
188# pragma clang diagnostic ignored "-Wcast-function-type"
189# else
190# pragma GCC diagnostic push
191# pragma GCC diagnostic ignored "-Wcast-function-type"
192# endif
193#endif
194
195static PyMethodDef BPy_InlineShaderNodes_methods[] = {
196 {"from_material",
198 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
199 bpy_inline_shader_nodes_from_material_doc},
200 {"from_light",
202 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
203 bpy_inline_shader_nodes_from_light_doc},
204 {"from_world",
206 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
207 bpy_inline_shader_nodes_from_world_doc},
208 {nullptr},
209};
210
211#ifdef __GNUC__
212# ifdef __clang__
213# pragma clang diagnostic pop
214# else
215# pragma GCC diagnostic pop
216# endif
217#endif
218
220 /* Wrap. */
221 bpy_inline_shader_nodes_doc,
222 "An inlined shader node tree.\n");
224 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
225 /*tp_name*/ "InlineShaderNodes",
226 /*tp_basicsize*/ sizeof(BPy_InlineShaderNodes),
227 /*tp_itemsize*/ 0,
228 /*tp_dealloc*/ reinterpret_cast<destructor>(BPy_InlineShaderNodes_dealloc),
229 /*tp_vectorcall_offset*/ 0,
230 /*tp_getattr*/ nullptr,
231 /*tp_setattr*/ nullptr,
232 /*tp_as_async*/ nullptr,
233 /*tp_repr*/ nullptr,
234 /*tp_as_number*/ nullptr,
235 /*tp_as_sequence*/ nullptr,
236 /*tp_as_mapping*/ nullptr,
237 /*tp_hash*/ nullptr,
238 /*tp_call*/ nullptr,
239 /*tp_str*/ nullptr,
240 /*tp_getattro*/ nullptr,
241 /*tp_setattro*/ nullptr,
242 /*tp_as_buffer*/ nullptr,
243 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
244 /*tp_doc*/ bpy_inline_shader_nodes_doc,
245 /*tp_traverse*/ nullptr,
246 /*tp_clear*/ nullptr,
247 /*tp_richcompare*/ nullptr,
248 /*tp_weaklistoffset*/ 0,
249 /*tp_iter*/ nullptr,
250 /*tp_iternext*/ nullptr,
251 /*tp_methods*/ BPy_InlineShaderNodes_methods,
252 /*tp_members*/ nullptr,
254 /*tp_base*/ nullptr,
255 /*tp_dict*/ nullptr,
256 /*tp_descr_get*/ nullptr,
257 /*tp_descr_set*/ nullptr,
258 /*tp_dictoffset*/ 0,
259 /*tp_init*/ nullptr,
260 /*tp_alloc*/ nullptr,
261 /*tp_new*/ nullptr,
262};
263
265{
266 if (PyType_Ready(&bpy_inline_shader_nodes_Type) < 0) {
267 return nullptr;
268 }
269 return reinterpret_cast<PyObject *>(&bpy_inline_shader_nodes_Type);
270}
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:164
void BKE_id_free(Main *bmain, void *idv)
const char * BKE_id_name(const ID &id)
@ ID_LA
@ ID_WO
@ ID_MA
PyObject * self
static PyMethodDef BPy_InlineShaderNodes_methods[]
static PyGetSetDef BPy_InlineShaderNodes_getseters[]
static BPy_InlineShaderNodes * BPy_InlineShaderNodes_static_from_world(PyObject *, PyObject *args, PyObject *kwds)
PyDoc_STRVAR(bpy_inline_shader_nodes_from_material_doc, ".. staticmethod:: from_material(material)\n" "\n" " Create an inlined shader node tree from a material.\n" "\n" " :arg material: The material to inline the node tree of.\n" " :type material: bpy.types.Material\n")
static BPy_InlineShaderNodes * create_from_shader_node_tree(const bNodeTree &tree)
static void BPy_InlineShaderNodes_dealloc(BPy_InlineShaderNodes *self)
static PyObject * BPy_InlineShaderNodes_get_node_tree(BPy_InlineShaderNodes *self, void *)
static BPy_InlineShaderNodes * BPy_InlineShaderNodes_static_from_material(PyObject *, PyObject *args, PyObject *kwds)
PyTypeObject bpy_inline_shader_nodes_Type
static BPy_InlineShaderNodes * BPy_InlineShaderNodes_static_from_light(PyObject *, PyObject *args, PyObject *kwds)
PyObject * BPyInit_inline_shader_nodes_type()
KDTree_3d * tree
#define GS(x)
PyObject * pyrna_id_CreatePyObject(ID *id)
Definition bpy_rna.cc:8601
bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
Definition bpy_rna.cc:8611
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
bNodeTree * node_tree_add_tree(Main *bmain, StringRef name, StringRef idname)
Definition node.cc:4085
bool inline_shader_node_tree(const bNodeTree &src_tree, bNodeTree &dst_tree, InlineShaderNodeTreeParams &params)
PyObject_HEAD bNodeTree * inline_node_tree
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
struct bNodeTree * nodetree
struct bNodeTree * nodetree
struct bNodeTree * nodetree