Adds operator handlers to operators. #117912
@ -13,8 +13,27 @@ _op_as_string = _ops_module.as_string
|
||||
_op_get_rna_type = _ops_module.get_rna_type
|
||||
_op_get_bl_options = _ops_module.get_bl_options
|
||||
|
||||
_op_handlers = _ops_module.handlers
|
||||
|
||||
_ModuleType = type(_ops_module)
|
||||
|
||||
class handler_action:
|
||||
def __init__(self, mod, append_func, remove_func):
|
||||
self._mod = mod
|
||||
self._append_func = append_func
|
||||
self._remove_func = remove_func
|
||||
|
||||
def append(self,cb, owner = None, args = None, poll = None):
|
||||
#is there a way to remove self from console show?
|
||||
self._append_func(owner=owner, op = self._mod.idname(), cb=cb, args=args, poll = poll)
|
||||
|
||||
def remove(self, cb = None, owner = None):
|
||||
self._remove_func(owner=owner, op = self._mod.idname(), cb=cb, args=None, poll = None)
|
||||
|
||||
|
||||
def remove_handlers(owner = None, cb = None):
|
||||
_op_handlers.remove(owner = owner, cb = cb, op = None, args = None, poll = None)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Callable Operator Wrapper
|
||||
@ -26,7 +45,14 @@ class _BPyOpsSubModOp:
|
||||
eg. bpy.ops.object.somefunc
|
||||
"""
|
||||
|
||||
__slots__ = ("_module", "_func")
|
||||
__slots__ = ("_module", "_func", "handlers")
|
||||
|
||||
class _handlers:
|
||||
def __init__(self, mod):
|
||||
self.invoke_pre = handler_action(mod, _op_handlers.pre_invoke, _op_handlers.pre_invoke_remove)
|
||||
self.invoke_post = handler_action(mod, _op_handlers.post_invoke, _op_handlers.post_invoke_remove)
|
||||
self.modal = handler_action(mod, _op_handlers.modal, _op_handlers.modal_remove)
|
||||
self.modal_end = handler_action(mod, _op_handlers.modal_end, _op_handlers.modal_end_remove)
|
||||
|
||||
def _get_doc(self):
|
||||
idname = self.idname()
|
||||
@ -77,6 +103,7 @@ class _BPyOpsSubModOp:
|
||||
def __init__(self, module, func):
|
||||
self._module = module
|
||||
self._func = func
|
||||
self.handlers = self._handlers(self)
|
||||
|
||||
def poll(self, *args):
|
||||
C_exec, _C_undo = _BPyOpsSubModOp._parse_args(args)
|
||||
@ -178,4 +205,6 @@ def __dir__():
|
||||
else:
|
||||
submodules.add(id_split[0])
|
||||
|
||||
submodules.add("remove_handlers")
|
||||
|
||||
return list(submodules)
|
||||
|
@ -69,6 +69,7 @@ struct View3D;
|
||||
struct ViewLayer;
|
||||
struct wmGizmoGroup;
|
||||
struct wmMsgBus;
|
||||
struct wmOpHandlers;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
struct WorkSpace;
|
||||
@ -191,6 +192,7 @@ void *CTX_wm_region_data(const bContext *C);
|
||||
ARegion *CTX_wm_menu(const bContext *C);
|
||||
wmGizmoGroup *CTX_wm_gizmo_group(const bContext *C);
|
||||
wmMsgBus *CTX_wm_message_bus(const bContext *C);
|
||||
wmOpHandlers *CTX_wm_op_handlers(const bContext *C);
|
||||
ReportList *CTX_wm_reports(const bContext *C);
|
||||
|
||||
View3D *CTX_wm_view3d(const bContext *C);
|
||||
|
@ -763,6 +763,11 @@ wmMsgBus *CTX_wm_message_bus(const bContext *C)
|
||||
return C->wm.manager ? C->wm.manager->message_bus : nullptr;
|
||||
}
|
||||
|
||||
struct wmOpHandlers *CTX_wm_op_handlers(const bContext *C)
|
||||
{
|
||||
return C->wm.manager ? C->wm.manager->op_handlers : nullptr;
|
||||
}
|
||||
|
||||
ReportList *CTX_wm_reports(const bContext *C)
|
||||
{
|
||||
if (C->wm.manager) {
|
||||
|
@ -213,6 +213,8 @@ typedef struct wmWindowManager {
|
||||
|
||||
struct wmMsgBus *message_bus;
|
||||
|
||||
struct wmOpHandlers *op_handlers;
|
||||
|
||||
// #ifdef WITH_XR_OPENXR
|
||||
wmXrData xr;
|
||||
// #endif
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_op_handlers.h"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
@ -460,11 +461,493 @@ static PyModuleDef bpy_ops_module = {
|
||||
/*m_free*/ nullptr,
|
||||
};
|
||||
|
||||
static int bpy_op_handler_check(void *py_data, void* owner, void *callback)
|
||||
{
|
||||
PyObject *py_owner = PyTuple_GET_ITEM(py_data, 0);
|
||||
PyObject *py_callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
if (owner != NULL && callback != NULL) {
|
||||
return (py_owner == owner && py_callback == callback);
|
||||
}
|
||||
else if (owner != NULL)
|
||||
{
|
||||
return (py_owner == owner);
|
||||
}
|
||||
else { //callback != NULL
|
||||
return (py_callback == callback);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @Properties Rna Properties that has been used to set the operator
|
||||
*/
|
||||
static PyObject *bpy_op_get_operator_params(PointerRNA *properties)
|
||||
{
|
||||
const char *arg_name = NULL;
|
||||
PyObject *py_dict = PyDict_New();
|
||||
PyObject *data;
|
||||
RNA_STRUCT_BEGIN (properties, prop) {
|
||||
arg_name = RNA_property_identifier(prop);
|
||||
data = NULL;
|
||||
if (STREQ(arg_name, "rna_type")) {
|
||||
continue;
|
||||
}
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_BOOLEAN: {
|
||||
bool val = RNA_property_boolean_get(properties, prop);
|
||||
// from Py Docs, Py_False and Py_truee needs to be treated just like any other object with
|
||||
// respect to reference counts.
|
||||
data = val ? Py_False : Py_True;
|
||||
break;
|
||||
}
|
||||
case PROP_INT: {
|
||||
const int prop_array_length = RNA_property_array_length(properties, prop);
|
||||
if (prop_array_length == 0) {
|
||||
int val = RNA_property_int_get(properties, prop);
|
||||
data = PyLong_FromLong(val);
|
||||
}
|
||||
else {
|
||||
int *values = (int*) MEM_callocN(sizeof(int) * prop_array_length, __func__);
|
||||
RNA_property_int_get_array(properties, prop, values);
|
||||
data = PyTuple_New(prop_array_length);
|
||||
for (int i = 0; i < prop_array_length; i++) {
|
||||
PyObject *py_val = PyLong_FromLong(*(values + i));
|
||||
PyTuple_SET_ITEM(data, i, py_val);
|
||||
}
|
||||
MEM_freeN(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_FLOAT: {
|
||||
const int prop_array_length = RNA_property_array_length(properties, prop);
|
||||
if (prop_array_length == 0) {
|
||||
float val;
|
||||
val = RNA_property_float_get(properties, prop);
|
||||
data = PyFloat_FromDouble(val);
|
||||
}
|
||||
else {
|
||||
float *values = (float*) MEM_callocN(sizeof(float) * prop_array_length, __func__);
|
||||
RNA_property_float_get_array(properties, prop, values);
|
||||
data = PyTuple_New(prop_array_length);
|
||||
for (int i = 0; i < prop_array_length; i++) {
|
||||
PyObject *py_val = PyFloat_FromDouble(*(values + i));
|
||||
PyTuple_SET_ITEM(data, i, py_val);
|
||||
}
|
||||
MEM_freeN(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_STRING: {
|
||||
char buff[256];
|
||||
char *value = RNA_property_string_get_alloc(properties, prop, buff, sizeof(buff), NULL);
|
||||
data = PyUnicode_FromString(value);
|
||||
if (value != buff) {
|
||||
MEM_freeN(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_ENUM: {
|
||||
int val = RNA_property_enum_get(properties, prop);
|
||||
data = PyLong_FromLong(val);
|
||||
break;
|
||||
}
|
||||
case PROP_POINTER: {
|
||||
data = PyUnicode_FromString("POINTER");
|
||||
break;
|
||||
}
|
||||
case PROP_COLLECTION: {
|
||||
data = PyUnicode_FromString("COLLECTION");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert(false);
|
||||
}
|
||||
if (data != NULL) {
|
||||
PyDict_SetItemString(py_dict, arg_name, data);
|
||||
}
|
||||
}
|
||||
RNA_STRUCT_END;
|
||||
return py_dict;
|
||||
}
|
||||
|
||||
|
||||
static bool bpy_op_callback_get_return_value(PyObject *callback, PyObject *py_ret)
|
||||
{
|
||||
bool ret = true; // Do not interrump on error
|
||||
if (py_ret == NULL) {
|
||||
PyC_Err_PrintWithFunc(callback);
|
||||
}
|
||||
else {
|
||||
if (py_ret == Py_None) {
|
||||
// pass
|
||||
}
|
||||
else if (py_ret == Py_True) {
|
||||
// pass
|
||||
}
|
||||
else if (py_ret == Py_False){
|
||||
ret = false;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, "the return value must be None or boolean");
|
||||
PyC_Err_PrintWithFunc(callback);
|
||||
}
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *bpy_op_get_callback_call(PyObject *callback,
|
||||
bContext *C, const wmEvent *event, int *operator_ret, PyObject *params, PyObject *callback_args)
|
||||
{
|
||||
PointerRNA ctx_ptr;
|
||||
PointerRNA event_ptr;
|
||||
|
||||
PyObject *bpy_ctx;
|
||||
PyObject *bpy_event;
|
||||
PyObject *py_ret;
|
||||
|
||||
ctx_ptr = RNA_pointer_create(nullptr, &RNA_Context, C);
|
||||
bpy_ctx = pyrna_struct_CreatePyObject(&ctx_ptr);
|
||||
|
||||
if (event != NULL) {
|
||||
event_ptr = RNA_pointer_create(NULL, &RNA_Event, (void*) event);
|
||||
bpy_event = pyrna_struct_CreatePyObject(&event_ptr);
|
||||
}
|
||||
else {
|
||||
bpy_event = Py_None;
|
||||
}
|
||||
|
||||
int s = (operator_ret == NULL) ? 3 : 4;
|
||||
int c = (callback_args == Py_None) ? s : PyTuple_GET_SIZE(callback_args) + s;
|
||||
PyObject *func_args = PyTuple_New(c);
|
||||
|
||||
PyTuple_SET_ITEM(func_args, 0, bpy_ctx);
|
||||
PyTuple_SET_ITEM(func_args, 1, bpy_event);
|
||||
PyTuple_SET_ITEM(func_args, 2, params);
|
||||
|
||||
if (operator_ret != NULL) {
|
||||
PyObject *op_ret = pyrna_enum_bitfield_to_py(rna_enum_operator_return_items, *operator_ret);
|
||||
PyTuple_SET_ITEM(func_args, 3, op_ret);
|
||||
}
|
||||
|
||||
for (int i = s; i < c; i++) {
|
||||
PyTuple_SET_ITEM(func_args, i, PyTuple_GET_ITEM(callback_args, i - s));
|
||||
}
|
||||
|
||||
py_ret = PyObject_CallObject(callback, func_args);
|
||||
Py_DECREF(func_args);
|
||||
return py_ret;
|
||||
}
|
||||
|
||||
|
||||
static bool bpy_op_handler_poll(struct bContext *C,
|
||||
const wmEvent *event, void *py_data,
|
||||
PointerRNA *properties)
|
||||
{
|
||||
bool ret = true;
|
||||
PyGILState_STATE gilstate; // this is because is not thread safe
|
||||
bpy_context_set(C, &gilstate);
|
||||
{
|
||||
PyObject *callback_args = PyTuple_GET_ITEM(py_data, 3);
|
||||
PyObject *py_poll = PyTuple_GET_ITEM(py_data, 4);
|
||||
|
||||
// Properties get null on modall poll, params are not bypassed to Py poll function
|
||||
PyObject *params = (properties == NULL) ? Py_None : bpy_op_get_operator_params(properties);
|
||||
if (py_poll != Py_None) {
|
||||
PyObject *py_ret = bpy_op_get_callback_call(py_poll, C, event, NULL, params, callback_args);
|
||||
|
||||
if (py_ret == NULL) {
|
||||
// Error
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
else if (py_ret == Py_True) {
|
||||
ret = true;
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
else if (py_ret == Py_False) {
|
||||
ret = false;
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
else {
|
||||
ret = false;
|
||||
Py_DECREF(py_ret);
|
||||
PyErr_SetString(PyExc_ValueError, "the return value must be boolean");
|
||||
PyC_Err_PrintWithFunc(py_poll);
|
||||
}
|
||||
}
|
||||
// Py_DECREF(params);
|
||||
}
|
||||
bpy_context_clear(C, &gilstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool bpy_op_handler_modal (bContext *C, const wmEvent *event, void *py_data, PointerRNA *properties, int operator_ret)
|
||||
{
|
||||
// this is because is not thread safe
|
||||
bool ret = true;
|
||||
PyGILState_STATE gilstate;
|
||||
bpy_context_set(C, &gilstate);
|
||||
{
|
||||
PyObject *callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
PyObject *callback_args = PyTuple_GET_ITEM(py_data, 3);
|
||||
PyObject *py_ret = bpy_op_get_callback_call(callback, C, event, &operator_ret, Py_None, callback_args);
|
||||
ret = bpy_op_callback_get_return_value(callback, py_ret);
|
||||
}
|
||||
bpy_context_clear(C, &gilstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool bpy_op_handler_invoke(bContext *C,
|
||||
const wmEvent *event,
|
||||
void *py_data,
|
||||
PointerRNA *properties,
|
||||
int operator_ret)
|
||||
{
|
||||
bool ret = true;
|
||||
// this is because is not thread safe
|
||||
PyGILState_STATE gilstate;
|
||||
bpy_context_set(C, &gilstate);
|
||||
{
|
||||
PyObject *callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
PyObject *callback_args = PyTuple_GET_ITEM(py_data, 3);
|
||||
PyObject *params = bpy_op_get_operator_params(properties);
|
||||
PyObject *py_ret = bpy_op_get_callback_call(callback, C, event, operator_ret ? &operator_ret : NULL , params, callback_args);
|
||||
ret = bpy_op_callback_get_return_value(callback, py_ret);
|
||||
}
|
||||
bpy_context_clear(C, &gilstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *bpy_op_handler_proc(
|
||||
PyObject *args,
|
||||
PyObject *kw)
|
||||
{
|
||||
const char *error_prefix = "op_handler_proc";
|
||||
|
||||
PyObject *py_op = NULL;
|
||||
PyObject *py_owner = NULL; // Object who creates the handler
|
||||
PyObject *callback = NULL, *py_poll = NULL;
|
||||
PyObject *callback_args = NULL;
|
||||
|
||||
|
||||
if (PyTuple_GET_SIZE(args) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "%s: only keyword arguments are supported", error_prefix);
|
||||
}
|
||||
|
||||
// see https://docs.python.org/3/c-api/arg.html
|
||||
static const char *_keywords[] = {"owner", "op", "cb", "args", "poll", NULL};
|
||||
static _PyArg_Parser _parser = {"OOOOO|:handler_proc", _keywords, 0};
|
||||
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &py_owner, &py_op, &callback, &callback_args, &py_poll)) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError, "Cannot set arguments, or types does not match");
|
||||
}
|
||||
|
||||
if (callback != Py_None && !PyFunction_Check(callback)) {
|
||||
// Callback may be none on remove
|
||||
PyErr_Format(
|
||||
PyExc_TypeError, "callback expects a function, found %.200s", Py_TYPE(callback)->tp_name);
|
||||
}
|
||||
|
||||
if (py_poll != Py_None && !PyFunction_Check(py_poll)) {
|
||||
// Callback may be none on remove
|
||||
PyErr_Format(
|
||||
PyExc_TypeError, "poll expects a function, found %.200s", Py_TYPE(callback)->tp_name);
|
||||
}
|
||||
|
||||
if (py_op != Py_None && !PyUnicode_Check(py_op)) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError, "op expects an astring, found %.200s", Py_TYPE(py_op)->tp_name);
|
||||
}
|
||||
|
||||
if (PyErr_Occurred() != NULL) {
|
||||
PyErr_Print();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_data = PyTuple_New(5);
|
||||
PyTuple_SET_ITEMS(py_data,
|
||||
Py_INCREF_RET(py_owner), // 0
|
||||
Py_INCREF_RET(py_op), // 1
|
||||
Py_INCREF_RET(callback), // 2
|
||||
Py_INCREF_RET(callback_args), // 3
|
||||
Py_INCREF_RET(py_poll)); // 4
|
||||
|
||||
return Py_INCREF_RET(py_data);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append(int handler_id , PyObject *args, PyObject *kw)
|
||||
{
|
||||
bContext *C = BPY_context_get();
|
||||
struct wmOpHandlers *op_handlers = CTX_wm_op_handlers(C);
|
||||
|
||||
PyObject *py_data = bpy_op_handler_proc(args, kw);
|
||||
|
||||
bool (*func)(bContext * C,const wmEvent * event, void *, PointerRNA *, int) = nullptr;
|
||||
|
||||
switch (handler_id) {
|
||||
case HANDLER_TYPE_PRE_INVOKE:
|
||||
case HANDLER_TYPE_POST_INVOKE:
|
||||
func = bpy_op_handler_invoke;
|
||||
break;
|
||||
case HANDLER_TYPE_MODAL:
|
||||
case HANDLER_TYPE_MODAL_END:
|
||||
func = bpy_op_handler_modal;
|
||||
break;
|
||||
}
|
||||
|
||||
if (py_data != NULL) {
|
||||
PyObject *py_owner = PyTuple_GET_ITEM(py_data, 0);
|
||||
PyObject *py_op = PyTuple_GET_ITEM(py_data, 1);
|
||||
PyObject *py_callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
PyObject *py_poll = PyTuple_GET_ITEM(py_data, 4);
|
||||
if (py_op == Py_None) {
|
||||
PyErr_Format(PyExc_TypeError, "missing operator");
|
||||
}
|
||||
else if (py_callback == Py_None) {
|
||||
PyErr_Format(PyExc_TypeError, "callback expects a function");
|
||||
} else {
|
||||
WM_op_handlers_append(op_handlers,
|
||||
handler_id,
|
||||
py_owner,
|
||||
PyUnicode_AsUTF8(py_op),
|
||||
func,
|
||||
bpy_op_handler_check,
|
||||
py_poll == Py_None ? NULL : bpy_op_handler_poll,
|
||||
py_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (PyErr_Occurred() != NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove(int handler_id, PyObject *args, PyObject *kw)
|
||||
{
|
||||
bContext *C = BPY_context_get();
|
||||
struct wmOpHandlers *op_handlers = CTX_wm_op_handlers(C);
|
||||
|
||||
PyObject *py_data = bpy_op_handler_proc(args, kw);
|
||||
|
||||
if (py_data != NULL) {
|
||||
PyObject *py_owner = PyTuple_GET_ITEM(py_data, 0);
|
||||
PyObject *py_op = PyTuple_GET_ITEM(py_data, 1);
|
||||
PyObject *py_cb = PyTuple_GET_ITEM(py_data, 2);
|
||||
if (py_owner == Py_None && py_cb == Py_None) {
|
||||
PyErr_Format(PyExc_TypeError, "missing owner or callback");
|
||||
} else {
|
||||
if (WM_op_handlers_remove(op_handlers,
|
||||
handler_id,
|
||||
(py_op == Py_None ? NULL : PyUnicode_AsUTF8(py_op)),
|
||||
(py_cb == Py_None ? NULL : py_cb),
|
||||
(py_owner == Py_None ? NULL : py_owner)) == 0) {
|
||||
PyErr_Format(PyExc_NameError, "data not found on %s", PyUnicode_AsUTF8(py_op));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PyErr_Occurred() != NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_pre_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_PRE_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_post_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_POST_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_modal(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_MODAL, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_modal_end(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_MODAL_END, args, kw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject *op_handler_remove_pre_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_PRE_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove_post_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_POST_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove_modal(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_MODAL, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove_modal_end(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_MODAL_END, args, kw);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *op_handlers_remove(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_ALL, args, kw);
|
||||
}
|
||||
|
||||
|
||||
static struct PyMethodDef bpy_ops_handlers_methods[] = {
|
||||
{"pre_invoke", (PyCFunction)op_handler_append_pre_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"post_invoke", (PyCFunction)op_handler_append_post_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal", (PyCFunction)op_handler_append_modal, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal_end", (PyCFunction)op_handler_append_modal_end, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"pre_invoke_remove", (PyCFunction)op_handler_remove_pre_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"post_invoke_remove", (PyCFunction)op_handler_remove_post_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal_remove",(PyCFunction)op_handler_remove_post_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal_end_remove", (PyCFunction)op_handler_remove_modal_end, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"remove", (PyCFunction)op_handlers_remove, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{NULL, NULL, 0, NULL},
|
||||
};
|
||||
|
||||
static struct PyModuleDef bpy_ops_handlers = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_bpy.ops.handlers",
|
||||
NULL,
|
||||
-1, /* multiple "initialization" just copies the module dict. */
|
||||
bpy_ops_handlers_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
PyObject *BPY_operator_module()
|
||||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&bpy_ops_module);
|
||||
|
||||
PyObject *handlers = PyModule_Create(&bpy_ops_handlers);
|
||||
|
||||
Py_INCREF(handlers);
|
||||
if (PyModule_AddObject(submodule, "handlers", handlers) < 0) {
|
||||
Py_DECREF(submodule);
|
||||
Py_DECREF(handlers);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
@ -1299,6 +1299,25 @@ static int pyrna_prop_to_enum_bitfield(
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *pyrna_enum_bitfield_to_py(const EnumPropertyItem *items, int value)
|
||||
{
|
||||
PyObject *ret = PySet_New(NULL);
|
||||
const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
|
||||
|
||||
if (RNA_enum_bitflag_identifiers(items, value, identifier)) {
|
||||
PyObject *item;
|
||||
int index;
|
||||
for (index = 0; identifier[index]; index++) {
|
||||
item = PyUnicode_FromString(identifier[index]);
|
||||
PySet_Add(ret, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
|
||||
{
|
||||
PyObject *item, *ret = nullptr;
|
||||
|
@ -189,6 +189,8 @@ PyObject *pyrna_id_CreatePyObject(struct ID *id);
|
||||
bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id);
|
||||
bool pyrna_id_CheckPyObject(PyObject *obj);
|
||||
|
||||
PyObject *pyrna_enum_bitfield_to_py(const struct EnumPropertyItem *items, int value);
|
||||
|
||||
/* operators also need this to set args */
|
||||
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, bool all_args, const char *error_prefix);
|
||||
PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop);
|
||||
|
@ -69,10 +69,12 @@ set(SRC
|
||||
message_bus/intern/wm_message_bus.cc
|
||||
message_bus/intern/wm_message_bus_rna.cc
|
||||
message_bus/intern/wm_message_bus_static.cc
|
||||
op_handlers/intern/wm_op_handlers.cc
|
||||
|
||||
WM_api.hh
|
||||
WM_keymap.hh
|
||||
WM_message.hh
|
||||
WM_op_handlers.h
|
||||
WM_toolsystem.hh
|
||||
WM_types.hh
|
||||
wm.hh
|
||||
@ -92,6 +94,8 @@ set(SRC
|
||||
gizmo/intern/wm_gizmo_intern.hh
|
||||
message_bus/intern/wm_message_bus_intern.hh
|
||||
message_bus/wm_message_bus.hh
|
||||
op_handlers/wm_op_handlers.h
|
||||
op_handlers/intern/wm_op_handlers_intern.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
25
source/blender/windowmanager/WM_op_handlers.h
Normal file
25
source/blender/windowmanager/WM_op_handlers.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct wmOpHandlers;
|
||||
|
||||
#include "op_handlers/wm_op_handlers.h"
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
#include "WM_op_handlers.h"
|
||||
#include "WM_types.hh"
|
||||
#include "wm.hh"
|
||||
#include "wm_draw.hh"
|
||||
@ -217,6 +218,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
wm->undo_stack = nullptr;
|
||||
|
||||
wm->message_bus = nullptr;
|
||||
wm->op_handlers = nullptr;
|
||||
|
||||
wm->xr.runtime = nullptr;
|
||||
|
||||
@ -474,6 +476,10 @@ void WM_check(bContext *C)
|
||||
wm->message_bus = WM_msgbus_create();
|
||||
}
|
||||
|
||||
if (wm->op_handlers == NULL) {
|
||||
wm->op_handlers = WM_op_handlers_create();
|
||||
}
|
||||
|
||||
if (!G.background) {
|
||||
/* Case: file-read. */
|
||||
if ((wm->init_flag & WM_INIT_FLAG_WINDOW) == 0) {
|
||||
@ -574,6 +580,11 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
|
||||
WM_msgbus_destroy(wm->message_bus);
|
||||
}
|
||||
|
||||
if (wm->op_handlers != nullptr) {
|
||||
WM_op_handlers_destroy(wm->op_handlers);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
BPY_callback_wm_free(wm);
|
||||
#endif
|
||||
|
@ -66,6 +66,7 @@
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
#include "WM_op_handlers.h"
|
||||
#include "WM_toolsystem.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
@ -1510,6 +1511,12 @@ static int wm_operator_invoke(bContext *C,
|
||||
return WM_operator_poll(C, ot);
|
||||
}
|
||||
|
||||
// Ensure any change is processed by poll
|
||||
if (WM_op_handlers_operator_pre_invoke(C, event, CTX_wm_op_handlers(C), ot, properties) ==
|
||||
false) {
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
if (WM_operator_poll(C, ot)) {
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
@ -1550,6 +1557,8 @@ static int wm_operator_invoke(bContext *C,
|
||||
retval = op->type->invoke(C, op, &event_temp);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
|
||||
WM_op_handlers_operator_post_invoke(C, event, CTX_wm_op_handlers(C), ot, op->ptr, retval);
|
||||
|
||||
if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
@ -1562,6 +1571,8 @@ static int wm_operator_invoke(bContext *C,
|
||||
retval = op->type->exec(C, op);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
|
||||
WM_op_handlers_operator_post_invoke(C, event, CTX_wm_op_handlers(C), ot, op->ptr, retval);
|
||||
|
||||
if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
@ -2476,9 +2487,20 @@ static eHandlerActionFlag wm_handler_operator_call(bContext *C,
|
||||
wm->op_undo_depth++;
|
||||
}
|
||||
|
||||
/* Warning, after this call all context data and 'event' may be freed. see check below. */
|
||||
retval = ot->modal(C, op, event);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
if ( (WM_get_op_handlers(CTX_wm_op_handlers(C), ot->idname) != NULL) && !ot->poll(C)) {
|
||||
// Py Handler, changing poll conditions
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
else {
|
||||
|
||||
/* Warning, after this call all context data and 'event' may be freed. see check below. */
|
||||
retval = ot->modal(C, op, event);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
|
||||
if (WM_op_handlers_operator_modal(C, event, CTX_wm_op_handlers(C), ot, retval) == false) {
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (ot->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
|
||||
wm->op_undo_depth--;
|
||||
@ -2492,6 +2514,9 @@ static eHandlerActionFlag wm_handler_operator_call(bContext *C,
|
||||
wm_event_modalkeymap_end(event, &event_backup);
|
||||
|
||||
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
|
||||
|
||||
WM_op_handlers_operator_modal_end(C, nullptr, CTX_wm_op_handlers(C), ot, retval);
|
||||
|
||||
wm_operator_reports(C, op, retval, false);
|
||||
|
||||
wmOperator *op_test = handler->op->opm ? handler->op->opm : handler->op;
|
||||
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "op_handlers/intern/wm_op_handlers_intern.h"
|
||||
#include "op_handlers/wm_op_handlers.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
|
||||
|
||||
struct wmOpHandlers *WM_op_handlers_create(void)
|
||||
{
|
||||
|
||||
struct wmOpHandlers *op_handlers = (wmOpHandlers*) MEM_callocN(sizeof(*op_handlers), __func__);
|
||||
return op_handlers;
|
||||
}
|
||||
|
||||
void WM_op_handlers_destroy(struct wmOpHandlers *op_handlers)
|
||||
{
|
||||
LISTBASE_FOREACH (wmOpHandlerData *, opHandlers, &op_handlers->handlers ) {
|
||||
BLI_freelistN(&opHandlers->pre_invoke);
|
||||
BLI_freelistN(&opHandlers->post_invoke);
|
||||
BLI_freelistN(&opHandlers->modal);
|
||||
BLI_freelistN(&opHandlers->modal_end);
|
||||
}
|
||||
BLI_freelistN(&op_handlers->handlers);
|
||||
MEM_freeN(op_handlers);
|
||||
op_handlers = NULL;
|
||||
}
|
||||
|
||||
ListBase *WM_op_handlers_get_handler_list(wmOpHandlerData *opHandlers, int id)
|
||||
{
|
||||
ListBase *list = NULL;
|
||||
switch (id) {
|
||||
case HANDLER_TYPE_PRE_INVOKE:
|
||||
list = &opHandlers->pre_invoke;
|
||||
break;
|
||||
case HANDLER_TYPE_POST_INVOKE:
|
||||
list = &opHandlers->post_invoke;
|
||||
break;
|
||||
case HANDLER_TYPE_MODAL:
|
||||
list = &opHandlers->modal;
|
||||
break;
|
||||
case HANDLER_TYPE_MODAL_END:
|
||||
list = &opHandlers->modal_end;
|
||||
break;
|
||||
default:
|
||||
BLI_assert(false);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
wmOpHandlerData *WM_get_op_handlers(struct wmOpHandlers *op_handlers, const char *op_name)
|
||||
{
|
||||
return (wmOpHandlerData*) BLI_findstring(&op_handlers->handlers, op_name, offsetof(wmOpHandlerData, id_name));
|
||||
}
|
||||
|
||||
|
||||
void WM_op_handlers_append(struct wmOpHandlers *op_handlers,
|
||||
int id,
|
||||
void *py_handle,
|
||||
const char *op_name,
|
||||
bool (*cb)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties, int),
|
||||
int (*check)(void *, void*, void*),
|
||||
bool (*poll)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties),
|
||||
void *py_data)
|
||||
{
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, op_name);
|
||||
wmHandlerData *data = (wmHandlerData *)MEM_mallocN(sizeof(wmHandlerData), "wmHandlerData");
|
||||
|
||||
if (opHandlers == NULL) {
|
||||
// Create
|
||||
opHandlers = (wmOpHandlerData *) MEM_callocN(sizeof(wmOpHandlerData), "wmOpHandlerData");
|
||||
BLI_strncpy(opHandlers->id_name, op_name, OP_MAX_TYPENAME);
|
||||
BLI_addtail(&op_handlers->handlers, opHandlers);
|
||||
}
|
||||
|
||||
data->py_handle = py_handle;
|
||||
data->id_name = opHandlers->id_name;
|
||||
data->cb = cb;
|
||||
data->check = check;
|
||||
data->poll = poll;
|
||||
data->py_data = py_data;
|
||||
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, id);
|
||||
BLI_addtail(list, data);
|
||||
}
|
||||
|
||||
int WM_op_handlers_remove_all(struct wmOpHandlers *op_handlers, void *cb, void *owner)
|
||||
{
|
||||
int ret = 0;
|
||||
LISTBASE_FOREACH (wmOpHandlerData *, opHandlers, &op_handlers->handlers) {
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_PRE_INVOKE, opHandlers->id_name, cb, owner);
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_POST_INVOKE, opHandlers->id_name, cb, owner);
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_MODAL, opHandlers->id_name, cb, owner);
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_MODAL_END, opHandlers->id_name, cb, owner);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WM_op_handlers_remove(
|
||||
struct wmOpHandlers *op_handlers, int id, const char *op_name, void *cb, void *owner)
|
||||
{
|
||||
int ret = 0;
|
||||
if (id == HANDLER_TYPE_ALL) {
|
||||
ret = WM_op_handlers_remove_all(op_handlers, cb, owner);
|
||||
}
|
||||
else {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, op_name);
|
||||
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, id);
|
||||
wmHandlerData *next;
|
||||
for (wmHandlerData *data = (wmHandlerData*) list->first; data; data = next) {
|
||||
next = data->next;
|
||||
if (data->check(data->py_data, owner, cb)) {
|
||||
BLI_freelinkN(list, data);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool WM_op_handlers_operator_exec(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
ListBase *list,
|
||||
struct wmOperatorType *ot,
|
||||
struct PointerRNA *properties,
|
||||
int retval)
|
||||
{
|
||||
bool ret = true;
|
||||
LISTBASE_FOREACH (wmHandlerData *, data, list) {
|
||||
if (data->poll == nullptr || data->poll(C, event, data->py_data, properties)) {
|
||||
ret = ret && data->cb(C, event, data->py_data, properties, retval);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Previous to invoke
|
||||
bool WM_op_handlers_operator_pre_invoke(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
PointerRNA *properties)
|
||||
{
|
||||
bool ret = true;
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_PRE_INVOKE);
|
||||
ret = ret && WM_op_handlers_operator_exec(C, event, list, ot, properties, 0);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Post To invoke
|
||||
void WM_op_handlers_operator_post_invoke(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
struct PointerRNA *properties,
|
||||
int retval)
|
||||
{
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_POST_INVOKE);
|
||||
WM_op_handlers_operator_exec(C, event, list, ot, properties, retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WM_op_handlers_operator_modal(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
int retval
|
||||
)
|
||||
{
|
||||
bool ret = true;
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_MODAL);
|
||||
ret = ret && WM_op_handlers_operator_exec(C, event, list, ot, NULL, retval);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WM_op_handlers_operator_modal_end(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
int retval)
|
||||
{
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_MODAL_END);
|
||||
WM_op_handlers_operator_exec(C, event, list, ot, NULL, retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \} */
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../wm_op_handlers.h"
|
||||
|
||||
|
||||
typedef struct wmHandlerData {
|
||||
struct wmHandlerData *next, *prev;
|
||||
char *id_name; // Pointer to wmOpHandlerData.id_name
|
||||
void *py_handle;
|
||||
void *py_data;
|
||||
bool (*cb)(struct bContext *, const wmEvent *event, void *, PointerRNA *properties, int); // callback
|
||||
int (*check)(void *, void*, void*);
|
||||
bool (*poll)(struct bContext *, const wmEvent *event, void *, PointerRNA *properties);
|
||||
} wmHandlerData;
|
||||
|
||||
|
101
source/blender/windowmanager/op_handlers/wm_op_handlers.h
Normal file
101
source/blender/windowmanager/op_handlers/wm_op_handlers.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#define HANDLER_TYPE_ALL 0
|
||||
#define HANDLER_TYPE_PRE_INVOKE 1
|
||||
#define HANDLER_TYPE_POST_INVOKE 2
|
||||
#define HANDLER_TYPE_MODAL 3
|
||||
#define HANDLER_TYPE_MODAL_END 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct wmOpHandlers {
|
||||
/** Handlers in order of being added. */
|
||||
ListBase handlers;
|
||||
};
|
||||
|
||||
|
||||
typedef struct wmOpHandlerData {
|
||||
struct wmOpHandlerData *next, *prev;
|
||||
char id_name[OP_MAX_TYPENAME];
|
||||
/** Handlers in order of being added. */
|
||||
ListBase pre_invoke;
|
||||
ListBase post_invoke;
|
||||
ListBase modal;
|
||||
ListBase modal_end;
|
||||
} wmOpHandlerData;
|
||||
|
||||
|
||||
struct wmOpHandlers *WM_op_handlers_create(void);
|
||||
void WM_op_handlers_destroy(struct wmOpHandlers *opHandlers);
|
||||
|
||||
wmOpHandlerData *WM_get_op_handlers(struct wmOpHandlers *op_handlers, const char *op_name);
|
||||
|
||||
void WM_op_handlers_append(struct wmOpHandlers *op_handlers, int id,
|
||||
void *handle,
|
||||
const char *op_name,
|
||||
bool (*cb)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties, int),
|
||||
int (*check)(void *, void*, void *),
|
||||
bool (*poll)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties),
|
||||
void *py_data);
|
||||
|
||||
int WM_op_handlers_remove(struct wmOpHandlers *op_handlers,
|
||||
int id,
|
||||
const char *op_name,
|
||||
void *cb,
|
||||
void *owner);
|
||||
|
||||
|
||||
bool WM_op_handlers_operator_pre_invoke(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
PointerRNA *properties);
|
||||
void WM_op_handlers_operator_post_invoke(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
PointerRNA *properties, int retval);
|
||||
|
||||
|
||||
bool WM_op_handlers_operator_modal(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot, int retval);
|
||||
|
||||
|
||||
void WM_op_handlers_operator_modal_end(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
int retval);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user