forked from bartvdbraak/blender
Manipulator: Add API target_get/set/range wrappers
Allows Python manipulators access the values of target properties needed for Python to make use of the general target property interface.
This commit is contained in:
parent
bd935b5aed
commit
f4fe405da9
@ -618,7 +618,12 @@ class Manipulator(StructRNA, metaclass=OrderedMeta):
|
||||
return delattr(properties, attr)
|
||||
return super().__delattr__(attr)
|
||||
|
||||
target_set_handler = _bpy._rna_manipulator_target_set_handler
|
||||
from _bpy import (
|
||||
_rna_manipulator_target_set_handler as target_set_handler,
|
||||
_rna_manipulator_target_get_value as target_get_value,
|
||||
_rna_manipulator_target_set_value as target_set_value,
|
||||
_rna_manipulator_target_get_range as target_get_range,
|
||||
)
|
||||
|
||||
# Convenience wrappers around private `_gawain` module.
|
||||
def draw_custom_shape(self, shape, *, matrix=None, select_id=None):
|
||||
|
@ -71,6 +71,10 @@ static void rna_manipulator_draw_preset_facemap(
|
||||
ED_manipulator_draw_preset_facemap(C, mpr, scene, ob, facemap, select_id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Manipulator Property Define
|
||||
* \{ */
|
||||
|
||||
static void rna_manipulator_target_set_prop(
|
||||
wmManipulator *mpr, ReportList *reports, const char *target_propname,
|
||||
PointerRNA *ptr, const char *propname, int index)
|
||||
@ -158,6 +162,27 @@ static PointerRNA rna_manipulator_target_set_operator(
|
||||
return mpr->op_data.ptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Manipulator Property Access
|
||||
* \{ */
|
||||
|
||||
static int rna_manipulator_target_is_valid(
|
||||
wmManipulator *mpr, ReportList *reports, const char *target_propname)
|
||||
{
|
||||
wmManipulatorProperty *mpr_prop =
|
||||
WM_manipulator_target_property_find(mpr, target_propname);
|
||||
if (mpr_prop == NULL) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Manipulator target property '%s.%s' not found",
|
||||
mpr->type->idname, target_propname);
|
||||
return false;
|
||||
}
|
||||
return WM_manipulator_target_property_is_valid(mpr_prop);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_manipulator(StructRNA *srna)
|
||||
@ -218,6 +243,7 @@ void RNA_api_manipulator(StructRNA *srna)
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Property API */
|
||||
|
||||
/* Define Properties */
|
||||
/* note, 'target_set_handler' is defined in 'bpy_rna_manipulator.c' */
|
||||
func = RNA_def_function(srna, "target_set_prop", "rna_manipulator_target_set_prop");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
@ -243,6 +269,16 @@ void RNA_api_manipulator(StructRNA *srna)
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* Access Properties */
|
||||
/* note, 'target_get', 'target_set' is defined in 'bpy_rna_manipulator.c' */
|
||||
func = RNA_def_function(srna, "target_is_valid", "rna_manipulator_target_is_valid");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm = RNA_def_string(func, "property", NULL, 0, "", "Property identifier");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
RNA_def_function_ui_description(func, "");
|
||||
parm = RNA_def_boolean(func, "result", 0, "", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_alloca.h"
|
||||
|
||||
#include "BKE_main.h"
|
||||
|
||||
@ -48,6 +49,11 @@
|
||||
|
||||
#include "bpy_rna.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Manipulator Target Property Define API
|
||||
* \{ */
|
||||
|
||||
enum {
|
||||
BPY_MANIPULATOR_FN_SLOT_GET = 0,
|
||||
BPY_MANIPULATOR_FN_SLOT_SET,
|
||||
@ -75,7 +81,7 @@ static void py_rna_manipulator_handler_get_cb(
|
||||
if (mpr_prop->type->data_type == PROP_FLOAT) {
|
||||
float *value = value_p;
|
||||
if (mpr_prop->type->array_length == 1) {
|
||||
if (((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) == 0) {
|
||||
if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -333,20 +339,275 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BPY_rna_manipulator_module(PyObject *mod_par)
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Manipulator Target Property Access API
|
||||
* \{ */
|
||||
|
||||
PyDoc_STRVAR(bpy_manipulator_target_get_value_doc,
|
||||
".. method:: target_get_value(target):\n"
|
||||
"\n"
|
||||
" Get the value of this target property.\n"
|
||||
"\n"
|
||||
" :arg target: Target property name.\n"
|
||||
" :type target: string\n"
|
||||
" :return: The value of the target property.\n"
|
||||
" :rtype: Single value or array based on the target type\n"
|
||||
);
|
||||
static PyObject *bpy_manipulator_target_get_value(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static PyMethodDef method_def = {
|
||||
"target_set_handler", (PyCFunction)bpy_manipulator_target_set_handler, METH_VARARGS | METH_KEYWORDS,
|
||||
bpy_manipulator_target_set_handler_doc};
|
||||
struct {
|
||||
PyObject *self;
|
||||
char *target;
|
||||
} params = {
|
||||
.self = NULL,
|
||||
.target = NULL,
|
||||
};
|
||||
|
||||
PyObject *func = PyCFunction_New(&method_def, NULL);
|
||||
PyObject *func_inst = PyInstanceMethod_New(func);
|
||||
static const char * const _keywords[] = {"self", "target", NULL};
|
||||
#define KW_FMT "Os:target_get_value"
|
||||
#if PY_VERSION_HEX >= 0x03070000
|
||||
static _PyArg_Parser _parser = {KW_FMT, _keywords, 0};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kwds,
|
||||
&_parser,
|
||||
¶ms.self,
|
||||
¶ms.target))
|
||||
#else
|
||||
if (!PyArg_ParseTupleAndKeywords(
|
||||
args, kwds,
|
||||
KW_FMT, (char **)_keywords,
|
||||
¶ms.self,
|
||||
¶ms.target))
|
||||
#endif
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
#undef KW_FMT
|
||||
|
||||
wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
|
||||
|
||||
/* TODO, return a type that binds nearly to a method. */
|
||||
PyModule_AddObject(mod_par, "_rna_manipulator_target_set_handler", func_inst);
|
||||
wmManipulatorProperty *mpr_prop =
|
||||
WM_manipulator_target_property_find(mpr, params.target);
|
||||
if (mpr_prop == NULL) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Manipulator target property '%s.%s' not found",
|
||||
mpr->type->idname, params.target);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
const int array_len = WM_manipulator_target_property_array_length(mpr, mpr_prop);
|
||||
switch (mpr_prop->type->data_type) {
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
if (array_len != 0) {
|
||||
float *value = BLI_array_alloca(value, array_len);
|
||||
WM_manipulator_target_property_value_get_array(mpr, mpr_prop, value);
|
||||
return PyC_Tuple_PackArray_F32(value, array_len);
|
||||
}
|
||||
else {
|
||||
float value = WM_manipulator_target_property_value_get(mpr, mpr_prop);
|
||||
return PyFloat_FromDouble(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_manipulator_target_set_value_doc,
|
||||
".. method:: target_set_value(target):\n"
|
||||
"\n"
|
||||
" Set the value of this target property.\n"
|
||||
"\n"
|
||||
" :arg target: Target property name.\n"
|
||||
" :type target: string\n"
|
||||
);
|
||||
static PyObject *bpy_manipulator_target_set_value(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
struct {
|
||||
PyObject *self;
|
||||
char *target;
|
||||
PyObject *value;
|
||||
} params = {
|
||||
.self = NULL,
|
||||
.target = NULL,
|
||||
.value = NULL,
|
||||
};
|
||||
|
||||
static const char * const _keywords[] = {"self", "target", "value", NULL};
|
||||
#define KW_FMT "OsO:target_set_value"
|
||||
#if PY_VERSION_HEX >= 0x03070000
|
||||
static _PyArg_Parser _parser = {KW_FMT, _keywords, 0};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kwds,
|
||||
&_parser,
|
||||
¶ms.self,
|
||||
¶ms.target,
|
||||
¶ms.value))
|
||||
#else
|
||||
if (!PyArg_ParseTupleAndKeywords(
|
||||
args, kwds,
|
||||
KW_FMT, (char **)_keywords,
|
||||
¶ms.self,
|
||||
¶ms.target,
|
||||
¶ms.value))
|
||||
#endif
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
#undef KW_FMT
|
||||
|
||||
wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
|
||||
|
||||
wmManipulatorProperty *mpr_prop =
|
||||
WM_manipulator_target_property_find(mpr, params.target);
|
||||
if (mpr_prop == NULL) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Manipulator target property '%s.%s' not found",
|
||||
mpr->type->idname, params.target);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
const int array_len = WM_manipulator_target_property_array_length(mpr, mpr_prop);
|
||||
switch (mpr_prop->type->data_type) {
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
if (array_len != 0) {
|
||||
float *value = BLI_array_alloca(value, array_len);
|
||||
if (PyC_AsArray(value, params.value, mpr_prop->type->array_length, &PyFloat_Type, false,
|
||||
"Manipulator target property array") == -1)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
WM_manipulator_target_property_value_set_array(BPy_GetContext(), mpr, mpr_prop, value);
|
||||
}
|
||||
else {
|
||||
float value;
|
||||
if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
|
||||
goto fail;
|
||||
}
|
||||
WM_manipulator_target_property_value_set(BPy_GetContext(), mpr, mpr_prop, value);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
default:
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(bpy_manipulator_target_get_range_doc,
|
||||
".. method:: target_get_range(target):\n"
|
||||
"\n"
|
||||
" Get the range for this target property.\n"
|
||||
"\n"
|
||||
" :arg target: Target property name.\n"
|
||||
" :Get the range for this target property"
|
||||
" :return: The range of this property (min, max).\n"
|
||||
" :rtype: tuple pair.\n"
|
||||
);
|
||||
static PyObject *bpy_manipulator_target_get_range(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
struct {
|
||||
PyObject *self;
|
||||
char *target;
|
||||
} params = {
|
||||
.self = NULL,
|
||||
.target = NULL,
|
||||
};
|
||||
|
||||
static const char * const _keywords[] = {"self", "target", NULL};
|
||||
#define KW_FMT "Os:target_get_range"
|
||||
#if PY_VERSION_HEX >= 0x03070000
|
||||
static _PyArg_Parser _parser = {KW_FMT, _keywords, 0};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kwds,
|
||||
&_parser,
|
||||
¶ms.self,
|
||||
¶ms.target))
|
||||
#else
|
||||
if (!PyArg_ParseTupleAndKeywords(
|
||||
args, kwds,
|
||||
KW_FMT, (char **)_keywords,
|
||||
¶ms.self,
|
||||
¶ms.target))
|
||||
#endif
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
#undef KW_FMT
|
||||
|
||||
wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
|
||||
|
||||
wmManipulatorProperty *mpr_prop =
|
||||
WM_manipulator_target_property_find(mpr, params.target);
|
||||
if (mpr_prop == NULL) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Manipulator target property '%s.%s' not found",
|
||||
mpr->type->idname, params.target);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (mpr_prop->type->data_type) {
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
float range[2];
|
||||
WM_manipulator_target_property_range_get(mpr, mpr_prop, range);
|
||||
return PyC_Tuple_PackArray_F32(range, 2);
|
||||
}
|
||||
default:
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
int BPY_rna_manipulator_module(PyObject *mod_par)
|
||||
{
|
||||
static PyMethodDef method_def_array[] = {
|
||||
/* Manipulator Target Property Define API */
|
||||
{"target_set_handler", (PyCFunction)bpy_manipulator_target_set_handler,
|
||||
METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_set_handler_doc},
|
||||
/* Manipulator Target Property Access API */
|
||||
{"target_get_value", (PyCFunction)bpy_manipulator_target_get_value,
|
||||
METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_get_value_doc},
|
||||
{"target_set_value", (PyCFunction)bpy_manipulator_target_set_value,
|
||||
METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_set_value_doc},
|
||||
{"target_get_range", (PyCFunction)bpy_manipulator_target_get_range,
|
||||
METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_get_range_doc},
|
||||
/* no sentinel needed. */
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) {
|
||||
PyMethodDef *m = &method_def_array[i];
|
||||
PyObject *func = PyCFunction_New(m, NULL);
|
||||
PyObject *func_inst = PyInstanceMethod_New(func);
|
||||
char name_prefix[128];
|
||||
PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_manipulator_%s", m->ml_name);
|
||||
/* TODO, return a type that binds nearly to a method. */
|
||||
PyModule_AddObject(mod_par, name_prefix, func_inst);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user