Blender  V3.3
bmesh_py_ops.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2012 Blender Foundation. All rights reserved. */
3 
11 #include <Python.h>
12 
13 #include "BLI_dynstr.h"
14 #include "BLI_utildefines.h"
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include "bmesh.h"
19 
20 #include "bmesh_py_ops.h" /* own include */
21 #include "bmesh_py_ops_call.h"
22 
23 /* bmesh operator 'bmesh.ops.*' callable types
24  * ******************************************* */
25 static PyTypeObject bmesh_op_Type;
26 
27 static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname)
28 {
29  BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type);
30 
31  self->opname = opname;
32 
33  return (PyObject *)self;
34 }
35 
36 static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self)
37 {
38  return PyUnicode_FromFormat("<%.200s bmesh.ops.%.200s()>", Py_TYPE(self)->tp_name, self->opname);
39 }
40 
41 /* methods
42  * ======= */
43 
44 /* __doc__
45  * ------- */
46 
47 static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out)
48 {
49  DynStr *dyn_str = BLI_dynstr_new();
50  char *ret;
51  bool quoted;
52  bool set;
53 
54  int i = 0;
55 
56  while (*slot_types[i].name) {
57  quoted = false;
58  set = false;
59  /* cut off '.out' by using a string size arg */
60  const int name_len = is_out ? (strchr(slot_types[i].name, '.') - slot_types[i].name) :
61  sizeof(slot_types[i].name);
62  const char *value = "<Unknown>";
63  switch (slot_types[i].type) {
64  case BMO_OP_SLOT_BOOL:
65  value = "False";
66  break;
67  case BMO_OP_SLOT_INT:
68  if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_ENUM) {
69  value = slot_types[i].enum_flags[0].identifier;
70  quoted = true;
71  }
72  else if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_FLAG) {
73  value = "";
74  set = true;
75  }
76  else {
77  value = "0";
78  }
79  break;
80  case BMO_OP_SLOT_FLT:
81  value = "0.0";
82  break;
83  case BMO_OP_SLOT_PTR:
84  value = "None";
85  break;
86  case BMO_OP_SLOT_MAT:
87  value = "Matrix()";
88  break;
89  case BMO_OP_SLOT_VEC:
90  value = "Vector()";
91  break;
93  value = (slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]";
94  break;
96  value = "{}";
97  break;
98  }
99  BLI_dynstr_appendf(dyn_str,
100  i ? ", %.*s=%s%s%s%s%s" : "%.*s=%s%s%s%s%s",
101  name_len,
102  slot_types[i].name,
103  set ? "{" : "",
104  quoted ? "'" : "",
105  value,
106  quoted ? "'" : "",
107  set ? "}" : "");
108  i++;
109  }
110 
111  ret = BLI_dynstr_get_cstring(dyn_str);
112  BLI_dynstr_free(dyn_str);
113  return ret;
114 }
115 
116 static PyObject *bpy_bmesh_op_doc_get(BPy_BMeshOpFunc *self, void *UNUSED(closure))
117 {
118  PyObject *ret;
119  char *slot_in;
120  char *slot_out;
121  int i;
122 
123  i = BMO_opcode_from_opname(self->opname);
124 
125  slot_in = bmp_slots_as_args(bmo_opdefines[i]->slot_types_in, false);
126  slot_out = bmp_slots_as_args(bmo_opdefines[i]->slot_types_out, true);
127 
128  ret = PyUnicode_FromFormat("%.200s bmesh.ops.%.200s(bmesh, %s)\n -> dict(%s)",
129  Py_TYPE(self)->tp_name,
130  self->opname,
131  slot_in,
132  slot_out);
133 
134  MEM_freeN(slot_in);
135  MEM_freeN(slot_out);
136 
137  return ret;
138 }
139 
140 static PyGetSetDef bpy_bmesh_op_getseters[] = {
141  {"__doc__", (getter)bpy_bmesh_op_doc_get, (setter)NULL, NULL, NULL},
142  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
143 };
144 
145 /* Types
146  * ===== */
147 
148 static PyTypeObject bmesh_op_Type = {
149  PyVarObject_HEAD_INIT(NULL, 0) "BMeshOpFunc", /* tp_name */
150  sizeof(BPy_BMeshOpFunc), /* tp_basicsize */
151  0, /* tp_itemsize */
152  /* methods */
153  NULL, /* tp_dealloc */
154  0, /* tp_vectorcall_offset */
155  NULL, /* getattrfunc tp_getattr; */
156  NULL, /* setattrfunc tp_setattr; */
157  NULL,
158  /* tp_compare */ /* DEPRECATED in python 3.0! */
159  (reprfunc)bpy_bmesh_op_repr, /* tp_repr */
160 
161  /* Method suites for standard classes */
162 
163  NULL, /* PyNumberMethods *tp_as_number; */
164  NULL, /* PySequenceMethods *tp_as_sequence; */
165  NULL, /* PyMappingMethods *tp_as_mapping; */
166 
167  /* More standard operations (here for binary compatibility) */
168 
169  NULL, /* hashfunc tp_hash; */
170  (ternaryfunc)BPy_BMO_call, /* ternaryfunc tp_call; */
171  NULL, /* reprfunc tp_str; */
172 
173  /* will only use these if this is a subtype of a py class */
174  NULL, /* getattrofunc tp_getattro; */
175  NULL, /* setattrofunc tp_setattro; */
176 
177  /* Functions to access object as input/output buffer */
178  NULL, /* PyBufferProcs *tp_as_buffer; */
179 
180  /*** Flags to define presence of optional/expanded features ***/
181  Py_TPFLAGS_DEFAULT, /* long tp_flags; */
182 
183  NULL, /* char *tp_doc; Documentation string */
184  /*** Assigned meaning in release 2.0 ***/
185  /* call function for all accessible objects */
186  NULL, /* traverseproc tp_traverse; */
187 
188  /* delete references to contained objects */
189  NULL, /* inquiry tp_clear; */
190 
191  /*** Assigned meaning in release 2.1 ***/
192  /*** rich comparisons ***/
193  NULL, /* richcmpfunc tp_richcompare; */
194 
195  /*** weak reference enabler ***/
196  0,
197  /*** Added in release 2.2 ***/
198  /* Iterators */
199  NULL, /* getiterfunc tp_iter; */
200  NULL, /* iternextfunc tp_iternext; */
201 
202  /*** Attribute descriptor and subclassing stuff ***/
203  NULL, /* struct PyMethodDef *tp_methods; */
204  NULL, /* struct PyMemberDef *tp_members; */
205  bpy_bmesh_op_getseters, /* struct PyGetSetDef *tp_getset; */
206  NULL, /* struct _typeobject *tp_base; */
207  NULL, /* PyObject *tp_dict; */
208  NULL, /* descrgetfunc tp_descr_get; */
209  NULL, /* descrsetfunc tp_descr_set; */
210  0, /* long tp_dictoffset; */
211  NULL, /* initproc tp_init; */
212  NULL, /* allocfunc tp_alloc; */
213  NULL, /* newfunc tp_new; */
214  /* Low-level free-memory routine */
215  NULL, /* freefunc tp_free; */
216  /* For PyObject_IS_GC */
217  NULL, /* inquiry tp_is_gc; */
218  NULL, /* PyObject *tp_bases; */
219  /* method resolution order */
220  NULL, /* PyObject *tp_mro; */
221  NULL, /* PyObject *tp_cache; */
222  NULL, /* PyObject *tp_subclasses; */
223  NULL, /* PyObject *tp_weaklist; */
224  NULL,
225 };
226 
227 /* bmesh module 'bmesh.ops'
228  * ************************ */
229 
230 static PyObject *bpy_bmesh_ops_module_getattro(PyObject *UNUSED(self), PyObject *pyname)
231 {
232  const char *opname = PyUnicode_AsUTF8(pyname);
233 
234  if (BMO_opcode_from_opname(opname) != -1) {
235  return bpy_bmesh_op_CreatePyObject(opname);
236  }
237 
238  PyErr_Format(PyExc_AttributeError, "BMeshOpsModule: operator \"%.200s\" doesn't exist", opname);
239  return NULL;
240 }
241 
242 static PyObject *bpy_bmesh_ops_module_dir(PyObject *UNUSED(self))
243 {
244  const uint tot = bmo_opdefines_total;
245  uint i;
246  PyObject *ret;
247 
248  ret = PyList_New(bmo_opdefines_total);
249 
250  for (i = 0; i < tot; i++) {
251  PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname));
252  }
253 
254  return ret;
255 }
256 
257 static struct PyMethodDef BPy_BM_ops_methods[] = {
258  {"__getattr__", (PyCFunction)bpy_bmesh_ops_module_getattro, METH_O, NULL},
259  {"__dir__", (PyCFunction)bpy_bmesh_ops_module_dir, METH_NOARGS, NULL},
260  {NULL, NULL, 0, NULL},
261 };
262 
263 PyDoc_STRVAR(BPy_BM_ops_doc, "Access to BMesh operators");
264 static struct PyModuleDef BPy_BM_ops_module_def = {
265  PyModuleDef_HEAD_INIT,
266  "bmesh.ops", /* m_name */
267  BPy_BM_ops_doc, /* m_doc */
268  0, /* m_size */
269  BPy_BM_ops_methods, /* m_methods */
270  NULL, /* m_reload */
271  NULL, /* m_traverse */
272  NULL, /* m_clear */
273  NULL, /* m_free */
274 };
275 
276 PyObject *BPyInit_bmesh_ops(void)
277 {
278  PyObject *submodule = PyModule_Create(&BPy_BM_ops_module_def);
279 
280  if (PyType_Ready(&bmesh_op_Type) < 0) {
281  return NULL;
282  }
283 
284  return submodule;
285 }
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:256
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
const int bmo_opdefines_total
const BMOpDefine * bmo_opdefines[]
@ BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE
@ BMO_OP_SLOT_ELEMENT_BUF
@ BMO_OP_SLOT_PTR
@ BMO_OP_SLOT_BOOL
@ BMO_OP_SLOT_FLT
@ BMO_OP_SLOT_INT
@ BMO_OP_SLOT_VEC
@ BMO_OP_SLOT_MAPPING
@ BMO_OP_SLOT_MAT
int BMO_opcode_from_opname(const char *opname)
@ BMO_OP_SLOT_SUBTYPE_INT_FLAG
@ BMO_OP_SLOT_SUBTYPE_INT_ENUM
#define BMO_OP_MAX_SLOTS
static PyObject * bpy_bmesh_ops_module_dir(PyObject *UNUSED(self))
Definition: bmesh_py_ops.c:242
static struct PyMethodDef BPy_BM_ops_methods[]
Definition: bmesh_py_ops.c:257
static PyObject * bpy_bmesh_op_repr(BPy_BMeshOpFunc *self)
Definition: bmesh_py_ops.c:36
static PyObject * bpy_bmesh_op_doc_get(BPy_BMeshOpFunc *self, void *UNUSED(closure))
Definition: bmesh_py_ops.c:116
static PyObject * bpy_bmesh_op_CreatePyObject(const char *opname)
Definition: bmesh_py_ops.c:27
static PyGetSetDef bpy_bmesh_op_getseters[]
Definition: bmesh_py_ops.c:140
PyDoc_STRVAR(BPy_BM_ops_doc, "Access to BMesh operators")
PyObject * BPyInit_bmesh_ops(void)
Definition: bmesh_py_ops.c:276
static PyTypeObject bmesh_op_Type
Definition: bmesh_py_ops.c:25
static PyObject * bpy_bmesh_ops_module_getattro(PyObject *UNUSED(self), PyObject *pyname)
Definition: bmesh_py_ops.c:230
static struct PyModuleDef BPy_BM_ops_module_def
Definition: bmesh_py_ops.c:264
static char * bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out)
Definition: bmesh_py_ops.c:47
PyObject * BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
PyObject * self
Definition: bpy_driver.c:165
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
return ret