13#define PY_SSIZE_T_CLEAN
16#include <structmember.h>
63 "`bpyunits_ucategories_items` should match `B_UNIT_` enum items in `BKE_units.h`")
74 "bpy.utils.units.systems",
75 "This named tuple contains all predefined unit systems",
76 bpyunits_systems_fields,
80 "bpy.utils.units.categories",
81 "This named tuple contains all predefined unit names",
90 PyStructSequence_Desc *py_sseq_desc,
91 const char **str_items)
93 PyObject *py_struct_seq;
96 const char **str_iter;
97 PyStructSequence_Field *desc;
101 for (str_iter = str_items, desc = py_sseq_desc->fields; *str_iter; str_iter++, desc++) {
102 desc->name = (
char *)*str_iter;
106 desc->name = desc->doc =
nullptr;
108 PyStructSequence_InitType(py_type, py_sseq_desc);
111 py_struct_seq = PyStructSequence_New(py_type);
114 for (str_iter = str_items; *str_iter; str_iter++) {
115 PyStructSequence_SET_ITEM(py_struct_seq,
pos++, PyUnicode_FromString(*str_iter));
118 return py_struct_seq;
121static bool bpyunits_validate(
const char *usys_str,
const char *ucat_str,
int *r_usys,
int *r_ucat)
125 PyErr_Format(PyExc_ValueError,
"Unknown unit system specified: %.200s.", usys_str);
131 PyErr_Format(PyExc_ValueError,
"Unknown unit category specified: %.200s.", ucat_str);
136 PyErr_Format(PyExc_ValueError,
137 "%.200s / %.200s unit system/category combination is not valid.",
148 bpyunits_to_value_doc,
149 ".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n"
151 " Convert a given input string into a float value.\n"
153 " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n"
154 " :type unit_system: str\n"
155 " :arg unit_category: The category of data we are converting (length, area, rotation, "
157 " from :attr:`bpy.utils.units.categories`.\n"
158 " :type unit_category: str\n"
159 " :arg str_input: The string to convert to a float value.\n"
160 " :type str_input: str\n"
161 " :arg str_ref_unit: A reference string from which to extract a default unit, if none is "
162 "found in ``str_input``.\n"
163 " :type str_ref_unit: str | None\n"
164 " :return: The converted/interpreted value.\n"
166 " :raises ValueError: if conversion fails to generate a valid Python float value.\n");
169 char *usys_str =
nullptr, *ucat_str =
nullptr, *inpt =
nullptr, *uref =
nullptr;
170 const float scale = 1.0f;
178 static const char *_keywords[] = {
185 static _PyArg_Parser _parser = {
196 if (!_PyArg_ParseTupleAndKeywordsFast(
197 args, kw, &_parser, &usys_str, &ucat_str, &inpt, &str_len, &uref))
206 str_len = str_len * 2 + 64;
207 str =
static_cast<char *
>(PyMem_MALLOC(
sizeof(*
str) *
size_t(str_len)));
213 if (PyErr_Occurred()) {
219 PyExc_ValueError,
"'%.200s' (converted as '%s') could not be evaluated.", inpt,
str);
223 ret = PyFloat_FromDouble(result);
232 bpyunits_to_string_doc,
233 ".. method:: to_string(unit_system, unit_category, value, precision=3, "
234 "split_unit=False, compatible_unit=False)\n"
236 " Convert a given input float value into a string with units.\n"
238 " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n"
239 " :type unit_system: str\n"
240 " :arg unit_category: The category of data we are converting (length, area, "
242 " from :attr:`bpy.utils.units.categories`.\n"
243 " :type unit_category: str\n"
244 " :arg value: The value to convert to a string.\n"
245 " :type value: float\n"
246 " :arg precision: Number of digits after the comma.\n"
247 " :type precision: int\n"
248 " :arg split_unit: Whether to use several units if needed (1m1cm), or always only "
250 " :type split_unit: bool\n"
251 " :arg compatible_unit: Whether to use keyboard-friendly units (1m2) or nicer "
252 "utf-8 ones (1m²).\n"
253 " :type compatible_unit: bool\n"
254 " :return: The converted string.\n"
256 " :raises ValueError: if conversion fails to generate a valid Python string.\n");
259 char *usys_str =
nullptr, *ucat_str =
nullptr;
262 bool split_unit =
false, compatible_unit =
false;
266 static const char *_keywords[] = {
275 static _PyArg_Parser _parser = {
288 if (!_PyArg_ParseTupleAndKeywordsFast(args,
316 char buf1[64], buf2[64];
321 buf1,
sizeof(buf1), value, precision, usys, ucat,
bool(split_unit),
false);
323 if (compatible_unit) {
331 result = PyUnicode_FromString(
str);
337#if (defined(__GNUC__) && !defined(__clang__))
338# pragma GCC diagnostic push
339# pragma GCC diagnostic ignored "-Wcast-function-type"
345 METH_VARARGS | METH_KEYWORDS,
346 bpyunits_to_value_doc},
349 METH_VARARGS | METH_KEYWORDS,
350 bpyunits_to_string_doc},
351 {
nullptr,
nullptr, 0,
nullptr},
354#if (defined(__GNUC__) && !defined(__clang__))
355# pragma GCC diagnostic pop
361 "This module contains some data/methods regarding units handling.");
364 PyModuleDef_HEAD_INIT,
377 PyObject *submodule, *item;
380 PyDict_SetItemString(PyImport_GetModuleDict(),
bpyunits_module.m_name, submodule);
387 PyModule_AddObject(submodule,
"systems", item);
392 PyModule_AddObject(submodule,
"categories", item);
void BKE_unit_name_to_alt(char *str, int str_maxncpy, const char *orig_str, int system, int type)
bool BKE_unit_is_valid(int system, int type)
bool BKE_unit_replace_string(char *str, int str_maxncpy, const char *str_prev, double scale_pref, int system, int type)
size_t BKE_unit_value_as_string_adaptive(char *str, int str_maxncpy, double value, int prec, int system, int type, bool split, bool pad)
#define BLI_STATIC_ASSERT(a, msg)
int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
static const char * bpyunits_usystem_items[]
PyObject * BPY_utils_units()
static PyObject * bpyunits_to_string(PyObject *, PyObject *args, PyObject *kw)
static PyObject * py_structseq_from_strings(PyTypeObject *py_type, PyStructSequence_Desc *py_sseq_desc, const char **str_items)
static PyModuleDef bpyunits_module
static PyStructSequence_Desc bpyunits_categories_desc
static PyMethodDef bpyunits_methods[]
static PyStructSequence_Field bpyunits_categories_fields[ARRAY_SIZE(bpyunits_ucategories_items)]
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)
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: str\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: str\n" " :arg str_input: The string to convert to a float value.\n" " :type str_input: str\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: str | 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 PyObject * bpyunits_to_value(PyObject *, PyObject *args, PyObject *kw)
static PyStructSequence_Desc bpyunits_systems_desc
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)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()