コード例 #1
0
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';
			}
		}
	}
}
コード例 #2
0
ファイル: rna_wm_api.c プロジェクト: wisaac407/blender
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);
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: bpy_operator.c プロジェクト: Walid-Shouman/Blender
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;
}
コード例 #5
0
ファイル: bpy_operator.c プロジェクト: Walid-Shouman/Blender
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);

}