24 #include "../generic/py_capi_utils.h"
25 #include "../generic/python_utildefines.h"
26 #include "../mathutils/mathutils.h"
51 #define BPY_MSGBUS_RNA_MSGKEY_DOC \
52 " :arg key: Represents the type of data being subscribed to\n" \
54 " Arguments include\n" \
55 " - :class:`bpy.types.Property` instance.\n" \
56 " - :class:`bpy.types.Struct` type.\n" \
57 " - (:class:`bpy.types.Struct`, str) type and property name.\n" \
58 " :type key: Muliple\n"
72 const char *error_prefix)
78 if (py_sub_math->cb_user ==
NULL) {
79 PyErr_Format(PyExc_TypeError,
"%s: math argument has no owner", error_prefix);
82 py_sub = py_sub_math->cb_user;
89 msg_key_params->
ptr = data_prop->
ptr;
90 msg_key_params->
prop = data_prop->
prop;
96 msg_key_params->
ptr = data_srna->
ptr;
99 else if (PyType_Check(py_sub)) {
101 if (data_type ==
NULL) {
104 msg_key_params->
ptr.
type = data_type;
106 else if (PyTuple_CheckExact(py_sub)) {
107 if (PyTuple_GET_SIZE(py_sub) == 2) {
108 PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0);
109 PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1);
111 if (data_type ==
NULL) {
114 if (!PyUnicode_CheckExact(data_prop_py)) {
115 PyErr_Format(PyExc_TypeError,
"%s: expected property to be a string", error_prefix);
121 const char *data_prop_str = PyUnicode_AsUTF8(data_prop_py);
124 if (data_prop ==
NULL) {
125 PyErr_Format(PyExc_TypeError,
126 "%s: struct %.200s does not contain property %.200s",
133 msg_key_params->
ptr.
type = data_type;
134 msg_key_params->
prop = data_prop;
137 PyErr_Format(PyExc_ValueError,
"%s: Expected a pair (type, property_id)", error_prefix);
150 #define BPY_MSGBUS_USER_DATA_LEN 2
157 PyGILState_STATE gilstate;
163 PyObject *callback_args = PyTuple_GET_ITEM(
user_data, 0);
164 PyObject *callback_notify = PyTuple_GET_ITEM(
user_data, 1);
171 PyObject *
ret = PyObject_CallObject(callback_notify, callback_args);
177 if (
ret != Py_None) {
178 PyErr_SetString(PyExc_ValueError,
"the return value must be None");
195 const PyGILState_STATE gilstate = PyGILState_Ensure();
196 Py_DECREF(msg_val->
owner);
198 PyGILState_Release(gilstate);
208 bpy_msgbus_subscribe_rna_doc,
209 ".. function:: subscribe_rna(key, owner, args, notify, options=set())\n"
211 " :arg owner: Handle for this subscription (compared by identity).\n"
212 " :type owner: Any type.\n"
213 " :arg options: Change the behavior of the subscriber.\n"
215 " - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n"
217 " :type options: set of str.\n");
220 const char *error_prefix =
"subscribe_rna";
221 PyObject *py_sub =
NULL;
222 PyObject *py_owner =
NULL;
223 PyObject *callback_args =
NULL;
224 PyObject *callback_notify =
NULL;
227 IS_PERSISTENT = (1 << 0),
229 PyObject *py_options =
NULL;
231 {IS_PERSISTENT,
"PERSISTENT", 0,
""},
236 if (PyTuple_GET_SIZE(args) != 0) {
237 PyErr_Format(PyExc_TypeError,
"%s: only keyword arguments are supported", error_prefix);
240 static const char *_keywords[] = {
248 static _PyArg_Parser _parser = {
"OOO!O|O!:subscribe_rna", _keywords, 0};
249 if (!_PyArg_ParseTupleAndKeywordsFast(args,
278 if (!PyFunction_Check(callback_notify)) {
279 PyErr_Format(PyExc_TypeError,
280 "notify expects a function, found %.200s",
281 Py_TYPE(callback_notify)->tp_name);
293 msg_val_params.
owner = py_owner;
316 bpy_msgbus_publish_rna_doc,
317 ".. function:: publish_rna(key)\n"
320 " Notify subscribers of changes to this property\n"
321 " (this typically doesn't need to be called explicitly since changes will automatically "
322 "publish updates).\n"
323 " In some cases it may be useful to publish changes explicitly using more general keys.\n");
326 const char *error_prefix =
"publish_rna";
327 PyObject *py_sub =
NULL;
329 if (PyTuple_GET_SIZE(args) != 0) {
330 PyErr_Format(PyExc_TypeError,
"%s: only keyword arguments are supported", error_prefix);
333 static const char *_keywords[] = {
337 static _PyArg_Parser _parser = {
"O:publish_rna", _keywords, 0};
338 if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &py_sub)) {
357 ".. function:: clear_by_owner(owner)\n"
359 " Clear all subscribers using this owner.\n");
371 METH_VARARGS | METH_KEYWORDS,
372 bpy_msgbus_subscribe_rna_doc},
375 METH_VARARGS | METH_KEYWORDS,
376 bpy_msgbus_publish_rna_doc},
380 bpy_msgbus_clear_by_owner_doc},
385 PyModuleDef_HEAD_INIT,
struct wmMsgBus * CTX_wm_message_bus(const bContext *C)
struct bContext * BPY_context_get(void)
void bpy_context_clear(struct bContext *C, const PyGILState_STATE *gilstate)
void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate)
static struct PyMethodDef BPy_msgbus_methods[]
#define BPY_MSGBUS_USER_DATA_LEN
PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc, ".. function:: subscribe_rna(key, owner, args, notify, options=set())\n" "\n" BPY_MSGBUS_RNA_MSGKEY_DOC " :arg owner: Handle for this subscription (compared by identity).\n" " :type owner: Any type.\n" " :arg options: Change the behavior of the subscriber.\n" "\n" " - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n" "\n" " :type options: set of str.\n")
static PyObject * bpy_msgbus_clear_by_owner(PyObject *UNUSED(self), PyObject *py_owner)
static int py_msgbus_rna_key_from_py(PyObject *py_sub, wmMsgParams_RNA *msg_key_params, const char *error_prefix)
static PyObject * bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static PyObject * bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static void bpy_msgbus_notify(bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
static void bpy_msgbus_subscribe_value_free_data(struct wmMsgSubscribeKey *UNUSED(msg_key), struct wmMsgSubscribeValue *msg_val)
#define BPY_MSGBUS_RNA_MSGKEY_DOC
static struct PyModuleDef _bpy_msgbus_def
PyObject * BPY_msgbus_module(void)
int pyrna_set_to_enum_bitfield(const EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix)
bool pyrna_write_check(void)
StructRNA * pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix)
void pyrna_write_set(bool val)
#define PYRNA_STRUCT_CHECK_INT(obj)
#define PYRNA_PROP_CHECK_INT(obj)
#define BPy_StructRNA_Check(v)
#define BPy_PropertyRNA_Check(v)
CCL_NAMESPACE_BEGIN struct Options options
#define BaseMathObject_CheckExact(v)
void PyC_Err_PrintWithFunc(PyObject *py_func)
#define PyTuple_SET_ITEMS(op_arg,...)
const char * RNA_struct_identifier(const StructRNA *type)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
PyObject_HEAD PointerRNA ptr
PyObject_HEAD PointerRNA ptr
wmMsgSubscribeValueFreeDataFn free_data
void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner)
void WM_msg_dump(struct wmMsgBus *mbus, const char *info_str)
void WM_msg_subscribe_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params, const wmMsgSubscribeValue *msg_val_params, const char *id_repr)
void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params)