Blender V4.3
unit.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <algorithm> /* For `min/max`. */
10#include <cctype>
11#include <cstdio>
12#include <cstdlib>
13#include <cstring>
14
15#include "BLI_math_base.h"
16#include "BLI_string.h"
17#include "BLI_string_utf8.h"
19#include "BLI_sys_types.h"
20
21#include "DNA_scene_types.h"
22
23#include "BKE_unit.hh" /* own include */
24
25#ifdef WIN32
26# include "BLI_winstuff.h"
27#endif
28
29/* No BKE or DNA includes! */
30
31/* Keep alignment. */
32/* clang-format off */
33
34
35#define TEMP_STR_SIZE 256
36
37
38#define SEP_CHR '#'
39#define SEP_STR "#"
40
41
42#define EPS 0.001
43
44
45#define UN_SC_KM 1000.0f
46#define UN_SC_HM 100.0f
47#define UN_SC_DAM 10.0f
48#define UN_SC_M 1.0f
49#define UN_SC_DM 0.1f
50#define UN_SC_CM 0.01f
51#define UN_SC_MM 0.001f
52#define UN_SC_UM 0.000001f
53
54
55#define UN_SC_MI 1609.344f
56#define UN_SC_FUR 201.168f
57#define UN_SC_CH 20.1168f
58#define UN_SC_YD 0.9144f
59#define UN_SC_FT 0.3048f
60#define UN_SC_IN 0.0254f
61#define UN_SC_MIL 0.0000254f
62
63
64#define UN_SC_MTON 1000.0f /* Metric ton. */
65#define UN_SC_QL 100.0f
66#define UN_SC_KG 1.0f
67#define UN_SC_HG 0.1f
68#define UN_SC_DAG 0.01f
69#define UN_SC_G 0.001f
70#define UN_SC_MG 0.000001f
71
72
73#define UN_SC_ITON 907.18474f /* Imperial ton. */
74#define UN_SC_CWT 45.359237f
75#define UN_SC_ST 6.35029318f
76#define UN_SC_LB 0.45359237f
77#define UN_SC_OZ 0.028349523125f
78
79
80#define UN_SC_FAH 0.555555555555f
81
82/* clang-format on */
83
84/* Define a single unit.
85 * When changing the format, please check that the PYGETTEXT_KEYWORDS regex
86 * used to extract the unit names for translation still works
87 * in scripts/modules/bl_i18n_utils/settings.py. */
88struct bUnitDef {
89 const char *name;
91 const char *name_plural;
93 const char *name_short;
98 const char *name_alt;
99
101 const char *name_display;
103 const char *identifier;
104
105 double scalar;
107 double bias;
108 int flag;
109};
110
111enum {
121};
122
123/* Define a single unit system. */
133
134#define UNIT_COLLECTION_LENGTH(def) (ARRAY_SIZE(def) - 1)
135
136/* Clang-format wraps this define badly. */
137/* clang-format off */
138#define NULL_UNIT { \
139 /*name*/ nullptr, \
140 /*name_plural*/ nullptr, \
141 /*name_short*/ nullptr, \
142 /*name_alt*/ nullptr, \
143 /*name_display*/ nullptr, \
144 /*identifier*/ nullptr, \
145 /*scalar*/ 0.0, \
146 /*bias*/ 0.0, \
147 /*flag*/ 0, \
148 }
149/* clang-format on */
150
151/* Dummy */
153 {
154 /*name*/ "",
155 /*name_plural*/ nullptr,
156 /*name_short*/ "",
157 /*name_alt*/ nullptr,
158 /*name_display*/ nullptr,
159 /*identifier*/ nullptr,
160 /*scalar*/ 1.0,
161 /*bias*/ 0.0,
162 /*flag*/ 0,
163 },
164 NULL_UNIT,
165};
166
168 /*units*/ buDummyDef,
169 /*base_unit*/ 0,
170 /*flag*/ 0,
172};
173
174/* Lengths. */
176 {
177 /*name*/ "kilometer",
178 /*name_plural*/ "kilometers",
179 /*name_short*/ "km",
180 /*name_alt*/ nullptr,
181 /*name_display*/ "Kilometers",
182 /*identifier*/ "KILOMETERS",
183 /*scalar*/ UN_SC_KM,
184 /*bias*/ 0.0,
185 /*flag*/ B_UNIT_DEF_NONE,
186 },
187 {
188 /*name*/ "hectometer",
189 /*name_plural*/ "hectometers",
190 /*name_short*/ "hm",
191 /*name_alt*/ nullptr,
192 /*name_display*/ "100 Meters",
193 /*identifier*/ "HECTOMETERS",
194 /*scalar*/ UN_SC_HM,
195 /*bias*/ 0.0,
196 /*flag*/ B_UNIT_DEF_SUPPRESS,
197 },
198 {
199 /*name*/ "dekameter",
200 /*name_plural*/ "dekameters",
201 /*name_short*/ "dam",
202 /*name_alt*/ nullptr,
203 /*name_display*/ "10 Meters",
204 /*identifier*/ "DEKAMETERS",
205 /*scalar*/ UN_SC_DAM,
206 /*bias*/ 0.0,
207 /*flag*/ B_UNIT_DEF_SUPPRESS,
208 },
209 /* Base unit. */
210 {
211 /*name*/ "meter",
212 /*name_plural*/ "meters",
213 /*name_short*/ "m",
214 /*name_alt*/ nullptr,
215 /*name_display*/ "Meters",
216 /*identifier*/ "METERS",
217 /*scalar*/ UN_SC_M,
218 /*bias*/ 0.0,
219 /*flag*/ B_UNIT_DEF_NONE,
220 },
221 {
222 /*name*/ "decimeter",
223 /*name_plural*/ "decimeters",
224 /*name_short*/ "dm",
225 /*name_alt*/ nullptr,
226 /*name_display*/ "10 Centimeters",
227 /*identifier*/ "DECIMETERS",
228 /*scalar*/ UN_SC_DM,
229 /*bias*/ 0.0,
230 /*flag*/ B_UNIT_DEF_SUPPRESS,
231 },
232 {
233 /*name*/ "centimeter",
234 /*name_plural*/ "centimeters",
235 /*name_short*/ "cm",
236 /*name_alt*/ nullptr,
237 /*name_display*/ "Centimeters",
238 /*identifier*/ "CENTIMETERS",
239 /*scalar*/ UN_SC_CM,
240 /*bias*/ 0.0,
241 /*flag*/ B_UNIT_DEF_NONE,
242 },
243 {
244 /*name*/ "millimeter",
245 /*name_plural*/ "millimeters",
246 /*name_short*/ "mm",
247 /*name_alt*/ nullptr,
248 /*name_display*/ "Millimeters",
249 /*identifier*/ "MILLIMETERS",
250 /*scalar*/ UN_SC_MM,
251 /*bias*/ 0.0,
253 },
254 {
255 /*name*/ "micrometer",
256 /*name_plural*/ "micrometers",
257 /*name_short*/ "µm",
258 /*name_alt*/ "um",
259 /*name_display*/ "Micrometers",
260 /*identifier*/ "MICROMETERS",
261 /*scalar*/ UN_SC_UM,
262 /*bias*/ 0.0,
263 /*flag*/ B_UNIT_DEF_NONE,
264 },
265
266/* These get displayed because of float precision problems in the transform header,
267 * could work around, but for now probably people won't use these. */
268#if 0
269 {
270 /*name*/ "nanometer",
271 /*name_plural*/ "nanometers",
272 /*name_short*/ "nm",
273 /*name_alt*/ nullptr,
274 /*name_display*/ "Nanometers",
275 /*identifier*/ "NANOMETERS",
276 /*scalar*/ 0.000000001,
277 /*bias*/ 0.0,
278 /*flag*/ B_UNIT_DEF_NONE,
279 },
280 {
281 /*name*/ "picometer",
282 /*name_plural*/ "picometers",
283 /*name_short*/ "pm",
284 /*name_alt*/ nullptr,
285 /*name_display*/ "Picometers",
286 /*identifier*/ "PICOMETERS",
287 /*scalar*/ 0.000000000001,
288 /*bias*/ 0.0,
289 /*flag*/ B_UNIT_DEF_NONE,
290 },
291#endif
292 NULL_UNIT,
293};
295 /*units*/ buMetricLenDef,
296 /*base_unit*/ 3,
297 /*flag*/ 0,
299};
300
302 {
303 /*name*/ "mile",
304 /*name_plural*/ "miles",
305 /*name_short*/ "mi",
306 /*name_alt*/ nullptr,
307 /*name_display*/ "Miles",
308 /*identifier*/ "MILES",
309 /*scalar*/ UN_SC_MI,
310 /*bias*/ 0.0,
311 /*flag*/ B_UNIT_DEF_NONE,
312 },
313 {
314 /*name*/ "furlong",
315 /*name_plural*/ "furlongs",
316 /*name_short*/ "fur",
317 /*name_alt*/ nullptr,
318 /*name_display*/ "Furlongs",
319 /*identifier*/ "FURLONGS",
320 /*scalar*/ UN_SC_FUR,
321 /*bias*/ 0.0,
322 /*flag*/ B_UNIT_DEF_SUPPRESS,
323 },
324 {
325 /*name*/ "chain",
326 /*name_plural*/ "chains",
327 /*name_short*/ "ch",
328 /*name_alt*/ nullptr,
329 /*name_display*/ "Chains",
330 /*identifier*/ "CHAINS",
331 /*scalar*/ UN_SC_CH,
332 /*bias*/ 0.0,
333 /*flag*/ B_UNIT_DEF_SUPPRESS,
334 },
335 {
336 /*name*/ "yard",
337 /*name_plural*/ "yards",
338 /*name_short*/ "yd",
339 /*name_alt*/ nullptr,
340 /*name_display*/ "Yards",
341 /*identifier*/ "YARDS",
342 /*scalar*/ UN_SC_YD,
343 /*bias*/ 0.0,
344 /*flag*/ B_UNIT_DEF_SUPPRESS,
345 },
346 /* Base unit. */
347 {
348 /*name*/ "foot",
349 /*name_plural*/ "feet",
350 /*name_short*/ "'",
351 /*name_alt*/ "ft",
352 /*name_display*/ "Feet",
353 /*identifier*/ "FEET",
354 /*scalar*/ UN_SC_FT,
355 /*bias*/ 0.0,
357 },
358 {
359 /*name*/ "inch",
360 /*name_plural*/ "inches",
361 /*name_short*/ "\"",
362 /*name_alt*/ "in",
363 /*name_display*/ "Inches",
364 /*identifier*/ "INCHES",
365 /*scalar*/ UN_SC_IN,
366 /*bias*/ 0.0,
368 },
369 /* NOTE: Plural for "thou" has no 's'. */
370 {
371 /*name*/ "thou",
372 /*name_plural*/ "thou",
373 /*name_short*/ "thou",
374 /*name_alt*/ "mil",
375 /*name_display*/ "Thou",
376 /*identifier*/ "THOU",
377 /*scalar*/ UN_SC_MIL,
378 /*bias*/ 0.0,
379 /*flag*/ B_UNIT_DEF_NONE,
380 },
381 NULL_UNIT,
382};
384 /*units*/ buImperialLenDef,
385 /*base_unit*/ 4,
386 /*flag*/ 0,
388};
389
390/* Wavelengths (scene-independent, with nm as the base unit). */
392 {
393 /*name*/ "millimeter",
394 /*name_plural*/ "millimeters",
395 /*name_short*/ "mm",
396 /*name_alt*/ nullptr,
397 /*name_display*/ "Millimeters",
398 /*identifier*/ nullptr,
399 /*scalar*/ 1e6f,
400 /*bias*/ 0.0,
401 /*flag*/ B_UNIT_DEF_NONE,
402 },
403 {
404 /*name*/ "micrometer",
405 /*name_plural*/ "micrometers",
406 /*name_short*/ "µm",
407 /*name_alt*/ "um",
408 /*name_display*/ "Micrometers",
409 /*identifier*/ nullptr,
410 /*scalar*/ 1e3f,
411 /*bias*/ 0.0,
412 /*flag*/ B_UNIT_DEF_NONE,
413 },
414 /* Base unit. */
415 {
416 /*name*/ "nanometer",
417 /*name_plural*/ "nanometers",
418 /*name_short*/ "nm",
419 /*name_alt*/ nullptr,
420 /*name_display*/ "Nanometers",
421 /*identifier*/ nullptr,
422 /*scalar*/ 1.0f,
423 /*bias*/ 0.0,
424 /*flag*/ B_UNIT_DEF_NONE,
425 },
426 {
427 /*name*/ "picometer",
428 /*name_plural*/ "picometers",
429 /*name_short*/ "pm",
430 /*name_alt*/ nullptr,
431 /*name_display*/ "Picometers",
432 /*identifier*/ nullptr,
433 /*scalar*/ 1e-3f,
434 /*bias*/ 0.0,
435 /*flag*/ B_UNIT_DEF_NONE,
436 },
437 NULL_UNIT,
438};
440 /*units*/ buWavelengthLenDef,
441 /*base_unit*/ 2,
442 /*flag*/ 0,
444};
445
446/* Areas. */
448 {
449 /*name*/ "square kilometer",
450 /*name_plural*/ "square kilometers",
451 /*name_short*/ "km" BLI_STR_UTF8_SUPERSCRIPT_2,
452 /*name_alt*/ "km2",
453 /*name_display*/ "Square Kilometers",
454 /*identifier*/ nullptr,
455 /*scalar*/ UN_SC_KM *UN_SC_KM,
456 /*bias*/ 0.0,
457 /*flag*/ B_UNIT_DEF_NONE,
458 },
459 {
460 /*name*/ "square hectometer",
461 /*name_plural*/ "square hectometers",
462 /*name_short*/ "hm" BLI_STR_UTF8_SUPERSCRIPT_2,
463 /*name_alt*/ "hm2",
464 /*name_display*/ "Square Hectometers",
465 /*identifier*/ nullptr,
466 /*scalar*/ UN_SC_HM *UN_SC_HM,
467 /*bias*/ 0.0,
468 /*flag*/ B_UNIT_DEF_SUPPRESS,
469 }, /* Hectare. */
470 {
471 /*name*/ "square dekameter",
472 /*name_plural*/ "square dekameters",
473 /*name_short*/ "dam" BLI_STR_UTF8_SUPERSCRIPT_2,
474 /*name_alt*/ "dam2",
475 /*name_display*/ "Square Dekameters",
476 /*identifier*/ nullptr,
477 /*scalar*/ UN_SC_DAM *UN_SC_DAM,
478 /*bias*/ 0.0,
479 /*flag*/ B_UNIT_DEF_SUPPRESS,
480 },
481 /* Base unit. */
482 {
483 /*name*/ "square meter",
484 /*name_plural*/ "square meters",
485 /*name_short*/ "m" BLI_STR_UTF8_SUPERSCRIPT_2,
486 /*name_alt*/ "m2",
487 /*name_display*/ "Square Meters",
488 /*identifier*/ nullptr,
489 /*scalar*/ UN_SC_M *UN_SC_M,
490 /*bias*/ 0.0,
491 /*flag*/ B_UNIT_DEF_NONE,
492 },
493 {
494 /*name*/ "square decimeter",
495 /*name_plural*/ "square decimetees",
496 /*name_short*/ "dm" BLI_STR_UTF8_SUPERSCRIPT_2,
497 /*name_alt*/ "dm2",
498 /*name_display*/ "Square Decimeters",
499 /*identifier*/ nullptr,
500 /*scalar*/ UN_SC_DM *UN_SC_DM,
501 /*bias*/ 0.0,
502 /*flag*/ B_UNIT_DEF_SUPPRESS,
503 },
504 {
505 /*name*/ "square centimeter",
506 /*name_plural*/ "square centimeters",
507 /*name_short*/ "cm" BLI_STR_UTF8_SUPERSCRIPT_2,
508 /*name_alt*/ "cm2",
509 /*name_display*/ "Square Centimeters",
510 /*identifier*/ nullptr,
511 /*scalar*/ UN_SC_CM *UN_SC_CM,
512 /*bias*/ 0.0,
513 /*flag*/ B_UNIT_DEF_NONE,
514 },
515 {
516 /*name*/ "square millimeter",
517 /*name_plural*/ "square millimeters",
518 /*name_short*/ "mm" BLI_STR_UTF8_SUPERSCRIPT_2,
519 /*name_alt*/ "mm2",
520 /*name_display*/ "Square Millimeters",
521 /*identifier*/ nullptr,
522 /*scalar*/ UN_SC_MM *UN_SC_MM,
523 /*bias*/ 0.0,
525 },
526 {
527 /*name*/ "square micrometer",
528 /*name_plural*/ "square micrometers",
529 /*name_short*/ "µm" BLI_STR_UTF8_SUPERSCRIPT_2,
530 /*name_alt*/ "um2",
531 /*name_display*/ "Square Micrometers",
532 /*identifier*/ nullptr,
533 /*scalar*/ UN_SC_UM *UN_SC_UM,
534 /*bias*/ 0.0,
535 /*flag*/ B_UNIT_DEF_NONE,
536 },
537 NULL_UNIT,
538};
540 /*units*/ buMetricAreaDef,
541 /*base_unit*/ 3,
542 /*flag*/ 0,
544};
545
547 {
548 /*name*/ "square mile",
549 /*name_plural*/ "square miles",
550 /*name_short*/ "sq mi",
551 /*name_alt*/ nullptr,
552 /*name_display*/ "Square Miles",
553 /*identifier*/ nullptr,
554 /*scalar*/ UN_SC_MI *UN_SC_MI,
555 /*bias*/ 0.0,
556 /*flag*/ B_UNIT_DEF_NONE,
557 },
558 {
559 /*name*/ "square furlong",
560 /*name_plural*/ "square furlongs",
561 /*name_short*/ "sq fur",
562 /*name_alt*/ nullptr,
563 /*name_display*/ "Square Furlongs",
564 /*identifier*/ nullptr,
565 /*scalar*/ UN_SC_FUR *UN_SC_FUR,
566 /*bias*/ 0.0,
567 /*flag*/ B_UNIT_DEF_SUPPRESS,
568 },
569 {
570 /*name*/ "square chain",
571 /*name_plural*/ "square chains",
572 /*name_short*/ "sq ch",
573 /*name_alt*/ nullptr,
574 /*name_display*/ "Square Chains",
575 /*identifier*/ nullptr,
576 /*scalar*/ UN_SC_CH *UN_SC_CH,
577 /*bias*/ 0.0,
578 /*flag*/ B_UNIT_DEF_SUPPRESS,
579 },
580 {
581 /*name*/ "square yard",
582 /*name_plural*/ "square yards",
583 /*name_short*/ "sq yd",
584 /*name_alt*/ nullptr,
585 /*name_display*/ "Square Yards",
586 /*identifier*/ nullptr,
587 /*scalar*/ UN_SC_YD *UN_SC_YD,
588 /*bias*/ 0.0,
589 /*flag*/ B_UNIT_DEF_NONE,
590 },
591 /* Base unit. */
592 {
593 /*name*/ "square foot",
594 /*name_plural*/ "square feet",
595 /*name_short*/ "sq ft",
596 /*name_alt*/ nullptr,
597 /*name_display*/ "Square Feet",
598 /*identifier*/ nullptr,
599 /*scalar*/ UN_SC_FT *UN_SC_FT,
600 /*bias*/ 0.0,
601 /*flag*/ B_UNIT_DEF_NONE,
602 },
603 {
604 /*name*/ "square inch",
605 /*name_plural*/ "square inches",
606 /*name_short*/ "sq in",
607 /*name_alt*/ nullptr,
608 /*name_display*/ "Square Inches",
609 /*identifier*/ nullptr,
610 /*scalar*/ UN_SC_IN *UN_SC_IN,
611 /*bias*/ 0.0,
612 /*flag*/ B_UNIT_DEF_NONE,
613 },
614 {
615 /*name*/ "square thou",
616 /*name_plural*/ "square thou",
617 /*name_short*/ "sq mil",
618 /*name_alt*/ nullptr,
619 /*name_display*/ "Square Thou",
620 /*identifier*/ nullptr,
621 /*scalar*/ UN_SC_MIL *UN_SC_MIL,
622 /*bias*/ 0.0,
623 /*flag*/ B_UNIT_DEF_NONE,
624 },
625 NULL_UNIT,
626};
628 /*units*/ buImperialAreaDef,
629 /*base_unit*/ 4,
630 /*flag*/ 0,
632};
633
634/* Volumes. */
636 {
637 /*name*/ "cubic kilometer",
638 /*name_plural*/ "cubic kilometers",
639 /*name_short*/ "km" BLI_STR_UTF8_SUPERSCRIPT_3,
640 /*name_alt*/ "km3",
641 /*name_display*/ "Cubic Kilometers",
642 /*identifier*/ nullptr,
643 /*scalar*/ UN_SC_KM *UN_SC_KM *UN_SC_KM,
644 /*bias*/ 0.0,
645 /*flag*/ B_UNIT_DEF_NONE,
646 },
647 {
648 /*name*/ "cubic hectometer",
649 /*name_plural*/ "cubic hectometers",
650 /*name_short*/ "hm" BLI_STR_UTF8_SUPERSCRIPT_3,
651 /*name_alt*/ "hm3",
652 /*name_display*/ "Cubic Hectometers",
653 /*identifier*/ nullptr,
654 /*scalar*/ UN_SC_HM *UN_SC_HM *UN_SC_HM,
655 /*bias*/ 0.0,
656 /*flag*/ B_UNIT_DEF_SUPPRESS,
657 },
658 {
659 /*name*/ "cubic dekameter",
660 /*name_plural*/ "cubic dekameters",
661 /*name_short*/ "dam" BLI_STR_UTF8_SUPERSCRIPT_3,
662 /*name_alt*/ "dam3",
663 /*name_display*/ "Cubic Dekameters",
664 /*identifier*/ nullptr,
665 /*scalar*/ UN_SC_DAM *UN_SC_DAM *UN_SC_DAM,
666 /*bias*/ 0.0,
667 /*flag*/ B_UNIT_DEF_SUPPRESS,
668 },
669 /* Base unit. */
670 {
671 /*name*/ "cubic meter",
672 /*name_plural*/ "cubic meters",
673 /*name_short*/ "m" BLI_STR_UTF8_SUPERSCRIPT_3,
674 /*name_alt*/ "m3",
675 /*name_display*/ "Cubic Meters",
676 /*identifier*/ nullptr,
677 /*scalar*/ UN_SC_M *UN_SC_M *UN_SC_M,
678 /*bias*/ 0.0,
679 /*flag*/ B_UNIT_DEF_NONE,
680 },
681 {
682 /*name*/ "cubic decimeter",
683 /*name_plural*/ "cubic decimeters",
684 /*name_short*/ "dm" BLI_STR_UTF8_SUPERSCRIPT_3,
685 /*name_alt*/ "dm3",
686 /*name_display*/ "Cubic Decimeters",
687 /*identifier*/ nullptr,
688 /*scalar*/ UN_SC_DM *UN_SC_DM *UN_SC_DM,
689 /*bias*/ 0.0,
690 /*flag*/ B_UNIT_DEF_SUPPRESS,
691 },
692 {
693 /*name*/ "cubic centimeter",
694 /*name_plural*/ "cubic centimeters",
695 /*name_short*/ "cm" BLI_STR_UTF8_SUPERSCRIPT_3,
696 /*name_alt*/ "cm3",
697 /*name_display*/ "Cubic Centimeters",
698 /*identifier*/ nullptr,
699 /*scalar*/ UN_SC_CM *UN_SC_CM *UN_SC_CM,
700 /*bias*/ 0.0,
701 /*flag*/ B_UNIT_DEF_NONE,
702 },
703 {
704 /*name*/ "cubic millimeter",
705 /*name_plural*/ "cubic millimeters",
706 /*name_short*/ "mm" BLI_STR_UTF8_SUPERSCRIPT_3,
707 /*name_alt*/ "mm3",
708 /*name_display*/ "Cubic Millimeters",
709 /*identifier*/ nullptr,
710 /*scalar*/ UN_SC_MM *UN_SC_MM *UN_SC_MM,
711 /*bias*/ 0.0,
713 },
714 {
715 /*name*/ "cubic micrometer",
716 /*name_plural*/ "cubic micrometers",
717 /*name_short*/ "µm" BLI_STR_UTF8_SUPERSCRIPT_3,
718 /*name_alt*/ "um3",
719 /*name_display*/ "Cubic Micrometers",
720 /*identifier*/ nullptr,
721 /*scalar*/ UN_SC_UM *UN_SC_UM *UN_SC_UM,
722 /*bias*/ 0.0,
723 /*flag*/ B_UNIT_DEF_NONE,
724 },
725 NULL_UNIT,
726};
728 /*units*/ buMetricVolDef,
729 /*base_unit*/ 3,
730 /*flag*/ 0,
732};
733
735 {
736 /*name*/ "cubic mile",
737 /*name_plural*/ "cubic miles",
738 /*name_short*/ "cu mi",
739 /*name_alt*/ nullptr,
740 /*name_display*/ "Cubic Miles",
741 /*identifier*/ nullptr,
742 /*scalar*/ UN_SC_MI *UN_SC_MI *UN_SC_MI,
743 /*bias*/ 0.0,
744 /*flag*/ B_UNIT_DEF_NONE,
745 },
746 {
747 /*name*/ "cubic furlong",
748 /*name_plural*/ "cubic furlongs",
749 /*name_short*/ "cu fur",
750 /*name_alt*/ nullptr,
751 /*name_display*/ "Cubic Furlongs",
752 /*identifier*/ nullptr,
753 /*scalar*/ UN_SC_FUR *UN_SC_FUR *UN_SC_FUR,
754 /*bias*/ 0.0,
755 /*flag*/ B_UNIT_DEF_SUPPRESS,
756 },
757 {
758 /*name*/ "cubic chain",
759 /*name_plural*/ "cubic chains",
760 /*name_short*/ "cu ch",
761 /*name_alt*/ nullptr,
762 /*name_display*/ "Cubic Chains",
763 /*identifier*/ nullptr,
764 /*scalar*/ UN_SC_CH *UN_SC_CH *UN_SC_CH,
765 /*bias*/ 0.0,
766 /*flag*/ B_UNIT_DEF_SUPPRESS,
767 },
768 {
769 /*name*/ "cubic yard",
770 /*name_plural*/ "cubic yards",
771 /*name_short*/ "cu yd",
772 /*name_alt*/ nullptr,
773 /*name_display*/ "Cubic Yards",
774 /*identifier*/ nullptr,
775 /*scalar*/ UN_SC_YD *UN_SC_YD *UN_SC_YD,
776 /*bias*/ 0.0,
777 /*flag*/ B_UNIT_DEF_NONE,
778 },
779 /* Base unit. */
780 {
781 /*name*/ "cubic foot",
782 /*name_plural*/ "cubic feet",
783 /*name_short*/ "cu ft",
784 /*name_alt*/ nullptr,
785 /*name_display*/ "Cubic Feet",
786 /*identifier*/ nullptr,
787 /*scalar*/ UN_SC_FT *UN_SC_FT *UN_SC_FT,
788 /*bias*/ 0.0,
789 /*flag*/ B_UNIT_DEF_NONE,
790 },
791 {
792 /*name*/ "cubic inch",
793 /*name_plural*/ "cubic inches",
794 /*name_short*/ "cu in",
795 /*name_alt*/ nullptr,
796 /*name_display*/ "Cubic Inches",
797 /*identifier*/ nullptr,
798 /*scalar*/ UN_SC_IN *UN_SC_IN *UN_SC_IN,
799 /*bias*/ 0.0,
800 /*flag*/ B_UNIT_DEF_NONE,
801 },
802 {
803 /*name*/ "cubic thou",
804 /*name_plural*/ "cubic thou",
805 /*name_short*/ "cu mil",
806 /*name_alt*/ nullptr,
807 /*name_display*/ "Cubic Thou",
808 /*identifier*/ nullptr,
809 /*scalar*/ UN_SC_MIL *UN_SC_MIL *UN_SC_MIL,
810 /*bias*/ 0.0,
811 /*flag*/ B_UNIT_DEF_NONE,
812 },
813 NULL_UNIT,
814};
816 /*units*/ buImperialVolDef,
817 /*base_unit*/ 4,
818 /*flag*/ 0,
820};
821
822/* Mass. */
824 {
825 /*name*/ "tonne",
826 /*name_plural*/ "tonnes",
827 /*name_short*/ "t",
828 /*name_alt*/ "ton",
829 /*name_display*/ "Tonnes",
830 /*identifier*/ "TONNES",
831 /*scalar*/ UN_SC_MTON,
832 /*bias*/ 0.0,
833 /*flag*/ B_UNIT_DEF_NONE,
834 },
835 {
836 /*name*/ "quintal",
837 /*name_plural*/ "quintals",
838 /*name_short*/ "ql",
839 /*name_alt*/ "q",
840 /*name_display*/ "100 Kilograms",
841 /*identifier*/ "QUINTALS",
842 /*scalar*/ UN_SC_QL,
843 /*bias*/ 0.0,
844 /*flag*/ B_UNIT_DEF_SUPPRESS,
845 },
846 /* Base unit. */
847 {
848 /*name*/ "kilogram",
849 /*name_plural*/ "kilograms",
850 /*name_short*/ "kg",
851 /*name_alt*/ nullptr,
852 /*name_display*/ "Kilograms",
853 /*identifier*/ "KILOGRAMS",
854 /*scalar*/ UN_SC_KG,
855 /*bias*/ 0.0,
856 /*flag*/ B_UNIT_DEF_NONE,
857 },
858 {
859 /*name*/ "hectogram",
860 /*name_plural*/ "hectograms",
861 /*name_short*/ "hg",
862 /*name_alt*/ nullptr,
863 /*name_display*/ "Hectograms",
864 /*identifier*/ "HECTOGRAMS",
865 /*scalar*/ UN_SC_HG,
866 /*bias*/ 0.0,
867 /*flag*/ B_UNIT_DEF_SUPPRESS,
868 },
869 {
870 /*name*/ "dekagram",
871 /*name_plural*/ "dekagrams",
872 /*name_short*/ "dag",
873 /*name_alt*/ nullptr,
874 /*name_display*/ "10 Grams",
875 /*identifier*/ "DEKAGRAMS",
876 /*scalar*/ UN_SC_DAG,
877 /*bias*/ 0.0,
878 /*flag*/ B_UNIT_DEF_SUPPRESS,
879 },
880 {
881 /*name*/ "gram",
882 /*name_plural*/ "grams",
883 /*name_short*/ "g",
884 /*name_alt*/ nullptr,
885 /*name_display*/ "Grams",
886 /*identifier*/ "GRAMS",
887 /*scalar*/ UN_SC_G,
888 /*bias*/ 0.0,
889 /*flag*/ B_UNIT_DEF_NONE,
890 },
891 {
892 /*name*/ "milligram",
893 /*name_plural*/ "milligrams",
894 /*name_short*/ "mg",
895 /*name_alt*/ nullptr,
896 /*name_display*/ "Milligrams",
897 /*identifier*/ "MILLIGRAMS",
898 /*scalar*/ UN_SC_MG,
899 /*bias*/ 0.0,
900 /*flag*/ B_UNIT_DEF_NONE,
901 },
902 NULL_UNIT,
903};
905 /*units*/ buMetricMassDef,
906 /*base_unit*/ 2,
907 /*flag*/ 0,
909};
910
912 {
913 /*name*/ "ton",
914 /*name_plural*/ "tons",
915 /*name_short*/ "tn",
916 /*name_alt*/ nullptr,
917 /*name_display*/ "Tons",
918 /*identifier*/ "TONNES",
919 /*scalar*/ UN_SC_ITON,
920 /*bias*/ 0.0,
921 /*flag*/ B_UNIT_DEF_NONE,
922 },
923 {
924 /*name*/ "centum weight",
925 /*name_plural*/ "centum weights",
926 /*name_short*/ "cwt",
927 /*name_alt*/ nullptr,
928 /*name_display*/ "Centum weights",
929 /*identifier*/ "CENTUM_WEIGHTS",
930 /*scalar*/ UN_SC_CWT,
931 /*bias*/ 0.0,
932 /*flag*/ B_UNIT_DEF_NONE,
933 },
934 {
935 /*name*/ "stone",
936 /*name_plural*/ "stones",
937 /*name_short*/ "st",
938 /*name_alt*/ nullptr,
939 /*name_display*/ "Stones",
940 /*identifier*/ "STONES",
941 /*scalar*/ UN_SC_ST,
942 /*bias*/ 0.0,
943 /*flag*/ B_UNIT_DEF_NONE,
944 },
945 /* Base unit. */
946 {
947 /*name*/ "pound",
948 /*name_plural*/ "pounds",
949 /*name_short*/ "lb",
950 /*name_alt*/ nullptr,
951 /*name_display*/ "Pounds",
952 /*identifier*/ "POUNDS",
953 /*scalar*/ UN_SC_LB,
954 /*bias*/ 0.0,
955 /*flag*/ B_UNIT_DEF_NONE,
956 },
957 {
958 /*name*/ "ounce",
959 /*name_plural*/ "ounces",
960 /*name_short*/ "oz",
961 /*name_alt*/ nullptr,
962 /*name_display*/ "Ounces",
963 /*identifier*/ "OUNCES",
964 /*scalar*/ UN_SC_OZ,
965 /*bias*/ 0.0,
966 /*flag*/ B_UNIT_DEF_NONE,
967 },
968 NULL_UNIT,
969};
971 /*units*/ buImperialMassDef,
972 /*base_unit*/ 3,
973 /*flag*/ 0,
975};
976
977/* Even if user scales the system to a point where km^3 is used, velocity and
978 * acceleration aren't scaled: that's why we have so few units for them. */
979
980/* Velocity. */
982 /* Base unit. */
983 {
984 /*name*/ "meter per second",
985 /*name_plural*/ "meters per second",
986 /*name_short*/ "m/s",
987 /*name_alt*/ nullptr,
988 /*name_display*/ "Meters per second",
989 /*identifier*/ nullptr,
990 /*scalar*/ UN_SC_M,
991 /*bias*/ 0.0,
992 /*flag*/ B_UNIT_DEF_NONE,
993 },
994 {
995 /*name*/ "kilometer per hour",
996 /*name_plural*/ "kilometers per hour",
997 /*name_short*/ "km/h",
998 /*name_alt*/ "kph",
999 /*name_display*/ "Kilometers per hour",
1000 /*identifier*/ nullptr,
1001 /*scalar*/ UN_SC_KM / 3600.0f,
1002 /*bias*/ 0.0,
1003 /*flag*/ B_UNIT_DEF_SUPPRESS,
1004 },
1005 NULL_UNIT,
1006};
1008 /*units*/ buMetricVelDef,
1009 /*base_unit*/ 0,
1010 /*flag*/ 0,
1012};
1013
1015 /* Base unit. */
1016 {
1017 /*name*/ "foot per second",
1018 /*name_plural*/ "feet per second",
1019 /*name_short*/ "ft/s",
1020 /*name_alt*/ "fps",
1021 /*name_display*/ "Feet per second",
1022 /*identifier*/ nullptr,
1023 /*scalar*/ UN_SC_FT,
1024 /*bias*/ 0.0,
1025 /*flag*/ B_UNIT_DEF_NONE,
1026 },
1027 {
1028 /*name*/ "mile per hour",
1029 /*name_plural*/ "miles per hour",
1030 /*name_short*/ "mph",
1031 /*name_alt*/ nullptr,
1032 /*name_display*/ "Miles per hour",
1033 /*identifier*/ nullptr,
1034 /*scalar*/ UN_SC_MI / 3600.0f,
1035 /*bias*/ 0.0,
1036 /*flag*/ B_UNIT_DEF_SUPPRESS,
1037 },
1038 NULL_UNIT,
1039};
1041 /*units*/ buImperialVelDef,
1042 /*base_unit*/ 0,
1043 /*flag*/ 0,
1045};
1046
1047/* Acceleration. */
1049 /* Base unit. */
1050 {
1051 /*name*/ "meter per second squared",
1052 /*name_plural*/ "meters per second squared",
1053 /*name_short*/ "m/s" BLI_STR_UTF8_SUPERSCRIPT_2,
1054 /*name_alt*/ "m/s2",
1055 /*name_display*/ "Meters per second squared",
1056 /*identifier*/ nullptr,
1057 /*scalar*/ UN_SC_M,
1058 /*bias*/ 0.0,
1059 /*flag*/ B_UNIT_DEF_NONE,
1060 },
1061 NULL_UNIT,
1062};
1064 /*units*/ buMetricAclDef,
1065 /*base_unit*/ 0,
1066 /*flag*/ 0,
1068};
1069
1071 /* Base unit. */
1072 {
1073 /*name*/ "foot per second squared",
1074 /*name_plural*/ "feet per second squared",
1075 /*name_short*/ "ft/s" BLI_STR_UTF8_SUPERSCRIPT_2,
1076 /*name_alt*/ "ft/s2",
1077 /*name_display*/ "Feet per second squared",
1078 /*identifier*/ nullptr,
1079 /*scalar*/ UN_SC_FT,
1080 /*bias*/ 0.0,
1081 /*flag*/ B_UNIT_DEF_NONE,
1082 },
1083 NULL_UNIT,
1084};
1086 /*units*/ buImperialAclDef,
1087 /*base_unit*/ 0,
1088 /*flag*/ 0,
1090};
1091
1092/* Time. */
1094 /* Weeks? - probably not needed for Blender. */
1095 {
1096 /*name*/ "day",
1097 /*name_plural*/ "days",
1098 /*name_short*/ "d",
1099 /*name_alt*/ nullptr,
1100 /*name_display*/ "Days",
1101 /*identifier*/ "DAYS",
1102 /*scalar*/ 86400.0,
1103 /*bias*/ 0.0,
1104 /*flag*/ B_UNIT_DEF_NONE,
1105 },
1106 {
1107 /*name*/ "hour",
1108 /*name_plural*/ "hours",
1109 /*name_short*/ "h",
1110 /*name_alt*/ "hr",
1111 /*name_display*/ "Hours",
1112 /*identifier*/ "HOURS",
1113 /*scalar*/ 3600.0,
1114 /*bias*/ 0.0,
1115 /*flag*/ B_UNIT_DEF_NONE,
1116 },
1117 {
1118 /*name*/ "minute",
1119 /*name_plural*/ "minutes",
1120 /*name_short*/ "min",
1121 /*name_alt*/ "m",
1122 /*name_display*/ "Minutes",
1123 /*identifier*/ "MINUTES",
1124 /*scalar*/ 60.0,
1125 /*bias*/ 0.0,
1126 /*flag*/ B_UNIT_DEF_NONE,
1127 },
1128 /* Base unit. */
1129 {
1130 /*name*/ "second",
1131 /*name_plural*/ "seconds",
1132 /*name_short*/ "s",
1133 /*name_alt*/ "sec",
1134 /*name_display*/ "Seconds",
1135 /*identifier*/ "SECONDS",
1136 /*scalar*/ 1.0,
1137 /*bias*/ 0.0,
1138 /*flag*/ B_UNIT_DEF_NONE,
1139 },
1140 {
1141 /*name*/ "millisecond",
1142 /*name_plural*/ "milliseconds",
1143 /*name_short*/ "ms",
1144 /*name_alt*/ nullptr,
1145 /*name_display*/ "Milliseconds",
1146 /*identifier*/ "MILLISECONDS",
1147 /*scalar*/ 0.001,
1148 /*bias*/ 0.0,
1149 /*flag*/ B_UNIT_DEF_NONE,
1150 },
1151 {
1152 /*name*/ "microsecond",
1153 /*name_plural*/ "microseconds",
1154 /*name_short*/ "µs",
1155 /*name_alt*/ "us",
1156 /*name_display*/ "Microseconds",
1157 /*identifier*/ "MICROSECONDS",
1158 /*scalar*/ 0.000001,
1159 /*bias*/ 0.0,
1160 /*flag*/ B_UNIT_DEF_NONE,
1161 },
1162 NULL_UNIT,
1163};
1165 /*units*/ buNaturalTimeDef,
1166 /*base_unit*/ 3,
1167 /*flag*/ 0,
1169};
1170
1172 {
1173 /*name*/ "degree",
1174 /*name_plural*/ "degrees",
1175 /*name_short*/ BLI_STR_UTF8_DEGREE_SIGN,
1176 /*name_alt*/ "d",
1177 /*name_display*/ "Degrees",
1178 /*identifier*/ "DEGREES",
1179 /*scalar*/ M_PI / 180.0,
1180 /*bias*/ 0.0,
1182 },
1183 /* `arcminutes` / `arcseconds` are used in Astronomy/Navigation areas. */
1184 {
1185 /*name*/ "arcminute",
1186 /*name_plural*/ "arcminutes",
1187 /*name_short*/ "'",
1188 /*name_alt*/ "amin",
1189 /*name_display*/ "Arcminutes",
1190 /*identifier*/ "ARCMINUTES",
1191 /*scalar*/ (M_PI / 180.0) / 60.0,
1192 /*bias*/ 0.0,
1194 },
1195 {
1196 /*name*/ "arcsecond",
1197 /*name_plural*/ "arcseconds",
1198 /*name_short*/ "\"",
1199 /*name_alt*/ "asec",
1200 /*name_display*/ "Arcseconds",
1201 /*identifier*/ "ARCSECONDS",
1202 /*scalar*/ (M_PI / 180.0) / 3600.0,
1203 /*bias*/ 0.0,
1205 },
1206 {
1207 /*name*/ "radian",
1208 /*name_plural*/ "radians",
1209 /*name_short*/ "rad",
1210 /*name_alt*/ "r",
1211 /*name_display*/ "Radians",
1212 /*identifier*/ "RADIANS",
1213 /*scalar*/ 1.0,
1214 /*bias*/ 0.0,
1215 /*flag*/ B_UNIT_DEF_NONE,
1216 },
1217#if 0
1218 {
1219 /*name*/ "turn",
1220 /*name_plural*/ "turns",
1221 /*name_short*/ "t",
1222 /*name_alt*/ nullptr,
1223 /*name_display*/ "Turns",
1224 /*identifier*/ nullptr,
1225 /*scalar*/ 1.0 / (M_PI * 2.0),
1226 /*bias*/ 0.0,
1227 /*flag*/ B_UNIT_DEF_NONE,
1228 },
1229#endif
1230 NULL_UNIT,
1231};
1233 /*units*/ buNaturalRotDef,
1234 /*base_unit*/ 0,
1235 /*flag*/ 0,
1237};
1238
1239/* Camera Lengths. */
1241 /* Base unit. */
1242 {
1243 /*name*/ "meter",
1244 /*name_plural*/ "meters",
1245 /*name_short*/ "m",
1246 /*name_alt*/ nullptr,
1247 /*name_display*/ "Meters",
1248 /*identifier*/ nullptr,
1249 /*scalar*/ UN_SC_KM,
1250 /*bias*/ 0.0,
1251 /*flag*/ B_UNIT_DEF_NONE,
1252 },
1253 {
1254 /*name*/ "decimeter",
1255 /*name_plural*/ "decimeters",
1256 /*name_short*/ "dm",
1257 /*name_alt*/ nullptr,
1258 /*name_display*/ "10 Centimeters",
1259 /*identifier*/ nullptr,
1260 /*scalar*/ UN_SC_HM,
1261 /*bias*/ 0.0,
1262 /*flag*/ B_UNIT_DEF_SUPPRESS,
1263 },
1264 {
1265 /*name*/ "centimeter",
1266 /*name_plural*/ "centimeters",
1267 /*name_short*/ "cm",
1268 /*name_alt*/ nullptr,
1269 /*name_display*/ "Centimeters",
1270 /*identifier*/ nullptr,
1271 /*scalar*/ UN_SC_DAM,
1272 /*bias*/ 0.0,
1273 /*flag*/ B_UNIT_DEF_SUPPRESS,
1274 },
1275 {
1276 /*name*/ "millimeter",
1277 /*name_plural*/ "millimeters",
1278 /*name_short*/ "mm",
1279 /*name_alt*/ nullptr,
1280 /*name_display*/ "Millimeters",
1281 /*identifier*/ nullptr,
1282 /*scalar*/ UN_SC_M,
1283 /*bias*/ 0.0,
1284 /*flag*/ B_UNIT_DEF_NONE,
1285 },
1286 {
1287 /*name*/ "micrometer",
1288 /*name_plural*/ "micrometers",
1289 /*name_short*/ "µm",
1290 /*name_alt*/ "um",
1291 /*name_display*/ "Micrometers",
1292 /*identifier*/ nullptr,
1293 /*scalar*/ UN_SC_MM,
1294 /*bias*/ 0.0,
1295 /*flag*/ B_UNIT_DEF_SUPPRESS,
1296 },
1297 NULL_UNIT,
1298};
1300 /*units*/ buCameraLenDef,
1301 /*base_unit*/ 3,
1302 /*flag*/ 0,
1304};
1305
1306/* (Light) Power. */
1308 {
1309 /*name*/ "gigawatt",
1310 /*name_plural*/ "gigawatts",
1311 /*name_short*/ "GW",
1312 /*name_alt*/ nullptr,
1313 /*name_display*/ "Gigawatts",
1314 /*identifier*/ nullptr,
1315 /*scalar*/ 1e9f,
1316 /*bias*/ 0.0,
1317 /*flag*/ B_UNIT_DEF_NONE,
1318 },
1319 {
1320 /*name*/ "megawatt",
1321 /*name_plural*/ "megawatts",
1322 /*name_short*/ "MW",
1323 /*name_alt*/ nullptr,
1324 /*name_display*/ "Megawatts",
1325 /*identifier*/ nullptr,
1326 /*scalar*/ 1e6f,
1327 /*bias*/ 0.0,
1329 },
1330 {
1331 /*name*/ "kilowatt",
1332 /*name_plural*/ "kilowatts",
1333 /*name_short*/ "kW",
1334 /*name_alt*/ nullptr,
1335 /*name_display*/ "Kilowatts",
1336 /*identifier*/ nullptr,
1337 /*scalar*/ 1e3f,
1338 /*bias*/ 0.0,
1339 /*flag*/ B_UNIT_DEF_SUPPRESS,
1340 },
1341 /* Base unit. */
1342 {
1343 /*name*/ "watt",
1344 /*name_plural*/ "watts",
1345 /*name_short*/ "W",
1346 /*name_alt*/ nullptr,
1347 /*name_display*/ "Watts",
1348 /*identifier*/ nullptr,
1349 /*scalar*/ 1.0f,
1350 /*bias*/ 0.0,
1351 /*flag*/ B_UNIT_DEF_NONE,
1352 },
1353 {
1354 /*name*/ "milliwatt",
1355 /*name_plural*/ "milliwatts",
1356 /*name_short*/ "mW",
1357 /*name_alt*/ nullptr,
1358 /*name_display*/ "Milliwatts",
1359 /*identifier*/ nullptr,
1360 /*scalar*/ 1e-3f,
1361 /*bias*/ 0.0,
1363 },
1364 {
1365 /*name*/ "microwatt",
1366 /*name_plural*/ "microwatts",
1367 /*name_short*/ "µW",
1368 /*name_alt*/ "uW",
1369 /*name_display*/ "Microwatts",
1370 /*identifier*/ nullptr,
1371 /*scalar*/ 1e-6f,
1372 /*bias*/ 0.0,
1373 /*flag*/ B_UNIT_DEF_NONE,
1374 },
1375 {
1376 /*name*/ "nanowatt",
1377 /*name_plural*/ "nanowatts",
1378 /*name_short*/ "nW",
1379 /*name_alt*/ nullptr,
1380 /*name_display*/ "Nanowatts",
1381 /*identifier*/ nullptr,
1382 /*scalar*/ 1e-9f,
1383 /*bias*/ 0.0,
1384 /*flag*/ B_UNIT_DEF_NONE,
1385 },
1386 NULL_UNIT,
1387};
1389 /*units*/ buPowerDef,
1390 /*base_unit*/ 3,
1391 /*flag*/ 0,
1393};
1394
1395/* Temperature */
1397 {
1398 /*name*/ "kelvin",
1399 /*name_plural*/ "kelvin",
1400 /*name_short*/ "K",
1401 /*name_alt*/ nullptr,
1402 /*name_display*/ "Kelvin",
1403 /*identifier*/ "KELVIN",
1404 /*scalar*/ 1.0f,
1405 /*bias*/ 0.0,
1406 /*flag*/ B_UNIT_DEF_NONE,
1407 },
1408 /* Base unit. */
1409 {
1410 /*name*/ "celsius",
1411 /*name_plural*/ "celsius",
1412 /*name_short*/ BLI_STR_UTF8_DEGREE_SIGN "C",
1413 /*name_alt*/ "C",
1414 /*name_display*/ "Celsius",
1415 /*identifier*/ "CELSIUS",
1416 /*scalar*/ 1.0f,
1417 /*bias*/ 273.15,
1418 /*flag*/ B_UNIT_DEF_NONE,
1419 },
1420 NULL_UNIT,
1421};
1423 /*units*/ buMetricTempDef,
1424 /*base_unit*/ 0,
1425 /*flag*/ 0,
1427};
1428
1430 {
1431 /*name*/ "kelvin",
1432 /*name_plural*/ "kelvin",
1433 /*name_short*/ "K",
1434 /*name_alt*/ nullptr,
1435 /*name_display*/ "Kelvin",
1436 /*identifier*/ "KELVIN",
1437 /*scalar*/ 1.0f,
1438 /*bias*/ 0.0,
1439 /*flag*/ B_UNIT_DEF_NONE,
1440 },
1441 /* Base unit. */
1442 {
1443 /*name*/ "fahrenheit",
1444 /*name_plural*/ "fahrenheit",
1445 /*name_short*/ BLI_STR_UTF8_DEGREE_SIGN "F",
1446 /*name_alt*/ "F",
1447 /*name_display*/ "Fahrenheit",
1448 /*identifier*/ "FAHRENHEIT",
1449 /*scalar*/ UN_SC_FAH,
1450 /*bias*/ 459.67,
1451 /*flag*/ B_UNIT_DEF_NONE,
1452 },
1453 NULL_UNIT,
1454};
1456 /*units*/ buImperialTempDef,
1457 /*base_unit*/ 1,
1458 /*flag*/ 0,
1460};
1461
1462/* Color Temperature */
1464 /* Base unit. */
1465 {
1466 /*name*/ "kelvin",
1467 /*name_plural*/ "kelvin",
1468 /*name_short*/ "K",
1469 /*name_alt*/ nullptr,
1470 /*name_display*/ "Kelvin",
1471 /*identifier*/ "KELVIN",
1472 /*scalar*/ 1.0f,
1473 /*bias*/ 0.0,
1474 /*flag*/ B_UNIT_DEF_NONE,
1475 },
1476 NULL_UNIT,
1477};
1479 /*units*/ buColorTempDef,
1480 /*base_unit*/ 0,
1481 /*flag*/ 0,
1483};
1484
1485/* Frequency */
1487 /* Base unit. */
1488 {
1489 /*name*/ "hertz",
1490 /*name_plural*/ "hertz",
1491 /*name_short*/ "Hz",
1492 /*name_alt*/ nullptr,
1493 /*name_display*/ "Hertz",
1494 /*identifier*/ "HERTZ",
1495 /*scalar*/ 1.0f,
1496 /*bias*/ 0.0,
1497 /*flag*/ B_UNIT_DEF_NONE,
1498 },
1499 {
1500 /*name*/ "kilohertz",
1501 /*name_plural*/ "kilohertz",
1502 /*name_short*/ "kHz",
1503 /*name_alt*/ nullptr,
1504 /*name_display*/ "Kilohertz",
1505 /*identifier*/ "KILOHERTZ",
1506 /*scalar*/ 1e3f,
1507 /*bias*/ 0.0,
1508 /*flag*/ B_UNIT_DEF_NONE,
1509 },
1510 NULL_UNIT,
1511};
1513 /*units*/ buFrequencyDef,
1514 /*base_unit*/ 0,
1515 /*flag*/ 0,
1517};
1518
1519#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1)
1521 /* Natural. */
1522 {
1523 /*B_UNIT_NONE*/ nullptr,
1524 /*B_UNIT_LENGTH*/ nullptr,
1525 /*B_UNIT_AREA*/ nullptr,
1526 /*B_UNIT_VOLUME*/ nullptr,
1527 /*B_UNIT_MASS*/ nullptr,
1528 /*B_UNIT_ROTATION*/ &buNaturalRotCollection,
1529 /*B_UNIT_TIME*/ &buNaturalTimeCollection,
1530 /*B_UNIT_TIME_ABSOLUTE*/ &buNaturalTimeCollection,
1531 /*B_UNIT_VELOCITY*/ nullptr,
1532 /*B_UNIT_ACCELERATION*/ nullptr,
1533 /*B_UNIT_CAMERA*/ nullptr,
1534 /*B_UNIT_POWER*/ nullptr,
1535 /*B_UNIT_TEMPERATURE*/ nullptr,
1536 /*B_UNIT_WAVELENGTH*/ nullptr,
1537 /*B_UNIT_COLOR_TEMPERATURE*/ nullptr,
1538 /*B_UNIT_FREQUENCY*/ nullptr,
1539 },
1540 /* Metric. */
1541 {
1542 /*B_UNIT_NONE*/ nullptr,
1543 /*B_UNIT_LENGTH*/ &buMetricLenCollection,
1544 /*B_UNIT_AREA*/ &buMetricAreaCollection,
1545 /*B_UNIT_VOLUME*/ &buMetricVolCollection,
1546 /*B_UNIT_MASS*/ &buMetricMassCollection,
1547 /*B_UNIT_ROTATION*/ &buNaturalRotCollection,
1548 /*B_UNIT_TIME*/ &buNaturalTimeCollection,
1549 /*B_UNIT_TIME_ABSOLUTE*/ &buNaturalTimeCollection,
1550 /*B_UNIT_VELOCITY*/ &buMetricVelCollection,
1551 /*B_UNIT_ACCELERATION*/ &buMetricAclCollection,
1552 /*B_UNIT_CAMERA*/ &buCameraLenCollection,
1553 /*B_UNIT_POWER*/ &buPowerCollection,
1554 /*B_UNIT_TEMPERATURE*/ &buMetricTempCollection,
1555 /*B_UNIT_WAVELENGTH*/ &buWavelengthLenCollection,
1556 /*B_UNIT_COLOR_TEMPERATURE*/ &buColorTempCollection,
1557 /*B_UNIT_FREQUENCY*/ &buFrequencyCollection,
1558 },
1559 /* Imperial. */
1560 {
1561 /*B_UNIT_NONE*/ nullptr,
1562 /*B_UNIT_LENGTH*/ &buImperialLenCollection,
1563 /*B_UNIT_AREA*/ &buImperialAreaCollection,
1564 /*B_UNIT_VOLUME*/ &buImperialVolCollection,
1565 /*B_UNIT_MASS*/ &buImperialMassCollection,
1566 /*B_UNIT_ROTATION*/ &buNaturalRotCollection,
1567 /*B_UNIT_TIME*/ &buNaturalTimeCollection,
1568 /*B_UNIT_TIME_ABSOLUTE*/ &buNaturalTimeCollection,
1569 /*B_UNIT_VELOCITY*/ &buImperialVelCollection,
1570 /*B_UNIT_ACCELERATION*/ &buImperialAclCollection,
1571 /*B_UNIT_CAMERA*/ &buCameraLenCollection,
1572 /*B_UNIT_POWER*/ &buPowerCollection,
1573 /*B_UNIT_TEMPERATURE*/ &buImperialTempCollection,
1574 /*B_UNIT_WAVELENGTH*/ &buWavelengthLenCollection,
1575 /*B_UNIT_COLOR_TEMPERATURE*/ &buColorTempCollection,
1576 /*B_UNIT_FREQUENCY*/ &buFrequencyCollection,
1577 },
1578 {nullptr},
1579};
1580
1581static const bUnitCollection *unit_get_system(int system, int type)
1582{
1583 BLI_assert((system > -1) && (system < UNIT_SYSTEM_TOT) && (type > -1) &&
1584 (type < B_UNIT_TYPE_TOT));
1585 return bUnitSystems[system][type]; /* Select system to use: metric/imperial/other? */
1586}
1587
1588static const bUnitDef *unit_default(const bUnitCollection *usys)
1589{
1590 return &usys->units[usys->base_unit];
1591}
1592
1593static const bUnitDef *unit_best_fit(double value,
1594 const bUnitCollection *usys,
1595 const bUnitDef *unit_start,
1596 int suppress)
1597{
1598 double value_abs = value > 0.0 ? value : -value;
1599
1600 for (const bUnitDef *unit = unit_start ? unit_start : usys->units; unit->name; unit++) {
1601
1602 if (suppress && (unit->flag & B_UNIT_DEF_SUPPRESS)) {
1603 continue;
1604 }
1605
1606 /* Scale down scalar so 1cm doesn't convert to 10mm because of float error. */
1607 if (UNLIKELY(unit->flag & B_UNIT_DEF_TENTH)) {
1608 if (value_abs >= unit->scalar * (0.1 - EPS)) {
1609 return unit;
1610 }
1611 }
1612 else {
1613 if (value_abs >= unit->scalar * (1.0 - EPS)) {
1614 return unit;
1615 }
1616 }
1617 }
1618
1619 return unit_default(usys);
1620}
1621
1622/* Convert into 2 units and 2 values for "2ft, 3inch" syntax. */
1623static void unit_dual_convert(double value,
1624 const bUnitCollection *usys,
1625 bUnitDef const **r_unit_a,
1626 bUnitDef const **r_unit_b,
1627 double *r_value_a,
1628 double *r_value_b,
1629 const bUnitDef *main_unit)
1630{
1631 const bUnitDef *unit = (main_unit) ? main_unit : unit_best_fit(value, usys, nullptr, 1);
1632
1633 const double scaled_value = value / unit->scalar;
1634 *r_value_a = (value < 0.0 ? ceil(scaled_value) : floor(scaled_value)) * unit->scalar;
1635 *r_value_b = value - (*r_value_a);
1636
1637 *r_unit_a = unit;
1638 *r_unit_b = unit_best_fit(*r_value_b, usys, *r_unit_a, 1);
1639}
1640
1641static size_t unit_as_string(char *str,
1642 int str_maxncpy,
1643 double value,
1644 int prec,
1645 const bUnitCollection *usys,
1646 /* Non exposed options. */
1647 const bUnitDef *unit,
1648 char pad)
1649{
1650 if (unit == nullptr) {
1651 if (value == 0.0) {
1652 /* Use the default units since there is no way to convert. */
1653 unit = unit_default(usys);
1654 }
1655 else {
1656 unit = unit_best_fit(value, usys, nullptr, 1);
1657 }
1658 }
1659
1660 double value_conv = (value / unit->scalar) - unit->bias;
1661 bool strip_skip = false;
1662
1663 /* Negative precision is used to disable stripping of zeroes.
1664 * This reduces text jumping when changing values. */
1665 if (prec < 0) {
1666 strip_skip = true;
1667 prec *= -1;
1668 }
1669
1670 /* Adjust precision to expected number of significant digits.
1671 * Note that here, we shall not have to worry about very big/small numbers, units are expected
1672 * to replace 'scientific notation' in those cases. */
1673 prec -= integer_digits_d(value_conv);
1674
1675 CLAMP(prec, 0, 6);
1676
1677 /* Convert to a string. */
1678 size_t len = BLI_snprintf_rlen(str, str_maxncpy, "%.*f", prec, value_conv);
1679
1680 /* Add unit prefix and strip zeros. */
1681
1682 /* Replace trailing zero's with spaces so the number
1683 * is less complicated but alignment in a button won't
1684 * jump about while dragging. */
1685 size_t i = len - 1;
1686
1687 if (prec > 0) {
1688 if (!strip_skip) {
1689 while (i > 0 && str[i] == '0') { /* 4.300 -> 4.3 */
1690 str[i--] = pad;
1691 }
1692
1693 if (i > 0 && str[i] == '.') { /* 10. -> 10 */
1694 str[i--] = pad;
1695 }
1696 }
1697 }
1698
1699 /* Now add a space for all units except foot, inch, degree, arcminute, arcsecond. */
1700 if (!(unit->flag & B_UNIT_DEF_NO_SPACE)) {
1701 str[++i] = ' ';
1702 }
1703
1704 /* Now add the suffix. */
1705 if (i < str_maxncpy) {
1706 int j = 0;
1707 i++;
1708 while (unit->name_short[j] && (i < str_maxncpy)) {
1709 str[i++] = unit->name_short[j++];
1710 }
1711 }
1712
1713 /* Terminate no matter what's done with padding above. */
1714 if (i >= str_maxncpy) {
1715 i = str_maxncpy - 1;
1716 }
1717
1718 str[i] = '\0';
1719 return i;
1720}
1721
1722static bool unit_should_be_split(int type)
1723{
1725}
1726
1730 /* USER_UNIT_ADAPTIVE means none, otherwise the value is the index in the collection. */
1732 int mass;
1733 int time;
1735};
1736
1738{
1739 PreferredUnits units = {0};
1740 units.system = settings->system;
1741 units.rotation = settings->system_rotation;
1742 units.length = settings->length_unit;
1743 units.mass = settings->mass_unit;
1744 units.time = settings->time_unit;
1745 units.temperature = settings->temperature_unit;
1746 return units;
1747}
1748
1749static size_t unit_as_string_split_pair(char *str,
1750 int str_maxncpy,
1751 double value,
1752 int prec,
1753 const bUnitCollection *usys,
1754 const bUnitDef *main_unit)
1755{
1756 const bUnitDef *unit_a, *unit_b;
1757 double value_a, value_b;
1758 unit_dual_convert(value, usys, &unit_a, &unit_b, &value_a, &value_b, main_unit);
1759
1760 /* Check the 2 is a smaller unit. */
1761 if (unit_b > unit_a) {
1762 size_t i = unit_as_string(str, str_maxncpy, value_a, prec, usys, unit_a, '\0');
1763
1764 prec -= integer_digits_d(value_a / unit_b->scalar) -
1765 integer_digits_d(value_b / unit_b->scalar);
1766 prec = max_ii(prec, 0);
1767
1768 /* Is there enough space for at least 1 char of the next unit? */
1769 if (i + 2 < str_maxncpy) {
1770 str[i++] = ' ';
1771
1772 /* Use low precision since this is a smaller unit. */
1773 i += unit_as_string(str + i, str_maxncpy - i, value_b, prec, usys, unit_b, '\0');
1774 }
1775 return i;
1776 }
1777
1778 return -1;
1779}
1780
1782{
1783 return usys != nullptr && usys->units[0].name != nullptr;
1784}
1785
1787{
1788 const bUnitCollection *usys = unit_get_system(units.system, type);
1789 if (!is_valid_unit_collection(usys)) {
1790 return nullptr;
1791 }
1792
1793 int max_offset = usys->length - 1;
1794
1795 switch (type) {
1796 case B_UNIT_LENGTH:
1797 case B_UNIT_AREA:
1798 case B_UNIT_VOLUME:
1799 if (units.length == USER_UNIT_ADAPTIVE) {
1800 return nullptr;
1801 }
1802 return usys->units + std::min(units.length, max_offset);
1803 case B_UNIT_MASS:
1804 if (units.mass == USER_UNIT_ADAPTIVE) {
1805 return nullptr;
1806 }
1807 return usys->units + std::min(units.mass, max_offset);
1808 case B_UNIT_TIME:
1809 if (units.time == USER_UNIT_ADAPTIVE) {
1810 return nullptr;
1811 }
1812 return usys->units + std::min(units.time, max_offset);
1813 case B_UNIT_ROTATION:
1814 if (units.rotation == 0) {
1815 return usys->units + 0;
1816 }
1817 else if (units.rotation == USER_UNIT_ROT_RADIANS) {
1818 return usys->units + 3;
1819 }
1820 break;
1821 case B_UNIT_TEMPERATURE:
1822 if (units.temperature == USER_UNIT_ADAPTIVE) {
1823 return nullptr;
1824 }
1825 return usys->units + std::min(units.temperature, max_offset);
1826 default:
1827 break;
1828 }
1829 return nullptr;
1830}
1831
1832/* Return the length of the generated string. */
1833static size_t unit_as_string_main(char *str,
1834 int str_maxncpy,
1835 double value,
1836 int prec,
1837 int type,
1838 bool split,
1839 bool pad,
1840 const PreferredUnits &units)
1841{
1842 const bUnitCollection *usys = unit_get_system(units.system, type);
1843 const bUnitDef *main_unit = nullptr;
1844
1845 if (!is_valid_unit_collection(usys)) {
1846 usys = &buDummyCollection;
1847 }
1848 else {
1849 main_unit = get_preferred_display_unit_if_used(type, units);
1850 }
1851
1852 if (split && unit_should_be_split(type)) {
1853 int length = unit_as_string_split_pair(str, str_maxncpy, value, prec, usys, main_unit);
1854 /* Failed when length is negative, fallback to no split. */
1855 if (length >= 0) {
1856 return length;
1857 }
1858 }
1859
1860 return unit_as_string(str, str_maxncpy, value, prec, usys, main_unit, pad ? ' ' : '\0');
1861}
1862
1864 char *str, int str_maxncpy, double value, int prec, int system, int type, bool split, bool pad)
1865{
1866 PreferredUnits units;
1867 units.system = system;
1868 units.rotation = 0;
1869 units.length = USER_UNIT_ADAPTIVE;
1870 units.mass = USER_UNIT_ADAPTIVE;
1871 units.time = USER_UNIT_ADAPTIVE;
1872 units.temperature = USER_UNIT_ADAPTIVE;
1873 return unit_as_string_main(str, str_maxncpy, value, prec, type, split, pad, units);
1874}
1875
1877 int str_maxncpy,
1878 double value,
1879 int prec,
1880 int type,
1881 const UnitSettings *settings,
1882 bool pad)
1883{
1884 bool do_split = (settings->flag & USER_UNIT_OPT_SPLIT) != 0;
1886 return unit_as_string_main(str, str_maxncpy, value, prec, type, do_split, pad, units);
1887}
1888
1889BLI_INLINE bool isalpha_or_utf8(const int ch)
1890{
1891 return (ch >= 128 || isalpha(ch));
1892}
1893
1894static const char *unit_find_str(const char *str, const char *substr, bool case_sensitive)
1895{
1896 if (substr == nullptr || substr[0] == '\0') {
1897 return nullptr;
1898 }
1899
1900 while (true) {
1901 /* Unit detection is case insensitive. */
1902 const char *str_found;
1903 if (case_sensitive) {
1904 str_found = strstr(str, substr);
1905 }
1906 else {
1907 str_found = BLI_strcasestr(str, substr);
1908 }
1909
1910 if (str_found) {
1911 /* Previous char cannot be a letter. */
1912 if (str_found == str ||
1913 /* Weak unicode support!, so "µm" won't match up be replaced by "m"
1914 * since non ascii utf8 values will NEVER return true */
1916 {
1917 /* Next char cannot be alpha-numeric. */
1918 int len_name = strlen(substr);
1919
1920 if (!isalpha_or_utf8(*(str_found + len_name))) {
1921 return str_found;
1922 }
1923 }
1924 /* If str_found is not a valid unit, we have to check further in the string... */
1925 for (str_found++; isalpha_or_utf8(*str_found); str_found++) {
1926 /* Pass. */
1927 }
1928 str = str_found;
1929 }
1930 else {
1931 break;
1932 }
1933 }
1934
1935 return nullptr;
1936}
1937
1938/* Note that numbers are added within brackets.
1939 * ") " - is used to detect numbers we added so we can detect if commas need to be added.
1940 *
1941 * "1m1cm+2mm" - Original value.
1942 * "1*1#1*0.01#+2*0.001#" - Replace numbers.
1943 * "1*1+1*0.01 +2*0.001 " - Add plus signs if ( + - * / | & ~ < > ^ ! = % ) not found in between.
1944 */
1945
1946/* Not too strict, (+ - * /) are most common. */
1947static bool ch_is_op(char op)
1948{
1949 switch (op) {
1950 case '+':
1951 case '-':
1952 case '*':
1953 case '/':
1954 case '|':
1955 case '&':
1956 case '~':
1957 case '<':
1958 case '>':
1959 case '^':
1960 case '!':
1961 case '=':
1962 case '%':
1963 return true;
1964 default:
1965 return false;
1966 }
1967}
1968
1969static bool ch_is_op_unary(char op)
1970{
1971 switch (op) {
1972 case '+':
1973 case '-':
1974 case '~':
1975 return true;
1976 default:
1977 return false;
1978 }
1979}
1980
1987static const char *find_next_negative(const char *str, const char *remaining_str)
1988{
1989 const char *str_found = strstr(remaining_str, "-");
1990
1991 if (str_found == nullptr) {
1992 return nullptr;
1993 }
1994
1995 /* Don't use the "-" from scientific notation, but make sure we can look backwards first. */
1996 if ((str_found != str) && ELEM(*(str_found - 1), 'e', 'E')) {
1997 return find_next_negative(str, str_found + 1);
1998 }
1999
2000 if (*(str_found + 1) == ' ') {
2001 str_found++;
2002 }
2003
2004 return str_found + 1;
2005}
2006
2013static char *find_next_op(const char *str, char *remaining_str, int remaining_str_maxncpy)
2014{
2015 int i;
2016 for (i = 0; i < remaining_str_maxncpy; i++) {
2017 if (remaining_str[i] == '\0') {
2018 return remaining_str + i;
2019 }
2020
2021 if (ch_is_op(remaining_str[i])) {
2022 /* Make sure we don't look backwards before the start of the string. */
2023 if (remaining_str != str && i != 0) {
2024 /* Check for velocity or acceleration (e.g. '/' in 'ft/s' is not an op). */
2025 if ((remaining_str[i] == '/') && ELEM(remaining_str[i - 1], 't', 'T', 'm', 'M') &&
2026 ELEM(remaining_str[i + 1], 's', 'S'))
2027 {
2028 continue;
2029 }
2030
2031 /* Check for scientific notation. */
2032 if (ELEM(remaining_str[i - 1], 'e', 'E')) {
2033 continue;
2034 }
2035
2036 /* Return position before a space character. */
2037 if (remaining_str[i - 1] == ' ') {
2038 i--;
2039 }
2040 }
2041
2042 return remaining_str + i;
2043 }
2044 }
2045 BLI_assert_msg(0, "String should be nullptr terminated");
2046 return remaining_str + i;
2047}
2048
2053static char *skip_unary_op(char *str)
2054{
2055 while (*str == ' ' || ch_is_op_unary(*str)) {
2056 str++;
2057 }
2058 return str;
2059}
2060
2067static bool unit_distribute_negatives(char *str, const int str_maxncpy)
2068{
2069 bool changed = false;
2070
2071 char *remaining_str = str;
2072 while ((remaining_str = const_cast<char *>(find_next_negative(str, remaining_str))) != nullptr) {
2073 int remaining_str_maxncpy;
2074 /* Exit early in the unlikely situation that we've run out of length to add the parentheses. */
2075 remaining_str_maxncpy = str_maxncpy - int(remaining_str - str);
2076 if (remaining_str_maxncpy <= 2) {
2077 return changed;
2078 }
2079
2080 changed = true;
2081
2082 /* Add '(', shift the following characters to the right to make space. */
2083 memmove(remaining_str + 1, remaining_str, remaining_str_maxncpy - 2);
2084 *remaining_str = '(';
2085
2086 /* Add the ')' before the next operation or at the end.
2087 * Unary operators are skipped to allow `--` to be a supported prefix. */
2088 remaining_str = find_next_op(str, skip_unary_op(remaining_str + 1), remaining_str_maxncpy);
2089 remaining_str_maxncpy = str_maxncpy - int(remaining_str - str);
2090 memmove(remaining_str + 1, remaining_str, remaining_str_maxncpy - 2);
2091 *remaining_str = ')';
2092
2093 /* Only move forward by 1 even though we added two characters. Minus signs need to be able to
2094 * apply to the next block of values too. */
2095 remaining_str += 1;
2096 }
2097
2098 return changed;
2099}
2100
2105static int find_previous_non_value_char(const char *str, const int start_ofs)
2106{
2107 for (int i = start_ofs; i > 0; i--) {
2108 if (ch_is_op(str[i - 1]) || strchr("( )", str[i - 1])) {
2109 return i;
2110 }
2111 }
2112 return 0;
2113}
2114
2119static int find_end_of_value_chars(const char *str, const int str_maxncpy, const int start_ofs)
2120{
2121 int i;
2122 for (i = start_ofs; i < str_maxncpy; i++) {
2123 if (!strchr("0123456789eE.", str[i])) {
2124 return i;
2125 }
2126 }
2127 return i;
2128}
2129
2130static int unit_scale_str(char *str,
2131 int str_maxncpy,
2132 char *str_tmp,
2133 double scale_pref,
2134 const bUnitDef *unit,
2135 const char *replace_str,
2136 bool case_sensitive)
2137{
2138 if (str_maxncpy < 0) {
2139 return 0;
2140 }
2141
2142 /* XXX: investigate, does not respect str_maxncpy properly. */
2143 char *str_found = (char *)unit_find_str(str, replace_str, case_sensitive);
2144
2145 if (str_found == nullptr) {
2146 return 0;
2147 }
2148
2149 int found_ofs = int(str_found - str);
2150
2151 int len = strlen(str);
2152
2153 /* Deal with unit bias for temperature units. Order of operations is important, so we
2154 * have to add parentheses, add the bias, then multiply by the scalar like usual.
2155 *
2156 * NOTE: If these changes don't fit in the buffer properly unit evaluation has failed,
2157 * just try not to destroy anything while failing. */
2158 if (unit->bias != 0.0) {
2159 /* Add the open parenthesis. */
2160 int prev_op_ofs = find_previous_non_value_char(str, found_ofs);
2161 if (len + 1 < str_maxncpy) {
2162 memmove(str + prev_op_ofs + 1, str + prev_op_ofs, len - prev_op_ofs + 1);
2163 str[prev_op_ofs] = '(';
2164 len++;
2165 found_ofs++;
2166 str_found++;
2167 } /* If this doesn't fit, we have failed. */
2168
2169 /* Add the addition sign, the bias, and the close parenthesis after the value. */
2170 int value_end_ofs = find_end_of_value_chars(str, str_maxncpy, prev_op_ofs + 2);
2171 int len_bias_num = BLI_snprintf_rlen(str_tmp, TEMP_STR_SIZE, "+%.9g)", unit->bias);
2172 if (value_end_ofs + len_bias_num < str_maxncpy) {
2173 memmove(str + value_end_ofs + len_bias_num, str + value_end_ofs, len - value_end_ofs + 1);
2174 memcpy(str + value_end_ofs, str_tmp, len_bias_num);
2175 len += len_bias_num;
2176 found_ofs += len_bias_num;
2177 str_found += len_bias_num;
2178 } /* If this doesn't fit, we have failed. */
2179 }
2180
2181 int len_name = strlen(replace_str);
2182 int len_move = (len - (found_ofs + len_name)) + 1; /* 1+ to copy the string terminator. */
2183
2184 /* "#" Removed later */
2185 int len_num = BLI_snprintf_rlen(
2186 str_tmp, TEMP_STR_SIZE, "*%.9g" SEP_STR, unit->scalar / scale_pref);
2187
2188 if (len_num > str_maxncpy) {
2189 len_num = str_maxncpy;
2190 }
2191
2192 if (found_ofs + len_num + len_move > str_maxncpy) {
2193 /* Can't move the whole string, move just as much as will fit. */
2194 len_move -= (found_ofs + len_num + len_move) - str_maxncpy;
2195 }
2196
2197 if (len_move > 0) {
2198 /* Resize the last part of the string.
2199 * May grow or shrink the string. */
2200 memmove(str_found + len_num, str_found + len_name, len_move);
2201 }
2202
2203 if (found_ofs + len_num > str_maxncpy) {
2204 /* Not even the number will fit into the string, only copy part of it. */
2205 len_num -= (found_ofs + len_num) - str_maxncpy;
2206 }
2207
2208 if (len_num > 0) {
2209 /* It's possible none of the number could be copied in. */
2210 memcpy(str_found, str_tmp, len_num); /* Without the string terminator. */
2211 }
2212
2213 /* Since the null terminator won't be moved if the stringlen_max
2214 * was not long enough to fit everything in it. */
2215 str[str_maxncpy - 1] = '\0';
2216 return found_ofs + len_num;
2217}
2218
2219static int unit_replace(
2220 char *str, int str_maxncpy, char *str_tmp, double scale_pref, const bUnitDef *unit)
2221{
2222 const bool case_sensitive = (unit->flag & B_UNIT_DEF_CASE_SENSITIVE) != 0;
2223 int ofs = 0;
2224 ofs += unit_scale_str(
2225 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->name_short, case_sensitive);
2226 ofs += unit_scale_str(
2227 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->name_plural, false);
2228 ofs += unit_scale_str(
2229 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->name_alt, case_sensitive);
2230 ofs += unit_scale_str(
2231 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->name, false);
2232 return ofs;
2233}
2234
2235static bool unit_find(const char *str, const bUnitDef *unit)
2236{
2237 const bool case_sensitive = (unit->flag & B_UNIT_DEF_CASE_SENSITIVE) != 0;
2238 if (unit_find_str(str, unit->name_short, case_sensitive)) {
2239 return true;
2240 }
2241 if (unit_find_str(str, unit->name_plural, false)) {
2242 return true;
2243 }
2244 if (unit_find_str(str, unit->name_alt, case_sensitive)) {
2245 return true;
2246 }
2247 if (unit_find_str(str, unit->name, false)) {
2248 return true;
2249 }
2250
2251 return false;
2252}
2253
2254static const bUnitDef *unit_find_in_collection(const bUnitCollection *usys, const char *str)
2255{
2256 for (const bUnitDef *unit = usys->units; unit->name; unit++) {
2257 if (unit_find(str, unit)) {
2258 return unit;
2259 }
2260 }
2261 return nullptr;
2262}
2263
2271 const char *str,
2272 const char *str_prev)
2273{
2274 /* See which units the new value has. */
2275 const bUnitDef *unit = unit_find_in_collection(usys, str);
2276 /* Else, try to infer the default unit from the previous string. */
2277 if (str_prev && (unit == nullptr)) {
2278 /* See which units the original value had. */
2279 unit = unit_find_in_collection(usys, str_prev);
2280 }
2281 /* Else, fall back to default unit. */
2282 if (unit == nullptr) {
2283 unit = unit_default(usys);
2284 }
2285
2286 return unit;
2287}
2288
2289bool BKE_unit_string_contains_unit(const char *str, int type)
2290{
2291 for (int system = 0; system < UNIT_SYSTEM_TOT; system++) {
2292 const bUnitCollection *usys = unit_get_system(system, type);
2293 if (!is_valid_unit_collection(usys)) {
2294 continue;
2295 }
2296 if (unit_find_in_collection(usys, str)) {
2297 return true;
2298 }
2299 }
2300 return false;
2301}
2302
2303double BKE_unit_apply_preferred_unit(const UnitSettings *settings, int type, double value)
2304{
2306 const bUnitDef *unit = get_preferred_display_unit_if_used(type, units);
2307
2308 const double scalar = (unit == nullptr) ? BKE_unit_base_scalar(units.system, type) :
2309 unit->scalar;
2310 const double bias = (unit == nullptr) ? 0.0 : unit->bias; /* Base unit shouldn't have a bias. */
2311
2312 return value * scalar + bias;
2313}
2314
2316 char *str, int str_maxncpy, const char *str_prev, double scale_pref, int system, int type)
2317{
2318 const bUnitCollection *usys = unit_get_system(system, type);
2319 if (!is_valid_unit_collection(usys)) {
2320 return false;
2321 }
2322
2323 double scale_pref_base = scale_pref;
2324 char str_tmp[TEMP_STR_SIZE];
2325 bool changed = false;
2326
2327 /* Fix cases like "-1m50cm" which would evaluate to -0.5m without this. */
2328 changed |= unit_distribute_negatives(str, str_maxncpy);
2329
2330 /* Try to find a default unit from current or previous string. */
2331 const bUnitDef *default_unit = unit_detect_from_str(usys, str, str_prev);
2332
2333 /* We apply the default unit to the whole expression (default unit is now the reference
2334 * '1.0' one). */
2335 scale_pref_base *= default_unit->scalar;
2336
2337 /* Apply the default unit on the whole expression, this allows to handle nasty cases like
2338 * '2+2in'. */
2339 if (SNPRINTF(str_tmp, "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) {
2340 BLI_strncpy(str, str_tmp, str_maxncpy);
2341 }
2342 else {
2343 /* BLI_snprintf would not fit into str_tmp, can't do much in this case.
2344 * Check for this because otherwise BKE_unit_replace_string could call itself forever. */
2345 return changed;
2346 }
2347
2348 for (const bUnitDef *unit = usys->units; unit->name; unit++) {
2349 /* In case there are multiple instances. */
2350 while (unit_replace(str, str_maxncpy, str_tmp, scale_pref_base, unit)) {
2351 changed = true;
2352 }
2353 }
2354
2355 /* Try other unit systems now, so we can evaluate imperial when metric is set for eg. */
2356 /* Note that checking other systems at that point means we do not support their units as
2357 * 'default' one. In other words, when in metrics, typing '2+2in' will give 2 meters 2 inches,
2358 * not 4 inches. I do think this is the desired behavior!
2359 */
2360 for (int system_iter = 0; system_iter < UNIT_SYSTEM_TOT; system_iter++) {
2361 if (system_iter == system) {
2362 continue;
2363 }
2364 const bUnitCollection *usys_iter = unit_get_system(system_iter, type);
2365 if (usys_iter == nullptr) {
2366 continue;
2367 }
2368
2369 for (const bUnitDef *unit = usys_iter->units; unit->name; unit++) {
2370 int ofs = 0;
2371 /* In case there are multiple instances. */
2372 while ((ofs = unit_replace(str + ofs, str_maxncpy - ofs, str_tmp, scale_pref_base, unit))) {
2373 changed = true;
2374 }
2375 }
2376 }
2377
2378 /* Replace # with add sign when there is no operator between it and the next number.
2379 *
2380 * "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3"
2381 */
2382 {
2383 char *str_found = str;
2384
2385 while ((str_found = strchr(str_found, SEP_CHR))) {
2386 bool op_found = false;
2387
2388 /* Any operators after this? */
2389 for (const char *ch = str_found + 1; *ch != '\0'; ch++) {
2390 if (ELEM(*ch, ' ', '\t')) {
2391 continue;
2392 }
2393 op_found = (ch_is_op(*ch) || ELEM(*ch, ',', ')'));
2394 break;
2395 }
2396
2397 /* If found an op, comma or closing parenthesis, no need to insert a '+', else we need it. */
2398 *str_found++ = op_found ? ' ' : '+';
2399 }
2400 }
2401
2402 return changed;
2403}
2404
2405void BKE_unit_name_to_alt(char *str, int str_maxncpy, const char *orig_str, int system, int type)
2406{
2407 const bUnitCollection *usys = unit_get_system(system, type);
2408
2409 /* Find and substitute all units. */
2410 for (const bUnitDef *unit = usys->units; unit->name && (str_maxncpy > 0); unit++) {
2411 if (unit->name_alt == nullptr) {
2412 continue;
2413 }
2414 const bool case_sensitive = (unit->flag & B_UNIT_DEF_CASE_SENSITIVE) != 0;
2415 const char *found = unit_find_str(orig_str, unit->name_short, case_sensitive);
2416 if (found == nullptr) {
2417 continue;
2418 }
2419
2420 int offset = int(found - orig_str);
2421
2422 /* Copy everything before the unit. */
2423 if (offset < str_maxncpy) {
2424 memcpy(str, orig_str, offset);
2425 }
2426 else {
2427 BLI_strncpy(str, orig_str, str_maxncpy);
2428 offset = str_maxncpy;
2429 }
2430
2431 str += offset;
2432 orig_str += offset + strlen(unit->name_short);
2433 str_maxncpy -= offset;
2434
2435 /* Print the alt_name. */
2436 const int len_name = BLI_strncpy_rlen(str, unit->name_alt, str_maxncpy);
2437 BLI_assert(len_name < str_maxncpy);
2438 str += len_name;
2439 str_maxncpy -= len_name;
2440 }
2441
2442 /* Finally copy the rest of the string. */
2443 BLI_strncpy(str, orig_str, str_maxncpy);
2444}
2445
2446double BKE_unit_closest_scalar(double value, int system, int type)
2447{
2448 const bUnitCollection *usys = unit_get_system(system, type);
2449
2450 if (usys == nullptr) {
2451 return -1;
2452 }
2453
2454 const bUnitDef *unit = unit_best_fit(value, usys, nullptr, 1);
2455 if (unit == nullptr) {
2456 return -1;
2457 }
2458
2459 return unit->scalar;
2460}
2461
2462double BKE_unit_base_scalar(int system, int type)
2463{
2464 const bUnitCollection *usys = unit_get_system(system, type);
2465 if (usys) {
2466 return unit_default(usys)->scalar;
2467 }
2468
2469 return 1.0;
2470}
2471
2472bool BKE_unit_is_valid(int system, int type)
2473{
2474 return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT);
2475}
2476
2477void BKE_unit_system_get(int system, int type, void const **r_usys_pt, int *r_len)
2478{
2479 const bUnitCollection *usys = unit_get_system(system, type);
2480 *r_usys_pt = usys;
2481
2482 if (usys == nullptr) {
2483 *r_len = 0;
2484 return;
2485 }
2486
2487 *r_len = usys->length;
2488}
2489
2490int BKE_unit_base_get(const void *usys_pt)
2491{
2492 return ((bUnitCollection *)usys_pt)->base_unit;
2493}
2494
2495int BKE_unit_base_of_type_get(int system, int type)
2496{
2497 return unit_get_system(system, type)->base_unit;
2498}
2499
2500const char *BKE_unit_name_get(const void *usys_pt, int index)
2501{
2502 const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
2503 BLI_assert(uint(index) < uint(usys->length));
2504 return usys->units[index].name;
2505}
2506const char *BKE_unit_display_name_get(const void *usys_pt, int index)
2507{
2508 const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
2509 BLI_assert(uint(index) < uint(usys->length));
2510 return usys->units[index].name_display;
2511}
2512const char *BKE_unit_identifier_get(const void *usys_pt, int index)
2513{
2514 const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
2515 BLI_assert(uint(index) < uint(usys->length));
2516 const bUnitDef *unit = &usys->units[index];
2517 if (unit->identifier == nullptr) {
2518 BLI_assert_msg(0, "identifier for this unit is not specified yet");
2519 }
2520 return unit->identifier;
2521}
2522
2523double BKE_unit_scalar_get(const void *usys_pt, int index)
2524{
2525 const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
2526 BLI_assert(uint(index) < uint(usys->length));
2527 return usys->units[index].scalar;
2528}
2529
2530bool BKE_unit_is_suppressed(const void *usys_pt, int index)
2531{
2532 const bUnitCollection *usys = static_cast<const bUnitCollection *>(usys_pt);
2533 BLI_assert(uint(index) < uint(usys->length));
2534 return (usys->units[index].flag & B_UNIT_DEF_SUPPRESS) != 0;
2535}
@ B_UNIT_AREA
Definition BKE_unit.hh:108
@ B_UNIT_TYPE_TOT
Definition BKE_unit.hh:122
@ B_UNIT_VOLUME
Definition BKE_unit.hh:109
@ B_UNIT_LENGTH
Definition BKE_unit.hh:107
@ B_UNIT_ROTATION
Definition BKE_unit.hh:111
@ B_UNIT_TEMPERATURE
Definition BKE_unit.hh:118
@ B_UNIT_CAMERA
Definition BKE_unit.hh:116
@ B_UNIT_MASS
Definition BKE_unit.hh:110
@ B_UNIT_WAVELENGTH
Definition BKE_unit.hh:119
@ B_UNIT_TIME
Definition BKE_unit.hh:112
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_INLINE
MINLINE int integer_digits_d(double d)
MINLINE int max_ii(int a, int b)
#define M_PI
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
size_t BLI_snprintf_rlen(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char char size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
int char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
const char * BLI_str_find_prev_char_utf8(const char *p, const char *str_start) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1
#define BLI_STR_UTF8_DEGREE_SIGN
#define BLI_STR_UTF8_SUPERSCRIPT_2
#define BLI_STR_UTF8_SUPERSCRIPT_3
unsigned int uint
#define CLAMP(a, b, c)
#define UNLIKELY(x)
#define ELEM(...)
Compatibility-like things for windows.
@ USER_UNIT_ROT_RADIANS
@ USER_UNIT_OPT_SPLIT
#define USER_UNIT_ADAPTIVE
int pad[32 - sizeof(int)]
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define str(s)
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
int temperature
Definition unit.cc:1734
const bUnitDef * units
Definition unit.cc:125
const char * identifier
Definition unit.cc:103
const char * name_short
Definition unit.cc:93
const char * name_display
Definition unit.cc:101
const char * name_alt
Definition unit.cc:98
double scalar
Definition unit.cc:105
int flag
Definition unit.cc:108
const char * name
Definition unit.cc:89
const char * name_plural
Definition unit.cc:91
double bias
Definition unit.cc:107
static bUnitCollection buCameraLenCollection
Definition unit.cc:1299
static const bUnitCollection * unit_get_system(int system, int type)
Definition unit.cc:1581
static bool ch_is_op_unary(char op)
Definition unit.cc:1969
void BKE_unit_name_to_alt(char *str, int str_maxncpy, const char *orig_str, int system, int type)
Definition unit.cc:2405
static bUnitCollection buImperialVolCollection
Definition unit.cc:815
int BKE_unit_base_of_type_get(int system, int type)
Definition unit.cc:2495
static bUnitDef buImperialTempDef[]
Definition unit.cc:1429
static const bUnitCollection * bUnitSystems[][B_UNIT_TYPE_TOT]
Definition unit.cc:1520
#define UN_SC_ITON
Definition unit.cc:73
static bUnitCollection buNaturalTimeCollection
Definition unit.cc:1164
static bUnitDef buImperialAclDef[]
Definition unit.cc:1070
static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings *settings)
Definition unit.cc:1737
#define UN_SC_FUR
Definition unit.cc:56
static size_t unit_as_string(char *str, int str_maxncpy, double value, int prec, const bUnitCollection *usys, const bUnitDef *unit, char pad)
Definition unit.cc:1641
#define UN_SC_FT
Definition unit.cc:59
#define UN_SC_DAM
Definition unit.cc:47
static bUnitDef buWavelengthLenDef[]
Definition unit.cc:391
#define UN_SC_CWT
Definition unit.cc:74
#define UN_SC_DM
Definition unit.cc:49
#define UN_SC_MG
Definition unit.cc:70
bool BKE_unit_is_valid(int system, int type)
Definition unit.cc:2472
static bUnitCollection buMetricMassCollection
Definition unit.cc:904
static const bUnitDef * unit_find_in_collection(const bUnitCollection *usys, const char *str)
Definition unit.cc:2254
static bUnitCollection buDummyCollection
Definition unit.cc:167
#define UN_SC_MTON
Definition unit.cc:64
static bUnitCollection buImperialVelCollection
Definition unit.cc:1040
#define UN_SC_HG
Definition unit.cc:67
static bUnitDef buDummyDef[]
Definition unit.cc:152
#define SEP_CHR
Definition unit.cc:38
#define UN_SC_KM
Definition unit.cc:45
static void unit_dual_convert(double value, const bUnitCollection *usys, bUnitDef const **r_unit_a, bUnitDef const **r_unit_b, double *r_value_a, double *r_value_b, const bUnitDef *main_unit)
Definition unit.cc:1623
static bool is_valid_unit_collection(const bUnitCollection *usys)
Definition unit.cc:1781
const char * BKE_unit_identifier_get(const void *usys_pt, int index)
Definition unit.cc:2512
#define UN_SC_G
Definition unit.cc:69
#define UN_SC_IN
Definition unit.cc:60
static bUnitDef buCameraLenDef[]
Definition unit.cc:1240
static bUnitCollection buImperialAreaCollection
Definition unit.cc:627
#define NULL_UNIT
Definition unit.cc:138
bool BKE_unit_is_suppressed(const void *usys_pt, int index)
Definition unit.cc:2530
static bUnitCollection buNaturalRotCollection
Definition unit.cc:1232
#define UNIT_COLLECTION_LENGTH(def)
Definition unit.cc:134
static bUnitDef buImperialMassDef[]
Definition unit.cc:911
void BKE_unit_system_get(int system, int type, void const **r_usys_pt, int *r_len)
Definition unit.cc:2477
static bUnitCollection buImperialTempCollection
Definition unit.cc:1455
#define UN_SC_LB
Definition unit.cc:76
#define UN_SC_MIL
Definition unit.cc:61
static bUnitCollection buImperialAclCollection
Definition unit.cc:1085
#define TEMP_STR_SIZE
Definition unit.cc:35
static bUnitCollection buImperialMassCollection
Definition unit.cc:970
static bUnitDef buPowerDef[]
Definition unit.cc:1307
#define EPS
Definition unit.cc:42
static int unit_scale_str(char *str, int str_maxncpy, char *str_tmp, double scale_pref, const bUnitDef *unit, const char *replace_str, bool case_sensitive)
Definition unit.cc:2130
static const bUnitDef * unit_best_fit(double value, const bUnitCollection *usys, const bUnitDef *unit_start, int suppress)
Definition unit.cc:1593
static char * find_next_op(const char *str, char *remaining_str, int remaining_str_maxncpy)
Definition unit.cc:2013
static bUnitCollection buMetricAclCollection
Definition unit.cc:1063
@ B_UNIT_DEF_SUPPRESS
Definition unit.cc:114
@ B_UNIT_DEF_NO_SPACE
Definition unit.cc:120
@ B_UNIT_DEF_CASE_SENSITIVE
Definition unit.cc:118
@ B_UNIT_DEF_TENTH
Definition unit.cc:116
@ B_UNIT_DEF_NONE
Definition unit.cc:112
const char * BKE_unit_display_name_get(const void *usys_pt, int index)
Definition unit.cc:2506
static bUnitDef buFrequencyDef[]
Definition unit.cc:1486
#define UN_SC_MI
Definition unit.cc:55
static bUnitCollection buColorTempCollection
Definition unit.cc:1478
#define UN_SC_CH
Definition unit.cc:57
static bool unit_find(const char *str, const bUnitDef *unit)
Definition unit.cc:2235
const char * BKE_unit_name_get(const void *usys_pt, int index)
Definition unit.cc:2500
int BKE_unit_base_get(const void *usys_pt)
Definition unit.cc:2490
bool BKE_unit_replace_string(char *str, int str_maxncpy, const char *str_prev, double scale_pref, int system, int type)
Definition unit.cc:2315
static int unit_replace(char *str, int str_maxncpy, char *str_tmp, double scale_pref, const bUnitDef *unit)
Definition unit.cc:2219
double BKE_unit_scalar_get(const void *usys_pt, int index)
Definition unit.cc:2523
static bUnitDef buMetricMassDef[]
Definition unit.cc:823
#define UN_SC_YD
Definition unit.cc:58
static const char * find_next_negative(const char *str, const char *remaining_str)
Definition unit.cc:1987
static bool ch_is_op(char op)
Definition unit.cc:1947
static const bUnitDef * unit_detect_from_str(const bUnitCollection *usys, const char *str, const char *str_prev)
Definition unit.cc:2270
double BKE_unit_closest_scalar(double value, int system, int type)
Definition unit.cc:2446
static bUnitCollection buMetricAreaCollection
Definition unit.cc:539
#define UN_SC_ST
Definition unit.cc:75
size_t BKE_unit_value_as_string(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings *settings, bool pad)
Definition unit.cc:1876
static bUnitDef buMetricVelDef[]
Definition unit.cc:981
static const bUnitDef * unit_default(const bUnitCollection *usys)
Definition unit.cc:1588
double BKE_unit_apply_preferred_unit(const UnitSettings *settings, int type, double value)
Definition unit.cc:2303
static size_t unit_as_string_split_pair(char *str, int str_maxncpy, double value, int prec, const bUnitCollection *usys, const bUnitDef *main_unit)
Definition unit.cc:1749
#define UN_SC_QL
Definition unit.cc:65
static bUnitCollection buMetricVolCollection
Definition unit.cc:727
#define UN_SC_OZ
Definition unit.cc:77
static bool unit_distribute_negatives(char *str, const int str_maxncpy)
Definition unit.cc:2067
#define UN_SC_DAG
Definition unit.cc:68
static int find_previous_non_value_char(const char *str, const int start_ofs)
Definition unit.cc:2105
static bUnitDef buNaturalRotDef[]
Definition unit.cc:1171
static bUnitDef buImperialAreaDef[]
Definition unit.cc:546
#define UN_SC_MM
Definition unit.cc:51
static bUnitDef buImperialVelDef[]
Definition unit.cc:1014
static size_t unit_as_string_main(char *str, int str_maxncpy, double value, int prec, int type, bool split, bool pad, const PreferredUnits &units)
Definition unit.cc:1833
static const bUnitDef * get_preferred_display_unit_if_used(int type, const PreferredUnits &units)
Definition unit.cc:1786
double BKE_unit_base_scalar(int system, int type)
Definition unit.cc:2462
static bUnitDef buColorTempDef[]
Definition unit.cc:1463
static bUnitCollection buFrequencyCollection
Definition unit.cc:1512
#define UN_SC_CM
Definition unit.cc:50
static const char * unit_find_str(const char *str, const char *substr, bool case_sensitive)
Definition unit.cc:1894
static bUnitCollection buPowerCollection
Definition unit.cc:1388
bool BKE_unit_string_contains_unit(const char *str, int type)
Definition unit.cc:2289
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)
Definition unit.cc:1863
static bUnitDef buMetricAreaDef[]
Definition unit.cc:447
static bUnitDef buMetricTempDef[]
Definition unit.cc:1396
static bUnitDef buMetricAclDef[]
Definition unit.cc:1048
static bUnitCollection buImperialLenCollection
Definition unit.cc:383
static char * skip_unary_op(char *str)
Definition unit.cc:2053
static bUnitCollection buMetricTempCollection
Definition unit.cc:1422
static bUnitDef buMetricLenDef[]
Definition unit.cc:175
#define UN_SC_FAH
Definition unit.cc:80
static bUnitCollection buWavelengthLenCollection
Definition unit.cc:439
static int find_end_of_value_chars(const char *str, const int str_maxncpy, const int start_ofs)
Definition unit.cc:2119
#define UN_SC_UM
Definition unit.cc:52
#define UN_SC_KG
Definition unit.cc:66
static bUnitDef buImperialVolDef[]
Definition unit.cc:734
static bUnitDef buNaturalTimeDef[]
Definition unit.cc:1093
static bUnitDef buImperialLenDef[]
Definition unit.cc:301
static const bUnitCollection buMetricLenCollection
Definition unit.cc:294
#define UN_SC_HM
Definition unit.cc:46
static bUnitCollection buMetricVelCollection
Definition unit.cc:1007
BLI_INLINE bool isalpha_or_utf8(const int ch)
Definition unit.cc:1889
#define SEP_STR
Definition unit.cc:39
static bool unit_should_be_split(int type)
Definition unit.cc:1722
#define UN_SC_M
Definition unit.cc:48
static bUnitDef buMetricVolDef[]
Definition unit.cc:635
#define UNIT_SYSTEM_TOT
Definition unit.cc:1519