Commit: f94b87bbb89b2350be2f5b26c2afb2372fd9d99c
Author: Bastien Montagne
Date:   Tue Jun 17 16:03:40 2014 +0200
https://developer.blender.org/rBf94b87bbb89b2350be2f5b26c2afb2372fd9d99c

New python API for units handling.

Exposes all supported unit systems & types, and to_value()/to_string() 
functions.

Reviewed and enhanced by CampbellBarton, many thanks!

Differential Revision: https://developer.blender.org/D416

===================================================================

M       release/scripts/modules/bpy/utils.py
M       source/blender/python/generic/py_capi_utils.c
M       source/blender/python/generic/py_capi_utils.h
M       source/blender/python/intern/CMakeLists.txt
M       source/blender/python/intern/bpy.c
M       source/blender/python/intern/bpy_interface.c
A       source/blender/python/intern/bpy_utils_units.c
A       source/blender/python/intern/bpy_utils_units.h

===================================================================

diff --git a/release/scripts/modules/bpy/utils.py 
b/release/scripts/modules/bpy/utils.py
index ce1efa4..5621af2 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -44,6 +44,7 @@ __all__ = (
     "script_paths",
     "smpte_from_frame",
     "smpte_from_seconds",
+    "units",
     "unregister_class",
     "unregister_module",
     "user_resource",
@@ -58,6 +59,7 @@ from _bpy import (
     )
 from _bpy import script_paths as _bpy_script_paths
 from _bpy import user_resource as _user_resource
+from _bpy import _utils_units as units
 
 import bpy as _bpy
 import os as _os
diff --git a/source/blender/python/generic/py_capi_utils.c 
b/source/blender/python/generic/py_capi_utils.c
index 54e27a3..8454f5b 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -904,3 +904,73 @@ PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int 
flag)
 
        return ret;
 }
+
+
+/**
+ * \return -1 on error, else 0
+ *
+ * \note it is caller's responsibility to acquire & release GIL!
+ */
+int PyC_RunString_AsNumber(const char *expr, double *value, const char 
*filename)
+{
+       PyObject *py_dict, *mod, *retval;
+       int error_ret = 0;
+       PyObject *main_mod = NULL;
+
+       PyC_MainModule_Backup(&main_mod);
+
+       py_dict = PyC_DefaultNameSpace(filename);
+
+       mod = PyImport_ImportModule("math");
+       if (mod) {
+               PyDict_Merge(py_dict, PyModule_GetDict(mod), 0); /* 0 - don't 
overwrite existing values */
+               Py_DECREF(mod);
+       }
+       else { /* highly unlikely but possibly */
+               PyErr_Print();
+               PyErr_Clear();
+       }
+
+       retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
+
+       if (retval == NULL) {
+               error_ret = -1;
+       }
+       else {
+               double val;
+
+               if (PyTuple_Check(retval)) {
+                       /* Users my have typed in 10km, 2m
+                        * add up all values */
+                       int i;
+                       val = 0.0;
+
+                       for (i = 0; i < PyTuple_GET_SIZE(retval); i++) {
+                               const double val_item = 
PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
+                               if (val_item == -1 && PyErr_Occurred()) {
+                                       val = -1;
+                                       break;
+                               }
+                               val += val_item;
+                       }
+               }
+               else {
+                       val = PyFloat_AsDouble(retval);
+               }
+               Py_DECREF(retval);
+
+               if (val == -1 && PyErr_Occurred()) {
+                       error_ret = -1;
+               }
+               else if (!finite(val)) {
+                       *value = 0.0;
+               }
+               else {
+                       *value = val;
+               }
+       }
+
+       PyC_MainModule_Restore(main_mod);
+
+       return error_ret;
+}
diff --git a/source/blender/python/generic/py_capi_utils.h 
b/source/blender/python/generic/py_capi_utils.h
index 0afc4dd..559a8e1 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -73,4 +73,6 @@ int       PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const 
char *identifier, int
 int       PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int 
*r_value, const char *error_prefix);
 PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag);
 
+int PyC_RunString_AsNumber(const char *expr, double *value, const char 
*filename);
+
 #endif  /* __PY_CAPI_UTILS_H__ */
diff --git a/source/blender/python/intern/CMakeLists.txt 
b/source/blender/python/intern/CMakeLists.txt
index 0605f40..70b4df7 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -68,6 +68,7 @@ set(SRC
        bpy_rna_callback.c
        bpy_traceback.c
        bpy_util.c
+       bpy_utils_units.c
        stubs.c
 
        gpu.h
@@ -91,6 +92,7 @@ set(SRC
        bpy_rna_callback.h
        bpy_traceback.h
        bpy_util.h
+       bpy_utils_units.h
        ../BPY_extern.h
 )
 
diff --git a/source/blender/python/intern/bpy.c 
b/source/blender/python/intern/bpy.c
index 8910482..5fd19d3 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -49,6 +49,7 @@
 #include "bpy_props.h"
 #include "bpy_library.h"
 #include "bpy_operator.h"
+#include "bpy_utils_units.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -334,6 +335,7 @@ void BPy_init_modules(void)
        /* ops is now a python module that does the conversion from SOME_OT_foo 
-> some.foo */
        PyModule_AddObject(mod, "ops", BPY_operator_module());
        PyModule_AddObject(mod, "app", BPY_app_struct());
+       PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
 
        /* bpy context */
        RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), 
&ctx_ptr);
diff --git a/source/blender/python/intern/bpy_interface.c 
b/source/blender/python/intern/bpy_interface.c
index bf2de02..b7752b3 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -566,15 +566,12 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
        PyGILState_Release(gilstate);
 }
 
