Blender V4.5
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
10
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
25#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
26
27#include "RNA_access.hh"
28#include "RNA_prototypes.hh"
29
30#include "bpy_rna.hh"
31
32/* -------------------------------------------------------------------- */
37
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
129
130/* -------------------------------------------------------------------- */
133
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{
251 const PyGILState_STATE gilstate = PyGILState_Ensure();
252
254 gz_prop->custom_func.user_data);
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{
305 const PyGILState_STATE gilstate = PyGILState_Ensure();
306
308 gz_prop->custom_func.user_data);
309
310 for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
311 Py_XDECREF(data->fn_slots[i]);
312 }
313 PyGILState_Release(gilstate);
314
316}
317
319 /* Wrap. */
320 bpy_gizmo_target_set_handler_doc,
321 ".. method:: target_set_handler(target, get, set, range=None):\n"
322 "\n"
323 " Assigns callbacks to a gizmos property.\n"
324 "\n"
325 " :arg target: Target property name.\n"
326 " :type target: str\n"
327 " :arg get: Function that returns the value for this property (single value or sequence).\n"
328 " :type get: Callable[[], float | Sequence[float]]\n"
329 " :arg set: Function that takes a single value argument and applies it.\n"
330 " :type set: Callable[[tuple[float, ...]], Any]\n"
331 " :arg range: Function that returns a (min, max) tuple for gizmos that use a range. "
332 "The returned value is not used.\n"
333 " :type range: callable\n");
334static PyObject *bpy_gizmo_target_set_handler(PyObject * /*self*/, PyObject *args, PyObject *kw)
335{
336 struct {
337 BPyGizmoWithTargetType gz_with_target_type;
338 PyObject *py_fn_slots[BPY_GIZMO_FN_SLOT_LEN];
339 } params = {
340 {nullptr, nullptr},
341 {nullptr},
342 };
343
344 /* NOTE: this is a counter-part to functions:
345 * 'Gizmo.target_set_prop & target_set_operator'
346 * (see: rna_wm_gizmo_api.cc). conventions should match. */
347 static const char *const _keywords[] = {"self", "target", "get", "set", "range", nullptr};
348 static _PyArg_Parser _parser = {
350 "O&" /* `self` */
351 "O&" /* `target` */
352 "|$" /* Optional keyword only arguments. */
353 "O" /* `get` */
354 "O" /* `set` */
355 "O" /* `range` */
356 ":target_set_handler",
357 _keywords,
358 nullptr,
359 };
360
362 const wmGizmoPropertyType *gz_prop_type;
363 wmGizmo *gz;
364
365 if (!_PyArg_ParseTupleAndKeywordsFast(args,
366 kw,
367 &_parser,
368 /* `self` */
370 &params.gz_with_target_type.gz,
371 /* `target` */
373 &params.gz_with_target_type,
374 /* `get/set/range` */
375 &params.py_fn_slots[BPY_GIZMO_FN_SLOT_GET],
376 &params.py_fn_slots[BPY_GIZMO_FN_SLOT_SET],
377 &params.py_fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET]))
378 {
379 goto fail;
380 }
381
382 gz = params.gz_with_target_type.gz;
383 gz_prop_type = params.gz_with_target_type.gz_prop_type;
384
385 {
386 const int slots_required = 2;
387 const int slots_start = 2;
388 for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
389 if (params.py_fn_slots[i] == nullptr) {
390 if (i < slots_required) {
391 PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]);
392 goto fail;
393 }
394 }
395 else if (!PyCallable_Check(params.py_fn_slots[i])) {
396 PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]);
397 goto fail;
398 }
399 }
400 }
401
403
404 for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
405 data->fn_slots[i] = params.py_fn_slots[i];
406 Py_XINCREF(params.py_fn_slots[i]);
407 }
408
409 {
410 wmGizmoPropertyFnParams fn_params{};
415 fn_params.user_data = data;
416 WM_gizmo_target_property_def_func_ptr(gz, gz_prop_type, &fn_params);
417 }
418
419 Py_RETURN_NONE;
420
421fail:
422 return nullptr;
423}
424
426
427/* -------------------------------------------------------------------- */
430
432 /* Wrap. */
433 bpy_gizmo_target_get_value_doc,
434 ".. method:: target_get_value(target):\n"
435 "\n"
436 " Get the value of this target property.\n"
437 "\n"
438 " :arg target: Target property name.\n"
439 " :type target: str\n"
440 " :return: The value of the target property as a value or array based on the target type.\n"
441 " :rtype: float | tuple[float, ...]\n");
442static PyObject *bpy_gizmo_target_get_value(PyObject * /*self*/, PyObject *args, PyObject *kw)
443{
444 struct {
445 BPyGizmoWithTarget gz_with_target;
446 } params = {
447 {nullptr, nullptr},
448 };
449
450 static const char *const _keywords[] = {"self", "target", nullptr};
451 static _PyArg_Parser _parser = {
453 "O&" /* `self` */
454 "O&" /* `target` */
455 ":target_get_value",
456 _keywords,
457 nullptr,
458 };
459
460 int array_len;
461 wmGizmo *gz;
462 wmGizmoProperty *gz_prop;
463
464 if (!_PyArg_ParseTupleAndKeywordsFast(args,
465 kw,
466 &_parser,
467 /* `self` */
469 &params.gz_with_target.gz,
470 /* `target` */
472 &params.gz_with_target))
473 {
474 goto fail;
475 }
476
477 gz = params.gz_with_target.gz;
478 gz_prop = params.gz_with_target.gz_prop;
479
480 array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
481 switch (gz_prop->type->data_type) {
482 case PROP_FLOAT: {
483 if (array_len != 0) {
484 float *value = static_cast<float *>(BLI_array_alloca(value, array_len));
486 return PyC_Tuple_PackArray_F32(value, array_len);
487 }
488
489 const float value = WM_gizmo_target_property_float_get(gz, gz_prop);
490 return PyFloat_FromDouble(value);
491 }
492 default: {
493 PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
494 goto fail;
495 }
496 }
497
498fail:
499 return nullptr;
500}
501
503 /* Wrap. */
504 bpy_gizmo_target_set_value_doc,
505 ".. method:: target_set_value(target):\n"
506 "\n"
507 " Set the value of this target property.\n"
508 "\n"
509 " :arg target: Target property name.\n"
510 " :type target: str\n");
511static PyObject *bpy_gizmo_target_set_value(PyObject * /*self*/, PyObject *args, PyObject *kw)
512{
513 struct {
514 BPyGizmoWithTarget gz_with_target;
515 PyObject *value;
516 } params = {
517 {nullptr, nullptr},
518 nullptr,
519 };
520
521 static const char *const _keywords[] = {"self", "target", "value", nullptr};
522 static _PyArg_Parser _parser = {
524 "O&" /* `self` */
525 "O&" /* `target` */
526 "O" /* `value` */
527 ":target_set_value",
528 _keywords,
529 nullptr,
530 };
531
532 wmGizmo *gz;
533 wmGizmoProperty *gz_prop;
534 int array_len;
535
536 if (!_PyArg_ParseTupleAndKeywordsFast(args,
537 kw,
538 &_parser,
539 /* `self` */
541 &params.gz_with_target.gz,
542 /* `target` */
544 &params.gz_with_target,
545 /* `value` */
546 &params.value))
547 {
548 goto fail;
549 }
550
551 gz = params.gz_with_target.gz;
552 gz_prop = params.gz_with_target.gz_prop;
553
554 array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
555 switch (gz_prop->type->data_type) {
556 case PROP_FLOAT: {
557 if (array_len != 0) {
558 float *value = static_cast<float *>(BLI_array_alloca(value, array_len));
559 if (PyC_AsArray(value,
560 sizeof(*value),
561 params.value,
562 gz_prop->type->array_length,
563 &PyFloat_Type,
564 "Gizmo target property array: ") == -1)
565 {
566 goto fail;
567 }
569 }
570 else {
571 float value;
572 if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
573 goto fail;
574 }
576 }
577 Py_RETURN_NONE;
578 }
579 default: {
580 PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
581 goto fail;
582 }
583 }
584
585fail:
586 return nullptr;
587}
588
590 /* Wrap. */
591 bpy_gizmo_target_get_range_doc,
592 ".. method:: target_get_range(target):\n"
593 "\n"
594 " Get the range for this target property.\n"
595 "\n"
596 " :arg target: Target property name.\n"
597 " :return: The range of this property (min, max).\n"
598 " :rtype: tuple[float, float]\n");
599static PyObject *bpy_gizmo_target_get_range(PyObject * /*self*/, PyObject *args, PyObject *kw)
600{
601 struct {
602 BPyGizmoWithTarget gz_with_target;
603 } params = {
604 {nullptr, nullptr},
605 };
606
607 static const char *const _keywords[] = {"self", "target", nullptr};
608 static _PyArg_Parser _parser = {
610 "O&" /* `self` */
611 "O&" /* `target` */
612 ":target_get_range",
613 _keywords,
614 nullptr,
615 };
616
617 wmGizmo *gz;
618 wmGizmoProperty *gz_prop;
619
620 if (!_PyArg_ParseTupleAndKeywordsFast(args,
621 kw,
622 &_parser,
623 /* `self` */
625 &params.gz_with_target.gz,
626 /* `target` */
628 &params.gz_with_target))
629 {
630 goto fail;
631 }
632
633 gz = params.gz_with_target.gz;
634 gz_prop = params.gz_with_target.gz_prop;
635
636 switch (gz_prop->type->data_type) {
637 case PROP_FLOAT: {
638 float range[2];
640 return PyC_Tuple_PackArray_F32(range, 2);
641 }
642 default: {
643 PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
644 goto fail;
645 }
646 }
647
648fail:
649 return nullptr;
650}
651
653
654/* -------------------------------------------------------------------- */
657
658bool BPY_rna_gizmo_module(PyObject *mod_par)
659{
660
661#ifdef __GNUC__
662# ifdef __clang__
663# pragma clang diagnostic push
664# pragma clang diagnostic ignored "-Wcast-function-type"
665# else
666# pragma GCC diagnostic push
667# pragma GCC diagnostic ignored "-Wcast-function-type"
668# endif
669#endif
670
671 static PyMethodDef method_def_array[] = {
672 /* Gizmo Target Property Define API */
673 {"target_set_handler",
674 (PyCFunction)bpy_gizmo_target_set_handler,
675 METH_VARARGS | METH_KEYWORDS,
676 bpy_gizmo_target_set_handler_doc},
677 /* Gizmo Target Property Access API */
678 {"target_get_value",
679 (PyCFunction)bpy_gizmo_target_get_value,
680 METH_VARARGS | METH_KEYWORDS,
681 bpy_gizmo_target_get_value_doc},
682 {"target_set_value",
683 (PyCFunction)bpy_gizmo_target_set_value,
684 METH_VARARGS | METH_KEYWORDS,
685 bpy_gizmo_target_set_value_doc},
686 {"target_get_range",
687 (PyCFunction)bpy_gizmo_target_get_range,
688 METH_VARARGS | METH_KEYWORDS,
689 bpy_gizmo_target_get_range_doc},
690 /* no sentinel needed. */
691 };
692
693#ifdef __GNUC__
694# ifdef __clang__
695# pragma clang diagnostic pop
696# else
697# pragma GCC diagnostic pop
698# endif
699#endif
700
701 for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) {
702 PyMethodDef *m = &method_def_array[i];
703 PyObject *func = PyCFunction_New(m, nullptr);
704 PyObject *func_inst = PyInstanceMethod_New(func);
705 char name_prefix[128];
706 PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name);
707 /* TODO: return a type that binds nearly to a method. */
708 PyModule_AddObject(mod_par, name_prefix, func_inst);
709 }
710
711 return false;
712}
713
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:18
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ARRAY_SIZE(arr)
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:152
BMesh const char void * data
struct bContext * BPY_context_get()
#define BPy_StructRNA_Check(v)
Definition bpy_rna.hh:73
@ BPY_GIZMO_FN_SLOT_GET
@ BPY_GIZMO_FN_SLOT_RANGE_GET
@ BPY_GIZMO_FN_SLOT_SET
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)
static int py_rna_gizmo_parse(PyObject *o, void *p)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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
wmGizmoPropertyFnGet value_get_fn
wmGizmoPropertyFnRangeGet range_get_fn
wmGizmoPropertyFnFree free_fn
wmGizmoPropertyFnSet value_set_fn
struct wmGizmoProperty::@046017364211037167053011312355256221126135017103 custom_func
const wmGizmoPropertyType * type
const char * idname
const wmGizmoType * type
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4226
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])