Blender V4.3
bpy_rna_gizmo.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <Python.h>
12#include <cstddef>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_alloca.h"
17#include "BLI_utildefines.h"
18
19#include "WM_types.hh"
20
21#include "bpy_capi_utils.hh"
22#include "bpy_rna_gizmo.hh"
23
26
27#include "RNA_access.hh"
28#include "RNA_prototypes.hh"
29
30#include "bpy_rna.hh"
31
32/* -------------------------------------------------------------------- */
39 wmGizmo *gz; /* Must be first. */
41};
42
44 wmGizmo *gz; /* Must be first. */
46};
47
48static int py_rna_gizmo_parse(PyObject *o, void *p)
49{
50 /* No type checking (this is `self` not a user defined argument). */
52 BLI_assert(RNA_struct_is_a(((const BPy_StructRNA *)o)->ptr.type, &RNA_Gizmo));
53
54 wmGizmo **gz_p = static_cast<wmGizmo **>(p);
55 *gz_p = static_cast<wmGizmo *>(((const BPy_StructRNA *)o)->ptr.data);
56 return 1;
57}
58
59static int py_rna_gizmo_target_id_parse(PyObject *o, void *p)
60{
61 BPyGizmoWithTarget *gizmo_with_target = static_cast<BPyGizmoWithTarget *>(p);
62 /* Must be set by `py_rna_gizmo_parse`. */
63 wmGizmo *gz = gizmo_with_target->gz;
64 BLI_assert(gz != nullptr);
65
66 if (!PyUnicode_Check(o)) {
67 PyErr_Format(PyExc_TypeError, "expected a string (got %.200s)", Py_TYPE(o)->tp_name);
68 return 0;
69 }
70 const char *gz_prop_id = PyUnicode_AsUTF8(o);
71 wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, gz_prop_id);
72 if (gz_prop == nullptr) {
73 PyErr_Format(PyExc_ValueError,
74 "Gizmo target property '%s.%s' not found!",
75 gz->type->idname,
76 gz_prop_id);
77 return 0;
78 }
79 gizmo_with_target->gz_prop = gz_prop;
80 return 1;
81}
82
84{
85 if (py_rna_gizmo_target_id_parse(o, p) == 0) {
86 return 0;
87 }
88 BPyGizmoWithTarget *gizmo_with_target = static_cast<BPyGizmoWithTarget *>(p);
89 wmGizmo *gz = gizmo_with_target->gz;
90 wmGizmoProperty *gz_prop = gizmo_with_target->gz_prop;
92 const char *gz_prop_id = PyUnicode_AsUTF8(o);
93 PyErr_Format(PyExc_ValueError,
94 "Gizmo target property '%s.%s' has not been initialized, "
95 "Call \"target_set_prop\" first!",
96 gz->type->idname,
97 gz_prop_id);
98 return 0;
99 }
100 return 1;
101}
102
103static int py_rna_gizmo_target_type_id_parse(PyObject *o, void *p)
104{
105 BPyGizmoWithTargetType *gizmo_with_target = static_cast<BPyGizmoWithTargetType *>(p);
106 /* Must be set first. */
107 wmGizmo *gz = gizmo_with_target->gz;
108 BLI_assert(gz != nullptr);
109
110 if (!PyUnicode_Check(o)) {
111 PyErr_Format(PyExc_TypeError, "expected a string (got %.200s)", Py_TYPE(o)->tp_name);
112 return 0;
113 }
114 const char *gz_prop_id = PyUnicode_AsUTF8(o);
116 gz_prop_id);
117 if (gz_prop_type == nullptr) {
118 PyErr_Format(PyExc_ValueError,
119 "Gizmo target property '%s.%s' not found!",
120 gz->type->idname,
121 gz_prop_id);
122 return 0;
123 }
124 gizmo_with_target->gz_prop_type = gz_prop_type;
125 return 1;
126}
127
130/* -------------------------------------------------------------------- */
134enum {
138};
139#define BPY_GIZMO_FN_SLOT_LEN (BPY_GIZMO_FN_SLOT_RANGE_GET + 1)
140
145
146static void py_rna_gizmo_handler_get_cb(const wmGizmo * /*gz*/,
147 wmGizmoProperty *gz_prop,
148 void *value_p)
149{
150 const PyGILState_STATE gilstate = PyGILState_Ensure();
151
153 gz_prop->custom_func.user_data);
154 PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_GET], nullptr);
155 if (ret == nullptr) {
156 goto fail;
157 }
158
159 if (gz_prop->type->data_type == PROP_FLOAT) {
160 float *value = static_cast<float *>(value_p);
161 if (gz_prop->type->array_length == 1) {
162 if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) {
163 goto fail;
164 }
165 }
166 else {
167 if (PyC_AsArray(value,
168 sizeof(*value),
169 ret,
170 gz_prop->type->array_length,
171 &PyFloat_Type,
172 "Gizmo get callback: ") == -1)
173 {
174 goto fail;
175 }
176 }
177 }
178 else {
179 PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
180 goto fail;
181 }
182
183 Py_DECREF(ret);
184
185 PyGILState_Release(gilstate);
186 return;
187
188fail:
189 PyErr_Print();
190 PyErr_Clear();
191
192 Py_XDECREF(ret);
193
194 PyGILState_Release(gilstate);
195}
196
197static void py_rna_gizmo_handler_set_cb(const wmGizmo * /*gz*/,
198 wmGizmoProperty *gz_prop,
199 const void *value_p)
200{
201 const PyGILState_STATE gilstate = PyGILState_Ensure();
202
204 gz_prop->custom_func.user_data);
205
206 PyObject *args = PyTuple_New(1);
207 PyObject *ret;
208
209 if (gz_prop->type->data_type == PROP_FLOAT) {
210 const float *value = static_cast<const float *>(value_p);
211 PyObject *py_value;
212 if (gz_prop->type->array_length == 1) {
213 py_value = PyFloat_FromDouble(*value);
214 }
215 else {
216 py_value = PyC_Tuple_PackArray_F32(value, gz_prop->type->array_length);
217 }
218 if (py_value == nullptr) {
219 goto fail;
220 }
221 PyTuple_SET_ITEM(args, 0, py_value);
222 }
223 else {
224 PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
225 goto fail;
226 }
227
228 ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_SET], args);
229 if (ret == nullptr) {
230 goto fail;
231 }
232 Py_DECREF(args);
233 Py_DECREF(ret);
234
235 PyGILState_Release(gilstate);
236 return;
237
238fail:
239 PyErr_Print();
240 PyErr_Clear();
241
242 Py_DECREF(args);
243
244 PyGILState_Release(gilstate);
245}
246
248 wmGizmoProperty *gz_prop,
249 void *value_p)
250{
252 gz_prop->custom_func.user_data);
253
254 const PyGILState_STATE gilstate = PyGILState_Ensure();
255
256 PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET], nullptr);
257 if (ret == nullptr) {
258 goto fail;
259 }
260
261 if (!PyTuple_Check(ret)) {
262 PyErr_Format(PyExc_TypeError, "Expected a tuple, not %.200s", Py_TYPE(ret)->tp_name);
263 goto fail;
264 }
265
266 if (PyTuple_GET_SIZE(ret) != 2) {
267 PyErr_Format(PyExc_TypeError, "Expected a tuple of size 2, not %d", PyTuple_GET_SIZE(ret));
268 goto fail;
269 }
270
271 if (gz_prop->type->data_type == PROP_FLOAT) {
272 float range[2];
273 for (int i = 0; i < 2; i++) {
274 if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) ==
275 0)
276 {
277 /* pass */
278 }
279 else {
280 goto fail;
281 }
282 }
283 memcpy(value_p, range, sizeof(range));
284 }
285 else {
286 PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
287 goto fail;
288 }
289
290 Py_DECREF(ret);
291 PyGILState_Release(gilstate);
292 return;
293
294fail:
295 PyErr_Print();
296 PyErr_Clear();
297
298 Py_XDECREF(ret);
299
300 PyGILState_Release(gilstate);
301}
302
303static void py_rna_gizmo_handler_free_cb(const wmGizmo * /*gz*/, wmGizmoProperty *gz_prop)
304{
306 gz_prop->custom_func.user_data);
307
308 const PyGILState_STATE gilstate = PyGILState_Ensure();
309 for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
310 Py_XDECREF(data->fn_slots[i]);
311 }
312 PyGILState_Release(gilstate);
313
314 MEM_freeN(data);
315}
316
318 /* Wrap. */
319 bpy_gizmo_target_set_handler_doc,
320 ".. method:: target_set_handler(target, get, set, range=None):\n"
321 "\n"
322 " Assigns callbacks to a gizmos property.\n"
323 "\n"
324 " :arg target: Target property name.\n"
325 " :type target: str\n"
326 " :arg get: Function that returns the value for this property (single value or sequence).\n"
327 " :type get: Callable[[], float | Sequence[float]]\n"
328 " :arg set: Function that takes a single value argument and applies it.\n"
329 " :type set: Callable[[tuple[float, ...]], Any]\n"
330 " :arg range: Function that returns a (min, max) tuple for gizmos that use a range. "
331 "The returned value is not used.\n"
332 " :type range: callable\n");
333static PyObject *bpy_gizmo_target_set_handler(PyObject * /*self*/, PyObject *args, PyObject *kw)
334{
335 const PyGILState_STATE gilstate = PyGILState_Ensure();
336
337 struct {
338 BPyGizmoWithTargetType gz_with_target_type;
339 PyObject *py_fn_slots[BPY_GIZMO_FN_SLOT_LEN];
340 } params = {
341 {nullptr, nullptr},
342 {nullptr},
343 };
344
345 /* NOTE: this is a counter-part to functions:
346 * 'Gizmo.target_set_prop & target_set_operator'
347 * (see: rna_wm_gizmo_api.cc). conventions should match. */
348 static const char *const _keywords[] = {"self", "target", "get", "set", "range", nullptr};
349 static _PyArg_Parser _parser = {
351 "O&" /* `self` */
352 "O&" /* `target` */
353 "|$" /* Optional keyword only arguments. */
354 "O" /* `get` */
355 "O" /* `set` */
356 "O" /* `range` */
357 ":target_set_handler",
358 _keywords,
359 nullptr,
360 };
361
363 const wmGizmoPropertyType *gz_prop_type;
364 wmGizmo *gz;
365
366 if (!_PyArg_ParseTupleAndKeywordsFast(args,
367 kw,
368 &_parser,
369 /* `self` */
371 &params.gz_with_target_type.gz,
372 /* `target` */
374 &params.gz_with_target_type,
375 /* `get/set/range` */
376 &params.py_fn_slots[BPY_GIZMO_FN_SLOT_GET],
377 &params.py_fn_slots[BPY_GIZMO_FN_SLOT_SET],
378 &params.py_fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET]))
379 {
380 goto fail;
381 }
382
383 gz = params.gz_with_target_type.gz;
384 gz_prop_type = params.gz_with_target_type.gz_prop_type;
385
386 {
387 const int slots_required = 2;
388 const int slots_start = 2;
389 for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
390 if (params.py_fn_slots[i] == nullptr) {
391 if (i < slots_required) {
392 PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]);
393 goto fail;
394 }
395 }
396 else if (!PyCallable_Check(params.py_fn_slots[i])) {
397 PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]);
398 goto fail;
399 }
400 }
401 }
402
403 data = static_cast<BPyGizmoHandlerUserData *>(MEM_callocN(sizeof(*data), __func__));
404
405 for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
406 data->fn_slots[i] = params.py_fn_slots[i];
407 Py_XINCREF(params.py_fn_slots[i]);
408 }
409
410 {
411 wmGizmoPropertyFnParams fn_params{};
413 fn_params.value_set_fn = py_rna_gizmo_handler_set_cb;
414 fn_params.range_get_fn = py_rna_gizmo_handler_range_get_cb;
415 fn_params.free_fn = py_rna_gizmo_handler_free_cb;
416 fn_params.user_data = data;
417 WM_gizmo_target_property_def_func_ptr(gz, gz_prop_type, &fn_params);
418 }
419
420 PyGILState_Release(gilstate);
421
422 Py_RETURN_NONE;
423
424fail:
425 PyGILState_Release(gilstate);
426 return nullptr;
427}
428
431/* -------------------------------------------------------------------- */
436 /* Wrap. */
437 bpy_gizmo_target_get_value_doc,
438 ".. method:: target_get_value(target):\n"
439 "\n"
440 " Get the value of this target property.\n"
441 "\n"
442 " :arg target: Target property name.\n"
443 " :type target: str\n"
444 " :return: The value of the target property as a value or array based on the target type.\n"
445 " :rtype: float | tuple[float, ...]\n");
446static PyObject *bpy_gizmo_target_get_value(PyObject * /*self*/, PyObject *args, PyObject *kw)
447{
448 struct {
449 BPyGizmoWithTarget gz_with_target;
450 } params = {
451 {nullptr, nullptr},
452 };
453
454 static const char *const _keywords[] = {"self", "target", nullptr};
455 static _PyArg_Parser _parser = {
457 "O&" /* `self` */
458 "O&" /* `target` */
459 ":target_get_value",
460 _keywords,
461 nullptr,
462 };
463
464 int array_len;
465 wmGizmo *gz;
466 wmGizmoProperty *gz_prop;
467
468 if (!_PyArg_ParseTupleAndKeywordsFast(args,
469 kw,
470 &_parser,
471 /* `self` */
473 &params.gz_with_target.gz,
474 /* `target` */
476 &params.gz_with_target))
477 {
478 goto fail;
479 }
480
481 gz = params.gz_with_target.gz;
482 gz_prop = params.gz_with_target.gz_prop;
483
484 array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
485 switch (gz_prop->type->data_type) {
486 case PROP_FLOAT: {
487 if (array_len != 0) {
488 float *value = static_cast<float *>(BLI_array_alloca(value, array_len));
490 return PyC_Tuple_PackArray_F32(value, array_len);
491 }
492
493 const float value = WM_gizmo_target_property_float_get(gz, gz_prop);
494 return PyFloat_FromDouble(value);
495 }
496 default: {
497 PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
498 goto fail;
499 }
500 }
501
502fail:
503 return nullptr;
504}
505
507 /* Wrap. */
508 bpy_gizmo_target_set_value_doc,
509 ".. method:: target_set_value(target):\n"
510 "\n"
511 " Set the value of this target property.\n"
512 "\n"
513 " :arg target: Target property name.\n"
514 " :type target: str\n");
515static PyObject *bpy_gizmo_target_set_value(PyObject * /*self*/, PyObject *args, PyObject *kw)
516{
517 struct {
518 BPyGizmoWithTarget gz_with_target;
519 PyObject *value;
520 } params = {
521 {nullptr, nullptr},
522 nullptr,
523 };
524
525 static const char *const _keywords[] = {"self", "target", "value", nullptr};
526 static _PyArg_Parser _parser = {
528 "O&" /* `self` */
529 "O&" /* `target` */
530 "O" /* `value` */
531 ":target_set_value",
532 _keywords,
533 nullptr,
534 };
535
536 wmGizmo *gz;
537 wmGizmoProperty *gz_prop;
538 int array_len;
539
540 if (!_PyArg_ParseTupleAndKeywordsFast(args,
541 kw,
542 &_parser,
543 /* `self` */
545 &params.gz_with_target.gz,
546 /* `target` */
548 &params.gz_with_target,
549 /* `value` */
550 &params.value))
551 {
552 goto fail;
553 }
554
555 gz = params.gz_with_target.gz;
556 gz_prop = params.gz_with_target.gz_prop;
557
558 array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
559 switch (gz_prop->type->data_type) {
560 case PROP_FLOAT: {
561 if (array_len != 0) {
562 float *value = static_cast<float *>(BLI_array_alloca(value, array_len));
563 if (PyC_AsArray(value,
564 sizeof(*value),
565 params.value,
566 gz_prop->type->array_length,
567 &PyFloat_Type,
568 "Gizmo target property array: ") == -1)
569 {
570 goto fail;
571 }
573 }
574 else {
575 float value;
576 if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
577 goto fail;
578 }
580 }
581 Py_RETURN_NONE;
582 }
583 default: {
584 PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
585 goto fail;
586 }
587 }
588
589fail:
590 return nullptr;
591}
592
594 /* Wrap. */
595 bpy_gizmo_target_get_range_doc,
596 ".. method:: target_get_range(target):\n"
597 "\n"
598 " Get the range for this target property.\n"
599 "\n"
600 " :arg target: Target property name.\n"
601 " :return: The range of this property (min, max).\n"
602 " :rtype: tuple[float, float]\n");
603static PyObject *bpy_gizmo_target_get_range(PyObject * /*self*/, PyObject *args, PyObject *kw)
604{
605 struct {
606 BPyGizmoWithTarget gz_with_target;
607 } params = {
608 {nullptr, nullptr},
609 };
610
611 static const char *const _keywords[] = {"self", "target", nullptr};
612 static _PyArg_Parser _parser = {
614 "O&" /* `self` */
615 "O&" /* `target` */
616 ":target_get_range",
617 _keywords,
618 nullptr,
619 };
620
621 wmGizmo *gz;
622 wmGizmoProperty *gz_prop;
623
624 if (!_PyArg_ParseTupleAndKeywordsFast(args,
625 kw,
626 &_parser,
627 /* `self` */
629 &params.gz_with_target.gz,
630 /* `target` */
632 &params.gz_with_target))
633 {
634 goto fail;
635 }
636
637 gz = params.gz_with_target.gz;
638 gz_prop = params.gz_with_target.gz_prop;
639
640 switch (gz_prop->type->data_type) {
641 case PROP_FLOAT: {
642 float range[2];
644 return PyC_Tuple_PackArray_F32(range, 2);
645 }
646 default: {
647 PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
648 goto fail;
649 }
650 }
651
652fail:
653 return nullptr;
654}
655
658/* -------------------------------------------------------------------- */
662bool BPY_rna_gizmo_module(PyObject *mod_par)
663{
664
665#if (defined(__GNUC__) && !defined(__clang__))
666# pragma GCC diagnostic push
667# pragma GCC diagnostic ignored "-Wcast-function-type"
668#endif
669
670 static PyMethodDef method_def_array[] = {
671 /* Gizmo Target Property Define API */
672 {"target_set_handler",
673 (PyCFunction)bpy_gizmo_target_set_handler,
674 METH_VARARGS | METH_KEYWORDS,
675 bpy_gizmo_target_set_handler_doc},
676 /* Gizmo Target Property Access API */
677 {"target_get_value",
678 (PyCFunction)bpy_gizmo_target_get_value,
679 METH_VARARGS | METH_KEYWORDS,
680 bpy_gizmo_target_get_value_doc},
681 {"target_set_value",
682 (PyCFunction)bpy_gizmo_target_set_value,
683 METH_VARARGS | METH_KEYWORDS,
684 bpy_gizmo_target_set_value_doc},
685 {"target_get_range",
686 (PyCFunction)bpy_gizmo_target_get_range,
687 METH_VARARGS | METH_KEYWORDS,
688 bpy_gizmo_target_get_range_doc},
689 /* no sentinel needed. */
690 };
691
692#if (defined(__GNUC__) && !defined(__clang__))
693# pragma GCC diagnostic pop
694#endif
695
696 for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) {
697 PyMethodDef *m = &method_def_array[i];
698 PyObject *func = PyCFunction_New(m, nullptr);
699 PyObject *func_inst = PyInstanceMethod_New(func);
700 char name_prefix[128];
701 PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name);
702 /* TODO: return a type that binds nearly to a method. */
703 PyModule_AddObject(mod_par, name_prefix, func_inst);
704 }
705
706 return false;
707}
708
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:25
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ARRAY_SIZE(arr)
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:67
struct bContext * BPY_context_get(void)
#define BPy_StructRNA_Check(v)
Definition bpy_rna.hh:69
static void py_rna_gizmo_handler_range_get_cb(const wmGizmo *, wmGizmoProperty *gz_prop, void *value_p)
static void py_rna_gizmo_handler_free_cb(const wmGizmo *, wmGizmoProperty *gz_prop)
bool BPY_rna_gizmo_module(PyObject *mod_par)
static int py_rna_gizmo_target_id_parse(PyObject *o, void *p)
static int py_rna_gizmo_target_id_parse_and_ensure_is_valid(PyObject *o, void *p)
PyDoc_STRVAR(bpy_gizmo_target_set_handler_doc, ".. method:: target_set_handler(target, get, set, range=None):\n" "\n" " Assigns callbacks to a gizmos property.\n" "\n" " :arg target: Target property name.\n" " :type target: str\n" " :arg get: Function that returns the value for this property (single value or sequence).\n" " :type get: Callable[[], float | Sequence[float]]\n" " :arg set: Function that takes a single value argument and applies it.\n" " :type set: Callable[[tuple[float, ...]], Any]\n" " :arg range: Function that returns a (min, max) tuple for gizmos that use a range. " "The returned value is not used.\n" " :type range: callable\n")
static PyObject * bpy_gizmo_target_set_handler(PyObject *, PyObject *args, PyObject *kw)
static PyObject * bpy_gizmo_target_set_value(PyObject *, PyObject *args, PyObject *kw)
static PyObject * bpy_gizmo_target_get_value(PyObject *, PyObject *args, PyObject *kw)
#define BPY_GIZMO_FN_SLOT_LEN
static PyObject * bpy_gizmo_target_get_range(PyObject *, PyObject *args, PyObject *kw)
static int py_rna_gizmo_target_type_id_parse(PyObject *o, void *p)
static void py_rna_gizmo_handler_get_cb(const wmGizmo *, wmGizmoProperty *gz_prop, void *value_p)
static void py_rna_gizmo_handler_set_cb(const wmGizmo *, wmGizmoProperty *gz_prop, const void *value_p)
@ BPY_GIZMO_FN_SLOT_GET
@ BPY_GIZMO_FN_SLOT_RANGE_GET
@ BPY_GIZMO_FN_SLOT_SET
static int py_rna_gizmo_parse(PyObject *o, void *p)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
int PyC_AsArray(void *array, const size_t array_item_size, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix)
PyObject * PyC_Tuple_PackArray_F32(const float *array, uint len)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
return ret
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
PyObject * fn_slots[BPY_GIZMO_FN_SLOT_LEN]
const wmGizmoPropertyType * gz_prop_type
wmGizmoProperty * gz_prop
StructRNA * type
Definition RNA_types.hh:41
wmGizmoPropertyFnGet value_get_fn
const wmGizmoPropertyType * type
struct wmGizmoProperty::@1373 custom_func
const char * idname
const wmGizmoType * type
PointerRNA * ptr
Definition wm_files.cc:4126
void WM_gizmo_target_property_float_set(bContext *C, const wmGizmo *gz, wmGizmoProperty *gz_prop, const float value)
const wmGizmoPropertyType * WM_gizmotype_target_property_find(const wmGizmoType *gzt, const char *idname)
bool WM_gizmo_target_property_is_valid(const wmGizmoProperty *gz_prop)
void WM_gizmo_target_property_float_get_array(const wmGizmo *gz, wmGizmoProperty *gz_prop, float *value)
int WM_gizmo_target_property_array_length(const wmGizmo *, wmGizmoProperty *gz_prop)
void WM_gizmo_target_property_def_func_ptr(wmGizmo *gz, const wmGizmoPropertyType *gz_prop_type, const wmGizmoPropertyFnParams *params)
float WM_gizmo_target_property_float_get(const wmGizmo *gz, wmGizmoProperty *gz_prop)
void WM_gizmo_target_property_float_set_array(bContext *C, const wmGizmo *gz, wmGizmoProperty *gz_prop, const float *value)
wmGizmoProperty * WM_gizmo_target_property_find(wmGizmo *gz, const char *idname)
bool WM_gizmo_target_property_float_range_get(const wmGizmo *gz, wmGizmoProperty *gz_prop, float range[2])