-
 /* return -1 on error, else 0 */
 int BPY_button_exec(bContext *C, const char *expr, double *value, const bool 
verbose)
 {
        PyGILState_STATE gilstate;
-       PyObject *py_dict, *mod, *retval;
        int error_ret = 0;
-       PyObject *main_mod = NULL;
-       
+
        if (!value || !expr) return -1;
 
        if (expr[0] == '\0') {
@@ -584,59 +581,8 @@ int BPY_button_exec(bContext *C, const char *expr, double 
*value, const bool ver
 
        bpy_context_set(C, &gilstate);
 
-       PyC_MainModule_Backup(&main_mod);
-
-       py_dict = PyC_DefaultNameSpace("<blender button>");
-
-       mod = PyImport_ImportModule("math");
-       if (mod) {
-               PyDict_Merge(py_dict, PyModule_GetDict(mod), 0); /* 0 - don't 
overwrite existing values */
-               Py_DECREF(mod);
-       }
-       else { /* highly unlikely but possibly */
-               PyErr_Print();
-               PyErr_Clear();
-       }
-       
-       retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
-       
-       if (retval == NULL) {
-               error_ret = -1;
-       }
-       else {
-               double val;
-
-               if (PyTuple_Check(retval)) {
-                       /* Users my have typed in 10km, 2m
-                        * add up all values */
-                       int i;
-                       val = 0.0;
+       error_ret = PyC_RunString_AsNumber(expr, value, "<blender button>");
 
-                       for (i = 0; i < PyTuple_GET_SIZE(retval); i++) {
-                               const double val_item = 
PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
-                               if (val_item == -1 && PyErr_Occurred()) {
-                                       val = -1;
-                                       break;
-                               }
-                               val += val_item;
-                       }
-               }
-               else {
-                       val = PyFloat_AsDouble(retval);
-               }
-               Py_DECREF(retval);
-               
-               if (val == -1 && PyErr_Occurred()) {
-                       error_ret = -1;
-               }
-               else if (!finite(val)) {
-                       *value = 0.0;
-               }
-               else {
-                       *value = val;
-               }
-       }
-       
        if (error_ret) {
                if (verbose) {
                        BPy_errors_to_report(CTX_wm_reports(C));
@@ -646,10 +592,8 @@ int BPY_button_exec(bContext *C, const char *expr, double 
*value, const bool ver
                }
        }
 
-       PyC_MainModule_Restore(main_mod);
-       
        bpy_context_clear(C, &gilstate);
-       
+
        return error_ret;
 }
 
diff --git a/source/blender/python/intern/bpy_utils_units.c 
b/source/blender/python/intern/bpy_utils_units.c
new file mode 100644
index 0000000..cdbd57b
--- /dev/null
+++ b/source/blender/python/intern/bpy_utils_units.c
@@ -0,0 +1,332 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * Contributor(s): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_utils_units.c
+ *  \ingroup pythonintern
+ *
+ * This file defines a singleton py object accessed via 'bpy.utils.units',
+ * which exposes various data and functions useful in units handling.
+ */
+
+/* Future-proof, See 
https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_ghash.h"
+
+#include "BPY_extern.h"
+#include "bpy_utils_units.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "BKE_unit.h"
+
+/***** C-defined systems and types *****/
+
+static PyTypeObject BPyUnitsSystemsType;
+static PyTypeObject BPyUnitsCategoriesType;
+
+/* XXX Maybe better as externs of BKE_unit.h ? */
+static const char *bpyunits_usystem_items[] = {
+       "NONE",
+       "METRIC",
+       "IMPERIAL",
+       NULL,
+};
+
+static const char *bpyunits_ucategorie_items[] = {
+       "NONE",
+       "LENGTH",
+       "AREA",
+       "VOLUME",
+       "MASS",
+       "ROTATION",
+       "TIME",
+       "VELOCITY",
+       "ACCELERATION",
+       "CAMERA",
+       NULL,
+};
+
+/**
+ * These fields are just empty placeholders, actual values get set in 
initializations functions.
+ * This allows us to avoid many handwriting, and above all, to keep all 
systems/categories definition stuff in
+ * ``BKE_unit.h``.
+ */
+static PyStructSequence_Field 
bpyunits_systems_fields[ARRAY_SIZE(bpyunits_usystem_items)];
+static PyStructSequence_Field 
bpyunits_categories_fields[ARRAY_SIZE(bpyunits_ucategorie_items)];
+
+static PyStructSequence_Desc bpyunits_systems_desc = {
+       (char *)"bpy.utils.units.systems",     /* name */
+       (char *)"This named tuple contains all pre-defined unit systems",    /* 
doc */
+       bpyunits_systems_fields,    /* fields */
+       ARRAY_SIZE(bpyunits_systems_fields) - 1
+};
+static PyStructSequence_Desc bpyunits_categories_desc = {
+       (char *)"bpy.utils.units.categories",     /* name */
+       (char *)"This named tuple contains all pre-defined unit names",    /* 
doc */
+       bpyunits_categories_fields,    /* fields */
+       ARRAY_SIZE(bpyunits_categories_fields) - 1
+};
+
+/**
+ * Simple utility function to initialize #PyStructSequence_Desc
+ */
+static PyObject *py_structseq_from_strings(
+        PyTypeObject *py_type,
+        PyStructSequence_Desc *py_sseq_desc,
+        const char **str_items)
+{
+       PyObject *py_struct_seq;
+       int pos = 0;
+
+       const char **str_iter;
+       PyStructSequence_Field *desc;
+
+       /* initialize array */
+       /* We really populate the contexts' fields here! */
+       for (str_iter = str_items, desc = py_sseq_desc->fields; *str_iter; 
str_iter++, desc++) {
+               desc->name = (ch

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to