static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km) { /* here we convert propvalue string values delayed, due to python keymaps * being created before the actual modal keymaps, so no modal_items */ wmKeyMap *defaultkm; wmKeyMapItem *kmi; int propvalue; if (km && (km->flag & KEYMAP_MODAL) && !km->modal_items) { defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); if (!defaultkm) return; km->modal_items = defaultkm->modal_items; km->poll = defaultkm->poll; for (kmi = km->items.first; kmi; kmi = kmi->next) { if (kmi->propvalue_str[0]) { if (RNA_enum_value_from_id(km->modal_items, kmi->propvalue_str, &propvalue)) kmi->propvalue = propvalue; kmi->propvalue_str[0] = '\0'; } } } }
static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, ReportList *reports, const char *propvalue_str, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) { int modifier = 0; int propvalue = 0; /* only modal maps */ if ((km->flag & KEYMAP_MODAL) == 0) { BKE_report(reports, RPT_ERROR, "Not a modal keymap"); return NULL; } if (shift) modifier |= KM_SHIFT; if (ctrl) modifier |= KM_CTRL; if (alt) modifier |= KM_ALT; if (oskey) modifier |= KM_OSKEY; if (any) modifier = KM_ANY; /* not initialized yet, do delayed lookup */ if (!km->modal_items) return WM_modalkeymap_add_item_str(km, type, value, modifier, keymodifier, propvalue_str); if (RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue) == 0) BKE_report(reports, RPT_WARNING, "Property value not in enumeration"); return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue); }
static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) { StructRNA *srna; BPY_PROPDEF_HEAD(FloatProperty) if(srna) { static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f; int precision= 2; PropertyRNA *prop; PyObject *pyopts= NULL; int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; char *pyunit= NULL; int unit= PROP_UNIT_NONE; PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssffffffiO!ssO:FloatProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, &pyopts, &pysubtype, &pyunit, &update_cb)) { return NULL; } BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_flag_items, property_subtype_number_items) if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) { PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit", pyunit); return NULL; } if (bpy_prop_callback_check(update_cb, 2) == -1) { return NULL; } prop= RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); RNA_def_property_float_default(prop, def); RNA_def_property_range(prop, min, max); RNA_def_property_ui_text(prop, name, description); RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); if(pyopts) { if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; }
static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; char *opname; PyObject *context_dict = NULL; /* optional args */ PyObject *context_dict_back; char *context_str = NULL; PyObject *ret; int context = WM_OP_EXEC_DEFAULT; /* XXX Todo, work out a better solution for passing on context, * could make a tuple from self and pack the name and Context into it... */ bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); return NULL; } if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) return NULL; ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "Polling operator \"bpy.ops.%s\" error, " "could not be found", opname); return NULL; } if (context_str) { if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) { char *enum_str = BPy_enum_as_string(operator_context_items); PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, " "expected a string enum in (%.200s)", opname, enum_str); MEM_freeN(enum_str); return NULL; } } if (context_dict == NULL || context_dict == Py_None) { context_dict = NULL; } else if (!PyDict_Check(context_dict)) { PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, " "custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name); return NULL; } context_dict_back = CTX_py_dict_get(C); CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ /* main purpose of thsi function */ ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False; /* restore with original context dict, probably NULL but need this for nested operator calls */ Py_XDECREF(context_dict); CTX_py_dict_set(C, (void *)context_dict_back); Py_INCREF(ret); return ret; }
static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; int error_val = 0; PointerRNA ptr; int operator_ret = OPERATOR_CANCELLED; char *opname; char *context_str = NULL; PyObject *kw = NULL; /* optional args */ PyObject *context_dict = NULL; /* optional args */ PyObject *context_dict_back; /* note that context is an int, python does the conversion in this case */ int context = WM_OP_EXEC_DEFAULT; int is_undo = false; /* XXX Todo, work out a better solution for passing on context, * could make a tuple from self and pack the name and Context into it... */ bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); return NULL; } if (!PyArg_ParseTuple(args, "sO|O!si:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str, &is_undo)) { return NULL; } ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "Calling operator \"bpy.ops.%s\" error, " "could not be found", opname); return NULL; } if (!pyrna_write_check()) { PyErr_Format(PyExc_RuntimeError, "Calling operator \"bpy.ops.%s\" error, " "can't modify blend data in this state (drawing/rendering)", opname); return NULL; } if (context_str) { if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) { char *enum_str = BPy_enum_as_string(operator_context_items); PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, " "expected a string enum in (%.200s)", opname, enum_str); MEM_freeN(enum_str); return NULL; } } if (context_dict == NULL || context_dict == Py_None) { context_dict = NULL; } else if (!PyDict_Check(context_dict)) { PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, " "custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name); return NULL; } context_dict_back = CTX_py_dict_get(C); CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ if (WM_operator_poll_context((bContext *)C, ot, context) == false) { const char *msg = CTX_wm_operator_poll_msg_get(C); PyErr_Format(PyExc_RuntimeError, "Operator bpy.ops.%.200s.poll() %.200s", opname, msg ? msg : "failed, context is incorrect"); CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */ error_val = -1; } else { WM_operator_properties_create_ptr(&ptr, ot); WM_operator_properties_sanitize(&ptr, 0); if (kw && PyDict_Size(kw)) error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); if (error_val == 0) { ReportList *reports; reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */ #ifdef BPY_RELEASE_GIL /* release GIL, since a thread could be started from an operator * that updates a driver */ /* note: I have not seen any examples of code that does this * so it may not be officially supported but seems to work ok. */ { PyThreadState *ts = PyEval_SaveThread(); #endif operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo); #ifdef BPY_RELEASE_GIL /* regain GIL */ PyEval_RestoreThread(ts); } #endif error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false); /* operator output is nice to have in the terminal/console too */ if (reports->list.first) { char *report_str = BKE_reports_string(reports, 0); /* all reports */ if (report_str) { PySys_WriteStdout("%s\n", report_str); MEM_freeN(report_str); } } BKE_reports_clear(reports); if ((reports->flag & RPT_FREE) == 0) { MEM_freeN(reports); } } WM_operator_properties_free(&ptr); #if 0 /* if there is some way to know an operator takes args we should use this */ { /* no props */ if (kw != NULL) { PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname); return NULL; } WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); } #endif } /* restore with original context dict, probably NULL but need this for nested operator calls */ Py_XDECREF(context_dict); CTX_py_dict_set(C, (void *)context_dict_back); if (error_val == -1) { return NULL; } /* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(), * further access will crash blender. setting context is not needed in this case, only calling because this * function corrects bpy.data (internal Main pointer) */ BPY_modules_update(C); /* needed for when WM_OT_read_factory_settings us called from within a script */ bpy_import_main_set(CTX_data_main(C)); /* return operator_ret as a bpy enum */ return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret); }