10 #include "../generic/py_capi_rna.h"
11 #include "../generic/py_capi_utils.h"
12 #include "../generic/python_utildefines.h"
13 #include "../mathutils/mathutils.h"
38 #define BPY_MSGBUS_RNA_MSGKEY_DOC \
39 " :arg key: Represents the type of data being subscribed to\n" \
41 " Arguments include\n" \
42 " - :class:`bpy.types.Property` instance.\n" \
43 " - :class:`bpy.types.Struct` type.\n" \
44 " - (:class:`bpy.types.Struct`, str) type and property name.\n" \
45 " :type key: Muliple\n"
59 const char *error_prefix)
65 if (py_sub_math->cb_user ==
NULL) {
66 PyErr_Format(PyExc_TypeError,
"%s: math argument has no owner", error_prefix);
69 py_sub = py_sub_math->cb_user;
76 msg_key_params->
ptr = data_prop->
ptr;
77 msg_key_params->
prop = data_prop->
prop;
83 msg_key_params->
ptr = data_srna->
ptr;
86 else if (PyType_Check(py_sub)) {
88 if (data_type ==
NULL) {
91 msg_key_params->
ptr.
type = data_type;
93 else if (PyTuple_CheckExact(py_sub)) {
94 if (PyTuple_GET_SIZE(py_sub) == 2) {
95 PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0);
96 PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1);
98 if (data_type ==
NULL) {
101 if (!PyUnicode_CheckExact(data_prop_py)) {
102 PyErr_Format(PyExc_TypeError,
"%s: expected property to be a string", error_prefix);
108 const char *data_prop_str = PyUnicode_AsUTF8(data_prop_py);
111 if (data_prop ==
NULL) {
112 PyErr_Format(PyExc_TypeError,
113 "%s: struct %.200s does not contain property %.200s",
120 msg_key_params->
ptr.
type = data_type;
121 msg_key_params->
prop = data_prop;
124 PyErr_Format(PyExc_ValueError,
"%s: Expected a pair (type, property_id)", error_prefix);
137 #define BPY_MSGBUS_USER_DATA_LEN 2
144 PyGILState_STATE gilstate;
150 PyObject *callback_args = PyTuple_GET_ITEM(
user_data, 0);
151 PyObject *callback_notify = PyTuple_GET_ITEM(
user_data, 1);
158 PyObject *
ret = PyObject_CallObject(callback_notify, callback_args);
164 if (
ret != Py_None) {
165 PyErr_SetString(PyExc_ValueError,
"the return value must be None");
182 const PyGILState_STATE gilstate = PyGILState_Ensure();
183 Py_DECREF(msg_val->
owner);
185 PyGILState_Release(gilstate);
195 bpy_msgbus_subscribe_rna_doc,
196 ".. function:: subscribe_rna(key, owner, args, notify, options=set())\n"
198 " Register a message bus subscription. It will be cleared when another blend file is\n"
199 " loaded, or can be cleared explicitly via :func:`bpy.msgbus.clear_by_owner`.\n"
201 " :arg owner: Handle for this subscription (compared by identity).\n"
202 " :type owner: Any type.\n"
203 " :arg options: Change the behavior of the subscriber.\n"
205 " - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n"
207 " :type options: set of str.\n"
211 " All subscribers will be cleared on file-load. Subscribers can be re-registered on load,\n"
212 " see :mod:`bpy.app.handlers.load_post`.\n");
215 const char *error_prefix =
"subscribe_rna";
216 PyObject *py_sub =
NULL;
217 PyObject *py_owner =
NULL;
218 PyObject *callback_args =
NULL;
219 PyObject *callback_notify =
NULL;
222 IS_PERSISTENT = (1 << 0),
224 PyObject *py_options =
NULL;
226 {IS_PERSISTENT,
"PERSISTENT", 0,
""},
231 if (PyTuple_GET_SIZE(args) != 0) {
232 PyErr_Format(PyExc_TypeError,
"%s: only keyword arguments are supported", error_prefix);
235 static const char *_keywords[] = {
243 static _PyArg_Parser _parser = {
254 if (!_PyArg_ParseTupleAndKeywordsFast(args,
283 if (!PyFunction_Check(callback_notify)) {
284 PyErr_Format(PyExc_TypeError,
285 "notify expects a function, found %.200s",
286 Py_TYPE(callback_notify)->tp_name);
298 msg_val_params.
owner = py_owner;
321 bpy_msgbus_publish_rna_doc,
322 ".. function:: publish_rna(key)\n"
325 " Notify subscribers of changes to this property\n"
326 " (this typically doesn't need to be called explicitly since changes will automatically "
327 "publish updates).\n"
328 " In some cases it may be useful to publish changes explicitly using more general keys.\n");
331 const char *error_prefix =
"publish_rna";
332 PyObject *py_sub =
NULL;
334 if (PyTuple_GET_SIZE(args) != 0) {
335 PyErr_Format(PyExc_TypeError,
"%s: only keyword arguments are supported", error_prefix);
338 static const char *_keywords[] = {
342 static _PyArg_Parser _parser = {
348 if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &py_sub)) {
367 ".. function:: clear_by_owner(owner)\n"
369 " Clear all subscribers using this owner.\n");
381 METH_VARARGS | METH_KEYWORDS,
382 bpy_msgbus_subscribe_rna_doc},
385 METH_VARARGS | METH_KEYWORDS,
386 bpy_msgbus_publish_rna_doc},
390 bpy_msgbus_clear_by_owner_doc},
395 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)
PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc, ".. function:: subscribe_rna(key, owner, args, notify, options=set())\n" "\n" " Register a message bus subscription. It will be cleared when another blend file is\n" " loaded, or can be cleared explicitly via :func:`bpy.msgbus.clear_by_owner`.\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" "\n" ".. note::\n" "\n" " All subscribers will be cleared on file-load. Subscribers can be re-registered on load,\n" " see :mod:`bpy.app.handlers.load_post`.\n")
static struct PyMethodDef BPy_msgbus_methods[]
#define BPY_MSGBUS_USER_DATA_LEN
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)
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)
int pyrna_enum_bitfield_from_set(const EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix)
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)