11 #define PY_SSIZE_T_CLEAN
14 #include <structmember.h>
21 #include "../generic/py_capi_utils.h"
57 "`bpyunits_ucategories_items` should match `B_UNIT_` enum items in `BKE_units.h`")
67 static PyStructSequence_Desc bpyunits_systems_desc = {
68 "bpy.utils.units.systems",
69 "This named tuple contains all predefined unit systems",
70 bpyunits_systems_fields,
74 "bpy.utils.units.categories",
75 "This named tuple contains all predefined unit names",
76 bpyunits_categories_fields,
84 PyStructSequence_Desc *py_sseq_desc,
85 const char **str_items)
87 PyObject *py_struct_seq;
90 const char **str_iter;
91 PyStructSequence_Field *desc;
95 for (str_iter = str_items, desc = py_sseq_desc->fields; *str_iter; str_iter++, desc++) {
96 desc->name = (
char *)*str_iter;
100 desc->name = desc->doc =
NULL;
102 PyStructSequence_InitType(py_type, py_sseq_desc);
105 py_struct_seq = PyStructSequence_New(py_type);
108 for (str_iter = str_items; *str_iter; str_iter++) {
109 PyStructSequence_SET_ITEM(py_struct_seq,
pos++, PyUnicode_FromString(*str_iter));
112 return py_struct_seq;
115 static bool bpyunits_validate(
const char *usys_str,
const char *ucat_str,
int *r_usys,
int *r_ucat)
119 PyErr_Format(PyExc_ValueError,
"Unknown unit system specified: %.200s.", usys_str);
125 PyErr_Format(PyExc_ValueError,
"Unknown unit category specified: %.200s.", ucat_str);
130 PyErr_Format(PyExc_ValueError,
131 "%.200s / %.200s unit system/category combination is not valid.",
141 bpyunits_to_value_doc,
142 ".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n"
144 " Convert a given input string into a float value.\n"
146 " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n"
147 " :type unit_system: string\n"
148 " :arg unit_category: The category of data we are converting (length, area, rotation, "
150 " from :attr:`bpy.utils.units.categories`.\n"
151 " :type unit_category: string\n"
152 " :arg str_input: The string to convert to a float value.\n"
153 " :type str_input: string\n"
154 " :arg str_ref_unit: A reference string from which to extract a default unit, if none is "
155 "found in ``str_input``.\n"
156 " :type str_ref_unit: string or None\n"
157 " :return: The converted/interpreted value.\n"
159 " :raises ValueError: if conversion fails to generate a valid python float value.\n");
163 const float scale = 1.0f;
171 static const char *_keywords[] = {
178 static _PyArg_Parser _parser = {
188 if (!_PyArg_ParseTupleAndKeywordsFast(
189 args, kw, &_parser, &usys_str, &ucat_str, &inpt, &str_len, &uref)) {
197 str_len = str_len * 2 + 64;
198 str = PyMem_MALLOC(
sizeof(*
str) * (
size_t)str_len);
204 if (PyErr_Occurred()) {
210 PyExc_ValueError,
"'%.200s' (converted as '%s') could not be evaluated.", inpt,
str);
222 ".. method:: to_string(unit_system, unit_category, value, precision=3, "
223 "split_unit=False, compatible_unit=False)\n"
225 " Convert a given input float value into a string with units.\n"
227 " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n"
228 " :type unit_system: string\n"
229 " :arg unit_category: The category of data we are converting (length, area, "
231 " from :attr:`bpy.utils.units.categories`.\n"
232 " :type unit_category: string\n"
233 " :arg value: The value to convert to a string.\n"
234 " :type value: float\n"
235 " :arg precision: Number of digits after the comma.\n"
236 " :type precision: int\n"
237 " :arg split_unit: Whether to use several units if needed (1m1cm), or always only "
239 " :type split_unit: bool\n"
240 " :arg compatible_unit: Whether to use keyboard-friendly units (1m2) or nicer "
241 "utf-8 ones (1m²).\n"
242 " :type compatible_unit: bool\n"
243 " :return: The converted string.\n"
245 " :raises ValueError: if conversion fails to generate a valid python string.\n");
248 char *usys_str =
NULL, *ucat_str =
NULL;
251 bool split_unit =
false, compatible_unit =
false;
255 static const char *_keywords[] = {
264 static _PyArg_Parser _parser = {
276 if (!_PyArg_ParseTupleAndKeywordsFast(args,
303 char buf1[64], buf2[64], *
str;
307 buf1,
sizeof(buf1), value, precision, usys, ucat, (
bool)split_unit,
false);
309 if (compatible_unit) {
326 METH_VARARGS | METH_KEYWORDS,
327 bpyunits_to_value_doc},
330 METH_VARARGS | METH_KEYWORDS,
331 bpyunits_to_string_doc},
335 PyDoc_STRVAR(bpyunits_doc,
"This module contains some data/methods regarding units handling.");
338 PyModuleDef_HEAD_INIT,
351 PyObject *submodule, *item;
354 PyDict_SetItemString(PyImport_GetModuleDict(),
bpyunits_module.m_name, submodule);
361 PyModule_AddObject(submodule,
"systems", item);
366 PyModule_AddObject(submodule,
"categories", item);
bool BKE_unit_is_valid(int system, int type)
size_t BKE_unit_value_as_string_adaptive(char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad)
void BKE_unit_name_to_alt(char *str, int len_max, const char *orig_str, int system, int type)
bool BKE_unit_replace_string(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array) ATTR_NONNULL()
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
static PyObject * py_structseq_from_strings(PyTypeObject *py_type, PyStructSequence_Desc *py_sseq_desc, const char **str_items)
static PyObject * bpyunits_to_string(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
PyObject * BPY_utils_units(void)
static const char * bpyunits_usystem_items[]
static PyStructSequence_Desc bpyunits_categories_desc
static PyMethodDef bpyunits_methods[]
static PyObject * bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static const char * bpyunits_ucategories_items[]
static PyTypeObject BPyUnitsCategoriesType
static bool bpyunits_validate(const char *usys_str, const char *ucat_str, int *r_usys, int *r_ucat)
BLI_STATIC_ASSERT(ARRAY_SIZE(bpyunits_ucategories_items)==B_UNIT_TYPE_TOT+1, "`bpyunits_ucategories_items` should match `B_UNIT_` enum items in `BKE_units.h`")
PyDoc_STRVAR(bpyunits_to_value_doc, ".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n" "\n" " Convert a given input string into a float value.\n" "\n" " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" " :type unit_system: string\n" " :arg unit_category: The category of data we are converting (length, area, rotation, " "etc.),\n" " from :attr:`bpy.utils.units.categories`.\n" " :type unit_category: string\n" " :arg str_input: The string to convert to a float value.\n" " :type str_input: string\n" " :arg str_ref_unit: A reference string from which to extract a default unit, if none is " "found in ``str_input``.\n" " :type str_ref_unit: string or None\n" " :return: The converted/interpreted value.\n" " :rtype: float\n" " :raises ValueError: if conversion fails to generate a valid python float value.\n")
static struct PyModuleDef bpyunits_module
static PyTypeObject BPyUnitsSystemsType
bool PyC_RunString_AsNumber(const char *imports[], const char *expr, const char *filename, double *r_value)
int PyC_ParseBool(PyObject *o, void *p)