From 6c951fbb98a5ddb29240c3efc9af4304ab942396 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 10 Aug 2009 11:58:53 +0000 Subject: adding back button evaluation so you can do 1/60, 90*0.1 etc as well as dimension conversion 1km-10cm+4ft Note... - Python3.1 you don't need to add the .0 for divisions anymore (was esp annoying for button eval) - Simple dimension input, imperial mi/yd/ft/in, metric km/m/cm/mm, Later could display these values and have a pref for scene scale, atm it assumes 1BU == 1m. --- release/ui/bpy_ops.py | 45 ++++++++++++++++++++ source/blender/editors/interface/SConscript | 1 + source/blender/editors/interface/interface.c | 9 ++-- source/blender/python/BPY_extern.h | 2 +- source/blender/python/intern/bpy_interface.c | 62 ++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 5 deletions(-) diff --git a/release/ui/bpy_ops.py b/release/ui/bpy_ops.py index aa9bfb460f0..1d79f1a331f 100644 --- a/release/ui/bpy_ops.py +++ b/release/ui/bpy_ops.py @@ -111,3 +111,48 @@ class bpy_ops_submodule_op(object): import bpy bpy.ops = bpy_ops() + + + + +# A bit out of place but add button conversion code here +module_type = type(__builtins__) +import types +mod = types.ModuleType('button_convert') + +import sys +sys.modules['button_convert'] = mod + +def convert(expr): + + def replace(string, unit, scaler): + # in need of regex + change = True + while change: + change = False + i = string.find(unit) + if i != -1: + if i>0 and not string[i-1].isalpha(): + i_end = i+len(unit) + if i_end+1 >= len(string) or (not string[i_end+1].isalpha()): + string = string.replace(unit, scaler) + change = True + # print(string) + return string + + #imperial + expr = replace(expr, 'mi', '*1609.344') + expr = replace(expr, 'yd', '*0.9144') + expr = replace(expr, 'ft', '*0.3048') + expr = replace(expr, 'in', '*0.0254') + + # metric + expr = replace(expr, 'km', '*1000') + expr = replace(expr, 'm', '') + expr = replace(expr, 'cm', '*0.01') + expr = replace(expr, 'mm', '*0.001') + + return expr + +mod.convert = convert + diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript index bac3742c12f..e44de5410f1 100644 --- a/source/blender/editors/interface/SConscript +++ b/source/blender/editors/interface/SConscript @@ -9,6 +9,7 @@ for source in env.Glob('*_api.c'): incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc' incs += ' #/extern/glew/include' +incs += ' ../../python/' # python button eval defs = [] diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 9e9b6165a73..f3bb975a1f7 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -66,6 +66,8 @@ #include "RNA_access.h" #include "RNA_types.h" +#include "BPY_extern.h" + #include "interface_intern.h" #define MENU_WIDTH 120 @@ -1434,10 +1436,9 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) double value; /* XXX 2.50 missing python api */ -#if 0 - if(BPY_button_eval(str, &value)) { - BKE_report(CTX_reports(C), RPT_WARNING, "Invalid Python expression, check console"); - value = 0.0f; /* Zero out value on error */ +#ifndef DISABLE_PYTHON + if(BPY_button_eval(C, str, &value)) { + value = ui_get_but_val(but); /* use its original value */ if(str[0]) return 0; diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index db0404c33a8..acb45790ed2 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -122,7 +122,7 @@ extern "C" { void BPY_pydriver_update(void); float BPY_pydriver_eval(struct ChannelDriver *driver); - int BPY_button_eval(char *expr, double *value); + int BPY_button_eval(struct bContext *C, char *expr, double *value); /* format importer hook */ int BPY_call_importloader( char *name ); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index e37e75ab80d..8cd4cdd5dfc 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -804,3 +804,65 @@ float BPY_pydriver_eval (ChannelDriver *driver) return result; } + +int BPY_button_eval(bContext *C, char *expr, double *value) +{ + PyGILState_STATE gilstate; + PyObject *dict, *retval, *expr_conv; + int error_ret = 0; + + if (!value || !expr || expr[0]=='\0') return -1; + + bpy_context_set(C, &gilstate); + + // experemental, fun. "button_convert.convert" is currently defined in bpy_ops.py + { + PyObject *mod= PyDict_GetItemString(PySys_GetObject("modules"), "button_convert"); + if(mod && PyModule_Check(mod)) { + PyObject *mod_dict= PyModule_GetDict(mod); + PyObject *func= PyDict_GetItemString(mod_dict, "convert"); + if(func) { + PyObject *expr_conv = PyObject_CallFunction(func, "s", expr); + if(expr_conv==NULL) { + PyErr_Print(); + PyErr_Clear(); + } + else { + expr= _PyUnicode_AsString(expr_conv); /* TODO, check */ + } + } + } + } + + dict= CreateGlobalDictionary(C); + retval = PyRun_String(expr, Py_eval_input, dict, dict); + + if(expr_conv) { + Py_DECREF(expr_conv); /* invalidates expr */ + } + + if (retval == NULL) { + error_ret= -1; + } + else { + double val = PyFloat_AsDouble(retval); + Py_DECREF(retval); + + if(val==-1 && PyErr_Occurred()) { + error_ret= -1; + } + else { + *value= val; + } + } + + if(error_ret) { + BPy_errors_to_report(CTX_wm_reports(C)); + } + + Py_DECREF(dict); + bpy_context_clear(C, &gilstate); + + return error_ret; +} + -- cgit v1.2.3