1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup RNA
19 */
20
21 #include <ctype.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "DNA_ID.h"
29 #include "DNA_constraint_types.h"
30 #include "DNA_modifier_types.h"
31 #include "DNA_scene_types.h"
32 #include "DNA_windowmanager_types.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_dynstr.h"
36 #include "BLI_ghash.h"
37 #include "BLI_math.h"
38 #include "BLI_utildefines.h"
39
40 #include "BLF_api.h"
41 #include "BLT_translation.h"
42
43 #include "BKE_anim_data.h"
44 #include "BKE_collection.h"
45 #include "BKE_context.h"
46 #include "BKE_fcurve.h"
47 #include "BKE_idprop.h"
48 #include "BKE_idtype.h"
49 #include "BKE_main.h"
50 #include "BKE_node.h"
51 #include "BKE_report.h"
52
53 #include "DEG_depsgraph.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57 #include "RNA_enum_types.h"
58
59 #include "WM_api.h"
60 #include "WM_message.h"
61
62 /* flush updates */
63 #include "DNA_object_types.h"
64 #include "WM_types.h"
65
66 #include "rna_access_internal.h"
67 #include "rna_internal.h"
68
69 const PointerRNA PointerRNA_NULL = {NULL};
70
71 /* Init/Exit */
72
RNA_init(void)73 void RNA_init(void)
74 {
75 StructRNA *srna;
76 PropertyRNA *prop;
77
78 BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
79 BLENDER_RNA.structs_len = 0;
80
81 for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
82 if (!srna->cont.prophash) {
83 srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
84
85 for (prop = srna->cont.properties.first; prop; prop = prop->next) {
86 if (!(prop->flag_internal & PROP_INTERN_BUILTIN)) {
87 BLI_ghash_insert(srna->cont.prophash, (void *)prop->identifier, prop);
88 }
89 }
90 }
91 BLI_assert(srna->flag & STRUCT_PUBLIC_NAMESPACE);
92 BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
93 BLENDER_RNA.structs_len += 1;
94 }
95 }
96
RNA_exit(void)97 void RNA_exit(void)
98 {
99 StructRNA *srna;
100
101 for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
102 if (srna->cont.prophash) {
103 BLI_ghash_free(srna->cont.prophash, NULL, NULL);
104 srna->cont.prophash = NULL;
105 }
106 }
107
108 RNA_free(&BLENDER_RNA);
109 }
110
111 /* Pointer */
112
RNA_main_pointer_create(struct Main * main,PointerRNA * r_ptr)113 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
114 {
115 r_ptr->owner_id = NULL;
116 r_ptr->type = &RNA_BlendData;
117 r_ptr->data = main;
118 }
119
RNA_id_pointer_create(ID * id,PointerRNA * r_ptr)120 void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
121 {
122 StructRNA *type, *idtype = NULL;
123
124 if (id) {
125 PointerRNA tmp = {NULL};
126 tmp.data = id;
127 idtype = rna_ID_refine(&tmp);
128
129 while (idtype->refine) {
130 type = idtype->refine(&tmp);
131
132 if (type == idtype) {
133 break;
134 }
135 idtype = type;
136 }
137 }
138
139 r_ptr->owner_id = id;
140 r_ptr->type = idtype;
141 r_ptr->data = id;
142 }
143
RNA_pointer_create(ID * id,StructRNA * type,void * data,PointerRNA * r_ptr)144 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
145 {
146 #if 0 /* UNUSED */
147 StructRNA *idtype = NULL;
148
149 if (id) {
150 PointerRNA tmp = {0};
151 tmp.data = id;
152 idtype = rna_ID_refine(&tmp);
153 }
154 #endif
155
156 r_ptr->owner_id = id;
157 r_ptr->type = type;
158 r_ptr->data = data;
159
160 if (data) {
161 while (r_ptr->type && r_ptr->type->refine) {
162 StructRNA *rtype = r_ptr->type->refine(r_ptr);
163
164 if (rtype == r_ptr->type) {
165 break;
166 }
167 r_ptr->type = rtype;
168 }
169 }
170 }
171
RNA_pointer_is_null(const PointerRNA * ptr)172 bool RNA_pointer_is_null(const PointerRNA *ptr)
173 {
174 return !((ptr->data != NULL) && (ptr->owner_id != NULL) && (ptr->type != NULL));
175 }
176
rna_pointer_inherit_id(StructRNA * type,PointerRNA * parent,PointerRNA * ptr)177 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
178 {
179 if (type && type->flag & STRUCT_ID) {
180 ptr->owner_id = ptr->data;
181 }
182 else {
183 ptr->owner_id = parent->owner_id;
184 }
185 }
186
RNA_blender_rna_pointer_create(PointerRNA * r_ptr)187 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
188 {
189 r_ptr->owner_id = NULL;
190 r_ptr->type = &RNA_BlenderRNA;
191 r_ptr->data = &BLENDER_RNA;
192 }
193
rna_pointer_inherit_refine(PointerRNA * ptr,StructRNA * type,void * data)194 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
195 {
196 if (data) {
197 PointerRNA result;
198 result.data = data;
199 result.type = type;
200 rna_pointer_inherit_id(type, ptr, &result);
201
202 while (result.type->refine) {
203 type = result.type->refine(&result);
204
205 if (type == result.type) {
206 break;
207 }
208 result.type = type;
209 }
210 return result;
211 }
212 return PointerRNA_NULL;
213 }
214
RNA_pointer_recast(PointerRNA * ptr,PointerRNA * r_ptr)215 void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
216 {
217 #if 0 /* works but this case if covered by more general code below. */
218 if (RNA_struct_is_ID(ptr->type)) {
219 /* simple case */
220 RNA_id_pointer_create(ptr->owner_id, r_ptr);
221 }
222 else
223 #endif
224 {
225 StructRNA *base;
226 PointerRNA t_ptr;
227 *r_ptr = *ptr; /* initialize as the same in case cant recast */
228
229 for (base = ptr->type->base; base; base = base->base) {
230 t_ptr = rna_pointer_inherit_refine(ptr, base, ptr->data);
231 if (t_ptr.type && t_ptr.type != ptr->type) {
232 *r_ptr = t_ptr;
233 }
234 }
235 }
236 }
237
238 /* ID Properties */
239
rna_idproperty_touch(IDProperty * idprop)240 void rna_idproperty_touch(IDProperty *idprop)
241 {
242 /* so the property is seen as 'set' by rna */
243 idprop->flag &= ~IDP_FLAG_GHOST;
244 }
245
rna_idproperty_ui_container(PropertyRNA * prop)246 static IDProperty *rna_idproperty_ui_container(PropertyRNA *prop)
247 {
248 IDProperty *idprop;
249
250 for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
251 if (STREQ(RNA_IDP_UI, idprop->name)) {
252 break;
253 }
254 }
255
256 if (idprop == NULL) {
257 for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
258 if (STREQ(RNA_IDP_UI, idprop->name)) {
259 break;
260 }
261 }
262 }
263
264 return idprop;
265 }
266
267 /* return a UI local ID prop definition for this prop */
rna_idproperty_ui(const PropertyRNA * prop)268 static const IDProperty *rna_idproperty_ui(const PropertyRNA *prop)
269 {
270 IDProperty *idprop = rna_idproperty_ui_container((PropertyRNA *)prop);
271
272 if (idprop) {
273 return IDP_GetPropertyTypeFromGroup(idprop, ((IDProperty *)prop)->name, IDP_GROUP);
274 }
275
276 return NULL;
277 }
278
279 /* return or create a UI local ID prop definition for this prop */
rna_idproperty_ui_ensure(PointerRNA * ptr,PropertyRNA * prop,bool create)280 static IDProperty *rna_idproperty_ui_ensure(PointerRNA *ptr, PropertyRNA *prop, bool create)
281 {
282 IDProperty *idprop = rna_idproperty_ui_container(prop);
283 IDPropertyTemplate dummy = {0};
284
285 if (idprop == NULL && create) {
286 IDProperty *props = RNA_struct_idprops(ptr, false);
287
288 /* Sanity check: props is the actual container of this property. */
289 if (props != NULL && BLI_findindex(&props->data.group, prop) >= 0) {
290 idprop = IDP_New(IDP_GROUP, &dummy, RNA_IDP_UI);
291
292 if (!IDP_AddToGroup(props, idprop)) {
293 IDP_FreePropertyContent(idprop);
294 return NULL;
295 }
296 }
297 }
298
299 if (idprop) {
300 const char *name = ((IDProperty *)prop)->name;
301 IDProperty *rv = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_GROUP);
302
303 if (rv == NULL && create) {
304 rv = IDP_New(IDP_GROUP, &dummy, name);
305
306 if (!IDP_AddToGroup(idprop, rv)) {
307 IDP_FreePropertyContent(rv);
308 return NULL;
309 }
310 }
311
312 return rv;
313 }
314
315 return NULL;
316 }
317
rna_idproperty_ui_set_default(PointerRNA * ptr,PropertyRNA * prop,const char type,IDPropertyTemplate * value)318 static bool rna_idproperty_ui_set_default(PointerRNA *ptr,
319 PropertyRNA *prop,
320 const char type,
321 IDPropertyTemplate *value)
322 {
323 BLI_assert(ELEM(type, IDP_INT, IDP_DOUBLE));
324
325 if (prop->magic == RNA_MAGIC) {
326 return false;
327 }
328
329 /* attempt to get the local ID values */
330 IDProperty *idp_ui = rna_idproperty_ui_ensure(ptr, prop, value != NULL);
331
332 if (idp_ui == NULL) {
333 return (value == NULL);
334 }
335
336 IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", type);
337
338 if (value == NULL) {
339 if (item != NULL) {
340 IDP_RemoveFromGroup(idp_ui, item);
341 }
342 }
343 else {
344 if (item != NULL) {
345 switch (type) {
346 case IDP_INT:
347 IDP_Int(item) = value->i;
348 break;
349 case IDP_DOUBLE:
350 IDP_Double(item) = value->d;
351 break;
352 default:
353 BLI_assert(false);
354 return false;
355 }
356 }
357 else {
358 item = IDP_New(type, value, "default");
359
360 if (!IDP_AddToGroup(idp_ui, item)) {
361 IDP_FreePropertyContent(item);
362 return false;
363 }
364 }
365 }
366
367 return true;
368 }
369
RNA_struct_idprops(PointerRNA * ptr,bool create)370 IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
371 {
372 StructRNA *type = ptr->type;
373
374 if (type && type->idproperties) {
375 return type->idproperties(ptr, create);
376 }
377
378 return NULL;
379 }
380
RNA_struct_idprops_check(StructRNA * srna)381 bool RNA_struct_idprops_check(StructRNA *srna)
382 {
383 return (srna && srna->idproperties);
384 }
385
rna_idproperty_find(PointerRNA * ptr,const char * name)386 IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
387 {
388 IDProperty *group = RNA_struct_idprops(ptr, 0);
389
390 if (group) {
391 if (group->type == IDP_GROUP) {
392 return IDP_GetPropertyFromGroup(group, name);
393 }
394 /* Not sure why that happens sometimes, with nested properties... */
395 /* Seems to be actually array prop, name is usually "0"... To be sorted out later. */
396 #if 0
397 printf(
398 "Got unexpected IDProp container when trying to retrieve %s: %d\n", name, group->type);
399 #endif
400 }
401
402 return NULL;
403 }
404
rna_idproperty_free(PointerRNA * ptr,const char * name)405 static void rna_idproperty_free(PointerRNA *ptr, const char *name)
406 {
407 IDProperty *group = RNA_struct_idprops(ptr, 0);
408
409 if (group) {
410 IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
411 if (idprop) {
412 IDP_FreeFromGroup(group, idprop);
413 }
414 }
415 }
416
rna_ensure_property_array_length(PointerRNA * ptr,PropertyRNA * prop)417 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
418 {
419 if (prop->magic == RNA_MAGIC) {
420 int arraylen[RNA_MAX_ARRAY_DIMENSION];
421 return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) : prop->totarraylength;
422 }
423 IDProperty *idprop = (IDProperty *)prop;
424
425 if (idprop->type == IDP_ARRAY) {
426 return idprop->len;
427 }
428 else {
429 return 0;
430 }
431 }
432
rna_ensure_property_array_check(PropertyRNA * prop)433 static bool rna_ensure_property_array_check(PropertyRNA *prop)
434 {
435 if (prop->magic == RNA_MAGIC) {
436 return (prop->getlength || prop->totarraylength);
437 }
438 IDProperty *idprop = (IDProperty *)prop;
439
440 return (idprop->type == IDP_ARRAY);
441 }
442
rna_ensure_property_multi_array_length(PointerRNA * ptr,PropertyRNA * prop,int length[])443 static void rna_ensure_property_multi_array_length(PointerRNA *ptr,
444 PropertyRNA *prop,
445 int length[])
446 {
447 if (prop->magic == RNA_MAGIC) {
448 if (prop->getlength) {
449 prop->getlength(ptr, length);
450 }
451 else {
452 memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
453 }
454 }
455 else {
456 IDProperty *idprop = (IDProperty *)prop;
457
458 if (idprop->type == IDP_ARRAY) {
459 length[0] = idprop->len;
460 }
461 else {
462 length[0] = 0;
463 }
464 }
465 }
466
rna_idproperty_verify_valid(PointerRNA * ptr,PropertyRNA * prop,IDProperty * idprop)467 static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
468 {
469 /* this verifies if the idproperty actually matches the property
470 * description and otherwise removes it. this is to ensure that
471 * rna property access is type safe, e.g. if you defined the rna
472 * to have a certain array length you can count on that staying so */
473
474 switch (idprop->type) {
475 case IDP_IDPARRAY:
476 if (prop->type != PROP_COLLECTION) {
477 return false;
478 }
479 break;
480 case IDP_ARRAY:
481 if (rna_ensure_property_array_length(ptr, prop) != idprop->len) {
482 return false;
483 }
484
485 if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT) {
486 return false;
487 }
488 if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) {
489 return false;
490 }
491
492 break;
493 case IDP_INT:
494 if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) {
495 return false;
496 }
497 break;
498 case IDP_FLOAT:
499 case IDP_DOUBLE:
500 if (prop->type != PROP_FLOAT) {
501 return false;
502 }
503 break;
504 case IDP_STRING:
505 if (prop->type != PROP_STRING) {
506 return false;
507 }
508 break;
509 case IDP_GROUP:
510 case IDP_ID:
511 if (prop->type != PROP_POINTER) {
512 return false;
513 }
514 break;
515 default:
516 return false;
517 }
518
519 return true;
520 }
521
522 static PropertyRNA *typemap[IDP_NUMTYPES] = {
523 (PropertyRNA *)&rna_PropertyGroupItem_string,
524 (PropertyRNA *)&rna_PropertyGroupItem_int,
525 (PropertyRNA *)&rna_PropertyGroupItem_float,
526 NULL,
527 NULL,
528 NULL,
529 (PropertyRNA *)&rna_PropertyGroupItem_group,
530 (PropertyRNA *)&rna_PropertyGroupItem_id,
531 (PropertyRNA *)&rna_PropertyGroupItem_double,
532 (PropertyRNA *)&rna_PropertyGroupItem_idp_array,
533 };
534
535 static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
536 NULL,
537 (PropertyRNA *)&rna_PropertyGroupItem_int_array,
538 (PropertyRNA *)&rna_PropertyGroupItem_float_array,
539 NULL,
540 NULL,
541 NULL,
542 (PropertyRNA *)&rna_PropertyGroupItem_collection,
543 NULL,
544 (PropertyRNA *)&rna_PropertyGroupItem_double_array,
545 };
546
547 /* This function initializes a PropertyRNAOrID with all required info, from a given PropertyRNA
548 * and PointerRNA data. It deals properly with the three cases (static RNA, runtime RNA, and
549 * IDProperty).
550 * WARNING: given `ptr` PointerRNA is assumed to be a valid data one here, calling code is
551 * responsible to ensure that.
552 */
rna_property_rna_or_id_get(PropertyRNA * prop,PointerRNA * ptr,PropertyRNAOrID * r_prop_rna_or_id)553 void rna_property_rna_or_id_get(PropertyRNA *prop,
554 PointerRNA *ptr,
555 PropertyRNAOrID *r_prop_rna_or_id)
556 {
557 /* This is quite a hack, but avoids some complexity in the API. we
558 * pass IDProperty structs as PropertyRNA pointers to the outside.
559 * We store some bytes in PropertyRNA structs that allows us to
560 * distinguish it from IDProperty structs. If it is an ID property,
561 * we look up an IDP PropertyRNA based on the type, and set the data
562 * pointer to the IDProperty. */
563 memset(r_prop_rna_or_id, 0, sizeof(*r_prop_rna_or_id));
564
565 r_prop_rna_or_id->ptr = *ptr;
566 r_prop_rna_or_id->rawprop = prop;
567
568 if (prop->magic == RNA_MAGIC) {
569 r_prop_rna_or_id->rnaprop = prop;
570 r_prop_rna_or_id->identifier = prop->identifier;
571
572 r_prop_rna_or_id->is_array = prop->getlength || prop->totarraylength;
573 if (r_prop_rna_or_id->is_array) {
574 int arraylen[RNA_MAX_ARRAY_DIMENSION];
575 r_prop_rna_or_id->array_len = (prop->getlength && ptr->data) ?
576 (uint)prop->getlength(ptr, arraylen) :
577 prop->totarraylength;
578 }
579
580 if (prop->flag & PROP_IDPROPERTY) {
581 IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier);
582
583 if (idprop != NULL && !rna_idproperty_verify_valid(ptr, prop, idprop)) {
584 IDProperty *group = RNA_struct_idprops(ptr, 0);
585
586 IDP_FreeFromGroup(group, idprop);
587 idprop = NULL;
588 }
589
590 r_prop_rna_or_id->idprop = idprop;
591 r_prop_rna_or_id->is_set = idprop != NULL && (idprop->flag & IDP_FLAG_GHOST) == 0;
592 }
593 else {
594 /* Full static RNA properties are always set. */
595 r_prop_rna_or_id->is_set = true;
596 }
597 }
598 else {
599 IDProperty *idprop = (IDProperty *)prop;
600 /* Given prop may come from the custom properties of another data, ensure we get the one from
601 * given data ptr. */
602 IDProperty *idprop_evaluated = rna_idproperty_find(ptr, idprop->name);
603 if (idprop_evaluated != NULL && idprop->type != idprop_evaluated->type) {
604 idprop_evaluated = NULL;
605 }
606
607 r_prop_rna_or_id->idprop = idprop_evaluated;
608 r_prop_rna_or_id->is_idprop = true;
609 /* Full IDProperties are always set, if it exists. */
610 r_prop_rna_or_id->is_set = (idprop_evaluated != NULL);
611
612 r_prop_rna_or_id->identifier = idprop->name;
613 if (idprop->type == IDP_ARRAY) {
614 r_prop_rna_or_id->rnaprop = arraytypemap[(int)(idprop->subtype)];
615 r_prop_rna_or_id->is_array = true;
616 r_prop_rna_or_id->array_len = idprop_evaluated != NULL ? (uint)idprop_evaluated->len : 0;
617 }
618 else {
619 r_prop_rna_or_id->rnaprop = typemap[(int)(idprop->type)];
620 }
621 }
622 }
623
624 /* This function only returns an IDProperty,
625 * or NULL (in case IDProp could not be found, or prop is a real RNA property). */
rna_idproperty_check(PropertyRNA ** prop,PointerRNA * ptr)626 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
627 {
628 PropertyRNAOrID prop_rna_or_id;
629
630 rna_property_rna_or_id_get(*prop, ptr, &prop_rna_or_id);
631
632 *prop = prop_rna_or_id.rnaprop;
633 return prop_rna_or_id.idprop;
634 }
635
636 /* This function always return the valid, real data pointer, be it a regular RNA property one,
637 * or an IDProperty one. */
rna_ensure_property_realdata(PropertyRNA ** prop,PointerRNA * ptr)638 PropertyRNA *rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr)
639 {
640 PropertyRNAOrID prop_rna_or_id;
641
642 rna_property_rna_or_id_get(*prop, ptr, &prop_rna_or_id);
643
644 *prop = prop_rna_or_id.rnaprop;
645 return (prop_rna_or_id.is_idprop || prop_rna_or_id.idprop != NULL) ?
646 (PropertyRNA *)prop_rna_or_id.idprop :
647 prop_rna_or_id.rnaprop;
648 }
649
rna_ensure_property(PropertyRNA * prop)650 PropertyRNA *rna_ensure_property(PropertyRNA *prop)
651 {
652 /* the quick version if we don't need the idproperty */
653
654 if (prop->magic == RNA_MAGIC) {
655 return prop;
656 }
657
658 {
659 IDProperty *idprop = (IDProperty *)prop;
660
661 if (idprop->type == IDP_ARRAY) {
662 return arraytypemap[(int)(idprop->subtype)];
663 }
664 return typemap[(int)(idprop->type)];
665 }
666 }
667
rna_ensure_property_identifier(const PropertyRNA * prop)668 static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
669 {
670 if (prop->magic == RNA_MAGIC) {
671 return prop->identifier;
672 }
673 return ((const IDProperty *)prop)->name;
674 }
675
rna_ensure_property_description(const PropertyRNA * prop)676 static const char *rna_ensure_property_description(const PropertyRNA *prop)
677 {
678 const char *description = NULL;
679
680 if (prop->magic == RNA_MAGIC) {
681 description = prop->description;
682 }
683 else {
684 /* attempt to get the local ID values */
685 const IDProperty *idp_ui = rna_idproperty_ui(prop);
686
687 if (idp_ui) {
688 IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "description", IDP_STRING);
689 if (item) {
690 description = IDP_String(item);
691 }
692 }
693
694 if (description == NULL) {
695 description = ((IDProperty *)prop)->name; /* XXX - not correct */
696 }
697 }
698
699 return description;
700 }
701
rna_ensure_property_name(const PropertyRNA * prop)702 static const char *rna_ensure_property_name(const PropertyRNA *prop)
703 {
704 const char *name;
705
706 if (prop->magic == RNA_MAGIC) {
707 name = prop->name;
708 }
709 else {
710 name = ((const IDProperty *)prop)->name;
711 }
712
713 return name;
714 }
715
716 /* Structs */
717
RNA_struct_find(const char * identifier)718 StructRNA *RNA_struct_find(const char *identifier)
719 {
720 return BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier);
721 }
722
RNA_struct_identifier(const StructRNA * type)723 const char *RNA_struct_identifier(const StructRNA *type)
724 {
725 return type->identifier;
726 }
727
RNA_struct_ui_name(const StructRNA * type)728 const char *RNA_struct_ui_name(const StructRNA *type)
729 {
730 return CTX_IFACE_(type->translation_context, type->name);
731 }
732
RNA_struct_ui_name_raw(const StructRNA * type)733 const char *RNA_struct_ui_name_raw(const StructRNA *type)
734 {
735 return type->name;
736 }
737
RNA_struct_ui_icon(const StructRNA * type)738 int RNA_struct_ui_icon(const StructRNA *type)
739 {
740 if (type) {
741 return type->icon;
742 }
743 return ICON_DOT;
744 }
745
RNA_struct_ui_description(const StructRNA * type)746 const char *RNA_struct_ui_description(const StructRNA *type)
747 {
748 return TIP_(type->description);
749 }
750
RNA_struct_ui_description_raw(const StructRNA * type)751 const char *RNA_struct_ui_description_raw(const StructRNA *type)
752 {
753 return type->description;
754 }
755
RNA_struct_translation_context(const StructRNA * type)756 const char *RNA_struct_translation_context(const StructRNA *type)
757 {
758 return type->translation_context;
759 }
760
RNA_struct_name_property(const StructRNA * type)761 PropertyRNA *RNA_struct_name_property(const StructRNA *type)
762 {
763 return type->nameproperty;
764 }
765
RNA_struct_property_tag_defines(const StructRNA * type)766 const EnumPropertyItem *RNA_struct_property_tag_defines(const StructRNA *type)
767 {
768 return type->prop_tag_defines;
769 }
770
RNA_struct_iterator_property(StructRNA * type)771 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
772 {
773 return type->iteratorproperty;
774 }
775
RNA_struct_base(StructRNA * type)776 StructRNA *RNA_struct_base(StructRNA *type)
777 {
778 return type->base;
779 }
780
781 /**
782 * Use to find the subtype directly below a base-type.
783 *
784 * So if type were `RNA_SpotLIght`, `RNA_struct_base_of(type, &RNA_ID)` would return `&RNA_Light`.
785 */
RNA_struct_base_child_of(const StructRNA * type,const StructRNA * parent_type)786 const StructRNA *RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
787 {
788 while (type) {
789 if (type->base == parent_type) {
790 return type;
791 }
792 type = type->base;
793 }
794 return NULL;
795 }
796
RNA_struct_is_ID(const StructRNA * type)797 bool RNA_struct_is_ID(const StructRNA *type)
798 {
799 return (type->flag & STRUCT_ID) != 0;
800 }
801
RNA_struct_undo_check(const StructRNA * type)802 bool RNA_struct_undo_check(const StructRNA *type)
803 {
804 return (type->flag & STRUCT_UNDO) != 0;
805 }
806
RNA_struct_idprops_register_check(const StructRNA * type)807 bool RNA_struct_idprops_register_check(const StructRNA *type)
808 {
809 return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
810 }
811
RNA_struct_idprops_datablock_allowed(const StructRNA * type)812 bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
813 {
814 return (type->flag & (STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_NO_IDPROPERTIES)) == 0;
815 }
816
817 /**
818 * Whether given type implies datablock usage by IDProperties.
819 * This is used to prevent classes allowed to have IDProperties,
820 * but not datablock ones, to indirectly use some
821 * (e.g. by assigning an IDP_GROUP containing some IDP_ID pointers...).
822 */
RNA_struct_idprops_contains_datablock(const StructRNA * type)823 bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
824 {
825 return (type->flag & (STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES | STRUCT_ID)) != 0;
826 }
827
828 /* remove an id-property */
RNA_struct_idprops_unset(PointerRNA * ptr,const char * identifier)829 bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
830 {
831 IDProperty *group = RNA_struct_idprops(ptr, 0);
832
833 if (group) {
834 IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
835 if (idp) {
836 IDP_FreeFromGroup(group, idp);
837
838 return true;
839 }
840 }
841 return false;
842 }
843
RNA_struct_is_a(const StructRNA * type,const StructRNA * srna)844 bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
845 {
846 const StructRNA *base;
847
848 if (srna == &RNA_AnyType) {
849 return true;
850 }
851
852 if (!type) {
853 return false;
854 }
855
856 /* ptr->type is always maximally refined */
857 for (base = type; base; base = base->base) {
858 if (base == srna) {
859 return true;
860 }
861 }
862
863 return false;
864 }
865
RNA_struct_find_property(PointerRNA * ptr,const char * identifier)866 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
867 {
868 if (identifier[0] == '[' && identifier[1] == '"') { /* " (dummy comment to avoid confusing some
869 * function lists in text editors) */
870 /* id prop lookup, not so common */
871 PropertyRNA *r_prop = NULL;
872 PointerRNA r_ptr; /* only support single level props */
873 if (RNA_path_resolve_property(ptr, identifier, &r_ptr, &r_prop) && (r_ptr.type == ptr->type) &&
874 (r_ptr.data == ptr->data)) {
875 return r_prop;
876 }
877 }
878 else {
879 /* most common case */
880 PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
881 PointerRNA propptr;
882
883 if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr)) {
884 return propptr.data;
885 }
886 }
887
888 return NULL;
889 }
890
891 /* Find the property which uses the given nested struct */
RNA_struct_find_nested(PointerRNA * ptr,StructRNA * srna)892 static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
893 {
894 PropertyRNA *prop = NULL;
895
896 RNA_STRUCT_BEGIN (ptr, iprop) {
897 /* This assumes that there can only be one user of this nested struct */
898 if (RNA_property_pointer_type(ptr, iprop) == srna) {
899 prop = iprop;
900 break;
901 }
902 }
903 RNA_PROP_END;
904
905 return prop;
906 }
907
RNA_struct_contains_property(PointerRNA * ptr,PropertyRNA * prop_test)908 bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
909 {
910 /* note, prop_test could be freed memory, only use for comparison */
911
912 /* validate the RNA is ok */
913 PropertyRNA *iterprop;
914 bool found = false;
915
916 iterprop = RNA_struct_iterator_property(ptr->type);
917
918 RNA_PROP_BEGIN (ptr, itemptr, iterprop) {
919 /* PropertyRNA *prop = itemptr.data; */
920 if (prop_test == (PropertyRNA *)itemptr.data) {
921 found = true;
922 break;
923 }
924 }
925 RNA_PROP_END;
926
927 return found;
928 }
929
RNA_struct_count_properties(StructRNA * srna)930 unsigned int RNA_struct_count_properties(StructRNA *srna)
931 {
932 PointerRNA struct_ptr;
933 unsigned int counter = 0;
934
935 RNA_pointer_create(NULL, srna, NULL, &struct_ptr);
936
937 RNA_STRUCT_BEGIN (&struct_ptr, prop) {
938 counter++;
939 UNUSED_VARS(prop);
940 }
941 RNA_STRUCT_END;
942
943 return counter;
944 }
945
946 /* Low level direct access to type->properties,
947 * note this ignores parent classes so should be used with care. */
RNA_struct_type_properties(StructRNA * srna)948 const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
949 {
950 return &srna->cont.properties;
951 }
952
RNA_struct_type_find_property(StructRNA * srna,const char * identifier)953 PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
954 {
955 return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
956 }
957
RNA_struct_find_function(StructRNA * srna,const char * identifier)958 FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
959 {
960 #if 1
961 FunctionRNA *func;
962 StructRNA *type;
963 for (type = srna; type; type = type->base) {
964 func = (FunctionRNA *)BLI_findstring_ptr(
965 &type->functions, identifier, offsetof(FunctionRNA, identifier));
966 if (func) {
967 return func;
968 }
969 }
970 return NULL;
971
972 /* functional but slow */
973 #else
974 PointerRNA tptr;
975 PropertyRNA *iterprop;
976 FunctionRNA *func;
977
978 RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr);
979 iterprop = RNA_struct_find_property(&tptr, "functions");
980
981 func = NULL;
982
983 RNA_PROP_BEGIN (&tptr, funcptr, iterprop) {
984 if (STREQ(identifier, RNA_function_identifier(funcptr.data))) {
985 func = funcptr.data;
986 break;
987 }
988 }
989 RNA_PROP_END;
990
991 return func;
992 #endif
993 }
994
RNA_struct_type_functions(StructRNA * srna)995 const ListBase *RNA_struct_type_functions(StructRNA *srna)
996 {
997 return &srna->functions;
998 }
999
RNA_struct_register(StructRNA * type)1000 StructRegisterFunc RNA_struct_register(StructRNA *type)
1001 {
1002 return type->reg;
1003 }
1004
RNA_struct_unregister(StructRNA * type)1005 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
1006 {
1007 do {
1008 if (type->unreg) {
1009 return type->unreg;
1010 }
1011 } while ((type = type->base));
1012
1013 return NULL;
1014 }
1015
RNA_struct_instance(PointerRNA * ptr)1016 void **RNA_struct_instance(PointerRNA *ptr)
1017 {
1018 StructRNA *type = ptr->type;
1019
1020 do {
1021 if (type->instance) {
1022 return type->instance(ptr);
1023 }
1024 } while ((type = type->base));
1025
1026 return NULL;
1027 }
1028
RNA_struct_py_type_get(StructRNA * srna)1029 void *RNA_struct_py_type_get(StructRNA *srna)
1030 {
1031 return srna->py_type;
1032 }
1033
RNA_struct_py_type_set(StructRNA * srna,void * py_type)1034 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
1035 {
1036 srna->py_type = py_type;
1037 }
1038
RNA_struct_blender_type_get(StructRNA * srna)1039 void *RNA_struct_blender_type_get(StructRNA *srna)
1040 {
1041 return srna->blender_type;
1042 }
1043
RNA_struct_blender_type_set(StructRNA * srna,void * blender_type)1044 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
1045 {
1046 srna->blender_type = blender_type;
1047 }
1048
RNA_struct_name_get_alloc(PointerRNA * ptr,char * fixedbuf,int fixedlen,int * r_len)1049 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
1050 {
1051 PropertyRNA *nameprop;
1052
1053 if (ptr->data && (nameprop = RNA_struct_name_property(ptr->type))) {
1054 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
1055 }
1056
1057 return NULL;
1058 }
1059
1060 /**
1061 * Use when registering structs with the #STRUCT_PUBLIC_NAMESPACE flag.
1062 */
RNA_struct_available_or_report(ReportList * reports,const char * identifier)1063 bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
1064 {
1065 const StructRNA *srna_exists = RNA_struct_find(identifier);
1066 if (UNLIKELY(srna_exists != NULL)) {
1067 /* Use comprehensive string construction since this is such a rare occurrence
1068 * and information here may cut down time troubleshooting. */
1069 DynStr *dynstr = BLI_dynstr_new();
1070 BLI_dynstr_appendf(dynstr, "Type identifier '%s' is already in use: '", identifier);
1071 BLI_dynstr_append(dynstr, srna_exists->identifier);
1072 int i = 0;
1073 if (srna_exists->base) {
1074 for (const StructRNA *base = srna_exists->base; base; base = base->base) {
1075 BLI_dynstr_append(dynstr, "(");
1076 BLI_dynstr_append(dynstr, base->identifier);
1077 i += 1;
1078 }
1079 while (i--) {
1080 BLI_dynstr_append(dynstr, ")");
1081 }
1082 }
1083 BLI_dynstr_append(dynstr, "'.");
1084 char *result = BLI_dynstr_get_cstring(dynstr);
1085 BLI_dynstr_free(dynstr);
1086 BKE_report(reports, RPT_ERROR, result);
1087 MEM_freeN(result);
1088 return false;
1089 }
1090 return true;
1091 }
1092
RNA_struct_bl_idname_ok_or_report(ReportList * reports,const char * identifier,const char * sep)1093 bool RNA_struct_bl_idname_ok_or_report(ReportList *reports,
1094 const char *identifier,
1095 const char *sep)
1096 {
1097 const int len_sep = strlen(sep);
1098 const int len_id = strlen(identifier);
1099 const char *p = strstr(identifier, sep);
1100 /* TODO: make error, for now warning until add-ons update. */
1101 #if 1
1102 const int report_level = RPT_WARNING;
1103 const bool failure = true;
1104 #else
1105 const int report_level = RPT_ERROR;
1106 const bool failure = false;
1107 #endif
1108 if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) {
1109 BKE_reportf(
1110 reports, report_level, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep);
1111 return failure;
1112 }
1113
1114 const char *c, *start, *end, *last;
1115 start = identifier;
1116 end = p;
1117 last = end - 1;
1118 for (c = start; c != end; c++) {
1119 if (((*c >= 'A' && *c <= 'Z') || ((c != start) && (*c >= '0' && *c <= '9')) ||
1120 ((c != start) && (c != last) && (*c == '_'))) == 0) {
1121 BKE_reportf(
1122 reports, report_level, "'%s' doesn't have upper case alpha-numeric prefix", identifier);
1123 return failure;
1124 }
1125 }
1126
1127 start = p + len_sep;
1128 end = identifier + len_id;
1129 last = end - 1;
1130 for (c = start; c != end; c++) {
1131 if (((*c >= 'A' && *c <= 'Z') || (*c >= 'a' && *c <= 'z') || (*c >= '0' && *c <= '9') ||
1132 ((c != start) && (c != last) && (*c == '_'))) == 0) {
1133 BKE_reportf(reports, report_level, "'%s' doesn't have an alpha-numeric suffix", identifier);
1134 return failure;
1135 }
1136 }
1137 return true;
1138 }
1139
1140 /* Property Information */
1141
RNA_property_identifier(const PropertyRNA * prop)1142 const char *RNA_property_identifier(const PropertyRNA *prop)
1143 {
1144 return rna_ensure_property_identifier(prop);
1145 }
1146
RNA_property_description(PropertyRNA * prop)1147 const char *RNA_property_description(PropertyRNA *prop)
1148 {
1149 return TIP_(rna_ensure_property_description(prop));
1150 }
1151
RNA_property_type(PropertyRNA * prop)1152 PropertyType RNA_property_type(PropertyRNA *prop)
1153 {
1154 return rna_ensure_property(prop)->type;
1155 }
1156
RNA_property_subtype(PropertyRNA * prop)1157 PropertySubType RNA_property_subtype(PropertyRNA *prop)
1158 {
1159 PropertyRNA *rna_prop = rna_ensure_property(prop);
1160
1161 /* For custom properties, find and parse the 'subtype' metadata field. */
1162 if (prop->magic != RNA_MAGIC) {
1163 IDProperty *idprop = (IDProperty *)prop;
1164
1165 /* Restrict to arrays only for now for performance reasons. */
1166 if (idprop->type == IDP_ARRAY && ELEM(idprop->subtype, IDP_INT, IDP_FLOAT, IDP_DOUBLE)) {
1167 const IDProperty *idp_ui = rna_idproperty_ui(prop);
1168
1169 if (idp_ui) {
1170 IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "subtype", IDP_STRING);
1171
1172 if (item) {
1173 int result = PROP_NONE;
1174 RNA_enum_value_from_id(rna_enum_property_subtype_items, IDP_String(item), &result);
1175 return (PropertySubType)result;
1176 }
1177 }
1178 }
1179 }
1180
1181 return rna_prop->subtype;
1182 }
1183
RNA_property_unit(PropertyRNA * prop)1184 PropertyUnit RNA_property_unit(PropertyRNA *prop)
1185 {
1186 return RNA_SUBTYPE_UNIT(RNA_property_subtype(prop));
1187 }
1188
RNA_property_flag(PropertyRNA * prop)1189 int RNA_property_flag(PropertyRNA *prop)
1190 {
1191 return rna_ensure_property(prop)->flag;
1192 }
1193
1194 /**
1195 * Get the tags set for \a prop as int bitfield.
1196 * \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this
1197 * in debug builds (to avoid performance issues in non-debug builds), which should be
1198 * the only way to set tags. Hence, at this point we assume the tag bitfield to be valid.
1199 */
RNA_property_tags(PropertyRNA * prop)1200 int RNA_property_tags(PropertyRNA *prop)
1201 {
1202 return rna_ensure_property(prop)->tags;
1203 }
1204
RNA_property_builtin(PropertyRNA * prop)1205 bool RNA_property_builtin(PropertyRNA *prop)
1206 {
1207 return (rna_ensure_property(prop)->flag_internal & PROP_INTERN_BUILTIN) != 0;
1208 }
1209
RNA_property_py_data_get(PropertyRNA * prop)1210 void *RNA_property_py_data_get(PropertyRNA *prop)
1211 {
1212 return prop->py_data;
1213 }
1214
RNA_property_array_length(PointerRNA * ptr,PropertyRNA * prop)1215 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
1216 {
1217 return rna_ensure_property_array_length(ptr, prop);
1218 }
1219
RNA_property_array_check(PropertyRNA * prop)1220 bool RNA_property_array_check(PropertyRNA *prop)
1221 {
1222 return rna_ensure_property_array_check(prop);
1223 }
1224
1225 /* used by BPY to make an array from the python object */
RNA_property_array_dimension(PointerRNA * ptr,PropertyRNA * prop,int length[])1226 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
1227 {
1228 PropertyRNA *rprop = rna_ensure_property(prop);
1229
1230 if (length) {
1231 rna_ensure_property_multi_array_length(ptr, prop, length);
1232 }
1233
1234 return rprop->arraydimension;
1235 }
1236
1237 /* Return the size of Nth dimension. */
RNA_property_multi_array_length(PointerRNA * ptr,PropertyRNA * prop,int dim)1238 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
1239 {
1240 int len[RNA_MAX_ARRAY_DIMENSION];
1241
1242 rna_ensure_property_multi_array_length(ptr, prop, len);
1243
1244 return len[dim];
1245 }
1246
RNA_property_array_item_char(PropertyRNA * prop,int index)1247 char RNA_property_array_item_char(PropertyRNA *prop, int index)
1248 {
1249 const char *vectoritem = "XYZW";
1250 const char *quatitem = "WXYZ";
1251 const char *coloritem = "RGBA";
1252 PropertySubType subtype = RNA_property_subtype(prop);
1253
1254 BLI_assert(index >= 0);
1255
1256 /* get string to use for array index */
1257 if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1258 return quatitem[index];
1259 }
1260 if ((index < 4) && ELEM(subtype,
1261 PROP_TRANSLATION,
1262 PROP_DIRECTION,
1263 PROP_XYZ,
1264 PROP_XYZ_LENGTH,
1265 PROP_EULER,
1266 PROP_VELOCITY,
1267 PROP_ACCELERATION,
1268 PROP_COORDS)) {
1269 return vectoritem[index];
1270 }
1271 else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1272 return coloritem[index];
1273 }
1274
1275 return '\0';
1276 }
1277
RNA_property_array_item_index(PropertyRNA * prop,char name)1278 int RNA_property_array_item_index(PropertyRNA *prop, char name)
1279 {
1280 /* Don't use custom property subtypes in RNA path lookup. */
1281 PropertySubType subtype = rna_ensure_property(prop)->subtype;
1282
1283 /* get index based on string name/alias */
1284 /* maybe a function to find char index in string would be better than all the switches */
1285 if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1286 switch (name) {
1287 case 'w':
1288 return 0;
1289 case 'x':
1290 return 1;
1291 case 'y':
1292 return 2;
1293 case 'z':
1294 return 3;
1295 }
1296 }
1297 else if (ELEM(subtype,
1298 PROP_TRANSLATION,
1299 PROP_DIRECTION,
1300 PROP_XYZ,
1301 PROP_XYZ_LENGTH,
1302 PROP_EULER,
1303 PROP_VELOCITY,
1304 PROP_ACCELERATION)) {
1305 switch (name) {
1306 case 'x':
1307 return 0;
1308 case 'y':
1309 return 1;
1310 case 'z':
1311 return 2;
1312 case 'w':
1313 return 3;
1314 }
1315 }
1316 else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1317 switch (name) {
1318 case 'r':
1319 return 0;
1320 case 'g':
1321 return 1;
1322 case 'b':
1323 return 2;
1324 case 'a':
1325 return 3;
1326 }
1327 }
1328
1329 return -1;
1330 }
1331
RNA_property_int_range(PointerRNA * ptr,PropertyRNA * prop,int * hardmin,int * hardmax)1332 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
1333 {
1334 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1335 int softmin, softmax;
1336
1337 if (prop->magic != RNA_MAGIC) {
1338 /* attempt to get the local ID values */
1339 const IDProperty *idp_ui = rna_idproperty_ui(prop);
1340
1341 if (idp_ui) {
1342 IDProperty *item;
1343
1344 item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
1345 *hardmin = item ? IDP_Int(item) : INT_MIN;
1346
1347 item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
1348 *hardmax = item ? IDP_Int(item) : INT_MAX;
1349
1350 return;
1351 }
1352 }
1353
1354 if (iprop->range) {
1355 *hardmin = INT_MIN;
1356 *hardmax = INT_MAX;
1357
1358 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1359 }
1360 else if (iprop->range_ex) {
1361 *hardmin = INT_MIN;
1362 *hardmax = INT_MAX;
1363
1364 iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1365 }
1366 else {
1367 *hardmin = iprop->hardmin;
1368 *hardmax = iprop->hardmax;
1369 }
1370 }
1371
RNA_property_int_ui_range(PointerRNA * ptr,PropertyRNA * prop,int * softmin,int * softmax,int * step)1372 void RNA_property_int_ui_range(
1373 PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
1374 {
1375 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1376 int hardmin, hardmax;
1377
1378 if (prop->magic != RNA_MAGIC) {
1379 /* attempt to get the local ID values */
1380 const IDProperty *idp_ui = rna_idproperty_ui(prop);
1381
1382 if (idp_ui) {
1383 IDProperty *item;
1384
1385 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
1386 *softmin = item ? IDP_Int(item) : INT_MIN;
1387
1388 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
1389 *softmax = item ? IDP_Int(item) : INT_MAX;
1390
1391 item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
1392 *step = item ? IDP_Int(item) : 1;
1393
1394 return;
1395 }
1396 }
1397
1398 *softmin = iprop->softmin;
1399 *softmax = iprop->softmax;
1400
1401 if (iprop->range) {
1402 hardmin = INT_MIN;
1403 hardmax = INT_MAX;
1404
1405 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1406
1407 *softmin = max_ii(*softmin, hardmin);
1408 *softmax = min_ii(*softmax, hardmax);
1409 }
1410 else if (iprop->range_ex) {
1411 hardmin = INT_MIN;
1412 hardmax = INT_MAX;
1413
1414 iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1415
1416 *softmin = max_ii(*softmin, hardmin);
1417 *softmax = min_ii(*softmax, hardmax);
1418 }
1419
1420 *step = iprop->step;
1421 }
1422
RNA_property_float_range(PointerRNA * ptr,PropertyRNA * prop,float * hardmin,float * hardmax)1423 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1424 {
1425 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1426 float softmin, softmax;
1427
1428 if (prop->magic != RNA_MAGIC) {
1429 /* attempt to get the local ID values */
1430 const IDProperty *idp_ui = rna_idproperty_ui(prop);
1431
1432 if (idp_ui) {
1433 IDProperty *item;
1434
1435 item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
1436 *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1437
1438 item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1439 *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1440
1441 return;
1442 }
1443 }
1444
1445 if (fprop->range) {
1446 *hardmin = -FLT_MAX;
1447 *hardmax = FLT_MAX;
1448
1449 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1450 }
1451 else if (fprop->range_ex) {
1452 *hardmin = -FLT_MAX;
1453 *hardmax = FLT_MAX;
1454
1455 fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1456 }
1457 else {
1458 *hardmin = fprop->hardmin;
1459 *hardmax = fprop->hardmax;
1460 }
1461 }
1462
RNA_property_float_ui_range(PointerRNA * ptr,PropertyRNA * prop,float * softmin,float * softmax,float * step,float * precision)1463 void RNA_property_float_ui_range(PointerRNA *ptr,
1464 PropertyRNA *prop,
1465 float *softmin,
1466 float *softmax,
1467 float *step,
1468 float *precision)
1469 {
1470 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1471 float hardmin, hardmax;
1472
1473 if (prop->magic != RNA_MAGIC) {
1474 /* attempt to get the local ID values */
1475 const IDProperty *idp_ui = rna_idproperty_ui(prop);
1476
1477 if (idp_ui) {
1478 IDProperty *item;
1479
1480 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1481 *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1482
1483 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1484 *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1485
1486 item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1487 *step = item ? (float)IDP_Double(item) : 1.0f;
1488
1489 item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1490 *precision = item ? (float)IDP_Double(item) : 3.0f;
1491
1492 return;
1493 }
1494 }
1495
1496 *softmin = fprop->softmin;
1497 *softmax = fprop->softmax;
1498
1499 if (fprop->range) {
1500 hardmin = -FLT_MAX;
1501 hardmax = FLT_MAX;
1502
1503 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1504
1505 *softmin = max_ff(*softmin, hardmin);
1506 *softmax = min_ff(*softmax, hardmax);
1507 }
1508 else if (fprop->range_ex) {
1509 hardmin = -FLT_MAX;
1510 hardmax = FLT_MAX;
1511
1512 fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1513
1514 *softmin = max_ff(*softmin, hardmin);
1515 *softmax = min_ff(*softmax, hardmax);
1516 }
1517
1518 *step = fprop->step;
1519 *precision = (float)fprop->precision;
1520 }
1521
RNA_property_float_clamp(PointerRNA * ptr,PropertyRNA * prop,float * value)1522 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1523 {
1524 float min, max;
1525
1526 RNA_property_float_range(ptr, prop, &min, &max);
1527
1528 if (*value < min) {
1529 *value = min;
1530 return -1;
1531 }
1532 if (*value > max) {
1533 *value = max;
1534 return 1;
1535 }
1536 else {
1537 return 0;
1538 }
1539 }
1540
RNA_property_int_clamp(PointerRNA * ptr,PropertyRNA * prop,int * value)1541 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1542 {
1543 int min, max;
1544
1545 RNA_property_int_range(ptr, prop, &min, &max);
1546
1547 if (*value < min) {
1548 *value = min;
1549 return -1;
1550 }
1551 if (*value > max) {
1552 *value = max;
1553 return 1;
1554 }
1555 else {
1556 return 0;
1557 }
1558 }
1559
1560 /* this is the max length including \0 terminator.
1561 * '0' used when their is no maximum */
RNA_property_string_maxlength(PropertyRNA * prop)1562 int RNA_property_string_maxlength(PropertyRNA *prop)
1563 {
1564 StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1565 return sprop->maxlength;
1566 }
1567
RNA_property_pointer_type(PointerRNA * ptr,PropertyRNA * prop)1568 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1569 {
1570 prop = rna_ensure_property(prop);
1571
1572 if (prop->type == PROP_POINTER) {
1573 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1574
1575 if (pprop->typef) {
1576 return pprop->typef(ptr);
1577 }
1578 if (pprop->type) {
1579 return pprop->type;
1580 }
1581 }
1582 else if (prop->type == PROP_COLLECTION) {
1583 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1584
1585 if (cprop->item_type) {
1586 return cprop->item_type;
1587 }
1588 }
1589 /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1590
1591 return &RNA_UnknownType;
1592 }
1593
RNA_property_pointer_poll(PointerRNA * ptr,PropertyRNA * prop,PointerRNA * value)1594 bool RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1595 {
1596 prop = rna_ensure_property(prop);
1597
1598 if (prop->type == PROP_POINTER) {
1599 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1600
1601 if (pprop->poll) {
1602 if (rna_idproperty_check(&prop, ptr)) {
1603 return ((PropPointerPollFuncPy)pprop->poll)(ptr, *value, prop);
1604 }
1605 return pprop->poll(ptr, *value);
1606 }
1607
1608 return 1;
1609 }
1610
1611 printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
1612 return 0;
1613 }
1614
RNA_property_enum_items_ex(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const bool use_static,const EnumPropertyItem ** r_item,int * r_totitem,bool * r_free)1615 void RNA_property_enum_items_ex(bContext *C,
1616 PointerRNA *ptr,
1617 PropertyRNA *prop,
1618 const bool use_static,
1619 const EnumPropertyItem **r_item,
1620 int *r_totitem,
1621 bool *r_free)
1622 {
1623 EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1624
1625 *r_free = false;
1626
1627 if (!use_static && eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1628 const EnumPropertyItem *item;
1629
1630 if (prop->flag & PROP_ENUM_NO_CONTEXT) {
1631 item = eprop->itemf(NULL, ptr, prop, r_free);
1632 }
1633 else {
1634 item = eprop->itemf(C, ptr, prop, r_free);
1635 }
1636
1637 /* any callbacks returning NULL should be fixed */
1638 BLI_assert(item != NULL);
1639
1640 if (r_totitem) {
1641 int tot;
1642 for (tot = 0; item[tot].identifier; tot++) {
1643 /* pass */
1644 }
1645 *r_totitem = tot;
1646 }
1647
1648 *r_item = item;
1649 }
1650 else {
1651 *r_item = eprop->item;
1652 if (r_totitem) {
1653 *r_totitem = eprop->totitem;
1654 }
1655 }
1656 }
1657
RNA_property_enum_items(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const EnumPropertyItem ** r_item,int * r_totitem,bool * r_free)1658 void RNA_property_enum_items(bContext *C,
1659 PointerRNA *ptr,
1660 PropertyRNA *prop,
1661 const EnumPropertyItem **r_item,
1662 int *r_totitem,
1663 bool *r_free)
1664 {
1665 RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free);
1666 }
1667
1668 #ifdef WITH_INTERNATIONAL
property_enum_translate(PropertyRNA * prop,EnumPropertyItem ** r_item,int * r_totitem,bool * r_free)1669 static void property_enum_translate(PropertyRNA *prop,
1670 EnumPropertyItem **r_item,
1671 int *r_totitem,
1672 bool *r_free)
1673 {
1674 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1675 int i;
1676
1677 /* Note: Only do those tests once, and then use BLT_pgettext. */
1678 bool do_iface = BLT_translate_iface();
1679 bool do_tooltip = BLT_translate_tooltips();
1680 EnumPropertyItem *nitem;
1681
1682 if (!(do_iface || do_tooltip)) {
1683 return;
1684 }
1685
1686 if (*r_free) {
1687 nitem = *r_item;
1688 }
1689 else {
1690 const EnumPropertyItem *item = *r_item;
1691 int tot;
1692
1693 if (r_totitem) {
1694 tot = *r_totitem;
1695 }
1696 else {
1697 /* count */
1698 for (tot = 0; item[tot].identifier; tot++) {
1699 /* pass */
1700 }
1701 }
1702
1703 nitem = MEM_mallocN(sizeof(EnumPropertyItem) * (tot + 1), "enum_items_gettexted");
1704 memcpy(nitem, item, sizeof(EnumPropertyItem) * (tot + 1));
1705
1706 *r_free = true;
1707 }
1708
1709 for (i = 0; nitem[i].identifier; i++) {
1710 if (nitem[i].name && do_iface) {
1711 nitem[i].name = BLT_pgettext(prop->translation_context, nitem[i].name);
1712 }
1713 if (nitem[i].description && do_tooltip) {
1714 nitem[i].description = BLT_pgettext(NULL, nitem[i].description);
1715 }
1716 }
1717
1718 *r_item = nitem;
1719 }
1720 }
1721 #endif
1722
RNA_property_enum_items_gettexted(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const EnumPropertyItem ** r_item,int * r_totitem,bool * r_free)1723 void RNA_property_enum_items_gettexted(bContext *C,
1724 PointerRNA *ptr,
1725 PropertyRNA *prop,
1726 const EnumPropertyItem **r_item,
1727 int *r_totitem,
1728 bool *r_free)
1729 {
1730 RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
1731
1732 #ifdef WITH_INTERNATIONAL
1733 /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory
1734 * so allow the exception (callers are creating new arrays in this case). */
1735 property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free);
1736 #endif
1737 }
1738
RNA_property_enum_items_gettexted_all(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const EnumPropertyItem ** r_item,int * r_totitem,bool * r_free)1739 void RNA_property_enum_items_gettexted_all(bContext *C,
1740 PointerRNA *ptr,
1741 PropertyRNA *prop,
1742 const EnumPropertyItem **r_item,
1743 int *r_totitem,
1744 bool *r_free)
1745 {
1746 EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1747 int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
1748 /* first return all items */
1749 EnumPropertyItem *item_array = MEM_mallocN(mem_size, "enum_gettext_all");
1750 *r_free = true;
1751 memcpy(item_array, eprop->item, mem_size);
1752
1753 if (r_totitem) {
1754 *r_totitem = eprop->totitem;
1755 }
1756
1757 if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1758 const EnumPropertyItem *item;
1759 int i;
1760 bool free = false;
1761
1762 if (prop->flag & PROP_ENUM_NO_CONTEXT) {
1763 item = eprop->itemf(NULL, ptr, prop, &free);
1764 }
1765 else {
1766 item = eprop->itemf(C, ptr, prop, &free);
1767 }
1768
1769 /* any callbacks returning NULL should be fixed */
1770 BLI_assert(item != NULL);
1771
1772 for (i = 0; i < eprop->totitem; i++) {
1773 bool exists = false;
1774 int i_fixed;
1775
1776 /* Items that do not exist on list are returned,
1777 * but have their names/identifiers NULL'ed out. */
1778 for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
1779 if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
1780 exists = true;
1781 break;
1782 }
1783 }
1784
1785 if (!exists) {
1786 item_array[i].name = NULL;
1787 item_array[i].identifier = "";
1788 }
1789 }
1790
1791 if (free) {
1792 MEM_freeN((void *)item);
1793 }
1794 }
1795
1796 #ifdef WITH_INTERNATIONAL
1797 property_enum_translate(prop, &item_array, r_totitem, r_free);
1798 #endif
1799 *r_item = item_array;
1800 }
1801
RNA_property_enum_value(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const char * identifier,int * r_value)1802 bool RNA_property_enum_value(
1803 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
1804 {
1805 const EnumPropertyItem *item;
1806 bool free;
1807 bool found;
1808
1809 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1810
1811 if (item) {
1812 const int i = RNA_enum_from_identifier(item, identifier);
1813 if (i != -1) {
1814 *r_value = item[i].value;
1815 found = true;
1816 }
1817 else {
1818 found = false;
1819 }
1820
1821 if (free) {
1822 MEM_freeN((void *)item);
1823 }
1824 }
1825 else {
1826 found = false;
1827 }
1828 return found;
1829 }
1830
RNA_enum_identifier(const EnumPropertyItem * item,const int value,const char ** r_identifier)1831 bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
1832 {
1833 const int i = RNA_enum_from_value(item, value);
1834 if (i != -1) {
1835 *r_identifier = item[i].identifier;
1836 return true;
1837 }
1838 return false;
1839 }
1840
RNA_enum_bitflag_identifiers(const EnumPropertyItem * item,const int value,const char ** r_identifier)1841 int RNA_enum_bitflag_identifiers(const EnumPropertyItem *item,
1842 const int value,
1843 const char **r_identifier)
1844 {
1845 int index = 0;
1846 for (; item->identifier; item++) {
1847 if (item->identifier[0] && item->value & value) {
1848 r_identifier[index++] = item->identifier;
1849 }
1850 }
1851 r_identifier[index] = NULL;
1852 return index;
1853 }
1854
RNA_enum_name(const EnumPropertyItem * item,const int value,const char ** r_name)1855 bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
1856 {
1857 const int i = RNA_enum_from_value(item, value);
1858 if (i != -1) {
1859 *r_name = item[i].name;
1860 return true;
1861 }
1862 return false;
1863 }
1864
RNA_enum_description(const EnumPropertyItem * item,const int value,const char ** r_description)1865 bool RNA_enum_description(const EnumPropertyItem *item,
1866 const int value,
1867 const char **r_description)
1868 {
1869 const int i = RNA_enum_from_value(item, value);
1870 if (i != -1) {
1871 *r_description = item[i].description;
1872 return true;
1873 }
1874 return false;
1875 }
1876
RNA_enum_from_identifier(const EnumPropertyItem * item,const char * identifier)1877 int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
1878 {
1879 int i = 0;
1880 for (; item->identifier; item++, i++) {
1881 if (item->identifier[0] && STREQ(item->identifier, identifier)) {
1882 return i;
1883 }
1884 }
1885 return -1;
1886 }
1887
1888 /**
1889 * Take care using this with translated enums,
1890 * prefer #RNA_enum_from_identifier where possible.
1891 */
RNA_enum_from_name(const EnumPropertyItem * item,const char * name)1892 int RNA_enum_from_name(const EnumPropertyItem *item, const char *name)
1893 {
1894 int i = 0;
1895 for (; item->identifier; item++, i++) {
1896 if (item->identifier[0] && STREQ(item->name, name)) {
1897 return i;
1898 }
1899 }
1900 return -1;
1901 }
1902
RNA_enum_from_value(const EnumPropertyItem * item,const int value)1903 int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
1904 {
1905 int i = 0;
1906 for (; item->identifier; item++, i++) {
1907 if (item->identifier[0] && item->value == value) {
1908 return i;
1909 }
1910 }
1911 return -1;
1912 }
1913
RNA_enum_items_count(const EnumPropertyItem * item)1914 unsigned int RNA_enum_items_count(const EnumPropertyItem *item)
1915 {
1916 unsigned int i = 0;
1917
1918 while (item->identifier) {
1919 item++;
1920 i++;
1921 }
1922
1923 return i;
1924 }
1925
RNA_property_enum_identifier(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const int value,const char ** identifier)1926 bool RNA_property_enum_identifier(
1927 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
1928 {
1929 const EnumPropertyItem *item = NULL;
1930 bool free;
1931
1932 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1933 if (item) {
1934 bool result;
1935 result = RNA_enum_identifier(item, value, identifier);
1936 if (free) {
1937 MEM_freeN((void *)item);
1938 }
1939 return result;
1940 }
1941 return false;
1942 }
1943
RNA_property_enum_name(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const int value,const char ** name)1944 bool RNA_property_enum_name(
1945 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1946 {
1947 const EnumPropertyItem *item = NULL;
1948 bool free;
1949
1950 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1951 if (item) {
1952 bool result;
1953 result = RNA_enum_name(item, value, name);
1954 if (free) {
1955 MEM_freeN((void *)item);
1956 }
1957
1958 return result;
1959 }
1960 return false;
1961 }
1962
RNA_property_enum_name_gettexted(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const int value,const char ** name)1963 bool RNA_property_enum_name_gettexted(
1964 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1965 {
1966 bool result;
1967
1968 result = RNA_property_enum_name(C, ptr, prop, value, name);
1969
1970 if (result) {
1971 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1972 if (BLT_translate_iface()) {
1973 *name = BLT_pgettext(prop->translation_context, *name);
1974 }
1975 }
1976 }
1977
1978 return result;
1979 }
1980
RNA_property_enum_item_from_value(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const int value,EnumPropertyItem * r_item)1981 bool RNA_property_enum_item_from_value(
1982 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
1983 {
1984 const EnumPropertyItem *item = NULL;
1985 bool free;
1986
1987 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1988 if (item) {
1989 const int i = RNA_enum_from_value(item, value);
1990 bool result;
1991
1992 if (i != -1) {
1993 *r_item = item[i];
1994 result = true;
1995 }
1996 else {
1997 result = false;
1998 }
1999
2000 if (free) {
2001 MEM_freeN((void *)item);
2002 }
2003
2004 return result;
2005 }
2006 return false;
2007 }
2008
RNA_property_enum_item_from_value_gettexted(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const int value,EnumPropertyItem * r_item)2009 bool RNA_property_enum_item_from_value_gettexted(
2010 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
2011 {
2012 bool result;
2013
2014 result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
2015
2016 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
2017 if (BLT_translate_iface()) {
2018 r_item->name = BLT_pgettext(prop->translation_context, r_item->name);
2019 }
2020 }
2021
2022 return result;
2023 }
2024
RNA_property_enum_bitflag_identifiers(bContext * C,PointerRNA * ptr,PropertyRNA * prop,const int value,const char ** identifier)2025 int RNA_property_enum_bitflag_identifiers(
2026 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
2027 {
2028 const EnumPropertyItem *item = NULL;
2029 bool free;
2030
2031 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
2032 if (item) {
2033 int result;
2034 result = RNA_enum_bitflag_identifiers(item, value, identifier);
2035 if (free) {
2036 MEM_freeN((void *)item);
2037 }
2038
2039 return result;
2040 }
2041 return 0;
2042 }
2043
RNA_property_ui_name(const PropertyRNA * prop)2044 const char *RNA_property_ui_name(const PropertyRNA *prop)
2045 {
2046 return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
2047 }
2048
RNA_property_ui_name_raw(const PropertyRNA * prop)2049 const char *RNA_property_ui_name_raw(const PropertyRNA *prop)
2050 {
2051 return rna_ensure_property_name(prop);
2052 }
2053
RNA_property_ui_description(const PropertyRNA * prop)2054 const char *RNA_property_ui_description(const PropertyRNA *prop)
2055 {
2056 return TIP_(rna_ensure_property_description(prop));
2057 }
2058
RNA_property_ui_description_raw(const PropertyRNA * prop)2059 const char *RNA_property_ui_description_raw(const PropertyRNA *prop)
2060 {
2061 return rna_ensure_property_description(prop);
2062 }
2063
RNA_property_translation_context(const PropertyRNA * prop)2064 const char *RNA_property_translation_context(const PropertyRNA *prop)
2065 {
2066 return rna_ensure_property((PropertyRNA *)prop)->translation_context;
2067 }
2068
RNA_property_ui_icon(const PropertyRNA * prop)2069 int RNA_property_ui_icon(const PropertyRNA *prop)
2070 {
2071 return rna_ensure_property((PropertyRNA *)prop)->icon;
2072 }
2073
RNA_property_editable(PointerRNA * ptr,PropertyRNA * prop_orig)2074 bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop_orig)
2075 {
2076 ID *id = ptr->owner_id;
2077 int flag;
2078 const char *dummy_info;
2079
2080 PropertyRNA *prop = rna_ensure_property(prop_orig);
2081 flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
2082
2083 return (
2084 (flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0 &&
2085 (!id || ((!ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)) &&
2086 (!ID_IS_OVERRIDE_LIBRARY(id) || RNA_property_overridable_get(ptr, prop_orig)))));
2087 }
2088
2089 /**
2090 * Version of #RNA_property_editable that tries to return additional info in \a r_info
2091 * that can be exposed in UI.
2092 */
RNA_property_editable_info(PointerRNA * ptr,PropertyRNA * prop,const char ** r_info)2093 bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
2094 {
2095 ID *id = ptr->owner_id;
2096 int flag;
2097
2098 PropertyRNA *prop_type = rna_ensure_property(prop);
2099 *r_info = "";
2100
2101 /* get flag */
2102 if (prop_type->editable) {
2103 flag = prop_type->editable(ptr, r_info);
2104 }
2105 else {
2106 flag = prop_type->flag;
2107 if ((flag & PROP_EDITABLE) == 0 || (flag & PROP_REGISTER)) {
2108 *r_info = N_("This property is for internal use only and can't be edited");
2109 }
2110 }
2111
2112 /* property from linked data-block */
2113 if (id) {
2114 if (ID_IS_LINKED(id) && (prop_type->flag & PROP_LIB_EXCEPTION) == 0) {
2115 if (!(*r_info)[0]) {
2116 *r_info = N_("Can't edit this property from a linked data-block");
2117 }
2118 return false;
2119 }
2120 if (ID_IS_OVERRIDE_LIBRARY(id)) {
2121 if (!RNA_property_overridable_get(ptr, prop)) {
2122 if (!(*r_info)[0]) {
2123 *r_info = N_("Can't edit this property from an override data-block");
2124 }
2125 return false;
2126 }
2127 }
2128 }
2129
2130 return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
2131 }
2132
RNA_property_editable_flag(PointerRNA * ptr,PropertyRNA * prop)2133 bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
2134 {
2135 int flag;
2136 const char *dummy_info;
2137
2138 prop = rna_ensure_property(prop);
2139 flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
2140 return (flag & PROP_EDITABLE) != 0;
2141 }
2142
2143 /* same as RNA_property_editable(), except this checks individual items in an array */
RNA_property_editable_index(PointerRNA * ptr,PropertyRNA * prop,int index)2144 bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2145 {
2146 ID *id;
2147 int flag;
2148
2149 BLI_assert(index >= 0);
2150
2151 prop = rna_ensure_property(prop);
2152
2153 flag = prop->flag;
2154
2155 if (prop->editable) {
2156 const char *dummy_info;
2157 flag &= prop->editable(ptr, &dummy_info);
2158 }
2159
2160 if (prop->itemeditable) {
2161 flag &= prop->itemeditable(ptr, index);
2162 }
2163
2164 id = ptr->owner_id;
2165
2166 return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION));
2167 }
2168
RNA_property_animateable(PointerRNA * ptr,PropertyRNA * prop)2169 bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
2170 {
2171 /* check that base ID-block can support animation data */
2172 if (!id_can_have_animdata(ptr->owner_id)) {
2173 return false;
2174 }
2175
2176 prop = rna_ensure_property(prop);
2177
2178 if (!(prop->flag & PROP_ANIMATABLE)) {
2179 return false;
2180 }
2181
2182 return (prop->flag & PROP_EDITABLE) != 0;
2183 }
2184
RNA_property_animated(PointerRNA * ptr,PropertyRNA * prop)2185 bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
2186 {
2187 int len = 1, index;
2188 bool driven, special;
2189
2190 if (!prop) {
2191 return false;
2192 }
2193
2194 if (RNA_property_array_check(prop)) {
2195 len = RNA_property_array_length(ptr, prop);
2196 }
2197
2198 for (index = 0; index < len; index++) {
2199 if (BKE_fcurve_find_by_rna(ptr, prop, index, NULL, NULL, &driven, &special)) {
2200 return true;
2201 }
2202 }
2203
2204 return false;
2205 }
2206 /* this function is to check if its possible to create a valid path from the ID
2207 * its slow so don't call in a loop */
RNA_property_path_from_ID_check(PointerRNA * ptr,PropertyRNA * prop)2208 bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
2209 {
2210 char *path = RNA_path_from_ID_to_property(ptr, prop);
2211 bool ret = false;
2212
2213 if (path) {
2214 PointerRNA id_ptr;
2215 PointerRNA r_ptr;
2216 PropertyRNA *r_prop;
2217
2218 RNA_id_pointer_create(ptr->owner_id, &id_ptr);
2219 if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
2220 ret = (prop == r_prop);
2221 }
2222 MEM_freeN(path);
2223 }
2224
2225 return ret;
2226 }
2227
rna_property_update(bContext * C,Main * bmain,Scene * scene,PointerRNA * ptr,PropertyRNA * prop)2228 static void rna_property_update(
2229 bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2230 {
2231 const bool is_rna = (prop->magic == RNA_MAGIC);
2232 prop = rna_ensure_property(prop);
2233
2234 if (is_rna) {
2235 if (prop->update) {
2236 /* ideally no context would be needed for update, but there's some
2237 * parts of the code that need it still, so we have this exception */
2238 if (prop->flag & PROP_CONTEXT_UPDATE) {
2239 if (C) {
2240 if ((prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) == PROP_CONTEXT_PROPERTY_UPDATE) {
2241 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
2242 }
2243 else {
2244 ((ContextUpdateFunc)prop->update)(C, ptr);
2245 }
2246 }
2247 }
2248 else {
2249 prop->update(bmain, scene, ptr);
2250 }
2251 }
2252
2253 #if 1
2254 /* TODO(campbell): Should eventually be replaced entirely by message bus (below)
2255 * for now keep since COW, bugs are hard to track when we have other missing updates. */
2256 if (prop->noteflag) {
2257 WM_main_add_notifier(prop->noteflag, ptr->owner_id);
2258 }
2259 #endif
2260
2261 /* if C is NULL, we're updating from animation.
2262 * avoid slow-down from f-curves by not publishing (for now). */
2263 if (C != NULL) {
2264 struct wmMsgBus *mbus = CTX_wm_message_bus(C);
2265 /* we could add NULL check, for now don't */
2266 WM_msg_publish_rna(mbus, ptr, prop);
2267 }
2268 if (ptr->owner_id != NULL && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) {
2269 const short id_type = GS(ptr->owner_id->name);
2270 if (ID_TYPE_IS_COW(id_type)) {
2271 DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE);
2272 }
2273 }
2274 /* End message bus. */
2275 }
2276
2277 if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
2278
2279 /* Disclaimer: this logic is not applied consistently, causing some confusing behavior.
2280 *
2281 * - When animated (which skips update functions).
2282 * - When ID-properties are edited via Python (since RNA properties aren't used in this case).
2283 *
2284 * Adding updates will add a lot of overhead in the case of animation.
2285 * For Python it may cause unexpected slow-downs for developers using ID-properties
2286 * for data storage. Further, the root ID isn't available with nested data-structures.
2287 *
2288 * So editing custom properties only causes updates in the UI,
2289 * keep this exception because it happens to be useful for driving settings.
2290 * Python developers on the other hand will need to manually 'update_tag', see: T74000. */
2291 DEG_id_tag_update(ptr->owner_id,
2292 ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_PARAMETERS);
2293
2294 WM_main_add_notifier(NC_WINDOW, NULL);
2295 /* Not nice as well, but the only way to make sure material preview
2296 * is updated with custom nodes.
2297 */
2298 if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->owner_id != NULL) &&
2299 (GS(ptr->owner_id->name) == ID_NT)) {
2300 WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
2301 }
2302 }
2303 }
2304
2305 /* must keep in sync with 'rna_property_update'
2306 * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
2307 * but this isn't likely to be a performance problem. */
RNA_property_update_check(PropertyRNA * prop)2308 bool RNA_property_update_check(PropertyRNA *prop)
2309 {
2310 return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
2311 }
2312
RNA_property_update(bContext * C,PointerRNA * ptr,PropertyRNA * prop)2313 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
2314 {
2315 rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
2316 }
2317
RNA_property_update_main(Main * bmain,Scene * scene,PointerRNA * ptr,PropertyRNA * prop)2318 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2319 {
2320 rna_property_update(NULL, bmain, scene, ptr, prop);
2321 }
2322
2323 /* ---------------------------------------------------------------------- */
2324
2325 /* Property Data */
2326
RNA_property_boolean_get(PointerRNA * ptr,PropertyRNA * prop)2327 bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
2328 {
2329 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2330 IDProperty *idprop;
2331 bool value;
2332
2333 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2334 BLI_assert(RNA_property_array_check(prop) == false);
2335
2336 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2337 value = IDP_Int(idprop) != 0;
2338 }
2339 else if (bprop->get) {
2340 value = bprop->get(ptr);
2341 }
2342 else if (bprop->get_ex) {
2343 value = bprop->get_ex(ptr, prop);
2344 }
2345 else {
2346 value = bprop->defaultvalue;
2347 }
2348
2349 BLI_assert(ELEM(value, false, true));
2350
2351 return value;
2352 }
2353
RNA_property_boolean_set(PointerRNA * ptr,PropertyRNA * prop,bool value)2354 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
2355 {
2356 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2357 IDProperty *idprop;
2358
2359 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2360 BLI_assert(RNA_property_array_check(prop) == false);
2361 BLI_assert(ELEM(value, false, true));
2362
2363 /* just in case other values are passed */
2364 BLI_assert(ELEM(value, true, false));
2365
2366 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2367 IDP_Int(idprop) = (int)value;
2368 rna_idproperty_touch(idprop);
2369 }
2370 else if (bprop->set) {
2371 bprop->set(ptr, value);
2372 }
2373 else if (bprop->set_ex) {
2374 bprop->set_ex(ptr, prop, value);
2375 }
2376 else if (prop->flag & PROP_EDITABLE) {
2377 IDPropertyTemplate val = {0};
2378 IDProperty *group;
2379
2380 val.i = value;
2381
2382 group = RNA_struct_idprops(ptr, 1);
2383 if (group) {
2384 IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2385 }
2386 }
2387 }
2388
rna_property_boolean_fill_default_array_values(const bool * defarr,int defarr_length,bool defvalue,int out_length,bool * r_values)2389 static void rna_property_boolean_fill_default_array_values(
2390 const bool *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values)
2391 {
2392 if (defarr && defarr_length > 0) {
2393 defarr_length = MIN2(defarr_length, out_length);
2394 memcpy(r_values, defarr, sizeof(bool) * defarr_length);
2395 }
2396 else {
2397 defarr_length = 0;
2398 }
2399
2400 for (int i = defarr_length; i < out_length; i++) {
2401 r_values[i] = defvalue;
2402 }
2403 }
2404
rna_property_boolean_get_default_array_values(PointerRNA * ptr,BoolPropertyRNA * bprop,bool * r_values)2405 static void rna_property_boolean_get_default_array_values(PointerRNA *ptr,
2406 BoolPropertyRNA *bprop,
2407 bool *r_values)
2408 {
2409 int length = bprop->property.totarraylength;
2410 int out_length = RNA_property_array_length(ptr, (PropertyRNA *)bprop);
2411
2412 rna_property_boolean_fill_default_array_values(
2413 bprop->defaultarray, length, bprop->defaultvalue, out_length, r_values);
2414 }
2415
RNA_property_boolean_get_array(PointerRNA * ptr,PropertyRNA * prop,bool * values)2416 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
2417 {
2418 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2419 IDProperty *idprop;
2420
2421 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2422 BLI_assert(RNA_property_array_check(prop) != false);
2423
2424 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2425 if (prop->arraydimension == 0) {
2426 values[0] = RNA_property_boolean_get(ptr, prop);
2427 }
2428 else {
2429 int *values_src = IDP_Array(idprop);
2430 for (uint i = 0; i < idprop->len; i++) {
2431 values[i] = (bool)values_src[i];
2432 }
2433 }
2434 }
2435 else if (prop->arraydimension == 0) {
2436 values[0] = RNA_property_boolean_get(ptr, prop);
2437 }
2438 else if (bprop->getarray) {
2439 bprop->getarray(ptr, values);
2440 }
2441 else if (bprop->getarray_ex) {
2442 bprop->getarray_ex(ptr, prop, values);
2443 }
2444 else {
2445 rna_property_boolean_get_default_array_values(ptr, bprop, values);
2446 }
2447 }
2448
RNA_property_boolean_get_index(PointerRNA * ptr,PropertyRNA * prop,int index)2449 bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2450 {
2451 bool tmp[RNA_MAX_ARRAY_LENGTH];
2452 int len = rna_ensure_property_array_length(ptr, prop);
2453 bool value;
2454
2455 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2456 BLI_assert(RNA_property_array_check(prop) != false);
2457 BLI_assert(index >= 0);
2458 BLI_assert(index < len);
2459
2460 if (len <= RNA_MAX_ARRAY_LENGTH) {
2461 RNA_property_boolean_get_array(ptr, prop, tmp);
2462 value = tmp[index];
2463 }
2464 else {
2465 bool *tmparray;
2466
2467 tmparray = MEM_mallocN(sizeof(bool) * len, __func__);
2468 RNA_property_boolean_get_array(ptr, prop, tmparray);
2469 value = tmparray[index];
2470 MEM_freeN(tmparray);
2471 }
2472
2473 BLI_assert(ELEM(value, false, true));
2474
2475 return value;
2476 }
2477
RNA_property_boolean_set_array(PointerRNA * ptr,PropertyRNA * prop,const bool * values)2478 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
2479 {
2480 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2481 IDProperty *idprop;
2482
2483 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2484 BLI_assert(RNA_property_array_check(prop) != false);
2485
2486 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2487 if (prop->arraydimension == 0) {
2488 IDP_Int(idprop) = values[0];
2489 }
2490 else {
2491 int *values_dst = IDP_Array(idprop);
2492 for (uint i = 0; i < idprop->len; i++) {
2493 values_dst[i] = (int)values[i];
2494 }
2495 }
2496 rna_idproperty_touch(idprop);
2497 }
2498 else if (prop->arraydimension == 0) {
2499 RNA_property_boolean_set(ptr, prop, values[0]);
2500 }
2501 else if (bprop->setarray) {
2502 bprop->setarray(ptr, values);
2503 }
2504 else if (bprop->setarray_ex) {
2505 bprop->setarray_ex(ptr, prop, values);
2506 }
2507 else if (prop->flag & PROP_EDITABLE) {
2508 IDPropertyTemplate val = {0};
2509 IDProperty *group;
2510
2511 val.array.len = prop->totarraylength;
2512 val.array.type = IDP_INT;
2513
2514 group = RNA_struct_idprops(ptr, 1);
2515 if (group) {
2516 idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2517 IDP_AddToGroup(group, idprop);
2518 int *values_dst = IDP_Array(idprop);
2519 for (uint i = 0; i < idprop->len; i++) {
2520 values_dst[i] = (int)values[i];
2521 }
2522 }
2523 }
2524 }
2525
RNA_property_boolean_set_index(PointerRNA * ptr,PropertyRNA * prop,int index,bool value)2526 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
2527 {
2528 bool tmp[RNA_MAX_ARRAY_LENGTH];
2529 int len = rna_ensure_property_array_length(ptr, prop);
2530
2531 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2532 BLI_assert(RNA_property_array_check(prop) != false);
2533 BLI_assert(index >= 0);
2534 BLI_assert(index < len);
2535 BLI_assert(ELEM(value, false, true));
2536
2537 if (len <= RNA_MAX_ARRAY_LENGTH) {
2538 RNA_property_boolean_get_array(ptr, prop, tmp);
2539 tmp[index] = value;
2540 RNA_property_boolean_set_array(ptr, prop, tmp);
2541 }
2542 else {
2543 bool *tmparray;
2544
2545 tmparray = MEM_mallocN(sizeof(bool) * len, __func__);
2546 RNA_property_boolean_get_array(ptr, prop, tmparray);
2547 tmparray[index] = value;
2548 RNA_property_boolean_set_array(ptr, prop, tmparray);
2549 MEM_freeN(tmparray);
2550 }
2551 }
2552
RNA_property_boolean_get_default(PointerRNA * UNUSED (ptr),PropertyRNA * prop)2553 bool RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2554 {
2555 BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2556
2557 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2558 BLI_assert(RNA_property_array_check(prop) == false);
2559 BLI_assert(ELEM(bprop->defaultvalue, false, true));
2560
2561 return bprop->defaultvalue;
2562 }
2563
RNA_property_boolean_get_default_array(PointerRNA * ptr,PropertyRNA * prop,bool * values)2564 void RNA_property_boolean_get_default_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
2565 {
2566 BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2567
2568 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2569 BLI_assert(RNA_property_array_check(prop) != false);
2570
2571 if (prop->arraydimension == 0) {
2572 values[0] = bprop->defaultvalue;
2573 }
2574 else {
2575 rna_property_boolean_get_default_array_values(ptr, bprop, values);
2576 }
2577 }
2578
RNA_property_boolean_get_default_index(PointerRNA * ptr,PropertyRNA * prop,int index)2579 bool RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2580 {
2581 bool tmp[RNA_MAX_ARRAY_LENGTH];
2582 int len = rna_ensure_property_array_length(ptr, prop);
2583
2584 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2585 BLI_assert(RNA_property_array_check(prop) != false);
2586 BLI_assert(index >= 0);
2587 BLI_assert(index < len);
2588
2589 if (len <= RNA_MAX_ARRAY_LENGTH) {
2590 RNA_property_boolean_get_default_array(ptr, prop, tmp);
2591 return tmp[index];
2592 }
2593 bool *tmparray, value;
2594
2595 tmparray = MEM_mallocN(sizeof(bool) * len, __func__);
2596 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
2597 value = tmparray[index];
2598 MEM_freeN(tmparray);
2599
2600 return value;
2601 }
2602
RNA_property_int_get(PointerRNA * ptr,PropertyRNA * prop)2603 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
2604 {
2605 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2606 IDProperty *idprop;
2607
2608 BLI_assert(RNA_property_type(prop) == PROP_INT);
2609 BLI_assert(RNA_property_array_check(prop) == false);
2610
2611 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2612 return IDP_Int(idprop);
2613 }
2614 if (iprop->get) {
2615 return iprop->get(ptr);
2616 }
2617 else if (iprop->get_ex) {
2618 return iprop->get_ex(ptr, prop);
2619 }
2620 else {
2621 return iprop->defaultvalue;
2622 }
2623 }
2624
RNA_property_int_set(PointerRNA * ptr,PropertyRNA * prop,int value)2625 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2626 {
2627 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2628 IDProperty *idprop;
2629
2630 BLI_assert(RNA_property_type(prop) == PROP_INT);
2631 BLI_assert(RNA_property_array_check(prop) == false);
2632 /* useful to check on bad values but set function should clamp */
2633 /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
2634
2635 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2636 RNA_property_int_clamp(ptr, prop, &value);
2637 IDP_Int(idprop) = value;
2638 rna_idproperty_touch(idprop);
2639 }
2640 else if (iprop->set) {
2641 iprop->set(ptr, value);
2642 }
2643 else if (iprop->set_ex) {
2644 iprop->set_ex(ptr, prop, value);
2645 }
2646 else if (prop->flag & PROP_EDITABLE) {
2647 IDPropertyTemplate val = {0};
2648 IDProperty *group;
2649
2650 RNA_property_int_clamp(ptr, prop, &value);
2651
2652 val.i = value;
2653
2654 group = RNA_struct_idprops(ptr, 1);
2655 if (group) {
2656 IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2657 }
2658 }
2659 }
2660
rna_property_int_fill_default_array_values(const int * defarr,int defarr_length,int defvalue,int out_length,int * r_values)2661 static void rna_property_int_fill_default_array_values(
2662 const int *defarr, int defarr_length, int defvalue, int out_length, int *r_values)
2663 {
2664 if (defarr && defarr_length > 0) {
2665 defarr_length = MIN2(defarr_length, out_length);
2666 memcpy(r_values, defarr, sizeof(int) * defarr_length);
2667 }
2668 else {
2669 defarr_length = 0;
2670 }
2671
2672 for (int i = defarr_length; i < out_length; i++) {
2673 r_values[i] = defvalue;
2674 }
2675 }
2676
rna_property_int_get_default_array_values(PointerRNA * ptr,IntPropertyRNA * iprop,int * r_values)2677 static void rna_property_int_get_default_array_values(PointerRNA *ptr,
2678 IntPropertyRNA *iprop,
2679 int *r_values)
2680 {
2681 int length = iprop->property.totarraylength;
2682 int out_length = RNA_property_array_length(ptr, (PropertyRNA *)iprop);
2683
2684 rna_property_int_fill_default_array_values(
2685 iprop->defaultarray, length, iprop->defaultvalue, out_length, r_values);
2686 }
2687
RNA_property_int_get_array(PointerRNA * ptr,PropertyRNA * prop,int * values)2688 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2689 {
2690 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2691 IDProperty *idprop;
2692
2693 BLI_assert(RNA_property_type(prop) == PROP_INT);
2694 BLI_assert(RNA_property_array_check(prop) != false);
2695
2696 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2697 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
2698 (prop->flag & PROP_IDPROPERTY));
2699 if (prop->arraydimension == 0) {
2700 values[0] = RNA_property_int_get(ptr, prop);
2701 }
2702 else {
2703 memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2704 }
2705 }
2706 else if (prop->arraydimension == 0) {
2707 values[0] = RNA_property_int_get(ptr, prop);
2708 }
2709 else if (iprop->getarray) {
2710 iprop->getarray(ptr, values);
2711 }
2712 else if (iprop->getarray_ex) {
2713 iprop->getarray_ex(ptr, prop, values);
2714 }
2715 else {
2716 rna_property_int_get_default_array_values(ptr, iprop, values);
2717 }
2718 }
2719
RNA_property_int_get_array_range(PointerRNA * ptr,PropertyRNA * prop,int values[2])2720 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
2721 {
2722 const int array_len = RNA_property_array_length(ptr, prop);
2723
2724 if (array_len <= 0) {
2725 values[0] = 0;
2726 values[1] = 0;
2727 }
2728 else if (array_len == 1) {
2729 RNA_property_int_get_array(ptr, prop, values);
2730 values[1] = values[0];
2731 }
2732 else {
2733 int arr_stack[32];
2734 int *arr;
2735 int i;
2736
2737 if (array_len > 32) {
2738 arr = MEM_mallocN(sizeof(int) * array_len, __func__);
2739 }
2740 else {
2741 arr = arr_stack;
2742 }
2743
2744 RNA_property_int_get_array(ptr, prop, arr);
2745 values[0] = values[1] = arr[0];
2746 for (i = 1; i < array_len; i++) {
2747 values[0] = MIN2(values[0], arr[i]);
2748 values[1] = MAX2(values[1], arr[i]);
2749 }
2750
2751 if (arr != arr_stack) {
2752 MEM_freeN(arr);
2753 }
2754 }
2755 }
2756
RNA_property_int_get_index(PointerRNA * ptr,PropertyRNA * prop,int index)2757 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2758 {
2759 int tmp[RNA_MAX_ARRAY_LENGTH];
2760 int len = rna_ensure_property_array_length(ptr, prop);
2761
2762 BLI_assert(RNA_property_type(prop) == PROP_INT);
2763 BLI_assert(RNA_property_array_check(prop) != false);
2764 BLI_assert(index >= 0);
2765 BLI_assert(index < len);
2766
2767 if (len <= RNA_MAX_ARRAY_LENGTH) {
2768 RNA_property_int_get_array(ptr, prop, tmp);
2769 return tmp[index];
2770 }
2771 int *tmparray, value;
2772
2773 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2774 RNA_property_int_get_array(ptr, prop, tmparray);
2775 value = tmparray[index];
2776 MEM_freeN(tmparray);
2777
2778 return value;
2779 }
2780
RNA_property_int_set_array(PointerRNA * ptr,PropertyRNA * prop,const int * values)2781 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2782 {
2783 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2784 IDProperty *idprop;
2785
2786 BLI_assert(RNA_property_type(prop) == PROP_INT);
2787 BLI_assert(RNA_property_array_check(prop) != false);
2788
2789 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2790 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
2791 (prop->flag & PROP_IDPROPERTY));
2792 if (prop->arraydimension == 0) {
2793 IDP_Int(idprop) = values[0];
2794 }
2795 else {
2796 memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2797 }
2798
2799 rna_idproperty_touch(idprop);
2800 }
2801 else if (prop->arraydimension == 0) {
2802 RNA_property_int_set(ptr, prop, values[0]);
2803 }
2804 else if (iprop->setarray) {
2805 iprop->setarray(ptr, values);
2806 }
2807 else if (iprop->setarray_ex) {
2808 iprop->setarray_ex(ptr, prop, values);
2809 }
2810 else if (prop->flag & PROP_EDITABLE) {
2811 IDPropertyTemplate val = {0};
2812 IDProperty *group;
2813
2814 /* TODO: RNA_property_int_clamp_array(ptr, prop, &value); */
2815
2816 val.array.len = prop->totarraylength;
2817 val.array.type = IDP_INT;
2818
2819 group = RNA_struct_idprops(ptr, 1);
2820 if (group) {
2821 idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2822 IDP_AddToGroup(group, idprop);
2823 memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2824 }
2825 }
2826 }
2827
RNA_property_int_set_index(PointerRNA * ptr,PropertyRNA * prop,int index,int value)2828 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2829 {
2830 int tmp[RNA_MAX_ARRAY_LENGTH];
2831 int len = rna_ensure_property_array_length(ptr, prop);
2832
2833 BLI_assert(RNA_property_type(prop) == PROP_INT);
2834 BLI_assert(RNA_property_array_check(prop) != false);
2835 BLI_assert(index >= 0);
2836 BLI_assert(index < len);
2837
2838 if (len <= RNA_MAX_ARRAY_LENGTH) {
2839 RNA_property_int_get_array(ptr, prop, tmp);
2840 tmp[index] = value;
2841 RNA_property_int_set_array(ptr, prop, tmp);
2842 }
2843 else {
2844 int *tmparray;
2845
2846 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2847 RNA_property_int_get_array(ptr, prop, tmparray);
2848 tmparray[index] = value;
2849 RNA_property_int_set_array(ptr, prop, tmparray);
2850 MEM_freeN(tmparray);
2851 }
2852 }
2853
RNA_property_int_get_default(PointerRNA * UNUSED (ptr),PropertyRNA * prop)2854 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2855 {
2856 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2857
2858 if (prop->magic != RNA_MAGIC) {
2859 /* attempt to get the local ID values */
2860 const IDProperty *idp_ui = rna_idproperty_ui(prop);
2861
2862 if (idp_ui) {
2863 IDProperty *item;
2864
2865 item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", IDP_INT);
2866 return item ? IDP_Int(item) : iprop->defaultvalue;
2867 }
2868 }
2869
2870 return iprop->defaultvalue;
2871 }
2872
RNA_property_int_set_default(PointerRNA * ptr,PropertyRNA * prop,int value)2873 bool RNA_property_int_set_default(PointerRNA *ptr, PropertyRNA *prop, int value)
2874 {
2875 if (value != 0) {
2876 IDPropertyTemplate val = {
2877 .i = value,
2878 };
2879 return rna_idproperty_ui_set_default(ptr, prop, IDP_INT, &val);
2880 }
2881 return rna_idproperty_ui_set_default(ptr, prop, IDP_INT, NULL);
2882 }
2883
RNA_property_int_get_default_array(PointerRNA * ptr,PropertyRNA * prop,int * values)2884 void RNA_property_int_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2885 {
2886 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2887
2888 BLI_assert(RNA_property_type(prop) == PROP_INT);
2889 BLI_assert(RNA_property_array_check(prop) != false);
2890
2891 if (prop->magic != RNA_MAGIC) {
2892 int length = rna_ensure_property_array_length(ptr, prop);
2893
2894 const IDProperty *idp_ui = rna_idproperty_ui(prop);
2895 IDProperty *item = idp_ui ? IDP_GetPropertyFromGroup(idp_ui, "default") : NULL;
2896
2897 int defval = (item && item->type == IDP_INT) ? IDP_Int(item) : iprop->defaultvalue;
2898
2899 if (item && item->type == IDP_ARRAY && item->subtype == IDP_INT) {
2900 rna_property_int_fill_default_array_values(
2901 IDP_Array(item), item->len, defval, length, values);
2902 }
2903 else {
2904 rna_property_int_fill_default_array_values(NULL, 0, defval, length, values);
2905 }
2906 }
2907 else if (prop->arraydimension == 0) {
2908 values[0] = iprop->defaultvalue;
2909 }
2910 else {
2911 rna_property_int_get_default_array_values(ptr, iprop, values);
2912 }
2913 }
2914
RNA_property_int_get_default_index(PointerRNA * ptr,PropertyRNA * prop,int index)2915 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2916 {
2917 int tmp[RNA_MAX_ARRAY_LENGTH];
2918 int len = rna_ensure_property_array_length(ptr, prop);
2919
2920 BLI_assert(RNA_property_type(prop) == PROP_INT);
2921 BLI_assert(RNA_property_array_check(prop) != false);
2922 BLI_assert(index >= 0);
2923 BLI_assert(index < len);
2924
2925 if (len <= RNA_MAX_ARRAY_LENGTH) {
2926 RNA_property_int_get_default_array(ptr, prop, tmp);
2927 return tmp[index];
2928 }
2929 int *tmparray, value;
2930
2931 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2932 RNA_property_int_get_default_array(ptr, prop, tmparray);
2933 value = tmparray[index];
2934 MEM_freeN(tmparray);
2935
2936 return value;
2937 }
2938
RNA_property_float_get(PointerRNA * ptr,PropertyRNA * prop)2939 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
2940 {
2941 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2942 IDProperty *idprop;
2943
2944 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2945 BLI_assert(RNA_property_array_check(prop) == false);
2946
2947 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2948 if (idprop->type == IDP_FLOAT) {
2949 return IDP_Float(idprop);
2950 }
2951 return (float)IDP_Double(idprop);
2952 }
2953 else if (fprop->get) {
2954 return fprop->get(ptr);
2955 }
2956 else if (fprop->get_ex) {
2957 return fprop->get_ex(ptr, prop);
2958 }
2959 else {
2960 return fprop->defaultvalue;
2961 }
2962 }
2963
RNA_property_float_set(PointerRNA * ptr,PropertyRNA * prop,float value)2964 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
2965 {
2966 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2967 IDProperty *idprop;
2968
2969 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2970 BLI_assert(RNA_property_array_check(prop) == false);
2971 /* useful to check on bad values but set function should clamp */
2972 /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
2973
2974 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2975 RNA_property_float_clamp(ptr, prop, &value);
2976 if (idprop->type == IDP_FLOAT) {
2977 IDP_Float(idprop) = value;
2978 }
2979 else {
2980 IDP_Double(idprop) = value;
2981 }
2982
2983 rna_idproperty_touch(idprop);
2984 }
2985 else if (fprop->set) {
2986 fprop->set(ptr, value);
2987 }
2988 else if (fprop->set_ex) {
2989 fprop->set_ex(ptr, prop, value);
2990 }
2991 else if (prop->flag & PROP_EDITABLE) {
2992 IDPropertyTemplate val = {0};
2993 IDProperty *group;
2994
2995 RNA_property_float_clamp(ptr, prop, &value);
2996
2997 val.f = value;
2998
2999 group = RNA_struct_idprops(ptr, 1);
3000 if (group) {
3001 IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
3002 }
3003 }
3004 }
3005
rna_property_float_fill_default_array_values(const float * defarr,int defarr_length,float defvalue,int out_length,float * r_values)3006 static void rna_property_float_fill_default_array_values(
3007 const float *defarr, int defarr_length, float defvalue, int out_length, float *r_values)
3008 {
3009 if (defarr && defarr_length > 0) {
3010 defarr_length = MIN2(defarr_length, out_length);
3011 memcpy(r_values, defarr, sizeof(float) * defarr_length);
3012 }
3013 else {
3014 defarr_length = 0;
3015 }
3016
3017 for (int i = defarr_length; i < out_length; i++) {
3018 r_values[i] = defvalue;
3019 }
3020 }
3021
rna_property_float_get_default_array_values(PointerRNA * ptr,FloatPropertyRNA * fprop,float * r_values)3022 static void rna_property_float_get_default_array_values(PointerRNA *ptr,
3023 FloatPropertyRNA *fprop,
3024 float *r_values)
3025 {
3026 int length = fprop->property.totarraylength;
3027 int out_length = RNA_property_array_length(ptr, (PropertyRNA *)fprop);
3028
3029 rna_property_float_fill_default_array_values(
3030 fprop->defaultarray, length, fprop->defaultvalue, out_length, r_values);
3031 }
3032
RNA_property_float_get_array(PointerRNA * ptr,PropertyRNA * prop,float * values)3033 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
3034 {
3035 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
3036 IDProperty *idprop;
3037 int i;
3038
3039 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3040 BLI_assert(RNA_property_array_check(prop) != false);
3041
3042 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3043 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
3044 (prop->flag & PROP_IDPROPERTY));
3045 if (prop->arraydimension == 0) {
3046 values[0] = RNA_property_float_get(ptr, prop);
3047 }
3048 else if (idprop->subtype == IDP_FLOAT) {
3049 memcpy(values, IDP_Array(idprop), sizeof(float) * idprop->len);
3050 }
3051 else {
3052 for (i = 0; i < idprop->len; i++) {
3053 values[i] = (float)(((double *)IDP_Array(idprop))[i]);
3054 }
3055 }
3056 }
3057 else if (prop->arraydimension == 0) {
3058 values[0] = RNA_property_float_get(ptr, prop);
3059 }
3060 else if (fprop->getarray) {
3061 fprop->getarray(ptr, values);
3062 }
3063 else if (fprop->getarray_ex) {
3064 fprop->getarray_ex(ptr, prop, values);
3065 }
3066 else {
3067 rna_property_float_get_default_array_values(ptr, fprop, values);
3068 }
3069 }
3070
RNA_property_float_get_array_range(PointerRNA * ptr,PropertyRNA * prop,float values[2])3071 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
3072 {
3073 const int array_len = RNA_property_array_length(ptr, prop);
3074
3075 if (array_len <= 0) {
3076 values[0] = 0.0f;
3077 values[1] = 0.0f;
3078 }
3079 else if (array_len == 1) {
3080 RNA_property_float_get_array(ptr, prop, values);
3081 values[1] = values[0];
3082 }
3083 else {
3084 float arr_stack[32];
3085 float *arr;
3086 int i;
3087
3088 if (array_len > 32) {
3089 arr = MEM_mallocN(sizeof(float) * array_len, __func__);
3090 }
3091 else {
3092 arr = arr_stack;
3093 }
3094
3095 RNA_property_float_get_array(ptr, prop, arr);
3096 values[0] = values[1] = arr[0];
3097 for (i = 1; i < array_len; i++) {
3098 values[0] = MIN2(values[0], arr[i]);
3099 values[1] = MAX2(values[1], arr[i]);
3100 }
3101
3102 if (arr != arr_stack) {
3103 MEM_freeN(arr);
3104 }
3105 }
3106 }
3107
RNA_property_float_get_index(PointerRNA * ptr,PropertyRNA * prop,int index)3108 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
3109 {
3110 float tmp[RNA_MAX_ARRAY_LENGTH];
3111 int len = rna_ensure_property_array_length(ptr, prop);
3112
3113 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3114 BLI_assert(RNA_property_array_check(prop) != false);
3115 BLI_assert(index >= 0);
3116 BLI_assert(index < len);
3117
3118 if (len <= RNA_MAX_ARRAY_LENGTH) {
3119 RNA_property_float_get_array(ptr, prop, tmp);
3120 return tmp[index];
3121 }
3122 float *tmparray, value;
3123
3124 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
3125 RNA_property_float_get_array(ptr, prop, tmparray);
3126 value = tmparray[index];
3127 MEM_freeN(tmparray);
3128
3129 return value;
3130 }
3131
RNA_property_float_set_array(PointerRNA * ptr,PropertyRNA * prop,const float * values)3132 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
3133 {
3134 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
3135 IDProperty *idprop;
3136 int i;
3137
3138 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3139 BLI_assert(RNA_property_array_check(prop) != false);
3140
3141 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3142 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
3143 (prop->flag & PROP_IDPROPERTY));
3144 if (prop->arraydimension == 0) {
3145 if (idprop->type == IDP_FLOAT) {
3146 IDP_Float(idprop) = values[0];
3147 }
3148 else {
3149 IDP_Double(idprop) = values[0];
3150 }
3151 }
3152 else if (idprop->subtype == IDP_FLOAT) {
3153 memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
3154 }
3155 else {
3156 for (i = 0; i < idprop->len; i++) {
3157 ((double *)IDP_Array(idprop))[i] = values[i];
3158 }
3159 }
3160
3161 rna_idproperty_touch(idprop);
3162 }
3163 else if (prop->arraydimension == 0) {
3164 RNA_property_float_set(ptr, prop, values[0]);
3165 }
3166 else if (fprop->setarray) {
3167 fprop->setarray(ptr, values);
3168 }
3169 else if (fprop->setarray_ex) {
3170 fprop->setarray_ex(ptr, prop, values);
3171 }
3172 else if (prop->flag & PROP_EDITABLE) {
3173 IDPropertyTemplate val = {0};
3174 IDProperty *group;
3175
3176 /* TODO: RNA_property_float_clamp_array(ptr, prop, &value); */
3177
3178 val.array.len = prop->totarraylength;
3179 val.array.type = IDP_FLOAT;
3180
3181 group = RNA_struct_idprops(ptr, 1);
3182 if (group) {
3183 idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
3184 IDP_AddToGroup(group, idprop);
3185 memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
3186 }
3187 }
3188 }
3189
RNA_property_float_set_index(PointerRNA * ptr,PropertyRNA * prop,int index,float value)3190 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
3191 {
3192 float tmp[RNA_MAX_ARRAY_LENGTH];
3193 int len = rna_ensure_property_array_length(ptr, prop);
3194
3195 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3196 BLI_assert(RNA_property_array_check(prop) != false);
3197 BLI_assert(index >= 0);
3198 BLI_assert(index < len);
3199
3200 if (len <= RNA_MAX_ARRAY_LENGTH) {
3201 RNA_property_float_get_array(ptr, prop, tmp);
3202 tmp[index] = value;
3203 RNA_property_float_set_array(ptr, prop, tmp);
3204 }
3205 else {
3206 float *tmparray;
3207
3208 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
3209 RNA_property_float_get_array(ptr, prop, tmparray);
3210 tmparray[index] = value;
3211 RNA_property_float_set_array(ptr, prop, tmparray);
3212 MEM_freeN(tmparray);
3213 }
3214 }
3215
RNA_property_float_get_default(PointerRNA * UNUSED (ptr),PropertyRNA * prop)3216 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3217 {
3218 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
3219
3220 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3221 BLI_assert(RNA_property_array_check(prop) == false);
3222
3223 if (prop->magic != RNA_MAGIC) {
3224 /* attempt to get the local ID values */
3225 const IDProperty *idp_ui = rna_idproperty_ui(prop);
3226
3227 if (idp_ui) {
3228 IDProperty *item;
3229
3230 item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", IDP_DOUBLE);
3231 return item ? IDP_Double(item) : fprop->defaultvalue;
3232 }
3233 }
3234
3235 return fprop->defaultvalue;
3236 }
3237
RNA_property_float_set_default(PointerRNA * ptr,PropertyRNA * prop,float value)3238 bool RNA_property_float_set_default(PointerRNA *ptr, PropertyRNA *prop, float value)
3239 {
3240 if (value != 0) {
3241 IDPropertyTemplate val = {
3242 .d = value,
3243 };
3244 return rna_idproperty_ui_set_default(ptr, prop, IDP_DOUBLE, &val);
3245 }
3246 return rna_idproperty_ui_set_default(ptr, prop, IDP_DOUBLE, NULL);
3247 }
3248
RNA_property_float_get_default_array(PointerRNA * ptr,PropertyRNA * prop,float * values)3249 void RNA_property_float_get_default_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
3250 {
3251 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
3252
3253 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3254 BLI_assert(RNA_property_array_check(prop) != false);
3255
3256 if (prop->magic != RNA_MAGIC) {
3257 int length = rna_ensure_property_array_length(ptr, prop);
3258
3259 const IDProperty *idp_ui = rna_idproperty_ui(prop);
3260 IDProperty *item = idp_ui ? IDP_GetPropertyFromGroup(idp_ui, "default") : NULL;
3261
3262 float defval = (item && item->type == IDP_DOUBLE) ? IDP_Double(item) : fprop->defaultvalue;
3263
3264 if (item && item->type == IDP_ARRAY && item->subtype == IDP_DOUBLE) {
3265 double *defarr = IDP_Array(item);
3266 for (int i = 0; i < length; i++) {
3267 values[i] = (i < item->len) ? (float)defarr[i] : defval;
3268 }
3269 }
3270 else if (item && item->type == IDP_ARRAY && item->subtype == IDP_FLOAT) {
3271 rna_property_float_fill_default_array_values(
3272 IDP_Array(item), item->len, defval, length, values);
3273 }
3274 else {
3275 rna_property_float_fill_default_array_values(NULL, 0, defval, length, values);
3276 }
3277 }
3278 else if (prop->arraydimension == 0) {
3279 values[0] = fprop->defaultvalue;
3280 }
3281 else {
3282 rna_property_float_get_default_array_values(ptr, fprop, values);
3283 }
3284 }
3285
RNA_property_float_get_default_index(PointerRNA * ptr,PropertyRNA * prop,int index)3286 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
3287 {
3288 float tmp[RNA_MAX_ARRAY_LENGTH];
3289 int len = rna_ensure_property_array_length(ptr, prop);
3290
3291 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3292 BLI_assert(RNA_property_array_check(prop) != false);
3293 BLI_assert(index >= 0);
3294 BLI_assert(index < len);
3295
3296 if (len <= RNA_MAX_ARRAY_LENGTH) {
3297 RNA_property_float_get_default_array(ptr, prop, tmp);
3298 return tmp[index];
3299 }
3300 float *tmparray, value;
3301
3302 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
3303 RNA_property_float_get_default_array(ptr, prop, tmparray);
3304 value = tmparray[index];
3305 MEM_freeN(tmparray);
3306
3307 return value;
3308 }
3309
RNA_property_string_get(PointerRNA * ptr,PropertyRNA * prop,char * value)3310 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
3311 {
3312 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3313 IDProperty *idprop;
3314
3315 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3316
3317 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3318 /* editing bytes is not 100% supported
3319 * since they can contain NIL chars */
3320 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
3321 memcpy(value, IDP_String(idprop), idprop->len);
3322 value[idprop->len] = '\0';
3323 }
3324 else {
3325 memcpy(value, IDP_String(idprop), idprop->len);
3326 }
3327 }
3328 else if (sprop->get) {
3329 sprop->get(ptr, value);
3330 }
3331 else if (sprop->get_ex) {
3332 sprop->get_ex(ptr, prop, value);
3333 }
3334 else {
3335 strcpy(value, sprop->defaultvalue);
3336 }
3337 }
3338
RNA_property_string_get_alloc(PointerRNA * ptr,PropertyRNA * prop,char * fixedbuf,int fixedlen,int * r_len)3339 char *RNA_property_string_get_alloc(
3340 PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
3341 {
3342 char *buf;
3343 int length;
3344
3345 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3346
3347 length = RNA_property_string_length(ptr, prop);
3348
3349 if (length + 1 < fixedlen) {
3350 buf = fixedbuf;
3351 }
3352 else {
3353 buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
3354 }
3355
3356 #ifndef NDEBUG
3357 /* safety check to ensure the string is actually set */
3358 buf[length] = 255;
3359 #endif
3360
3361 RNA_property_string_get(ptr, prop, buf);
3362
3363 #ifndef NDEBUG
3364 BLI_assert(buf[length] == '\0');
3365 #endif
3366
3367 if (r_len) {
3368 *r_len = length;
3369 }
3370
3371 return buf;
3372 }
3373
3374 /* this is the length without \0 terminator */
RNA_property_string_length(PointerRNA * ptr,PropertyRNA * prop)3375 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
3376 {
3377 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3378 IDProperty *idprop;
3379
3380 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3381
3382 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3383 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
3384 return idprop->len;
3385 }
3386 #ifndef NDEBUG
3387 /* these _must_ stay in sync */
3388 BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
3389 #endif
3390 return idprop->len - 1;
3391 }
3392 else if (sprop->length) {
3393 return sprop->length(ptr);
3394 }
3395 else if (sprop->length_ex) {
3396 return sprop->length_ex(ptr, prop);
3397 }
3398 else {
3399 return strlen(sprop->defaultvalue);
3400 }
3401 }
3402
RNA_property_string_set(PointerRNA * ptr,PropertyRNA * prop,const char * value)3403 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
3404 {
3405 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3406 IDProperty *idprop;
3407
3408 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3409
3410 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3411 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
3412 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
3413 rna_idproperty_touch(idprop);
3414 }
3415 else if (sprop->set) {
3416 sprop->set(ptr, value); /* set function needs to clamp its self */
3417 }
3418 else if (sprop->set_ex) {
3419 sprop->set_ex(ptr, prop, value); /* set function needs to clamp its self */
3420 }
3421 else if (prop->flag & PROP_EDITABLE) {
3422 IDProperty *group;
3423
3424 group = RNA_struct_idprops(ptr, 1);
3425 if (group) {
3426 IDP_AddToGroup(group,
3427 IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop)));
3428 }
3429 }
3430 }
3431
RNA_property_string_set_bytes(PointerRNA * ptr,PropertyRNA * prop,const char * value,int len)3432 void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const char *value, int len)
3433 {
3434 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3435 IDProperty *idprop;
3436
3437 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3438 BLI_assert(RNA_property_subtype(prop) == PROP_BYTESTRING);
3439
3440 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3441 IDP_ResizeArray(idprop, len);
3442 memcpy(idprop->data.pointer, value, (size_t)len);
3443
3444 rna_idproperty_touch(idprop);
3445 }
3446 else if (sprop->set) {
3447 /* XXX, should take length argument (currently not used). */
3448 sprop->set(ptr, value); /* set function needs to clamp its self */
3449 }
3450 else if (sprop->set_ex) {
3451 /* XXX, should take length argument (currently not used). */
3452 sprop->set_ex(ptr, prop, value); /* set function needs to clamp its self */
3453 }
3454 else if (prop->flag & PROP_EDITABLE) {
3455 IDProperty *group;
3456
3457 group = RNA_struct_idprops(ptr, 1);
3458 if (group) {
3459 IDPropertyTemplate val = {0};
3460 val.string.str = value;
3461 val.string.len = len;
3462 val.string.subtype = IDP_STRING_SUB_BYTE;
3463 IDP_AddToGroup(group, IDP_New(IDP_STRING, &val, prop->identifier));
3464 }
3465 }
3466 }
3467
RNA_property_string_get_default(PointerRNA * UNUSED (ptr),PropertyRNA * prop,char * value)3468 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
3469 {
3470 StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
3471
3472 if (prop->magic != RNA_MAGIC) {
3473 /* attempt to get the local ID values */
3474 const IDProperty *idp_ui = rna_idproperty_ui(prop);
3475
3476 if (idp_ui) {
3477 IDProperty *item;
3478
3479 item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", IDP_STRING);
3480 if (item) {
3481 strcpy(value, IDP_String(item));
3482 return;
3483 }
3484 }
3485
3486 strcpy(value, "");
3487 return;
3488 }
3489
3490 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3491
3492 strcpy(value, sprop->defaultvalue);
3493 }
3494
RNA_property_string_get_default_alloc(PointerRNA * ptr,PropertyRNA * prop,char * fixedbuf,int fixedlen)3495 char *RNA_property_string_get_default_alloc(PointerRNA *ptr,
3496 PropertyRNA *prop,
3497 char *fixedbuf,
3498 int fixedlen)
3499 {
3500 char *buf;
3501 int length;
3502
3503 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3504
3505 length = RNA_property_string_default_length(ptr, prop);
3506
3507 if (length + 1 < fixedlen) {
3508 buf = fixedbuf;
3509 }
3510 else {
3511 buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
3512 }
3513
3514 RNA_property_string_get_default(ptr, prop, buf);
3515
3516 return buf;
3517 }
3518
3519 /* this is the length without \0 terminator */
RNA_property_string_default_length(PointerRNA * UNUSED (ptr),PropertyRNA * prop)3520 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3521 {
3522 StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
3523
3524 if (prop->magic != RNA_MAGIC) {
3525 /* attempt to get the local ID values */
3526 const IDProperty *idp_ui = rna_idproperty_ui(prop);
3527
3528 if (idp_ui) {
3529 IDProperty *item;
3530
3531 item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", IDP_STRING);
3532 if (item) {
3533 return strlen(IDP_String(item));
3534 }
3535 }
3536
3537 return 0;
3538 }
3539
3540 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3541
3542 return strlen(sprop->defaultvalue);
3543 }
3544
RNA_property_enum_get(PointerRNA * ptr,PropertyRNA * prop)3545 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
3546 {
3547 EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3548 IDProperty *idprop;
3549
3550 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3551
3552 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3553 return IDP_Int(idprop);
3554 }
3555 if (eprop->get) {
3556 return eprop->get(ptr);
3557 }
3558 else if (eprop->get_ex) {
3559 return eprop->get_ex(ptr, prop);
3560 }
3561 else {
3562 return eprop->defaultvalue;
3563 }
3564 }
3565
RNA_property_enum_set(PointerRNA * ptr,PropertyRNA * prop,int value)3566 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
3567 {
3568 EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3569 IDProperty *idprop;
3570
3571 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3572
3573 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3574 IDP_Int(idprop) = value;
3575 rna_idproperty_touch(idprop);
3576 }
3577 else if (eprop->set) {
3578 eprop->set(ptr, value);
3579 }
3580 else if (eprop->set_ex) {
3581 eprop->set_ex(ptr, prop, value);
3582 }
3583 else if (prop->flag & PROP_EDITABLE) {
3584 IDPropertyTemplate val = {0};
3585 IDProperty *group;
3586
3587 val.i = value;
3588
3589 group = RNA_struct_idprops(ptr, 1);
3590 if (group) {
3591 IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
3592 }
3593 }
3594 }
3595
RNA_property_enum_get_default(PointerRNA * UNUSED (ptr),PropertyRNA * prop)3596 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3597 {
3598 EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
3599
3600 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3601
3602 return eprop->defaultvalue;
3603 }
3604
RNA_property_enum_py_data_get(PropertyRNA * prop)3605 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
3606 {
3607 EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3608
3609 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3610
3611 return eprop->py_data;
3612 }
3613
3614 /**
3615 * Get the value of the item that is \a step items away from \a from_value.
3616 *
3617 * \param from_value: Item value to start stepping from.
3618 * \param step: Absolute value defines step size, sign defines direction.
3619 * E.g to get the next item, pass 1, for the previous -1.
3620 */
RNA_property_enum_step(const bContext * C,PointerRNA * ptr,PropertyRNA * prop,int from_value,int step)3621 int RNA_property_enum_step(
3622 const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
3623 {
3624 const EnumPropertyItem *item_array;
3625 int totitem;
3626 bool free;
3627 int result_value = from_value;
3628 int i, i_init;
3629 int single_step = (step < 0) ? -1 : 1;
3630 int step_tot = 0;
3631
3632 RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
3633 i = RNA_enum_from_value(item_array, from_value);
3634 i_init = i;
3635
3636 do {
3637 i = mod_i(i + single_step, totitem);
3638 if (item_array[i].identifier[0]) {
3639 step_tot += single_step;
3640 }
3641 } while ((i != i_init) && (step_tot != step));
3642
3643 if (i != i_init) {
3644 result_value = item_array[i].value;
3645 }
3646
3647 if (free) {
3648 MEM_freeN((void *)item_array);
3649 }
3650
3651 return result_value;
3652 }
3653
RNA_property_pointer_get(PointerRNA * ptr,PropertyRNA * prop)3654 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
3655 {
3656 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3657 IDProperty *idprop;
3658
3659 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3660
3661 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3662 pprop = (PointerPropertyRNA *)prop;
3663
3664 if (RNA_struct_is_ID(pprop->type)) {
3665 return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop));
3666 }
3667
3668 /* for groups, data is idprop itself */
3669 if (pprop->typef) {
3670 return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
3671 }
3672 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
3673 }
3674 else if (pprop->get) {
3675 return pprop->get(ptr);
3676 }
3677 else if (prop->flag & PROP_IDPROPERTY) {
3678 /* XXX temporary hack to add it automatically, reading should
3679 * never do any write ops, to ensure thread safety etc .. */
3680 RNA_property_pointer_add(ptr, prop);
3681 return RNA_property_pointer_get(ptr, prop);
3682 }
3683 else {
3684 return PointerRNA_NULL;
3685 }
3686 }
3687
RNA_property_pointer_set(PointerRNA * ptr,PropertyRNA * prop,PointerRNA ptr_value,ReportList * reports)3688 void RNA_property_pointer_set(PointerRNA *ptr,
3689 PropertyRNA *prop,
3690 PointerRNA ptr_value,
3691 ReportList *reports)
3692 {
3693 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3694 IDProperty *idprop = rna_idproperty_check(&prop, ptr);
3695 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3696
3697 /* Check types. */
3698 if (pprop->set != NULL) {
3699 /* Assigning to a real RNA property. */
3700 if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
3701 BKE_reportf(reports,
3702 RPT_ERROR,
3703 "%s: expected %s type, not %s",
3704 __func__,
3705 pprop->type->identifier,
3706 ptr_value.type->identifier);
3707 return;
3708 }
3709 }
3710 else {
3711 /* Assigning to an IDProperty desguised as RNA one. */
3712 if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, &RNA_ID)) {
3713 BKE_reportf(reports,
3714 RPT_ERROR,
3715 "%s: expected ID type, not %s",
3716 __func__,
3717 ptr_value.type->identifier);
3718 return;
3719 }
3720 }
3721
3722 /* We got an existing IDProperty. */
3723 if (idprop != NULL) {
3724 /* Not-yet-defined ID IDProps have an IDP_GROUP type, not an IDP_ID one - because of reasons?
3725 * XXX This has to be investigated fully - there might be a good reason for it, but off hands
3726 * this seems really weird... */
3727 if (idprop->type == IDP_ID) {
3728 IDP_AssignID(idprop, ptr_value.data, 0);
3729 rna_idproperty_touch(idprop);
3730 }
3731 else {
3732 BLI_assert(idprop->type == IDP_GROUP);
3733
3734 IDPropertyTemplate val = {.id = ptr_value.data};
3735 IDProperty *group = RNA_struct_idprops(ptr, true);
3736 BLI_assert(group != NULL);
3737
3738 IDP_ReplaceInGroup_ex(group, IDP_New(IDP_ID, &val, idprop->name), idprop);
3739 }
3740 }
3741 /* RNA property. */
3742 else if (pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
3743 !((prop->flag & PROP_ID_SELF_CHECK) && ptr->owner_id == ptr_value.owner_id)) {
3744 pprop->set(ptr, ptr_value, reports);
3745 }
3746 /* IDProperty desguised as RNA property (and not yet defined in ptr). */
3747 else if (prop->flag & PROP_EDITABLE) {
3748 IDPropertyTemplate val = {0};
3749 IDProperty *group;
3750
3751 val.id = ptr_value.data;
3752
3753 group = RNA_struct_idprops(ptr, true);
3754 if (group) {
3755 IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier));
3756 }
3757 }
3758 }
3759
RNA_property_pointer_get_default(PointerRNA * UNUSED (ptr),PropertyRNA * UNUSED (prop))3760 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
3761 {
3762 /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
3763
3764 /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
3765
3766 return PointerRNA_NULL; /* FIXME: there has to be a way... */
3767 }
3768
RNA_property_pointer_add(PointerRNA * ptr,PropertyRNA * prop)3769 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
3770 {
3771 /*IDProperty *idprop;*/
3772
3773 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3774
3775 if ((/*idprop=*/rna_idproperty_check(&prop, ptr))) {
3776 /* already exists */
3777 }
3778 else if (prop->flag & PROP_IDPROPERTY) {
3779 IDPropertyTemplate val = {0};
3780 IDProperty *group;
3781
3782 val.i = 0;
3783
3784 group = RNA_struct_idprops(ptr, 1);
3785 if (group) {
3786 IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
3787 }
3788 }
3789 else {
3790 printf("%s %s.%s: only supported for id properties.\n",
3791 __func__,
3792 ptr->type->identifier,
3793 prop->identifier);
3794 }
3795 }
3796
RNA_property_pointer_remove(PointerRNA * ptr,PropertyRNA * prop)3797 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
3798 {
3799 IDProperty *idprop, *group;
3800
3801 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3802
3803 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3804 group = RNA_struct_idprops(ptr, 0);
3805
3806 if (group) {
3807 IDP_FreeFromGroup(group, idprop);
3808 }
3809 }
3810 else {
3811 printf("%s %s.%s: only supported for id properties.\n",
3812 __func__,
3813 ptr->type->identifier,
3814 prop->identifier);
3815 }
3816 }
3817
rna_property_collection_get_idp(CollectionPropertyIterator * iter)3818 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
3819 {
3820 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
3821
3822 iter->ptr.data = rna_iterator_array_get(iter);
3823 iter->ptr.type = cprop->item_type;
3824 rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
3825 }
3826
RNA_property_collection_begin(PointerRNA * ptr,PropertyRNA * prop,CollectionPropertyIterator * iter)3827 void RNA_property_collection_begin(PointerRNA *ptr,
3828 PropertyRNA *prop,
3829 CollectionPropertyIterator *iter)
3830 {
3831 IDProperty *idprop;
3832
3833 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3834
3835 memset(iter, 0, sizeof(*iter));
3836
3837 if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
3838 iter->parent = *ptr;
3839 iter->prop = prop;
3840
3841 if (idprop) {
3842 rna_iterator_array_begin(
3843 iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
3844 }
3845 else {
3846 rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
3847 }
3848
3849 if (iter->valid) {
3850 rna_property_collection_get_idp(iter);
3851 }
3852
3853 iter->idprop = 1;
3854 }
3855 else {
3856 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3857 cprop->begin(iter, ptr);
3858 }
3859 }
3860
RNA_property_collection_next(CollectionPropertyIterator * iter)3861 void RNA_property_collection_next(CollectionPropertyIterator *iter)
3862 {
3863 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3864
3865 if (iter->idprop) {
3866 rna_iterator_array_next(iter);
3867
3868 if (iter->valid) {
3869 rna_property_collection_get_idp(iter);
3870 }
3871 }
3872 else {
3873 cprop->next(iter);
3874 }
3875 }
3876
RNA_property_collection_skip(CollectionPropertyIterator * iter,int num)3877 void RNA_property_collection_skip(CollectionPropertyIterator *iter, int num)
3878 {
3879 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3880 int i;
3881
3882 if (num > 1 && (iter->idprop || (cprop->property.flag_internal & PROP_INTERN_RAW_ARRAY))) {
3883 /* fast skip for array */
3884 ArrayIterator *internal = &iter->internal.array;
3885
3886 if (!internal->skip) {
3887 internal->ptr += internal->itemsize * (num - 1);
3888 iter->valid = (internal->ptr < internal->endptr);
3889 if (iter->valid) {
3890 RNA_property_collection_next(iter);
3891 }
3892 return;
3893 }
3894 }
3895
3896 /* slow iteration otherwise */
3897 for (i = 0; i < num && iter->valid; i++) {
3898 RNA_property_collection_next(iter);
3899 }
3900 }
3901
RNA_property_collection_end(CollectionPropertyIterator * iter)3902 void RNA_property_collection_end(CollectionPropertyIterator *iter)
3903 {
3904 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3905
3906 if (iter->idprop) {
3907 rna_iterator_array_end(iter);
3908 }
3909 else {
3910 cprop->end(iter);
3911 }
3912 }
3913
RNA_property_collection_length(PointerRNA * ptr,PropertyRNA * prop)3914 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
3915 {
3916 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3917 IDProperty *idprop;
3918
3919 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3920
3921 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3922 return idprop->len;
3923 }
3924 if (cprop->length) {
3925 return cprop->length(ptr);
3926 }
3927 else {
3928 CollectionPropertyIterator iter;
3929 int length = 0;
3930
3931 RNA_property_collection_begin(ptr, prop, &iter);
3932 for (; iter.valid; RNA_property_collection_next(&iter)) {
3933 length++;
3934 }
3935 RNA_property_collection_end(&iter);
3936
3937 return length;
3938 }
3939 }
3940
3941 /* This helper checks whether given collection property itself is editable (we only currently
3942 * support a limited set of operations, insertion of new items, and re-ordering of those new items
3943 * exclusively). */
property_collection_liboverride_editable(PointerRNA * ptr,PropertyRNA * prop,bool * r_is_liboverride)3944 static bool property_collection_liboverride_editable(PointerRNA *ptr,
3945 PropertyRNA *prop,
3946 bool *r_is_liboverride)
3947 {
3948 ID *id = ptr->owner_id;
3949 if (id == NULL) {
3950 *r_is_liboverride = false;
3951 return true;
3952 }
3953
3954 const bool is_liboverride = *r_is_liboverride = ID_IS_OVERRIDE_LIBRARY(id);
3955
3956 if (!is_liboverride) {
3957 /* We return True also for linked data, as it allows tricks like py scripts 'overriding' data
3958 * of those.*/
3959 return true;
3960 }
3961
3962 if (!RNA_property_overridable_get(ptr, prop)) {
3963 return false;
3964 }
3965
3966 if (prop->magic != RNA_MAGIC || (prop->flag & PROP_IDPROPERTY) == 0) {
3967 /* Insertion and such not supported for pure IDProperties for now, nor for pure RNA/DNA ones.
3968 */
3969 return false;
3970 }
3971 if ((prop->flag_override & PROPOVERRIDE_LIBRARY_INSERTION) == 0) {
3972 return false;
3973 }
3974
3975 /* No more checks to do, this collections is overridable. */
3976 return true;
3977 }
3978
RNA_property_collection_add(PointerRNA * ptr,PropertyRNA * prop,PointerRNA * r_ptr)3979 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
3980 {
3981 IDProperty *idprop;
3982 /* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
3983
3984 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3985
3986 bool is_liboverride;
3987 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
3988 if (r_ptr) {
3989 memset(r_ptr, 0, sizeof(*r_ptr));
3990 }
3991 return;
3992 }
3993
3994 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3995 IDPropertyTemplate val = {0};
3996 IDProperty *item;
3997
3998 item = IDP_New(IDP_GROUP, &val, "");
3999 if (is_liboverride) {
4000 item->flag |= IDP_FLAG_OVERRIDELIBRARY_LOCAL;
4001 }
4002 IDP_AppendArray(idprop, item);
4003 /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
4004 /* IDP_FreePropertyContent(item); */
4005 MEM_freeN(item);
4006 rna_idproperty_touch(idprop);
4007 }
4008 else if (prop->flag & PROP_IDPROPERTY) {
4009 IDProperty *group, *item;
4010 IDPropertyTemplate val = {0};
4011
4012 group = RNA_struct_idprops(ptr, 1);
4013 if (group) {
4014 idprop = IDP_NewIDPArray(prop->identifier);
4015 IDP_AddToGroup(group, idprop);
4016
4017 item = IDP_New(IDP_GROUP, &val, "");
4018 if (is_liboverride) {
4019 item->flag |= IDP_FLAG_OVERRIDELIBRARY_LOCAL;
4020 }
4021 IDP_AppendArray(idprop, item);
4022 /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
4023 /* IDP_FreePropertyContent(item); */
4024 MEM_freeN(item);
4025 }
4026 }
4027
4028 /* py api calls directly */
4029 #if 0
4030 else if (cprop->add) {
4031 if (!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
4032 ParameterList params;
4033 RNA_parameter_list_create(¶ms, ptr, cprop->add);
4034 RNA_function_call(NULL, NULL, ptr, cprop->add, ¶ms);
4035 RNA_parameter_list_free(¶ms);
4036 }
4037 }
4038 # if 0
4039 else {
4040 printf("%s %s.%s: not implemented for this property.\n",
4041 __func__,
4042 ptr->type->identifier,
4043 prop->identifier);
4044 }
4045 # endif
4046 #endif
4047
4048 if (r_ptr) {
4049 if (idprop) {
4050 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
4051
4052 r_ptr->data = IDP_GetIndexArray(idprop, idprop->len - 1);
4053 r_ptr->type = cprop->item_type;
4054 rna_pointer_inherit_id(NULL, ptr, r_ptr);
4055 }
4056 else {
4057 memset(r_ptr, 0, sizeof(*r_ptr));
4058 }
4059 }
4060 }
4061
RNA_property_collection_remove(PointerRNA * ptr,PropertyRNA * prop,int key)4062 bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
4063 {
4064 IDProperty *idprop;
4065 /* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
4066
4067 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4068
4069 bool is_liboverride;
4070 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
4071 return false;
4072 }
4073
4074 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4075 IDProperty tmp, *array;
4076 int len;
4077
4078 len = idprop->len;
4079 array = IDP_IDPArray(idprop);
4080
4081 if (key >= 0 && key < len) {
4082 if (is_liboverride && (array[key].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) == 0) {
4083 /* We can only remove items that we actually inserted in the local override. */
4084 return false;
4085 }
4086
4087 if (key + 1 < len) {
4088 /* move element to be removed to the back */
4089 memcpy(&tmp, &array[key], sizeof(IDProperty));
4090 memmove(array + key, array + key + 1, sizeof(IDProperty) * (len - (key + 1)));
4091 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
4092 }
4093
4094 IDP_ResizeIDPArray(idprop, len - 1);
4095 }
4096
4097 return true;
4098 }
4099 if (prop->flag & PROP_IDPROPERTY) {
4100 return true;
4101 }
4102
4103 /* py api calls directly */
4104 #if 0
4105 else if (cprop->remove) {
4106 if (!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
4107 ParameterList params;
4108 RNA_parameter_list_create(¶ms, ptr, cprop->remove);
4109 RNA_function_call(NULL, NULL, ptr, cprop->remove, ¶ms);
4110 RNA_parameter_list_free(¶ms);
4111 }
4112
4113 return false;
4114 }
4115 # if 0
4116 else {
4117 printf("%s %s.%s: only supported for id properties.\n",
4118 __func__,
4119 ptr->type->identifier,
4120 prop->identifier);
4121 }
4122 # endif
4123 #endif
4124 return false;
4125 }
4126
RNA_property_collection_move(PointerRNA * ptr,PropertyRNA * prop,int key,int pos)4127 bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
4128 {
4129 IDProperty *idprop;
4130
4131 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4132
4133 bool is_liboverride;
4134 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
4135 return false;
4136 }
4137
4138 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4139 IDProperty tmp, *array;
4140 int len;
4141
4142 len = idprop->len;
4143 array = IDP_IDPArray(idprop);
4144
4145 if (key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
4146 if (is_liboverride && (array[key].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) == 0) {
4147 /* We can only move items that we actually inserted in the local override. */
4148 return false;
4149 }
4150
4151 memcpy(&tmp, &array[key], sizeof(IDProperty));
4152 if (pos < key) {
4153 memmove(array + pos + 1, array + pos, sizeof(IDProperty) * (key - pos));
4154 }
4155 else {
4156 memmove(array + key, array + key + 1, sizeof(IDProperty) * (pos - key));
4157 }
4158 memcpy(&array[pos], &tmp, sizeof(IDProperty));
4159 }
4160
4161 return true;
4162 }
4163 if (prop->flag & PROP_IDPROPERTY) {
4164 return true;
4165 }
4166
4167 return false;
4168 }
4169
RNA_property_collection_clear(PointerRNA * ptr,PropertyRNA * prop)4170 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
4171 {
4172 IDProperty *idprop;
4173
4174 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4175
4176 bool is_liboverride;
4177 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
4178 return;
4179 }
4180
4181 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4182 if (is_liboverride) {
4183 /* We can only move items that we actually inserted in the local override. */
4184 int len = idprop->len;
4185 IDProperty tmp, *array = IDP_IDPArray(idprop);
4186 for (int i = 0; i < len; i++) {
4187 if ((array[i].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) != 0) {
4188 memcpy(&tmp, &array[i], sizeof(IDProperty));
4189 memmove(array + i, array + i + 1, sizeof(IDProperty) * (len - (i + 1)));
4190 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
4191 IDP_ResizeIDPArray(idprop, --len);
4192 i--;
4193 }
4194 }
4195 }
4196 else {
4197 IDP_ResizeIDPArray(idprop, 0);
4198 }
4199 rna_idproperty_touch(idprop);
4200 }
4201 }
4202
RNA_property_collection_lookup_index(PointerRNA * ptr,PropertyRNA * prop,PointerRNA * t_ptr)4203 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
4204 {
4205 CollectionPropertyIterator iter;
4206 int index = 0;
4207
4208 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4209
4210 RNA_property_collection_begin(ptr, prop, &iter);
4211 for (index = 0; iter.valid; RNA_property_collection_next(&iter), index++) {
4212 if (iter.ptr.data == t_ptr->data) {
4213 break;
4214 }
4215 }
4216 RNA_property_collection_end(&iter);
4217
4218 /* did we find it? */
4219 if (iter.valid) {
4220 return index;
4221 }
4222 return -1;
4223 }
4224
RNA_property_collection_lookup_int(PointerRNA * ptr,PropertyRNA * prop,int key,PointerRNA * r_ptr)4225 int RNA_property_collection_lookup_int(PointerRNA *ptr,
4226 PropertyRNA *prop,
4227 int key,
4228 PointerRNA *r_ptr)
4229 {
4230 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
4231
4232 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4233
4234 if (cprop->lookupint) {
4235 /* we have a callback defined, use it */
4236 return cprop->lookupint(ptr, key, r_ptr);
4237 }
4238 /* no callback defined, just iterate and find the nth item */
4239 CollectionPropertyIterator iter;
4240 int i;
4241
4242 RNA_property_collection_begin(ptr, prop, &iter);
4243 for (i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
4244 if (i == key) {
4245 *r_ptr = iter.ptr;
4246 break;
4247 }
4248 }
4249 RNA_property_collection_end(&iter);
4250
4251 if (!iter.valid) {
4252 memset(r_ptr, 0, sizeof(*r_ptr));
4253 }
4254
4255 return iter.valid;
4256 }
4257
RNA_property_collection_lookup_string_index(PointerRNA * ptr,PropertyRNA * prop,const char * key,PointerRNA * r_ptr,int * r_index)4258 int RNA_property_collection_lookup_string_index(
4259 PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr, int *r_index)
4260 {
4261 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
4262
4263 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4264
4265 if (cprop->lookupstring) {
4266 /* we have a callback defined, use it */
4267 return cprop->lookupstring(ptr, key, r_ptr);
4268 }
4269 /* no callback defined, compare with name properties if they exist */
4270 CollectionPropertyIterator iter;
4271 PropertyRNA *nameprop;
4272 char name[256], *nameptr;
4273 int found = 0;
4274 int keylen = strlen(key);
4275 int namelen;
4276 int index = 0;
4277
4278 RNA_property_collection_begin(ptr, prop, &iter);
4279 for (; iter.valid; RNA_property_collection_next(&iter), index++) {
4280 if (iter.ptr.data && iter.ptr.type->nameproperty) {
4281 nameprop = iter.ptr.type->nameproperty;
4282
4283 nameptr = RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name), &namelen);
4284
4285 if ((keylen == namelen) && STREQ(nameptr, key)) {
4286 *r_ptr = iter.ptr;
4287 found = 1;
4288 }
4289
4290 if ((char *)&name != nameptr) {
4291 MEM_freeN(nameptr);
4292 }
4293
4294 if (found) {
4295 break;
4296 }
4297 }
4298 }
4299 RNA_property_collection_end(&iter);
4300
4301 if (!iter.valid) {
4302 memset(r_ptr, 0, sizeof(*r_ptr));
4303 *r_index = -1;
4304 }
4305 else {
4306 *r_index = index;
4307 }
4308
4309 return iter.valid;
4310 }
4311
RNA_property_collection_lookup_string(PointerRNA * ptr,PropertyRNA * prop,const char * key,PointerRNA * r_ptr)4312 int RNA_property_collection_lookup_string(PointerRNA *ptr,
4313 PropertyRNA *prop,
4314 const char *key,
4315 PointerRNA *r_ptr)
4316 {
4317 int index;
4318 return RNA_property_collection_lookup_string_index(ptr, prop, key, r_ptr, &index);
4319 }
4320
4321 /* zero return is an assignment error */
RNA_property_collection_assign_int(PointerRNA * ptr,PropertyRNA * prop,const int key,const PointerRNA * assign_ptr)4322 int RNA_property_collection_assign_int(PointerRNA *ptr,
4323 PropertyRNA *prop,
4324 const int key,
4325 const PointerRNA *assign_ptr)
4326 {
4327 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
4328
4329 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4330
4331 if (cprop->assignint) {
4332 /* we have a callback defined, use it */
4333 return cprop->assignint(ptr, key, assign_ptr);
4334 }
4335
4336 return 0;
4337 }
4338
RNA_property_collection_type_get(PointerRNA * ptr,PropertyRNA * prop,PointerRNA * r_ptr)4339 bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
4340 {
4341 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4342
4343 *r_ptr = *ptr;
4344 return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1 : 0);
4345 }
4346
RNA_property_collection_raw_array(PointerRNA * ptr,PropertyRNA * prop,PropertyRNA * itemprop,RawArray * array)4347 int RNA_property_collection_raw_array(PointerRNA *ptr,
4348 PropertyRNA *prop,
4349 PropertyRNA *itemprop,
4350 RawArray *array)
4351 {
4352 CollectionPropertyIterator iter;
4353 ArrayIterator *internal;
4354 char *arrayp;
4355
4356 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
4357
4358 if (!(prop->flag_internal & PROP_INTERN_RAW_ARRAY) ||
4359 !(itemprop->flag_internal & PROP_INTERN_RAW_ACCESS)) {
4360 return 0;
4361 }
4362
4363 RNA_property_collection_begin(ptr, prop, &iter);
4364
4365 if (iter.valid) {
4366 /* get data from array iterator and item property */
4367 internal = &iter.internal.array;
4368 arrayp = (iter.valid) ? iter.ptr.data : NULL;
4369
4370 if (internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
4371 /* we might skip some items, so it's not a proper array */
4372 RNA_property_collection_end(&iter);
4373 return 0;
4374 }
4375
4376 array->array = arrayp + itemprop->rawoffset;
4377 array->stride = internal->itemsize;
4378 array->len = ((char *)internal->endptr - arrayp) / internal->itemsize;
4379 array->type = itemprop->rawtype;
4380 }
4381 else {
4382 memset(array, 0, sizeof(RawArray));
4383 }
4384
4385 RNA_property_collection_end(&iter);
4386
4387 return 1;
4388 }
4389
4390 #define RAW_GET(dtype, var, raw, a) \
4391 { \
4392 switch (raw.type) { \
4393 case PROP_RAW_CHAR: \
4394 var = (dtype)((char *)raw.array)[a]; \
4395 break; \
4396 case PROP_RAW_SHORT: \
4397 var = (dtype)((short *)raw.array)[a]; \
4398 break; \
4399 case PROP_RAW_INT: \
4400 var = (dtype)((int *)raw.array)[a]; \
4401 break; \
4402 case PROP_RAW_BOOLEAN: \
4403 var = (dtype)((bool *)raw.array)[a]; \
4404 break; \
4405 case PROP_RAW_FLOAT: \
4406 var = (dtype)((float *)raw.array)[a]; \
4407 break; \
4408 case PROP_RAW_DOUBLE: \
4409 var = (dtype)((double *)raw.array)[a]; \
4410 break; \
4411 default: \
4412 var = (dtype)0; \
4413 } \
4414 } \
4415 (void)0
4416
4417 #define RAW_SET(dtype, raw, a, var) \
4418 { \
4419 switch (raw.type) { \
4420 case PROP_RAW_CHAR: \
4421 ((char *)raw.array)[a] = (char)var; \
4422 break; \
4423 case PROP_RAW_SHORT: \
4424 ((short *)raw.array)[a] = (short)var; \
4425 break; \
4426 case PROP_RAW_INT: \
4427 ((int *)raw.array)[a] = (int)var; \
4428 break; \
4429 case PROP_RAW_BOOLEAN: \
4430 ((bool *)raw.array)[a] = (bool)var; \
4431 break; \
4432 case PROP_RAW_FLOAT: \
4433 ((float *)raw.array)[a] = (float)var; \
4434 break; \
4435 case PROP_RAW_DOUBLE: \
4436 ((double *)raw.array)[a] = (double)var; \
4437 break; \
4438 default: \
4439 break; \
4440 } \
4441 } \
4442 (void)0
4443
RNA_raw_type_sizeof(RawPropertyType type)4444 int RNA_raw_type_sizeof(RawPropertyType type)
4445 {
4446 switch (type) {
4447 case PROP_RAW_CHAR:
4448 return sizeof(char);
4449 case PROP_RAW_SHORT:
4450 return sizeof(short);
4451 case PROP_RAW_INT:
4452 return sizeof(int);
4453 case PROP_RAW_BOOLEAN:
4454 return sizeof(bool);
4455 case PROP_RAW_FLOAT:
4456 return sizeof(float);
4457 case PROP_RAW_DOUBLE:
4458 return sizeof(double);
4459 default:
4460 return 0;
4461 }
4462 }
4463
rna_property_array_length_all_dimensions(PointerRNA * ptr,PropertyRNA * prop)4464 static int rna_property_array_length_all_dimensions(PointerRNA *ptr, PropertyRNA *prop)
4465 {
4466 int i, len[RNA_MAX_ARRAY_DIMENSION];
4467 const int dim = RNA_property_array_dimension(ptr, prop, len);
4468 int size;
4469
4470 if (dim == 0) {
4471 return 0;
4472 }
4473
4474 for (size = 1, i = 0; i < dim; i++) {
4475 size *= len[i];
4476 }
4477
4478 return size;
4479 }
4480
rna_raw_access(ReportList * reports,PointerRNA * ptr,PropertyRNA * prop,const char * propname,void * inarray,RawPropertyType intype,int inlen,int set)4481 static int rna_raw_access(ReportList *reports,
4482 PointerRNA *ptr,
4483 PropertyRNA *prop,
4484 const char *propname,
4485 void *inarray,
4486 RawPropertyType intype,
4487 int inlen,
4488 int set)
4489 {
4490 StructRNA *ptype;
4491 PointerRNA itemptr_base;
4492 PropertyRNA *itemprop, *iprop;
4493 PropertyType itemtype = 0;
4494 RawArray in;
4495 int itemlen = 0;
4496
4497 /* initialize in array, stride assumed 0 in following code */
4498 in.array = inarray;
4499 in.type = intype;
4500 in.len = inlen;
4501 in.stride = 0;
4502
4503 ptype = RNA_property_pointer_type(ptr, prop);
4504
4505 /* try to get item property pointer */
4506 RNA_pointer_create(NULL, ptype, NULL, &itemptr_base);
4507 itemprop = RNA_struct_find_property(&itemptr_base, propname);
4508
4509 if (itemprop) {
4510 /* we have item property pointer */
4511 RawArray out;
4512
4513 /* check type */
4514 itemtype = RNA_property_type(itemprop);
4515
4516 if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
4517 BKE_report(reports, RPT_ERROR, "Only boolean, int float and enum properties supported");
4518 return 0;
4519 }
4520
4521 /* check item array */
4522 itemlen = RNA_property_array_length(&itemptr_base, itemprop);
4523
4524 /* dynamic array? need to get length per item */
4525 if (itemprop->getlength) {
4526 itemprop = NULL;
4527 }
4528 /* try to access as raw array */
4529 else if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
4530 int arraylen = (itemlen == 0) ? 1 : itemlen;
4531 if (in.len != arraylen * out.len) {
4532 BKE_reportf(reports,
4533 RPT_ERROR,
4534 "Array length mismatch (expected %d, got %d)",
4535 out.len * arraylen,
4536 in.len);
4537 return 0;
4538 }
4539
4540 /* matching raw types */
4541 if (out.type == in.type) {
4542 void *inp = in.array;
4543 void *outp = out.array;
4544 int a, size;
4545
4546 size = RNA_raw_type_sizeof(out.type) * arraylen;
4547
4548 for (a = 0; a < out.len; a++) {
4549 if (set) {
4550 memcpy(outp, inp, size);
4551 }
4552 else {
4553 memcpy(inp, outp, size);
4554 }
4555
4556 inp = (char *)inp + size;
4557 outp = (char *)outp + out.stride;
4558 }
4559
4560 return 1;
4561 }
4562
4563 /* could also be faster with non-matching types,
4564 * for now we just do slower loop .. */
4565 }
4566 }
4567
4568 {
4569 void *tmparray = NULL;
4570 int tmplen = 0;
4571 int err = 0, j, a = 0;
4572 int needconv = 1;
4573
4574 if (((itemtype == PROP_INT) && (in.type == PROP_RAW_INT)) ||
4575 ((itemtype == PROP_BOOLEAN) && (in.type == PROP_RAW_BOOLEAN)) ||
4576 ((itemtype == PROP_FLOAT) && (in.type == PROP_RAW_FLOAT))) {
4577 /* avoid creating temporary buffer if the data type match */
4578 needconv = 0;
4579 }
4580 /* no item property pointer, can still be id property, or
4581 * property of a type derived from the collection pointer type */
4582 RNA_PROP_BEGIN (ptr, itemptr, prop) {
4583 if (itemptr.data) {
4584 if (itemprop) {
4585 /* we got the property already */
4586 iprop = itemprop;
4587 }
4588 else {
4589 /* not yet, look it up and verify if it is valid */
4590 iprop = RNA_struct_find_property(&itemptr, propname);
4591
4592 if (iprop) {
4593 itemlen = rna_property_array_length_all_dimensions(&itemptr, iprop);
4594 itemtype = RNA_property_type(iprop);
4595 }
4596 else {
4597 BKE_reportf(reports, RPT_ERROR, "Property named '%s' not found", propname);
4598 err = 1;
4599 break;
4600 }
4601
4602 if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
4603 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
4604 err = 1;
4605 break;
4606 }
4607 }
4608
4609 /* editable check */
4610 if (!set || RNA_property_editable(&itemptr, iprop)) {
4611 if (a + itemlen > in.len) {
4612 BKE_reportf(
4613 reports, RPT_ERROR, "Array length mismatch (got %d, expected more)", in.len);
4614 err = 1;
4615 break;
4616 }
4617
4618 if (itemlen == 0) {
4619 /* handle conversions */
4620 if (set) {
4621 switch (itemtype) {
4622 case PROP_BOOLEAN: {
4623 int b;
4624 RAW_GET(bool, b, in, a);
4625 RNA_property_boolean_set(&itemptr, iprop, b);
4626 break;
4627 }
4628 case PROP_INT: {
4629 int i;
4630 RAW_GET(int, i, in, a);
4631 RNA_property_int_set(&itemptr, iprop, i);
4632 break;
4633 }
4634 case PROP_FLOAT: {
4635 float f;
4636 RAW_GET(float, f, in, a);
4637 RNA_property_float_set(&itemptr, iprop, f);
4638 break;
4639 }
4640 default:
4641 break;
4642 }
4643 }
4644 else {
4645 switch (itemtype) {
4646 case PROP_BOOLEAN: {
4647 int b = RNA_property_boolean_get(&itemptr, iprop);
4648 RAW_SET(bool, in, a, b);
4649 break;
4650 }
4651 case PROP_INT: {
4652 int i = RNA_property_int_get(&itemptr, iprop);
4653 RAW_SET(int, in, a, i);
4654 break;
4655 }
4656 case PROP_FLOAT: {
4657 float f = RNA_property_float_get(&itemptr, iprop);
4658 RAW_SET(float, in, a, f);
4659 break;
4660 }
4661 default:
4662 break;
4663 }
4664 }
4665 a++;
4666 }
4667 else if (needconv == 1) {
4668 /* allocate temporary array if needed */
4669 if (tmparray && tmplen != itemlen) {
4670 MEM_freeN(tmparray);
4671 tmparray = NULL;
4672 }
4673 if (!tmparray) {
4674 tmparray = MEM_callocN(sizeof(float) * itemlen, "RNA tmparray");
4675 tmplen = itemlen;
4676 }
4677
4678 /* handle conversions */
4679 if (set) {
4680 switch (itemtype) {
4681 case PROP_BOOLEAN: {
4682 for (j = 0; j < itemlen; j++, a++) {
4683 RAW_GET(bool, ((bool *)tmparray)[j], in, a);
4684 }
4685 RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
4686 break;
4687 }
4688 case PROP_INT: {
4689 for (j = 0; j < itemlen; j++, a++) {
4690 RAW_GET(int, ((int *)tmparray)[j], in, a);
4691 }
4692 RNA_property_int_set_array(&itemptr, iprop, tmparray);
4693 break;
4694 }
4695 case PROP_FLOAT: {
4696 for (j = 0; j < itemlen; j++, a++) {
4697 RAW_GET(float, ((float *)tmparray)[j], in, a);
4698 }
4699 RNA_property_float_set_array(&itemptr, iprop, tmparray);
4700 break;
4701 }
4702 default:
4703 break;
4704 }
4705 }
4706 else {
4707 switch (itemtype) {
4708 case PROP_BOOLEAN: {
4709 RNA_property_boolean_get_array(&itemptr, iprop, tmparray);
4710 for (j = 0; j < itemlen; j++, a++) {
4711 RAW_SET(int, in, a, ((bool *)tmparray)[j]);
4712 }
4713 break;
4714 }
4715 case PROP_INT: {
4716 RNA_property_int_get_array(&itemptr, iprop, tmparray);
4717 for (j = 0; j < itemlen; j++, a++) {
4718 RAW_SET(int, in, a, ((int *)tmparray)[j]);
4719 }
4720 break;
4721 }
4722 case PROP_FLOAT: {
4723 RNA_property_float_get_array(&itemptr, iprop, tmparray);
4724 for (j = 0; j < itemlen; j++, a++) {
4725 RAW_SET(float, in, a, ((float *)tmparray)[j]);
4726 }
4727 break;
4728 }
4729 default:
4730 break;
4731 }
4732 }
4733 }
4734 else {
4735 if (set) {
4736 switch (itemtype) {
4737 case PROP_BOOLEAN: {
4738 RNA_property_boolean_set_array(&itemptr, iprop, &((bool *)in.array)[a]);
4739 a += itemlen;
4740 break;
4741 }
4742 case PROP_INT: {
4743 RNA_property_int_set_array(&itemptr, iprop, &((int *)in.array)[a]);
4744 a += itemlen;
4745 break;
4746 }
4747 case PROP_FLOAT: {
4748 RNA_property_float_set_array(&itemptr, iprop, &((float *)in.array)[a]);
4749 a += itemlen;
4750 break;
4751 }
4752 default:
4753 break;
4754 }
4755 }
4756 else {
4757 switch (itemtype) {
4758 case PROP_BOOLEAN: {
4759 RNA_property_boolean_get_array(&itemptr, iprop, &((bool *)in.array)[a]);
4760 a += itemlen;
4761 break;
4762 }
4763 case PROP_INT: {
4764 RNA_property_int_get_array(&itemptr, iprop, &((int *)in.array)[a]);
4765 a += itemlen;
4766 break;
4767 }
4768 case PROP_FLOAT: {
4769 RNA_property_float_get_array(&itemptr, iprop, &((float *)in.array)[a]);
4770 a += itemlen;
4771 break;
4772 }
4773 default:
4774 break;
4775 }
4776 }
4777 }
4778 }
4779 }
4780 }
4781 RNA_PROP_END;
4782
4783 if (tmparray) {
4784 MEM_freeN(tmparray);
4785 }
4786
4787 return !err;
4788 }
4789 }
4790
RNA_property_raw_type(PropertyRNA * prop)4791 RawPropertyType RNA_property_raw_type(PropertyRNA *prop)
4792 {
4793 if (prop->rawtype == PROP_RAW_UNSET) {
4794 /* this property has no raw access,
4795 * yet we try to provide a raw type to help building the array. */
4796 switch (prop->type) {
4797 case PROP_BOOLEAN:
4798 return PROP_RAW_BOOLEAN;
4799 case PROP_INT:
4800 return PROP_RAW_INT;
4801 case PROP_FLOAT:
4802 return PROP_RAW_FLOAT;
4803 case PROP_ENUM:
4804 return PROP_RAW_INT;
4805 default:
4806 break;
4807 }
4808 }
4809 return prop->rawtype;
4810 }
4811
RNA_property_collection_raw_get(ReportList * reports,PointerRNA * ptr,PropertyRNA * prop,const char * propname,void * array,RawPropertyType type,int len)4812 int RNA_property_collection_raw_get(ReportList *reports,
4813 PointerRNA *ptr,
4814 PropertyRNA *prop,
4815 const char *propname,
4816 void *array,
4817 RawPropertyType type,
4818 int len)
4819 {
4820 return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0);
4821 }
4822
RNA_property_collection_raw_set(ReportList * reports,PointerRNA * ptr,PropertyRNA * prop,const char * propname,void * array,RawPropertyType type,int len)4823 int RNA_property_collection_raw_set(ReportList *reports,
4824 PointerRNA *ptr,
4825 PropertyRNA *prop,
4826 const char *propname,
4827 void *array,
4828 RawPropertyType type,
4829 int len)
4830 {
4831 return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1);
4832 }
4833
4834 /* Standard iterator functions */
4835
rna_iterator_listbase_begin(CollectionPropertyIterator * iter,ListBase * lb,IteratorSkipFunc skip)4836 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter,
4837 ListBase *lb,
4838 IteratorSkipFunc skip)
4839 {
4840 ListBaseIterator *internal = &iter->internal.listbase;
4841
4842 internal->link = (lb) ? lb->first : NULL;
4843 internal->skip = skip;
4844
4845 iter->valid = (internal->link != NULL);
4846
4847 if (skip && iter->valid && skip(iter, internal->link)) {
4848 rna_iterator_listbase_next(iter);
4849 }
4850 }
4851
rna_iterator_listbase_next(CollectionPropertyIterator * iter)4852 void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
4853 {
4854 ListBaseIterator *internal = &iter->internal.listbase;
4855
4856 if (internal->skip) {
4857 do {
4858 internal->link = internal->link->next;
4859 iter->valid = (internal->link != NULL);
4860 } while (iter->valid && internal->skip(iter, internal->link));
4861 }
4862 else {
4863 internal->link = internal->link->next;
4864 iter->valid = (internal->link != NULL);
4865 }
4866 }
4867
rna_iterator_listbase_get(CollectionPropertyIterator * iter)4868 void *rna_iterator_listbase_get(CollectionPropertyIterator *iter)
4869 {
4870 ListBaseIterator *internal = &iter->internal.listbase;
4871
4872 return internal->link;
4873 }
4874
rna_iterator_listbase_end(CollectionPropertyIterator * UNUSED (iter))4875 void rna_iterator_listbase_end(CollectionPropertyIterator *UNUSED(iter))
4876 {
4877 }
4878
rna_listbase_lookup_int(PointerRNA * ptr,StructRNA * type,struct ListBase * lb,int index)4879 PointerRNA rna_listbase_lookup_int(PointerRNA *ptr,
4880 StructRNA *type,
4881 struct ListBase *lb,
4882 int index)
4883 {
4884 void *data = BLI_findlink(lb, index);
4885 return rna_pointer_inherit_refine(ptr, type, data);
4886 }
4887
rna_iterator_array_begin(CollectionPropertyIterator * iter,void * ptr,int itemsize,int length,bool free_ptr,IteratorSkipFunc skip)4888 void rna_iterator_array_begin(CollectionPropertyIterator *iter,
4889 void *ptr,
4890 int itemsize,
4891 int length,
4892 bool free_ptr,
4893 IteratorSkipFunc skip)
4894 {
4895 ArrayIterator *internal;
4896
4897 if (ptr == NULL) {
4898 length = 0;
4899 }
4900 else if (length == 0) {
4901 ptr = NULL;
4902 itemsize = 0;
4903 }
4904
4905 internal = &iter->internal.array;
4906 internal->ptr = ptr;
4907 internal->free_ptr = free_ptr ? ptr : NULL;
4908 internal->endptr = ((char *)ptr) + length * itemsize;
4909 internal->itemsize = itemsize;
4910 internal->skip = skip;
4911 internal->length = length;
4912
4913 iter->valid = (internal->ptr != internal->endptr);
4914
4915 if (skip && iter->valid && skip(iter, internal->ptr)) {
4916 rna_iterator_array_next(iter);
4917 }
4918 }
4919
rna_iterator_array_next(CollectionPropertyIterator * iter)4920 void rna_iterator_array_next(CollectionPropertyIterator *iter)
4921 {
4922 ArrayIterator *internal = &iter->internal.array;
4923
4924 if (internal->skip) {
4925 do {
4926 internal->ptr += internal->itemsize;
4927 iter->valid = (internal->ptr != internal->endptr);
4928 } while (iter->valid && internal->skip(iter, internal->ptr));
4929 }
4930 else {
4931 internal->ptr += internal->itemsize;
4932 iter->valid = (internal->ptr != internal->endptr);
4933 }
4934 }
4935
rna_iterator_array_get(CollectionPropertyIterator * iter)4936 void *rna_iterator_array_get(CollectionPropertyIterator *iter)
4937 {
4938 ArrayIterator *internal = &iter->internal.array;
4939
4940 return internal->ptr;
4941 }
4942
rna_iterator_array_dereference_get(CollectionPropertyIterator * iter)4943 void *rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
4944 {
4945 ArrayIterator *internal = &iter->internal.array;
4946
4947 /* for ** arrays */
4948 return *(void **)(internal->ptr);
4949 }
4950
rna_iterator_array_end(CollectionPropertyIterator * iter)4951 void rna_iterator_array_end(CollectionPropertyIterator *iter)
4952 {
4953 ArrayIterator *internal = &iter->internal.array;
4954
4955 if (internal->free_ptr) {
4956 MEM_freeN(internal->free_ptr);
4957 internal->free_ptr = NULL;
4958 }
4959 }
4960
rna_array_lookup_int(PointerRNA * ptr,StructRNA * type,void * data,int itemsize,int length,int index)4961 PointerRNA rna_array_lookup_int(
4962 PointerRNA *ptr, StructRNA *type, void *data, int itemsize, int length, int index)
4963 {
4964 if (index < 0 || index >= length) {
4965 return PointerRNA_NULL;
4966 }
4967
4968 return rna_pointer_inherit_refine(ptr, type, ((char *)data) + index * itemsize);
4969 }
4970
4971 /* RNA Path - Experiment */
4972
rna_path_token(const char ** path,char * fixedbuf,int fixedlen,int bracket)4973 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
4974 {
4975 const char *p;
4976 char *buf;
4977 char quote = '\0';
4978 int i, j, len, escape;
4979
4980 len = 0;
4981
4982 if (bracket) {
4983 /* get data between [], check escaping ] with \] */
4984 if (**path == '[') {
4985 (*path)++;
4986 }
4987 else {
4988 return NULL;
4989 }
4990
4991 p = *path;
4992
4993 /* 2 kinds of lookups now, quoted or unquoted */
4994 quote = *p;
4995
4996 if (quote != '"') { /* " - this comment is hack for Aligorith's text editor's sanity */
4997 quote = 0;
4998 }
4999
5000 if (quote == 0) {
5001 while (*p && (*p != ']')) {
5002 len++;
5003 p++;
5004 }
5005 }
5006 else {
5007 escape = 0;
5008 /* skip the first quote */
5009 len++;
5010 p++;
5011 while (*p && (*p != quote || escape)) {
5012 escape = (*p == '\\');
5013 len++;
5014 p++;
5015 }
5016
5017 /* skip the last quoted char to get the ']' */
5018 len++;
5019 p++;
5020 }
5021
5022 if (*p != ']') {
5023 return NULL;
5024 }
5025 }
5026 else {
5027 /* get data until . or [ */
5028 p = *path;
5029
5030 while (*p && *p != '.' && *p != '[') {
5031 len++;
5032 p++;
5033 }
5034 }
5035
5036 /* empty, return */
5037 if (len == 0) {
5038 return NULL;
5039 }
5040
5041 /* try to use fixed buffer if possible */
5042 if (len + 1 < fixedlen) {
5043 buf = fixedbuf;
5044 }
5045 else {
5046 buf = MEM_mallocN(sizeof(char) * (len + 1), "rna_path_token");
5047 }
5048
5049 /* copy string, taking into account escaped ] */
5050 if (bracket) {
5051 for (p = *path, i = 0, j = 0; i < len; i++, p++) {
5052 if (*p == '\\' && *(p + 1) == quote) {
5053 }
5054 else {
5055 buf[j++] = *p;
5056 }
5057 }
5058
5059 buf[j] = 0;
5060 }
5061 else {
5062 memcpy(buf, *path, sizeof(char) * len);
5063 buf[len] = '\0';
5064 }
5065
5066 /* set path to start of next token */
5067 if (*p == ']') {
5068 p++;
5069 }
5070 if (*p == '.') {
5071 p++;
5072 }
5073 *path = p;
5074
5075 return buf;
5076 }
5077
rna_token_strip_quotes(char * token)5078 static int rna_token_strip_quotes(char *token)
5079 {
5080 if (token[0] == '"') {
5081 int len = strlen(token);
5082 if (len >= 2 && token[len - 1] == '"') {
5083 /* strip away "" */
5084 token[len - 1] = '\0';
5085 return 1;
5086 }
5087 }
5088 return 0;
5089 }
5090
rna_path_parse_collection_key(const char ** path,PointerRNA * ptr,PropertyRNA * prop,PointerRNA * r_nextptr)5091 static bool rna_path_parse_collection_key(const char **path,
5092 PointerRNA *ptr,
5093 PropertyRNA *prop,
5094 PointerRNA *r_nextptr)
5095 {
5096 char fixedbuf[256];
5097 int intkey;
5098
5099 *r_nextptr = *ptr;
5100
5101 /* end of path, ok */
5102 if (!(**path)) {
5103 return true;
5104 }
5105
5106 if (**path == '[') {
5107 char *token;
5108
5109 /* resolve the lookup with [] brackets */
5110 token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1);
5111
5112 if (!token) {
5113 return false;
5114 }
5115
5116 /* check for "" to see if it is a string */
5117 if (rna_token_strip_quotes(token)) {
5118 if (RNA_property_collection_lookup_string(ptr, prop, token + 1, r_nextptr)) {
5119 /* pass */
5120 }
5121 else {
5122 r_nextptr->data = NULL;
5123 }
5124 }
5125 else {
5126 /* otherwise do int lookup */
5127 intkey = atoi(token);
5128 if (intkey == 0 && (token[0] != '0' || token[1] != '\0')) {
5129 return false; /* we can be sure the fixedbuf was used in this case */
5130 }
5131 if (RNA_property_collection_lookup_int(ptr, prop, intkey, r_nextptr)) {
5132 /* pass */
5133 }
5134 else {
5135 r_nextptr->data = NULL;
5136 }
5137 }
5138
5139 if (token != fixedbuf) {
5140 MEM_freeN(token);
5141 }
5142 }
5143 else {
5144 if (RNA_property_collection_type_get(ptr, prop, r_nextptr)) {
5145 /* pass */
5146 }
5147 else {
5148 /* ensure we quit on invalid values */
5149 r_nextptr->data = NULL;
5150 }
5151 }
5152
5153 return true;
5154 }
5155
rna_path_parse_array_index(const char ** path,PointerRNA * ptr,PropertyRNA * prop,int * r_index)5156 static bool rna_path_parse_array_index(const char **path,
5157 PointerRNA *ptr,
5158 PropertyRNA *prop,
5159 int *r_index)
5160 {
5161 char fixedbuf[256];
5162 int index_arr[RNA_MAX_ARRAY_DIMENSION] = {0};
5163 int len[RNA_MAX_ARRAY_DIMENSION];
5164 const int dim = RNA_property_array_dimension(ptr, prop, len);
5165 int i;
5166
5167 *r_index = -1;
5168
5169 /* end of path, ok */
5170 if (!(**path)) {
5171 return true;
5172 }
5173
5174 for (i = 0; i < dim; i++) {
5175 int temp_index = -1;
5176 char *token;
5177
5178 /* multi index resolve */
5179 if (**path == '[') {
5180 token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1);
5181
5182 if (token == NULL) {
5183 /* invalid syntax blah[] */
5184 return false;
5185 }
5186 /* check for "" to see if it is a string */
5187 if (rna_token_strip_quotes(token)) {
5188 temp_index = RNA_property_array_item_index(prop, *(token + 1));
5189 }
5190 else {
5191 /* otherwise do int lookup */
5192 temp_index = atoi(token);
5193
5194 if (temp_index == 0 && (token[0] != '0' || token[1] != '\0')) {
5195 if (token != fixedbuf) {
5196 MEM_freeN(token);
5197 }
5198
5199 return false;
5200 }
5201 }
5202 }
5203 else if (dim == 1) {
5204 /* location.x || scale.X, single dimension arrays only */
5205 token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 0);
5206 if (token == NULL) {
5207 /* invalid syntax blah.. */
5208 return false;
5209 }
5210 temp_index = RNA_property_array_item_index(prop, *token);
5211 }
5212 else {
5213 /* just to avoid uninitialized pointer use */
5214 token = fixedbuf;
5215 }
5216
5217 if (token != fixedbuf) {
5218 MEM_freeN(token);
5219 }
5220
5221 /* out of range */
5222 if (temp_index < 0 || temp_index >= len[i]) {
5223 return false;
5224 }
5225
5226 index_arr[i] = temp_index;
5227 /* end multi index resolve */
5228 }
5229
5230 /* arrays always contain numbers so further values are not valid */
5231 if (**path) {
5232 return false;
5233 }
5234
5235 /* flatten index over all dimensions */
5236 {
5237 int totdim = 1;
5238 int flat_index = 0;
5239
5240 for (i = dim - 1; i >= 0; i--) {
5241 flat_index += index_arr[i] * totdim;
5242 totdim *= len[i];
5243 }
5244
5245 *r_index = flat_index;
5246 }
5247 return true;
5248 }
5249
5250 /**
5251 * Generic rna path parser.
5252 *
5253 * \note All parameters besides \a ptr and \a path are optional.
5254 *
5255 * \param ptr: The root of given RNA path.
5256 * \param path: The RNA path.
5257 * \param r_ptr: The final RNA data holding the last property in \a path.
5258 * \param r_prop: The final property of \a r_ptr, from \a path.
5259 * \param r_index: The final index in the \a r_prop, if defined by \a path.
5260 * \param r_item_ptr: Only valid for Pointer and Collection,
5261 * return the actual value of the pointer, or of the collection item.
5262 * Mutually exclusive with \a eval_pointer option.
5263 * \param r_elements: A list of \a PropertyElemRNA items
5264 * (pairs of \a PointerRNA, \a PropertyRNA that represent the whole given \a path).
5265 * \param eval_pointer: If \a true, and \a path leads to a Pointer property,
5266 * or an item in a Collection property,
5267 * \a r_ptr will be set to the value of that property, and \a r_prop will be NULL.
5268 * Mutually exclusive with \a r_item_ptr.
5269 * \return \a true on success, \a false if the path is somehow invalid.
5270 */
rna_path_parse(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop,int * r_index,PointerRNA * r_item_ptr,ListBase * r_elements,const bool eval_pointer)5271 static bool rna_path_parse(PointerRNA *ptr,
5272 const char *path,
5273 PointerRNA *r_ptr,
5274 PropertyRNA **r_prop,
5275 int *r_index,
5276 PointerRNA *r_item_ptr,
5277 ListBase *r_elements,
5278 const bool eval_pointer)
5279 {
5280 BLI_assert(r_item_ptr == NULL || !eval_pointer);
5281 PropertyRNA *prop;
5282 PointerRNA curptr, nextptr;
5283 PropertyElemRNA *prop_elem = NULL;
5284 int index = -1;
5285 char fixedbuf[256];
5286 int type;
5287 const bool do_item_ptr = r_item_ptr != NULL && !eval_pointer;
5288
5289 if (do_item_ptr) {
5290 RNA_POINTER_INVALIDATE(&nextptr);
5291 }
5292
5293 prop = NULL;
5294 curptr = *ptr;
5295
5296 if (path == NULL || *path == '\0') {
5297 return false;
5298 }
5299
5300 while (*path) {
5301 if (do_item_ptr) {
5302 RNA_POINTER_INVALIDATE(&nextptr);
5303 }
5304
5305 int use_id_prop = (*path == '[') ? 1 : 0;
5306 char *token;
5307 /* custom property lookup ?
5308 * C.object["someprop"]
5309 */
5310
5311 if (!curptr.data) {
5312 return false;
5313 }
5314
5315 /* look up property name in current struct */
5316 token = rna_path_token(&path, fixedbuf, sizeof(fixedbuf), use_id_prop);
5317
5318 if (!token) {
5319 return false;
5320 }
5321
5322 prop = NULL;
5323 if (use_id_prop) { /* look up property name in current struct */
5324 IDProperty *group = RNA_struct_idprops(&curptr, 0);
5325 if (group && rna_token_strip_quotes(token)) {
5326 prop = (PropertyRNA *)IDP_GetPropertyFromGroup(group, token + 1);
5327 }
5328 }
5329 else {
5330 prop = RNA_struct_find_property(&curptr, token);
5331 }
5332
5333 if (token != fixedbuf) {
5334 MEM_freeN(token);
5335 }
5336
5337 if (!prop) {
5338 return false;
5339 }
5340
5341 if (r_elements) {
5342 prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
5343 prop_elem->ptr = curptr;
5344 prop_elem->prop = prop;
5345 prop_elem->index = -1; /* index will be added later, if needed. */
5346 BLI_addtail(r_elements, prop_elem);
5347 }
5348
5349 type = RNA_property_type(prop);
5350
5351 /* now look up the value of this property if it is a pointer or
5352 * collection, otherwise return the property rna so that the
5353 * caller can read the value of the property itself */
5354 switch (type) {
5355 case PROP_POINTER: {
5356 /* resolve pointer if further path elements follow
5357 * or explicitly requested
5358 */
5359 if (do_item_ptr || eval_pointer || *path != '\0') {
5360 nextptr = RNA_property_pointer_get(&curptr, prop);
5361 }
5362
5363 if (eval_pointer || *path != '\0') {
5364 curptr = nextptr;
5365 prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
5366 index = -1;
5367 }
5368 break;
5369 }
5370 case PROP_COLLECTION: {
5371 /* Resolve pointer if further path elements follow.
5372 * Note that if path is empty, rna_path_parse_collection_key will do nothing anyway,
5373 * so do_item_ptr is of no use in that case.
5374 */
5375 if (*path) {
5376 if (!rna_path_parse_collection_key(&path, &curptr, prop, &nextptr)) {
5377 return false;
5378 }
5379
5380 if (eval_pointer || *path != '\0') {
5381 curptr = nextptr;
5382 prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
5383 index = -1;
5384 }
5385 }
5386 break;
5387 }
5388 default:
5389 if (r_index || prop_elem) {
5390 if (!rna_path_parse_array_index(&path, &curptr, prop, &index)) {
5391 return false;
5392 }
5393
5394 if (prop_elem) {
5395 prop_elem->index = index;
5396 }
5397 }
5398 break;
5399 }
5400 }
5401
5402 if (r_ptr) {
5403 *r_ptr = curptr;
5404 }
5405 if (r_prop) {
5406 *r_prop = prop;
5407 }
5408 if (r_index) {
5409 *r_index = index;
5410 }
5411 if (r_item_ptr && do_item_ptr) {
5412 *r_item_ptr = nextptr;
5413 }
5414
5415 if (prop_elem && (prop_elem->ptr.data != curptr.data || prop_elem->prop != prop ||
5416 prop_elem->index != index)) {
5417 prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
5418 prop_elem->ptr = curptr;
5419 prop_elem->prop = prop;
5420 prop_elem->index = index;
5421 BLI_addtail(r_elements, prop_elem);
5422 }
5423
5424 return true;
5425 }
5426
5427 /**
5428 * Resolve the given RNA Path to find the pointer and/or property
5429 * indicated by fully resolving the path.
5430 *
5431 * \warning Unlike \a RNA_path_resolve_property(), that one *will* try to follow RNAPointers,
5432 * e.g. the path 'parent' applied to a RNAObject \a ptr will return the object.parent in \a r_ptr,
5433 * and a NULL \a r_prop...
5434 *
5435 * \note Assumes all pointers provided are valid
5436 * \return True if path can be resolved to a valid "pointer + property" OR "pointer only"
5437 */
RNA_path_resolve(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop)5438 bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
5439 {
5440 if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, NULL, true)) {
5441 return false;
5442 }
5443
5444 return r_ptr->data != NULL;
5445 }
5446
5447 /**
5448 * Resolve the given RNA Path to find the pointer and/or property + array index
5449 * indicated by fully resolving the path.
5450 *
5451 * \note Assumes all pointers provided are valid.
5452 * \return True if path can be resolved to a valid "pointer + property" OR "pointer only"
5453 */
RNA_path_resolve_full(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop,int * r_index)5454 bool RNA_path_resolve_full(
5455 PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
5456 {
5457 if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, NULL, true)) {
5458 return false;
5459 }
5460
5461 return r_ptr->data != NULL;
5462 }
5463
5464 /**
5465 * Resolve the given RNA Path to find both the pointer AND property
5466 * indicated by fully resolving the path.
5467 *
5468 * This is a convenience method to avoid logic errors and ugly syntax.
5469 * \note Assumes all pointers provided are valid
5470 * \return True only if both a valid pointer and property are found after resolving the path
5471 */
RNA_path_resolve_property(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop)5472 bool RNA_path_resolve_property(PointerRNA *ptr,
5473 const char *path,
5474 PointerRNA *r_ptr,
5475 PropertyRNA **r_prop)
5476 {
5477 if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, NULL, false)) {
5478 return false;
5479 }
5480
5481 return r_ptr->data != NULL && *r_prop != NULL;
5482 }
5483
5484 /**
5485 * Resolve the given RNA Path to find the pointer AND property (as well as the array index)
5486 * indicated by fully resolving the path.
5487 *
5488 * This is a convenience method to avoid logic errors and ugly syntax.
5489 * \note Assumes all pointers provided are valid
5490 * \return True only if both a valid pointer and property are found after resolving the path
5491 */
RNA_path_resolve_property_full(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop,int * r_index)5492 bool RNA_path_resolve_property_full(
5493 PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
5494 {
5495 if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, NULL, false)) {
5496 return false;
5497 }
5498
5499 return r_ptr->data != NULL && *r_prop != NULL;
5500 }
5501
5502 /**
5503 * Resolve the given RNA Path to find both the pointer AND property
5504 * indicated by fully resolving the path, and get the value of the Pointer property
5505 * (or item of the collection).
5506 *
5507 * This is a convenience method to avoid logic errors and ugly syntax,
5508 * it combines both \a RNA_path_resolve and #RNA_path_resolve_property in a single call.
5509 * \note Assumes all pointers provided are valid.
5510 * \param r_item_ptr: The final Pointer or Collection item value.
5511 * You must check for its validity before use!
5512 * \return True only if both a valid pointer and property are found after resolving the path
5513 */
RNA_path_resolve_property_and_item_pointer(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop,PointerRNA * r_item_ptr)5514 bool RNA_path_resolve_property_and_item_pointer(PointerRNA *ptr,
5515 const char *path,
5516 PointerRNA *r_ptr,
5517 PropertyRNA **r_prop,
5518 PointerRNA *r_item_ptr)
5519 {
5520 if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, r_item_ptr, NULL, false)) {
5521 return false;
5522 }
5523
5524 return r_ptr->data != NULL && *r_prop != NULL;
5525 }
5526
5527 /**
5528 * Resolve the given RNA Path to find both the pointer AND property (as well as the array index)
5529 * indicated by fully resolving the path,
5530 * and get the value of the Pointer property (or item of the collection).
5531 *
5532 * This is a convenience method to avoid logic errors and ugly syntax,
5533 * it combines both \a RNA_path_resolve_full and
5534 * \a RNA_path_resolve_property_full in a single call.
5535 * \note Assumes all pointers provided are valid.
5536 * \param r_item_ptr: The final Pointer or Collection item value.
5537 * You must check for its validity before use!
5538 * \return True only if both a valid pointer and property are found after resolving the path
5539 */
RNA_path_resolve_property_and_item_pointer_full(PointerRNA * ptr,const char * path,PointerRNA * r_ptr,PropertyRNA ** r_prop,int * r_index,PointerRNA * r_item_ptr)5540 bool RNA_path_resolve_property_and_item_pointer_full(PointerRNA *ptr,
5541 const char *path,
5542 PointerRNA *r_ptr,
5543 PropertyRNA **r_prop,
5544 int *r_index,
5545 PointerRNA *r_item_ptr)
5546 {
5547 if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, r_item_ptr, NULL, false)) {
5548 return false;
5549 }
5550
5551 return r_ptr->data != NULL && *r_prop != NULL;
5552 }
5553 /**
5554 * Resolve the given RNA Path into a linked list of PropertyElemRNA's.
5555 *
5556 * To be used when complex operations over path are needed, like e.g. get relative paths,
5557 * to avoid too much string operations.
5558 *
5559 * \return True if there was no error while resolving the path
5560 * \note Assumes all pointers provided are valid
5561 */
RNA_path_resolve_elements(PointerRNA * ptr,const char * path,ListBase * r_elements)5562 bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_elements)
5563 {
5564 return rna_path_parse(ptr, path, NULL, NULL, NULL, NULL, r_elements, false);
5565 }
5566
RNA_path_append(const char * path,PointerRNA * UNUSED (ptr),PropertyRNA * prop,int intkey,const char * strkey)5567 char *RNA_path_append(
5568 const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey)
5569 {
5570 DynStr *dynstr;
5571 const char *s;
5572 char appendstr[128], *result;
5573
5574 dynstr = BLI_dynstr_new();
5575
5576 /* add .identifier */
5577 if (path) {
5578 BLI_dynstr_append(dynstr, path);
5579 if (*path) {
5580 BLI_dynstr_append(dynstr, ".");
5581 }
5582 }
5583
5584 BLI_dynstr_append(dynstr, RNA_property_identifier(prop));
5585
5586 if (RNA_property_type(prop) == PROP_COLLECTION) {
5587 /* add ["strkey"] or [intkey] */
5588 BLI_dynstr_append(dynstr, "[");
5589
5590 if (strkey) {
5591 BLI_dynstr_append(dynstr, "\"");
5592 for (s = strkey; *s; s++) {
5593 if (*s == '[') {
5594 appendstr[0] = '\\';
5595 appendstr[1] = *s;
5596 appendstr[2] = 0;
5597 }
5598 else {
5599 appendstr[0] = *s;
5600 appendstr[1] = 0;
5601 }
5602 BLI_dynstr_append(dynstr, appendstr);
5603 }
5604 BLI_dynstr_append(dynstr, "\"");
5605 }
5606 else {
5607 BLI_snprintf(appendstr, sizeof(appendstr), "%d", intkey);
5608 BLI_dynstr_append(dynstr, appendstr);
5609 }
5610
5611 BLI_dynstr_append(dynstr, "]");
5612 }
5613
5614 result = BLI_dynstr_get_cstring(dynstr);
5615 BLI_dynstr_free(dynstr);
5616
5617 return result;
5618 }
5619
RNA_path_back(const char * path)5620 char *RNA_path_back(const char *path)
5621 {
5622 char fixedbuf[256];
5623 const char *previous, *current;
5624 char *result;
5625 int i;
5626
5627 if (!path) {
5628 return NULL;
5629 }
5630
5631 previous = NULL;
5632 current = path;
5633
5634 /* parse token by token until the end, then we back up to the previous
5635 * position and strip of the next token to get the path one step back */
5636 while (*current) {
5637 char *token;
5638
5639 token = rna_path_token(¤t, fixedbuf, sizeof(fixedbuf), 0);
5640
5641 if (!token) {
5642 return NULL;
5643 }
5644 if (token != fixedbuf) {
5645 MEM_freeN(token);
5646 }
5647
5648 /* in case of collection we also need to strip off [] */
5649 token = rna_path_token(¤t, fixedbuf, sizeof(fixedbuf), 1);
5650 if (token && token != fixedbuf) {
5651 MEM_freeN(token);
5652 }
5653
5654 if (!*current) {
5655 break;
5656 }
5657
5658 previous = current;
5659 }
5660
5661 if (!previous) {
5662 return NULL;
5663 }
5664
5665 /* copy and strip off last token */
5666 i = previous - path;
5667 result = BLI_strdup(path);
5668
5669 if (i > 0 && result[i - 1] == '.') {
5670 i--;
5671 }
5672 result[i] = 0;
5673
5674 return result;
5675 }
5676
5677 /* generic path search func
5678 * if its needed this could also reference the IDProperty direct */
5679 typedef struct IDP_Chain {
5680 struct IDP_Chain *up; /* parent member, reverse and set to child for path conversion. */
5681
5682 const char *name;
5683 int index;
5684
5685 } IDP_Chain;
5686
rna_idp_path_create(IDP_Chain * child_link)5687 static char *rna_idp_path_create(IDP_Chain *child_link)
5688 {
5689 DynStr *dynstr = BLI_dynstr_new();
5690 char *path;
5691 bool is_first = true;
5692
5693 int tot = 0;
5694 IDP_Chain *link = child_link;
5695
5696 /* reverse the list */
5697 IDP_Chain *link_prev;
5698 link_prev = NULL;
5699 while (link) {
5700 IDP_Chain *link_next = link->up;
5701 link->up = link_prev;
5702 link_prev = link;
5703 link = link_next;
5704 tot++;
5705 }
5706
5707 for (link = link_prev; link; link = link->up) {
5708 /* pass */
5709 if (link->index >= 0) {
5710 BLI_dynstr_appendf(dynstr, is_first ? "%s[%d]" : ".%s[%d]", link->name, link->index);
5711 }
5712 else {
5713 BLI_dynstr_appendf(dynstr, is_first ? "%s" : ".%s", link->name);
5714 }
5715
5716 is_first = false;
5717 }
5718
5719 path = BLI_dynstr_get_cstring(dynstr);
5720 BLI_dynstr_free(dynstr);
5721
5722 if (*path == '\0') {
5723 MEM_freeN(path);
5724 path = NULL;
5725 }
5726
5727 return path;
5728 }
5729
rna_idp_path(PointerRNA * ptr,IDProperty * haystack,IDProperty * needle,IDP_Chain * parent_link)5730 static char *rna_idp_path(PointerRNA *ptr,
5731 IDProperty *haystack,
5732 IDProperty *needle,
5733 IDP_Chain *parent_link)
5734 {
5735 char *path = NULL;
5736 IDP_Chain link;
5737
5738 IDProperty *iter;
5739 int i;
5740
5741 BLI_assert(haystack->type == IDP_GROUP);
5742
5743 link.up = parent_link;
5744 /* always set both name and index,
5745 * else a stale value might get used */
5746 link.name = NULL;
5747 link.index = -1;
5748
5749 for (i = 0, iter = haystack->data.group.first; iter; iter = iter->next, i++) {
5750 if (needle == iter) { /* found! */
5751 link.name = iter->name;
5752 link.index = -1;
5753 path = rna_idp_path_create(&link);
5754 break;
5755 }
5756 if (iter->type == IDP_GROUP) {
5757 /* ensure this is RNA */
5758 PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name);
5759 if (prop && prop->type == PROP_POINTER) {
5760 PointerRNA child_ptr = RNA_property_pointer_get(ptr, prop);
5761 link.name = iter->name;
5762 link.index = -1;
5763 if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) {
5764 break;
5765 }
5766 }
5767 }
5768 else if (iter->type == IDP_IDPARRAY) {
5769 PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name);
5770 if (prop && prop->type == PROP_COLLECTION) {
5771 IDProperty *array = IDP_IDPArray(iter);
5772 if (needle >= array && needle < (iter->len + array)) { /* found! */
5773 link.name = iter->name;
5774 link.index = (int)(needle - array);
5775 path = rna_idp_path_create(&link);
5776 break;
5777 }
5778 else {
5779 int j;
5780 link.name = iter->name;
5781 for (j = 0; j < iter->len; j++, array++) {
5782 PointerRNA child_ptr;
5783 if (RNA_property_collection_lookup_int(ptr, prop, j, &child_ptr)) {
5784 link.index = j;
5785 if ((path = rna_idp_path(&child_ptr, array, needle, &link))) {
5786 break;
5787 }
5788 }
5789 }
5790 if (path) {
5791 break;
5792 }
5793 }
5794 }
5795 }
5796 }
5797
5798 return path;
5799 }
5800
5801 /**
5802 * Find the path from the structure referenced by the pointer to the #IDProperty object.
5803 *
5804 * \param ptr: Reference to the object owning the custom property storage.
5805 * \param needle: Custom property object to find.
5806 * \return Relative path or NULL.
5807 */
RNA_path_from_struct_to_idproperty(PointerRNA * ptr,IDProperty * needle)5808 char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, IDProperty *needle)
5809 {
5810 IDProperty *haystack = RNA_struct_idprops(ptr, false);
5811
5812 if (haystack) { /* can fail when called on bones */
5813 return rna_idp_path(ptr, haystack, needle, NULL);
5814 }
5815 return NULL;
5816 }
5817
rna_path_from_ID_to_idpgroup(PointerRNA * ptr)5818 static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr)
5819 {
5820 PointerRNA id_ptr;
5821
5822 BLI_assert(ptr->owner_id != NULL);
5823
5824 /* TODO, Support Bones/PoseBones. no pointers stored to the bones from here, only the ID.
5825 * See example in T25746.
5826 * Unless this is added only way to find this is to also search
5827 * all bones and pose bones of an armature or object.
5828 */
5829 RNA_id_pointer_create(ptr->owner_id, &id_ptr);
5830
5831 return RNA_path_from_struct_to_idproperty(&id_ptr, ptr->data);
5832 }
5833
5834 /**
5835 * Find the actual ID pointer and path from it to the given ID.
5836 *
5837 * \param id: ID reference to search the global owner for.
5838 * \param[out] r_path: Path from the real ID to the initial ID.
5839 * \return The ID pointer, or NULL in case of failure.
5840 */
RNA_find_real_ID_and_path(Main * bmain,ID * id,const char ** r_path)5841 ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
5842 {
5843 if (r_path) {
5844 *r_path = "";
5845 }
5846
5847 if ((id != NULL) && (id->flag & LIB_EMBEDDED_DATA)) {
5848 switch (GS(id->name)) {
5849 case ID_NT:
5850 if (r_path) {
5851 *r_path = "node_tree";
5852 }
5853 return BKE_node_tree_find_owner_ID(bmain, (bNodeTree *)id);
5854 case ID_GR:
5855 if (r_path) {
5856 *r_path = "collection";
5857 }
5858 return (ID *)BKE_collection_master_scene_search(bmain, (Collection *)id);
5859
5860 default:
5861 return NULL;
5862 }
5863 }
5864 else {
5865 return id;
5866 }
5867 }
5868
rna_prepend_real_ID_path(Main * bmain,ID * id,char * path,ID ** r_real_id)5869 static char *rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id)
5870 {
5871 if (r_real_id != NULL) {
5872 *r_real_id = NULL;
5873 }
5874
5875 const char *prefix;
5876 ID *real_id = RNA_find_real_ID_and_path(bmain, id, &prefix);
5877
5878 if (r_real_id != NULL) {
5879 *r_real_id = real_id;
5880 }
5881
5882 if (path != NULL) {
5883 char *new_path = NULL;
5884
5885 if (real_id) {
5886 if (prefix[0]) {
5887 new_path = BLI_sprintfN("%s%s%s", prefix, path[0] == '[' ? "" : ".", path);
5888 }
5889 else {
5890 return path;
5891 }
5892 }
5893
5894 MEM_freeN(path);
5895 return new_path;
5896 }
5897 return prefix[0] != '\0' ? BLI_strdup(prefix) : NULL;
5898 }
5899
RNA_path_from_ID_to_struct(PointerRNA * ptr)5900 char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
5901 {
5902 char *ptrpath = NULL;
5903
5904 if (!ptr->owner_id || !ptr->data) {
5905 return NULL;
5906 }
5907
5908 if (!RNA_struct_is_ID(ptr->type)) {
5909 if (ptr->type->path) {
5910 /* if type has a path to some ID, use it */
5911 ptrpath = ptr->type->path(ptr);
5912 }
5913 else if (ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) {
5914 PointerRNA parentptr;
5915 PropertyRNA *userprop;
5916
5917 /* find the property in the struct we're nested in that references this struct, and
5918 * use its identifier as the first part of the path used...
5919 */
5920 RNA_id_pointer_create(ptr->owner_id, &parentptr);
5921 userprop = RNA_struct_find_nested(&parentptr, ptr->type);
5922
5923 if (userprop) {
5924 ptrpath = BLI_strdup(RNA_property_identifier(userprop));
5925 }
5926 else {
5927 return NULL; /* can't do anything about this case yet... */
5928 }
5929 }
5930 else if (RNA_struct_is_a(ptr->type, &RNA_PropertyGroup)) {
5931 /* special case, easier to deal with here than in ptr->type->path() */
5932 return rna_path_from_ID_to_idpgroup(ptr);
5933 }
5934 else {
5935 return NULL;
5936 }
5937 }
5938
5939 return ptrpath;
5940 }
5941
RNA_path_from_real_ID_to_struct(Main * bmain,PointerRNA * ptr,struct ID ** r_real)5942 char *RNA_path_from_real_ID_to_struct(Main *bmain, PointerRNA *ptr, struct ID **r_real)
5943 {
5944 char *path = RNA_path_from_ID_to_struct(ptr);
5945
5946 /* NULL path is valid in that case, when given struct is an ID one... */
5947 return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real);
5948 }
5949
rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH],const int totdims,const int index_dim,int index,int r_index_multi[RNA_MAX_ARRAY_LENGTH])5950 static void rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH],
5951 const int totdims,
5952 const int index_dim,
5953 int index,
5954 int r_index_multi[RNA_MAX_ARRAY_LENGTH])
5955 {
5956 int dimsize_step[RNA_MAX_ARRAY_LENGTH + 1];
5957 int i = totdims - 1;
5958 dimsize_step[i + 1] = 1;
5959 dimsize_step[i] = dimsize[i];
5960 while (--i != -1) {
5961 dimsize_step[i] = dimsize[i] * dimsize_step[i + 1];
5962 }
5963 while (++i != index_dim) {
5964 int index_round = index / dimsize_step[i + 1];
5965 r_index_multi[i] = index_round;
5966 index -= (index_round * dimsize_step[i + 1]);
5967 }
5968 BLI_assert(index == 0);
5969 }
5970
rna_path_array_multi_string_from_flat_index(PointerRNA * ptr,PropertyRNA * prop,int index_dim,int index,char * index_str,int index_str_len)5971 static void rna_path_array_multi_string_from_flat_index(PointerRNA *ptr,
5972 PropertyRNA *prop,
5973 int index_dim,
5974 int index,
5975 char *index_str,
5976 int index_str_len)
5977 {
5978 int dimsize[RNA_MAX_ARRAY_LENGTH];
5979 int totdims = RNA_property_array_dimension(ptr, prop, dimsize);
5980 int index_multi[RNA_MAX_ARRAY_LENGTH];
5981
5982 rna_path_array_multi_from_flat_index(dimsize, totdims, index_dim, index, index_multi);
5983
5984 for (int i = 0, offset = 0; (i < index_dim) && (offset < index_str_len); i++) {
5985 offset += BLI_snprintf_rlen(
5986 &index_str[offset], index_str_len - offset, "[%d]", index_multi[i]);
5987 }
5988 }
5989
5990 /**
5991 * \param index_dim: The dimension to show, 0 disables. 1 for 1d array, 2 for 2d. etc.
5992 * \param index: The *flattened* index to use when \a ``index_dim > 0``,
5993 * this is expanded when used with multi-dimensional arrays.
5994 */
RNA_path_from_ID_to_property_index(PointerRNA * ptr,PropertyRNA * prop,int index_dim,int index)5995 char *RNA_path_from_ID_to_property_index(PointerRNA *ptr,
5996 PropertyRNA *prop,
5997 int index_dim,
5998 int index)
5999 {
6000 const bool is_rna = (prop->magic == RNA_MAGIC);
6001 const char *propname;
6002 char *ptrpath, *path;
6003
6004 if (!ptr->owner_id || !ptr->data) {
6005 return NULL;
6006 }
6007
6008 /* path from ID to the struct holding this property */
6009 ptrpath = RNA_path_from_ID_to_struct(ptr);
6010
6011 propname = RNA_property_identifier(prop);
6012
6013 /* support indexing w/ multi-dimensional arrays */
6014 char index_str[RNA_MAX_ARRAY_LENGTH * 12 + 1];
6015 if (index_dim == 0) {
6016 index_str[0] = '\0';
6017 }
6018 else {
6019 rna_path_array_multi_string_from_flat_index(
6020 ptr, prop, index_dim, index, index_str, sizeof(index_str));
6021 }
6022
6023 if (ptrpath) {
6024 if (is_rna) {
6025 path = BLI_sprintfN("%s.%s%s", ptrpath, propname, index_str);
6026 }
6027 else {
6028 char propname_esc[MAX_IDPROP_NAME * 2];
6029 BLI_strescape(propname_esc, propname, sizeof(propname_esc));
6030 path = BLI_sprintfN("%s[\"%s\"]%s", ptrpath, propname_esc, index_str);
6031 }
6032 MEM_freeN(ptrpath);
6033 }
6034 else if (RNA_struct_is_ID(ptr->type)) {
6035 if (is_rna) {
6036 path = BLI_sprintfN("%s%s", propname, index_str);
6037 }
6038 else {
6039 char propname_esc[MAX_IDPROP_NAME * 2];
6040 BLI_strescape(propname_esc, propname, sizeof(propname_esc));
6041 path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str);
6042 }
6043 }
6044 else {
6045 path = NULL;
6046 }
6047
6048 return path;
6049 }
6050
RNA_path_from_ID_to_property(PointerRNA * ptr,PropertyRNA * prop)6051 char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
6052 {
6053 return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1);
6054 }
6055
RNA_path_from_real_ID_to_property_index(Main * bmain,PointerRNA * ptr,PropertyRNA * prop,int index_dim,int index,ID ** r_real_id)6056 char *RNA_path_from_real_ID_to_property_index(
6057 Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, ID **r_real_id)
6058 {
6059 char *path = RNA_path_from_ID_to_property_index(ptr, prop, index_dim, index);
6060
6061 /* NULL path is always an error here, in that case do not return the 'fake ID from real ID' part
6062 * of the path either. */
6063 return path != NULL ? rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real_id) : NULL;
6064 }
6065
6066 /**
6067 * \return the path to given ptr/prop from the closest ancestor of given type,
6068 * if any (else return NULL).
6069 */
RNA_path_resolve_from_type_to_property(PointerRNA * ptr,PropertyRNA * prop,const StructRNA * type)6070 char *RNA_path_resolve_from_type_to_property(PointerRNA *ptr,
6071 PropertyRNA *prop,
6072 const StructRNA *type)
6073 {
6074 /* Try to recursively find an "type"'d ancestor,
6075 * to handle situations where path from ID is not enough. */
6076 PointerRNA idptr;
6077 ListBase path_elems = {NULL};
6078 char *path = NULL;
6079 char *full_path = RNA_path_from_ID_to_property(ptr, prop);
6080
6081 if (full_path == NULL) {
6082 return NULL;
6083 }
6084
6085 RNA_id_pointer_create(ptr->owner_id, &idptr);
6086
6087 if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) {
6088 PropertyElemRNA *prop_elem;
6089
6090 for (prop_elem = path_elems.last; prop_elem; prop_elem = prop_elem->prev) {
6091 if (RNA_struct_is_a(prop_elem->ptr.type, type)) {
6092 char *ref_path = RNA_path_from_ID_to_struct(&prop_elem->ptr);
6093 if (ref_path) {
6094 path = BLI_strdup(full_path + strlen(ref_path) + 1); /* +1 for the linking '.' */
6095 MEM_freeN(ref_path);
6096 }
6097 break;
6098 }
6099 }
6100
6101 BLI_freelistN(&path_elems);
6102 }
6103
6104 MEM_freeN(full_path);
6105 return path;
6106 }
6107
6108 /**
6109 * Get the ID as a python representation, eg:
6110 * bpy.data.foo["bar"]
6111 */
RNA_path_full_ID_py(Main * bmain,ID * id)6112 char *RNA_path_full_ID_py(Main *bmain, ID *id)
6113 {
6114 const char *path;
6115 ID *id_real = RNA_find_real_ID_and_path(bmain, id, &path);
6116
6117 if (id_real) {
6118 id = id_real;
6119 }
6120 else {
6121 path = "";
6122 }
6123
6124 char id_esc[(sizeof(id->name) - 2) * 2];
6125
6126 BLI_strescape(id_esc, id->name + 2, sizeof(id_esc));
6127
6128 return BLI_sprintfN("bpy.data.%s[\"%s\"]%s%s",
6129 BKE_idtype_idcode_to_name_plural(GS(id->name)),
6130 id_esc,
6131 path[0] ? "." : "",
6132 path);
6133 }
6134
6135 /**
6136 * Get the ID.struct as a python representation, eg:
6137 * bpy.data.foo["bar"].some_struct
6138 */
RNA_path_full_struct_py(Main * bmain,struct PointerRNA * ptr)6139 char *RNA_path_full_struct_py(Main *bmain, struct PointerRNA *ptr)
6140 {
6141 char *id_path;
6142 char *data_path;
6143
6144 char *ret;
6145
6146 if (!ptr->owner_id) {
6147 return NULL;
6148 }
6149
6150 /* never fails */
6151 id_path = RNA_path_full_ID_py(bmain, ptr->owner_id);
6152
6153 data_path = RNA_path_from_ID_to_struct(ptr);
6154
6155 /* XXX data_path may be NULL (see T36788),
6156 * do we want to get the 'bpy.data.foo["bar"].(null)' stuff? */
6157 ret = BLI_sprintfN("%s.%s", id_path, data_path);
6158
6159 if (data_path) {
6160 MEM_freeN(data_path);
6161 }
6162 MEM_freeN(id_path);
6163
6164 return ret;
6165 }
6166
6167 /**
6168 * Get the ID.struct.property as a python representation, eg:
6169 * bpy.data.foo["bar"].some_struct.some_prop[10]
6170 */
RNA_path_full_property_py_ex(Main * bmain,PointerRNA * ptr,PropertyRNA * prop,int index,bool use_fallback)6171 char *RNA_path_full_property_py_ex(
6172 Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
6173 {
6174 char *id_path;
6175 const char *data_delim;
6176 const char *data_path;
6177 bool data_path_free;
6178
6179 char *ret;
6180
6181 if (!ptr->owner_id) {
6182 return NULL;
6183 }
6184
6185 /* never fails */
6186 id_path = RNA_path_full_ID_py(bmain, ptr->owner_id);
6187
6188 data_path = RNA_path_from_ID_to_property(ptr, prop);
6189 if (data_path) {
6190 data_delim = (data_path[0] == '[') ? "" : ".";
6191 data_path_free = true;
6192 }
6193 else {
6194 if (use_fallback) {
6195 /* fuzzy fallback. be explicit in our ignoranc. */
6196 data_path = RNA_property_identifier(prop);
6197 data_delim = " ... ";
6198 }
6199 else {
6200 data_delim = ".";
6201 }
6202 data_path_free = false;
6203 }
6204
6205 if ((index == -1) || (RNA_property_array_check(prop) == false)) {
6206 ret = BLI_sprintfN("%s%s%s", id_path, data_delim, data_path);
6207 }
6208 else {
6209 ret = BLI_sprintfN("%s%s%s[%d]", id_path, data_delim, data_path, index);
6210 }
6211 MEM_freeN(id_path);
6212 if (data_path_free) {
6213 MEM_freeN((void *)data_path);
6214 }
6215
6216 return ret;
6217 }
6218
RNA_path_full_property_py(Main * bmain,PointerRNA * ptr,PropertyRNA * prop,int index)6219 char *RNA_path_full_property_py(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index)
6220 {
6221 return RNA_path_full_property_py_ex(bmain, ptr, prop, index, false);
6222 }
6223
6224 /**
6225 * Get the struct.property as a python representation, eg:
6226 * some_struct.some_prop[10]
6227 */
RNA_path_struct_property_py(PointerRNA * ptr,PropertyRNA * prop,int index)6228 char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
6229 {
6230 char *data_path;
6231
6232 char *ret;
6233
6234 if (!ptr->owner_id) {
6235 return NULL;
6236 }
6237
6238 data_path = RNA_path_from_ID_to_property(ptr, prop);
6239
6240 if (data_path == NULL) {
6241 /* this may not be an ID at all, check for simple when pointer owns property.
6242 * TODO, more complex nested case */
6243 if (!RNA_struct_is_ID(ptr->type)) {
6244 const char *prop_identifier = RNA_property_identifier(prop);
6245 if (RNA_struct_find_property(ptr, prop_identifier) == prop) {
6246 data_path = BLI_strdup(prop_identifier);
6247 }
6248 }
6249 }
6250
6251 if ((index == -1) || (RNA_property_array_check(prop) == false)) {
6252 ret = BLI_sprintfN("%s", data_path);
6253 }
6254 else {
6255 ret = BLI_sprintfN("%s[%d]", data_path, index);
6256 }
6257
6258 if (data_path) {
6259 MEM_freeN(data_path);
6260 }
6261
6262 return ret;
6263 }
6264
6265 /**
6266 * Get the struct.property as a python representation, eg:
6267 * some_prop[10]
6268 */
RNA_path_property_py(PointerRNA * UNUSED (ptr),PropertyRNA * prop,int index)6269 char *RNA_path_property_py(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int index)
6270 {
6271 char *ret;
6272
6273 if ((index == -1) || (RNA_property_array_check(prop) == false)) {
6274 ret = BLI_sprintfN("%s", RNA_property_identifier(prop));
6275 }
6276 else {
6277 ret = BLI_sprintfN("%s[%d]", RNA_property_identifier(prop), index);
6278 }
6279
6280 return ret;
6281 }
6282
6283 /* Quick name based property access */
6284
RNA_boolean_get(PointerRNA * ptr,const char * name)6285 bool RNA_boolean_get(PointerRNA *ptr, const char *name)
6286 {
6287 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6288
6289 if (prop) {
6290 return RNA_property_boolean_get(ptr, prop);
6291 }
6292 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6293 return 0;
6294 }
6295
RNA_boolean_set(PointerRNA * ptr,const char * name,bool value)6296 void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
6297 {
6298 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6299
6300 if (prop) {
6301 RNA_property_boolean_set(ptr, prop, value);
6302 }
6303 else {
6304 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6305 }
6306 }
6307
RNA_boolean_get_array(PointerRNA * ptr,const char * name,bool * values)6308 void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
6309 {
6310 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6311
6312 if (prop) {
6313 RNA_property_boolean_get_array(ptr, prop, values);
6314 }
6315 else {
6316 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6317 }
6318 }
6319
RNA_boolean_set_array(PointerRNA * ptr,const char * name,const bool * values)6320 void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const bool *values)
6321 {
6322 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6323
6324 if (prop) {
6325 RNA_property_boolean_set_array(ptr, prop, values);
6326 }
6327 else {
6328 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6329 }
6330 }
6331
RNA_int_get(PointerRNA * ptr,const char * name)6332 int RNA_int_get(PointerRNA *ptr, const char *name)
6333 {
6334 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6335
6336 if (prop) {
6337 return RNA_property_int_get(ptr, prop);
6338 }
6339 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6340 return 0;
6341 }
6342
RNA_int_set(PointerRNA * ptr,const char * name,int value)6343 void RNA_int_set(PointerRNA *ptr, const char *name, int value)
6344 {
6345 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6346
6347 if (prop) {
6348 RNA_property_int_set(ptr, prop, value);
6349 }
6350 else {
6351 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6352 }
6353 }
6354
RNA_int_get_array(PointerRNA * ptr,const char * name,int * values)6355 void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
6356 {
6357 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6358
6359 if (prop) {
6360 RNA_property_int_get_array(ptr, prop, values);
6361 }
6362 else {
6363 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6364 }
6365 }
6366
RNA_int_set_array(PointerRNA * ptr,const char * name,const int * values)6367 void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
6368 {
6369 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6370
6371 if (prop) {
6372 RNA_property_int_set_array(ptr, prop, values);
6373 }
6374 else {
6375 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6376 }
6377 }
6378
RNA_float_get(PointerRNA * ptr,const char * name)6379 float RNA_float_get(PointerRNA *ptr, const char *name)
6380 {
6381 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6382
6383 if (prop) {
6384 return RNA_property_float_get(ptr, prop);
6385 }
6386 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6387 return 0;
6388 }
6389
RNA_float_set(PointerRNA * ptr,const char * name,float value)6390 void RNA_float_set(PointerRNA *ptr, const char *name, float value)
6391 {
6392 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6393
6394 if (prop) {
6395 RNA_property_float_set(ptr, prop, value);
6396 }
6397 else {
6398 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6399 }
6400 }
6401
RNA_float_get_array(PointerRNA * ptr,const char * name,float * values)6402 void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
6403 {
6404 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6405
6406 if (prop) {
6407 RNA_property_float_get_array(ptr, prop, values);
6408 }
6409 else {
6410 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6411 }
6412 }
6413
RNA_float_set_array(PointerRNA * ptr,const char * name,const float * values)6414 void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
6415 {
6416 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6417
6418 if (prop) {
6419 RNA_property_float_set_array(ptr, prop, values);
6420 }
6421 else {
6422 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6423 }
6424 }
6425
RNA_enum_get(PointerRNA * ptr,const char * name)6426 int RNA_enum_get(PointerRNA *ptr, const char *name)
6427 {
6428 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6429
6430 if (prop) {
6431 return RNA_property_enum_get(ptr, prop);
6432 }
6433 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6434 return 0;
6435 }
6436
RNA_enum_set(PointerRNA * ptr,const char * name,int value)6437 void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
6438 {
6439 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6440
6441 if (prop) {
6442 RNA_property_enum_set(ptr, prop, value);
6443 }
6444 else {
6445 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6446 }
6447 }
6448
RNA_enum_set_identifier(bContext * C,PointerRNA * ptr,const char * name,const char * id)6449 void RNA_enum_set_identifier(bContext *C, PointerRNA *ptr, const char *name, const char *id)
6450 {
6451 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6452
6453 if (prop) {
6454 int value;
6455 if (RNA_property_enum_value(C, ptr, prop, id, &value)) {
6456 RNA_property_enum_set(ptr, prop, value);
6457 }
6458 else {
6459 printf("%s: %s.%s has no enum id '%s'.\n", __func__, ptr->type->identifier, name, id);
6460 }
6461 }
6462 else {
6463 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6464 }
6465 }
6466
RNA_enum_is_equal(bContext * C,PointerRNA * ptr,const char * name,const char * enumname)6467 bool RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname)
6468 {
6469 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6470 const EnumPropertyItem *item;
6471 bool free;
6472
6473 if (prop) {
6474 int i;
6475 bool cmp = false;
6476
6477 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
6478 i = RNA_enum_from_identifier(item, enumname);
6479 if (i != -1) {
6480 cmp = (item[i].value == RNA_property_enum_get(ptr, prop));
6481 }
6482
6483 if (free) {
6484 MEM_freeN((void *)item);
6485 }
6486
6487 if (i != -1) {
6488 return cmp;
6489 }
6490
6491 printf("%s: %s.%s item %s not found.\n", __func__, ptr->type->identifier, name, enumname);
6492 return false;
6493 }
6494 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6495 return false;
6496 }
6497
RNA_enum_value_from_id(const EnumPropertyItem * item,const char * identifier,int * r_value)6498 bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
6499 {
6500 const int i = RNA_enum_from_identifier(item, identifier);
6501 if (i != -1) {
6502 *r_value = item[i].value;
6503 return true;
6504 }
6505 return false;
6506 }
6507
RNA_enum_id_from_value(const EnumPropertyItem * item,int value,const char ** r_identifier)6508 bool RNA_enum_id_from_value(const EnumPropertyItem *item, int value, const char **r_identifier)
6509 {
6510 const int i = RNA_enum_from_value(item, value);
6511 if (i != -1) {
6512 *r_identifier = item[i].identifier;
6513 return true;
6514 }
6515 return false;
6516 }
6517
RNA_enum_icon_from_value(const EnumPropertyItem * item,int value,int * r_icon)6518 bool RNA_enum_icon_from_value(const EnumPropertyItem *item, int value, int *r_icon)
6519 {
6520 const int i = RNA_enum_from_value(item, value);
6521 if (i != -1) {
6522 *r_icon = item[i].icon;
6523 return true;
6524 }
6525 return false;
6526 }
6527
RNA_enum_name_from_value(const EnumPropertyItem * item,int value,const char ** r_name)6528 bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name)
6529 {
6530 const int i = RNA_enum_from_value(item, value);
6531 if (i != -1) {
6532 *r_name = item[i].name;
6533 return true;
6534 }
6535 return false;
6536 }
6537
RNA_string_get(PointerRNA * ptr,const char * name,char * value)6538 void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
6539 {
6540 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6541
6542 if (prop) {
6543 RNA_property_string_get(ptr, prop, value);
6544 }
6545 else {
6546 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6547 value[0] = '\0';
6548 }
6549 }
6550
RNA_string_get_alloc(PointerRNA * ptr,const char * name,char * fixedbuf,int fixedlen)6551 char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen)
6552 {
6553 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6554
6555 if (prop) {
6556 /* TODO, pass length */
6557 return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen, NULL);
6558 }
6559 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6560 return NULL;
6561 }
6562
RNA_string_length(PointerRNA * ptr,const char * name)6563 int RNA_string_length(PointerRNA *ptr, const char *name)
6564 {
6565 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6566
6567 if (prop) {
6568 return RNA_property_string_length(ptr, prop);
6569 }
6570 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6571 return 0;
6572 }
6573
RNA_string_set(PointerRNA * ptr,const char * name,const char * value)6574 void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
6575 {
6576 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6577
6578 if (prop) {
6579 RNA_property_string_set(ptr, prop, value);
6580 }
6581 else {
6582 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6583 }
6584 }
6585
RNA_pointer_get(PointerRNA * ptr,const char * name)6586 PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
6587 {
6588 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6589
6590 if (prop) {
6591 return RNA_property_pointer_get(ptr, prop);
6592 }
6593 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6594
6595 return PointerRNA_NULL;
6596 }
6597
RNA_pointer_set(PointerRNA * ptr,const char * name,PointerRNA ptr_value)6598 void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
6599 {
6600 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6601
6602 if (prop) {
6603 RNA_property_pointer_set(ptr, prop, ptr_value, NULL);
6604 }
6605 else {
6606 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6607 }
6608 }
6609
RNA_pointer_add(PointerRNA * ptr,const char * name)6610 void RNA_pointer_add(PointerRNA *ptr, const char *name)
6611 {
6612 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6613
6614 if (prop) {
6615 RNA_property_pointer_add(ptr, prop);
6616 }
6617 else {
6618 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6619 }
6620 }
6621
RNA_collection_begin(PointerRNA * ptr,const char * name,CollectionPropertyIterator * iter)6622 void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter)
6623 {
6624 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6625
6626 if (prop) {
6627 RNA_property_collection_begin(ptr, prop, iter);
6628 }
6629 else {
6630 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6631 }
6632 }
6633
RNA_collection_add(PointerRNA * ptr,const char * name,PointerRNA * r_value)6634 void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
6635 {
6636 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6637
6638 if (prop) {
6639 RNA_property_collection_add(ptr, prop, r_value);
6640 }
6641 else {
6642 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6643 }
6644 }
6645
RNA_collection_clear(PointerRNA * ptr,const char * name)6646 void RNA_collection_clear(PointerRNA *ptr, const char *name)
6647 {
6648 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6649
6650 if (prop) {
6651 RNA_property_collection_clear(ptr, prop);
6652 }
6653 else {
6654 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6655 }
6656 }
6657
RNA_collection_length(PointerRNA * ptr,const char * name)6658 int RNA_collection_length(PointerRNA *ptr, const char *name)
6659 {
6660 PropertyRNA *prop = RNA_struct_find_property(ptr, name);
6661
6662 if (prop) {
6663 return RNA_property_collection_length(ptr, prop);
6664 }
6665 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6666 return 0;
6667 }
6668
RNA_property_is_set_ex(PointerRNA * ptr,PropertyRNA * prop,bool use_ghost)6669 bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost)
6670 {
6671 prop = rna_ensure_property(prop);
6672 if (prop->flag & PROP_IDPROPERTY) {
6673 IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier);
6674 return ((idprop != NULL) && (use_ghost == false || !(idprop->flag & IDP_FLAG_GHOST)));
6675 }
6676 return true;
6677 }
6678
RNA_property_is_set(PointerRNA * ptr,PropertyRNA * prop)6679 bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
6680 {
6681 prop = rna_ensure_property(prop);
6682 if (prop->flag & PROP_IDPROPERTY) {
6683 IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier);
6684 return ((idprop != NULL) && !(idprop->flag & IDP_FLAG_GHOST));
6685 }
6686 return true;
6687 }
6688
RNA_property_unset(PointerRNA * ptr,PropertyRNA * prop)6689 void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
6690 {
6691 prop = rna_ensure_property(prop);
6692 if (prop->flag & PROP_IDPROPERTY) {
6693 rna_idproperty_free(ptr, prop->identifier);
6694 }
6695 }
6696
RNA_struct_property_is_set_ex(PointerRNA * ptr,const char * identifier,bool use_ghost)6697 bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
6698 {
6699 PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
6700
6701 if (prop) {
6702 return RNA_property_is_set_ex(ptr, prop, use_ghost);
6703 }
6704 /* python raises an error */
6705 /* printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name); */
6706 return 0;
6707 }
6708
RNA_struct_property_is_set(PointerRNA * ptr,const char * identifier)6709 bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
6710 {
6711 PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
6712
6713 if (prop) {
6714 return RNA_property_is_set(ptr, prop);
6715 }
6716 /* python raises an error */
6717 /* printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name); */
6718 return 0;
6719 }
6720
RNA_struct_property_unset(PointerRNA * ptr,const char * identifier)6721 void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
6722 {
6723 PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
6724
6725 if (prop) {
6726 RNA_property_unset(ptr, prop);
6727 }
6728 }
6729
RNA_property_is_idprop(const PropertyRNA * prop)6730 bool RNA_property_is_idprop(const PropertyRNA *prop)
6731 {
6732 return (prop->magic != RNA_MAGIC);
6733 }
6734
6735 /* mainly for the UI */
RNA_property_is_unlink(PropertyRNA * prop)6736 bool RNA_property_is_unlink(PropertyRNA *prop)
6737 {
6738 const int flag = RNA_property_flag(prop);
6739 if (RNA_property_type(prop) == PROP_STRING) {
6740 return (flag & PROP_NEVER_UNLINK) == 0;
6741 }
6742 return (flag & (PROP_NEVER_UNLINK | PROP_NEVER_NULL)) == 0;
6743 }
6744
6745 /* string representation of a property, python
6746 * compatible but can be used for display too,
6747 * context may be NULL */
RNA_pointer_as_string_id(bContext * C,PointerRNA * ptr)6748 char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
6749 {
6750 DynStr *dynstr = BLI_dynstr_new();
6751 char *cstring;
6752
6753 const char *propname;
6754 int first_time = 1;
6755
6756 BLI_dynstr_append(dynstr, "{");
6757
6758 RNA_STRUCT_BEGIN (ptr, prop) {
6759 propname = RNA_property_identifier(prop);
6760
6761 if (STREQ(propname, "rna_type")) {
6762 continue;
6763 }
6764
6765 if (first_time == 0) {
6766 BLI_dynstr_append(dynstr, ", ");
6767 }
6768 first_time = 0;
6769
6770 cstring = RNA_property_as_string(C, ptr, prop, -1, INT_MAX);
6771 BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring);
6772 MEM_freeN(cstring);
6773 }
6774 RNA_STRUCT_END;
6775
6776 BLI_dynstr_append(dynstr, "}");
6777
6778 cstring = BLI_dynstr_get_cstring(dynstr);
6779 BLI_dynstr_free(dynstr);
6780 return cstring;
6781 }
6782
rna_pointer_as_string__bldata(Main * bmain,PointerRNA * ptr)6783 static char *rna_pointer_as_string__bldata(Main *bmain, PointerRNA *ptr)
6784 {
6785 if (ptr->type == NULL || ptr->owner_id == NULL) {
6786 return BLI_strdup("None");
6787 }
6788 if (RNA_struct_is_ID(ptr->type)) {
6789 return RNA_path_full_ID_py(bmain, ptr->owner_id);
6790 }
6791 else {
6792 return RNA_path_full_struct_py(bmain, ptr);
6793 }
6794 }
6795
RNA_pointer_as_string(bContext * C,PointerRNA * ptr,PropertyRNA * prop_ptr,PointerRNA * ptr_prop)6796 char *RNA_pointer_as_string(bContext *C,
6797 PointerRNA *ptr,
6798 PropertyRNA *prop_ptr,
6799 PointerRNA *ptr_prop)
6800 {
6801 IDProperty *prop;
6802 if (ptr_prop->data == NULL) {
6803 return BLI_strdup("None");
6804 }
6805 if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) {
6806 return RNA_pointer_as_string_id(C, ptr_prop);
6807 }
6808 else {
6809 return rna_pointer_as_string__bldata(CTX_data_main(C), ptr_prop);
6810 }
6811 }
6812
6813 /* context can be NULL */
RNA_pointer_as_string_keywords_ex(bContext * C,PointerRNA * ptr,const bool as_function,const bool all_args,const bool nested_args,const int max_prop_length,PropertyRNA * iterprop)6814 char *RNA_pointer_as_string_keywords_ex(bContext *C,
6815 PointerRNA *ptr,
6816 const bool as_function,
6817 const bool all_args,
6818 const bool nested_args,
6819 const int max_prop_length,
6820 PropertyRNA *iterprop)
6821 {
6822 const char *arg_name = NULL;
6823
6824 PropertyRNA *prop;
6825
6826 DynStr *dynstr = BLI_dynstr_new();
6827 char *cstring, *buf;
6828 bool first_iter = true;
6829 int flag, flag_parameter;
6830
6831 RNA_PROP_BEGIN (ptr, propptr, iterprop) {
6832 prop = propptr.data;
6833
6834 flag = RNA_property_flag(prop);
6835 flag_parameter = RNA_parameter_flag(prop);
6836
6837 if (as_function && (flag_parameter & PARM_OUTPUT)) {
6838 continue;
6839 }
6840
6841 arg_name = RNA_property_identifier(prop);
6842
6843 if (STREQ(arg_name, "rna_type")) {
6844 continue;
6845 }
6846
6847 if ((nested_args == false) && (RNA_property_type(prop) == PROP_POINTER)) {
6848 continue;
6849 }
6850
6851 if (as_function && (prop->flag_parameter & PARM_REQUIRED)) {
6852 /* required args don't have useful defaults */
6853 BLI_dynstr_appendf(dynstr, first_iter ? "%s" : ", %s", arg_name);
6854 first_iter = false;
6855 }
6856 else {
6857 bool ok = true;
6858
6859 if (all_args == true) {
6860 /* pass */
6861 }
6862 else if (RNA_struct_idprops_check(ptr->type)) {
6863 ok = RNA_property_is_set(ptr, prop);
6864 }
6865
6866 if (ok) {
6867 if (as_function && RNA_property_type(prop) == PROP_POINTER) {
6868 /* don't expand pointers for functions */
6869 if (flag & PROP_NEVER_NULL) {
6870 /* we cant really do the right thing here. arg=arg?, hrmf! */
6871 buf = BLI_strdup(arg_name);
6872 }
6873 else {
6874 buf = BLI_strdup("None");
6875 }
6876 }
6877 else {
6878 buf = RNA_property_as_string(C, ptr, prop, -1, max_prop_length);
6879 }
6880
6881 BLI_dynstr_appendf(dynstr, first_iter ? "%s=%s" : ", %s=%s", arg_name, buf);
6882 first_iter = false;
6883 MEM_freeN(buf);
6884 }
6885 }
6886 }
6887 RNA_PROP_END;
6888
6889 cstring = BLI_dynstr_get_cstring(dynstr);
6890 BLI_dynstr_free(dynstr);
6891 return cstring;
6892 }
6893
RNA_pointer_as_string_keywords(bContext * C,PointerRNA * ptr,const bool as_function,const bool all_args,const bool nested_args,const int max_prop_length)6894 char *RNA_pointer_as_string_keywords(bContext *C,
6895 PointerRNA *ptr,
6896 const bool as_function,
6897 const bool all_args,
6898 const bool nested_args,
6899 const int max_prop_length)
6900 {
6901 PropertyRNA *iterprop;
6902
6903 iterprop = RNA_struct_iterator_property(ptr->type);
6904
6905 return RNA_pointer_as_string_keywords_ex(
6906 C, ptr, as_function, all_args, nested_args, max_prop_length, iterprop);
6907 }
6908
RNA_function_as_string_keywords(bContext * C,FunctionRNA * func,const bool as_function,const bool all_args,const int max_prop_length)6909 char *RNA_function_as_string_keywords(bContext *C,
6910 FunctionRNA *func,
6911 const bool as_function,
6912 const bool all_args,
6913 const int max_prop_length)
6914 {
6915 PointerRNA funcptr;
6916 PropertyRNA *iterprop;
6917
6918 RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
6919
6920 iterprop = RNA_struct_find_property(&funcptr, "parameters");
6921
6922 RNA_struct_iterator_property(funcptr.type);
6923
6924 return RNA_pointer_as_string_keywords_ex(
6925 C, &funcptr, as_function, all_args, true, max_prop_length, iterprop);
6926 }
6927
bool_as_py_string(const int var)6928 static const char *bool_as_py_string(const int var)
6929 {
6930 return var ? "True" : "False";
6931 }
6932
rna_array_as_string_alloc(int type,int len,PointerRNA * ptr,PropertyRNA * prop,void ** r_buf_end)6933 static void *rna_array_as_string_alloc(
6934 int type, int len, PointerRNA *ptr, PropertyRNA *prop, void **r_buf_end)
6935 {
6936 void *buf_ret = NULL;
6937 if (type == PROP_BOOLEAN) {
6938 bool *buf = buf_ret = MEM_mallocN(sizeof(*buf) * len, __func__);
6939 RNA_property_boolean_get_array(ptr, prop, buf);
6940 *r_buf_end = buf + len;
6941 }
6942 else if (type == PROP_INT) {
6943 int *buf = buf_ret = MEM_mallocN(sizeof(*buf) * len, __func__);
6944 RNA_property_int_get_array(ptr, prop, buf);
6945 *r_buf_end = buf + len;
6946 }
6947 else if (type == PROP_FLOAT) {
6948 float *buf = buf_ret = MEM_mallocN(sizeof(*buf) * len, __func__);
6949 RNA_property_float_get_array(ptr, prop, buf);
6950 *r_buf_end = buf + len;
6951 }
6952 else {
6953 BLI_assert(0);
6954 }
6955 return buf_ret;
6956 }
6957
rna_array_as_string_elem(int type,void ** buf_p,int len,DynStr * dynstr)6958 static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dynstr)
6959 {
6960 /* This will print a comma separated string of the array elements from
6961 * buf start to len. We will add a comma if len == 1 to preserve tuples. */
6962 const int end = len - 1;
6963 if (type == PROP_BOOLEAN) {
6964 bool *buf = *buf_p;
6965 for (int i = 0; i < len; i++, buf++) {
6966 BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%s, " : "%s", bool_as_py_string(*buf));
6967 }
6968 *buf_p = buf;
6969 }
6970 else if (type == PROP_INT) {
6971 int *buf = *buf_p;
6972 for (int i = 0; i < len; i++, buf++) {
6973 BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%d, " : "%d", *buf);
6974 }
6975 *buf_p = buf;
6976 }
6977 else if (type == PROP_FLOAT) {
6978 float *buf = *buf_p;
6979 for (int i = 0; i < len; i++, buf++) {
6980 BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%g, " : "%g", *buf);
6981 }
6982 *buf_p = buf;
6983 }
6984 else {
6985 BLI_assert(0);
6986 }
6987 }
6988
rna_array_as_string_recursive(int type,void ** buf_p,int totdim,const int * dim_size,DynStr * dynstr)6989 static void rna_array_as_string_recursive(
6990 int type, void **buf_p, int totdim, const int *dim_size, DynStr *dynstr)
6991 {
6992 BLI_dynstr_append(dynstr, "(");
6993 if (totdim > 1) {
6994 totdim--;
6995 const int end = dim_size[totdim] - 1;
6996 for (int i = 0; i <= end; i++) {
6997 rna_array_as_string_recursive(type, buf_p, totdim, dim_size, dynstr);
6998 if (i < end || !end) {
6999 BLI_dynstr_append(dynstr, ", ");
7000 }
7001 }
7002 }
7003 else {
7004 rna_array_as_string_elem(type, buf_p, dim_size[0], dynstr);
7005 }
7006 BLI_dynstr_append(dynstr, ")");
7007 }
7008
rna_array_as_string(int type,int len,PointerRNA * ptr,PropertyRNA * prop,DynStr * dynstr)7009 static void rna_array_as_string(
7010 int type, int len, PointerRNA *ptr, PropertyRNA *prop, DynStr *dynstr)
7011 {
7012 void *buf_end;
7013 void *buf = rna_array_as_string_alloc(type, len, ptr, prop, &buf_end);
7014 void *buf_step = buf;
7015 int totdim, dim_size[RNA_MAX_ARRAY_DIMENSION];
7016
7017 totdim = RNA_property_array_dimension(ptr, prop, dim_size);
7018
7019 rna_array_as_string_recursive(type, &buf_step, totdim, dim_size, dynstr);
7020 BLI_assert(buf_step == buf_end);
7021 MEM_freeN(buf);
7022 }
7023
RNA_property_as_string(bContext * C,PointerRNA * ptr,PropertyRNA * prop,int index,int max_prop_length)7024 char *RNA_property_as_string(
7025 bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length)
7026 {
7027 int type = RNA_property_type(prop);
7028 int len = RNA_property_array_length(ptr, prop);
7029
7030 DynStr *dynstr = BLI_dynstr_new();
7031 char *cstring;
7032
7033 /* see if we can coerce into a python type - PropertyType */
7034 switch (type) {
7035 case PROP_BOOLEAN:
7036 if (len == 0) {
7037 BLI_dynstr_append(dynstr, bool_as_py_string(RNA_property_boolean_get(ptr, prop)));
7038 }
7039 else {
7040 if (index != -1) {
7041 BLI_dynstr_append(dynstr,
7042 bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index)));
7043 }
7044 else {
7045 rna_array_as_string(type, len, ptr, prop, dynstr);
7046 }
7047 }
7048 break;
7049 case PROP_INT:
7050 if (len == 0) {
7051 BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get(ptr, prop));
7052 }
7053 else {
7054 if (index != -1) {
7055 BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get_index(ptr, prop, index));
7056 }
7057 else {
7058 rna_array_as_string(type, len, ptr, prop, dynstr);
7059 }
7060 }
7061 break;
7062 case PROP_FLOAT:
7063 if (len == 0) {
7064 BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get(ptr, prop));
7065 }
7066 else {
7067 if (index != -1) {
7068 BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get_index(ptr, prop, index));
7069 }
7070 else {
7071 rna_array_as_string(type, len, ptr, prop, dynstr);
7072 }
7073 }
7074 break;
7075 case PROP_STRING: {
7076 char *buf_esc;
7077 char *buf;
7078 int length;
7079
7080 length = RNA_property_string_length(ptr, prop);
7081 buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_property_as_string");
7082 buf_esc = MEM_mallocN(sizeof(char) * (length * 2 + 1), "RNA_property_as_string esc");
7083 RNA_property_string_get(ptr, prop, buf);
7084 BLI_strescape(buf_esc, buf, length * 2 + 1);
7085 MEM_freeN(buf);
7086 BLI_dynstr_appendf(dynstr, "\"%s\"", buf_esc);
7087 MEM_freeN(buf_esc);
7088 break;
7089 }
7090 case PROP_ENUM: {
7091 /* string arrays don't exist */
7092 const char *identifier;
7093 int val = RNA_property_enum_get(ptr, prop);
7094
7095 if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
7096 /* represent as a python set */
7097 if (val) {
7098 const EnumPropertyItem *item_array;
7099 bool free;
7100
7101 BLI_dynstr_append(dynstr, "{");
7102
7103 RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free);
7104 if (item_array) {
7105 const EnumPropertyItem *item = item_array;
7106 bool is_first = true;
7107 for (; item->identifier; item++) {
7108 if (item->identifier[0] && item->value & val) {
7109 BLI_dynstr_appendf(dynstr, is_first ? "'%s'" : ", '%s'", item->identifier);
7110 is_first = false;
7111 }
7112 }
7113
7114 if (free) {
7115 MEM_freeN((void *)item_array);
7116 }
7117 }
7118
7119 BLI_dynstr_append(dynstr, "}");
7120 }
7121 else {
7122 /* annoying exception, don't confuse with dictionary syntax above: {} */
7123 BLI_dynstr_append(dynstr, "set()");
7124 }
7125 }
7126 else if (RNA_property_enum_identifier(C, ptr, prop, val, &identifier)) {
7127 BLI_dynstr_appendf(dynstr, "'%s'", identifier);
7128 }
7129 else {
7130 BLI_dynstr_append(dynstr, "'<UNKNOWN ENUM>'");
7131 }
7132 break;
7133 }
7134 case PROP_POINTER: {
7135 PointerRNA tptr = RNA_property_pointer_get(ptr, prop);
7136 cstring = RNA_pointer_as_string(C, ptr, prop, &tptr);
7137 BLI_dynstr_append(dynstr, cstring);
7138 MEM_freeN(cstring);
7139 break;
7140 }
7141 case PROP_COLLECTION: {
7142 int i = 0;
7143 CollectionPropertyIterator collect_iter;
7144 BLI_dynstr_append(dynstr, "[");
7145
7146 for (RNA_property_collection_begin(ptr, prop, &collect_iter);
7147 (i < max_prop_length) && collect_iter.valid;
7148 RNA_property_collection_next(&collect_iter), i++) {
7149 PointerRNA itemptr = collect_iter.ptr;
7150
7151 if (i != 0) {
7152 BLI_dynstr_append(dynstr, ", ");
7153 }
7154
7155 /* now get every prop of the collection */
7156 cstring = RNA_pointer_as_string(C, ptr, prop, &itemptr);
7157 BLI_dynstr_append(dynstr, cstring);
7158 MEM_freeN(cstring);
7159 }
7160
7161 RNA_property_collection_end(&collect_iter);
7162 BLI_dynstr_append(dynstr, "]");
7163 break;
7164 }
7165 default:
7166 BLI_dynstr_append(dynstr, "'<UNKNOWN TYPE>'"); /* TODO */
7167 break;
7168 }
7169
7170 cstring = BLI_dynstr_get_cstring(dynstr);
7171 BLI_dynstr_free(dynstr);
7172 return cstring;
7173 }
7174
7175 /* Function */
7176
RNA_function_identifier(FunctionRNA * func)7177 const char *RNA_function_identifier(FunctionRNA *func)
7178 {
7179 return func->identifier;
7180 }
7181
RNA_function_ui_description(FunctionRNA * func)7182 const char *RNA_function_ui_description(FunctionRNA *func)
7183 {
7184 return TIP_(func->description);
7185 }
7186
RNA_function_ui_description_raw(FunctionRNA * func)7187 const char *RNA_function_ui_description_raw(FunctionRNA *func)
7188 {
7189 return func->description;
7190 }
7191
RNA_function_flag(FunctionRNA * func)7192 int RNA_function_flag(FunctionRNA *func)
7193 {
7194 return func->flag;
7195 }
7196
RNA_function_defined(FunctionRNA * func)7197 int RNA_function_defined(FunctionRNA *func)
7198 {
7199 return func->call != NULL;
7200 }
7201
RNA_function_get_parameter(PointerRNA * UNUSED (ptr),FunctionRNA * func,int index)7202 PropertyRNA *RNA_function_get_parameter(PointerRNA *UNUSED(ptr), FunctionRNA *func, int index)
7203 {
7204 return BLI_findlink(&func->cont.properties, index);
7205 }
7206
RNA_function_find_parameter(PointerRNA * UNUSED (ptr),FunctionRNA * func,const char * identifier)7207 PropertyRNA *RNA_function_find_parameter(PointerRNA *UNUSED(ptr),
7208 FunctionRNA *func,
7209 const char *identifier)
7210 {
7211 PropertyRNA *parm;
7212
7213 parm = func->cont.properties.first;
7214 for (; parm; parm = parm->next) {
7215 if (STREQ(RNA_property_identifier(parm), identifier)) {
7216 break;
7217 }
7218 }
7219
7220 return parm;
7221 }
7222
RNA_function_defined_parameters(FunctionRNA * func)7223 const ListBase *RNA_function_defined_parameters(FunctionRNA *func)
7224 {
7225 return &func->cont.properties;
7226 }
7227
7228 /* Utility */
7229
RNA_parameter_flag(PropertyRNA * prop)7230 int RNA_parameter_flag(PropertyRNA *prop)
7231 {
7232 return (int)rna_ensure_property(prop)->flag_parameter;
7233 }
7234
RNA_parameter_list_create(ParameterList * parms,PointerRNA * UNUSED (ptr),FunctionRNA * func)7235 ParameterList *RNA_parameter_list_create(ParameterList *parms,
7236 PointerRNA *UNUSED(ptr),
7237 FunctionRNA *func)
7238 {
7239 PropertyRNA *parm;
7240 PointerRNA null_ptr = PointerRNA_NULL;
7241 void *data;
7242 int alloc_size = 0, size;
7243
7244 parms->arg_count = 0;
7245 parms->ret_count = 0;
7246
7247 /* allocate data */
7248 for (parm = func->cont.properties.first; parm; parm = parm->next) {
7249 alloc_size += rna_parameter_size(parm);
7250
7251 if (parm->flag_parameter & PARM_OUTPUT) {
7252 parms->ret_count++;
7253 }
7254 else {
7255 parms->arg_count++;
7256 }
7257 }
7258
7259 parms->data = MEM_callocN(alloc_size, "RNA_parameter_list_create");
7260 parms->func = func;
7261 parms->alloc_size = alloc_size;
7262
7263 /* set default values */
7264 data = parms->data;
7265
7266 for (parm = func->cont.properties.first; parm; parm = parm->next) {
7267 size = rna_parameter_size(parm);
7268
7269 /* set length to 0, these need to be set later, see bpy_array.c's py_to_array */
7270 if (parm->flag & PROP_DYNAMIC) {
7271 ParameterDynAlloc *data_alloc = data;
7272 data_alloc->array_tot = 0;
7273 data_alloc->array = NULL;
7274 }
7275
7276 if (!(parm->flag_parameter & PARM_REQUIRED) && !(parm->flag & PROP_DYNAMIC)) {
7277 switch (parm->type) {
7278 case PROP_BOOLEAN:
7279 if (parm->arraydimension) {
7280 rna_property_boolean_get_default_array_values(
7281 &null_ptr, (BoolPropertyRNA *)parm, data);
7282 }
7283 else {
7284 memcpy(data, &((BoolPropertyRNA *)parm)->defaultvalue, size);
7285 }
7286 break;
7287 case PROP_INT:
7288 if (parm->arraydimension) {
7289 rna_property_int_get_default_array_values(&null_ptr, (IntPropertyRNA *)parm, data);
7290 }
7291 else {
7292 memcpy(data, &((IntPropertyRNA *)parm)->defaultvalue, size);
7293 }
7294 break;
7295 case PROP_FLOAT:
7296 if (parm->arraydimension) {
7297 rna_property_float_get_default_array_values(&null_ptr, (FloatPropertyRNA *)parm, data);
7298 }
7299 else {
7300 memcpy(data, &((FloatPropertyRNA *)parm)->defaultvalue, size);
7301 }
7302 break;
7303 case PROP_ENUM:
7304 memcpy(data, &((EnumPropertyRNA *)parm)->defaultvalue, size);
7305 break;
7306 case PROP_STRING: {
7307 const char *defvalue = ((StringPropertyRNA *)parm)->defaultvalue;
7308 if (defvalue && defvalue[0]) {
7309 /* causes bug T29988, possibly this is only correct for thick wrapped
7310 * need to look further into it - campbell */
7311 #if 0
7312 BLI_strncpy(data, defvalue, size);
7313 #else
7314 memcpy(data, &defvalue, size);
7315 #endif
7316 }
7317 break;
7318 }
7319 case PROP_POINTER:
7320 case PROP_COLLECTION:
7321 break;
7322 }
7323 }
7324
7325 data = ((char *)data) + rna_parameter_size(parm);
7326 }
7327
7328 return parms;
7329 }
7330
RNA_parameter_list_free(ParameterList * parms)7331 void RNA_parameter_list_free(ParameterList *parms)
7332 {
7333 PropertyRNA *parm;
7334 int tot;
7335
7336 parm = parms->func->cont.properties.first;
7337 for (tot = 0; parm; parm = parm->next) {
7338 if (parm->type == PROP_COLLECTION) {
7339 BLI_freelistN((ListBase *)((char *)parms->data + tot));
7340 }
7341 else if (parm->flag & PROP_DYNAMIC) {
7342 /* for dynamic arrays and strings, data is a pointer to an array */
7343 ParameterDynAlloc *data_alloc = (void *)(((char *)parms->data) + tot);
7344 if (data_alloc->array) {
7345 MEM_freeN(data_alloc->array);
7346 }
7347 }
7348
7349 tot += rna_parameter_size(parm);
7350 }
7351
7352 MEM_freeN(parms->data);
7353 parms->data = NULL;
7354
7355 parms->func = NULL;
7356 }
7357
RNA_parameter_list_size(ParameterList * parms)7358 int RNA_parameter_list_size(ParameterList *parms)
7359 {
7360 return parms->alloc_size;
7361 }
7362
RNA_parameter_list_arg_count(ParameterList * parms)7363 int RNA_parameter_list_arg_count(ParameterList *parms)
7364 {
7365 return parms->arg_count;
7366 }
7367
RNA_parameter_list_ret_count(ParameterList * parms)7368 int RNA_parameter_list_ret_count(ParameterList *parms)
7369 {
7370 return parms->ret_count;
7371 }
7372
RNA_parameter_list_begin(ParameterList * parms,ParameterIterator * iter)7373 void RNA_parameter_list_begin(ParameterList *parms, ParameterIterator *iter)
7374 {
7375 /* may be useful but unused now */
7376 /* RNA_pointer_create(NULL, &RNA_Function, parms->func, &iter->funcptr); */ /*UNUSED*/
7377
7378 iter->parms = parms;
7379 iter->parm = parms->func->cont.properties.first;
7380 iter->valid = iter->parm != NULL;
7381 iter->offset = 0;
7382
7383 if (iter->valid) {
7384 iter->size = rna_parameter_size(iter->parm);
7385 iter->data = (((char *)iter->parms->data)); /* +iter->offset, always 0 */
7386 }
7387 }
7388
RNA_parameter_list_next(ParameterIterator * iter)7389 void RNA_parameter_list_next(ParameterIterator *iter)
7390 {
7391 iter->offset += iter->size;
7392 iter->parm = iter->parm->next;
7393 iter->valid = iter->parm != NULL;
7394
7395 if (iter->valid) {
7396 iter->size = rna_parameter_size(iter->parm);
7397 iter->data = (((char *)iter->parms->data) + iter->offset);
7398 }
7399 }
7400
RNA_parameter_list_end(ParameterIterator * UNUSED (iter))7401 void RNA_parameter_list_end(ParameterIterator *UNUSED(iter))
7402 {
7403 /* nothing to do */
7404 }
7405
RNA_parameter_get(ParameterList * parms,PropertyRNA * parm,void ** value)7406 void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **value)
7407 {
7408 ParameterIterator iter;
7409
7410 RNA_parameter_list_begin(parms, &iter);
7411
7412 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7413 if (iter.parm == parm) {
7414 break;
7415 }
7416 }
7417
7418 if (iter.valid) {
7419 if (parm->flag & PROP_DYNAMIC) {
7420 /* for dynamic arrays and strings, data is a pointer to an array */
7421 ParameterDynAlloc *data_alloc = iter.data;
7422 *value = data_alloc->array;
7423 }
7424 else {
7425 *value = iter.data;
7426 }
7427 }
7428 else {
7429 *value = NULL;
7430 }
7431
7432 RNA_parameter_list_end(&iter);
7433 }
7434
RNA_parameter_get_lookup(ParameterList * parms,const char * identifier,void ** value)7435 void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void **value)
7436 {
7437 PropertyRNA *parm;
7438
7439 parm = parms->func->cont.properties.first;
7440 for (; parm; parm = parm->next) {
7441 if (STREQ(RNA_property_identifier(parm), identifier)) {
7442 break;
7443 }
7444 }
7445
7446 if (parm) {
7447 RNA_parameter_get(parms, parm, value);
7448 }
7449 }
7450
RNA_parameter_set(ParameterList * parms,PropertyRNA * parm,const void * value)7451 void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *value)
7452 {
7453 ParameterIterator iter;
7454
7455 RNA_parameter_list_begin(parms, &iter);
7456
7457 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7458 if (iter.parm == parm) {
7459 break;
7460 }
7461 }
7462
7463 if (iter.valid) {
7464 if (parm->flag & PROP_DYNAMIC) {
7465 /* for dynamic arrays and strings, data is a pointer to an array */
7466 ParameterDynAlloc *data_alloc = iter.data;
7467 size_t size = 0;
7468 switch (parm->type) {
7469 case PROP_STRING:
7470 size = sizeof(char);
7471 break;
7472 case PROP_INT:
7473 case PROP_BOOLEAN:
7474 size = sizeof(int);
7475 break;
7476 case PROP_FLOAT:
7477 size = sizeof(float);
7478 break;
7479 default:
7480 break;
7481 }
7482 size *= data_alloc->array_tot;
7483 if (data_alloc->array) {
7484 MEM_freeN(data_alloc->array);
7485 }
7486 data_alloc->array = MEM_mallocN(size, __func__);
7487 memcpy(data_alloc->array, value, size);
7488 }
7489 else {
7490 memcpy(iter.data, value, iter.size);
7491 }
7492 }
7493
7494 RNA_parameter_list_end(&iter);
7495 }
7496
RNA_parameter_set_lookup(ParameterList * parms,const char * identifier,const void * value)7497 void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, const void *value)
7498 {
7499 PropertyRNA *parm;
7500
7501 parm = parms->func->cont.properties.first;
7502 for (; parm; parm = parm->next) {
7503 if (STREQ(RNA_property_identifier(parm), identifier)) {
7504 break;
7505 }
7506 }
7507
7508 if (parm) {
7509 RNA_parameter_set(parms, parm, value);
7510 }
7511 }
7512
RNA_parameter_dynamic_length_get(ParameterList * parms,PropertyRNA * parm)7513 int RNA_parameter_dynamic_length_get(ParameterList *parms, PropertyRNA *parm)
7514 {
7515 ParameterIterator iter;
7516 int len = 0;
7517
7518 RNA_parameter_list_begin(parms, &iter);
7519
7520 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7521 if (iter.parm == parm) {
7522 break;
7523 }
7524 }
7525
7526 if (iter.valid) {
7527 len = RNA_parameter_dynamic_length_get_data(parms, parm, iter.data);
7528 }
7529
7530 RNA_parameter_list_end(&iter);
7531
7532 return len;
7533 }
7534
RNA_parameter_dynamic_length_set(ParameterList * parms,PropertyRNA * parm,int length)7535 void RNA_parameter_dynamic_length_set(ParameterList *parms, PropertyRNA *parm, int length)
7536 {
7537 ParameterIterator iter;
7538
7539 RNA_parameter_list_begin(parms, &iter);
7540
7541 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7542 if (iter.parm == parm) {
7543 break;
7544 }
7545 }
7546
7547 if (iter.valid) {
7548 RNA_parameter_dynamic_length_set_data(parms, parm, iter.data, length);
7549 }
7550
7551 RNA_parameter_list_end(&iter);
7552 }
7553
RNA_parameter_dynamic_length_get_data(ParameterList * UNUSED (parms),PropertyRNA * parm,void * data)7554 int RNA_parameter_dynamic_length_get_data(ParameterList *UNUSED(parms),
7555 PropertyRNA *parm,
7556 void *data)
7557 {
7558 if (parm->flag & PROP_DYNAMIC) {
7559 return (int)((ParameterDynAlloc *)data)->array_tot;
7560 }
7561 return 0;
7562 }
7563
RNA_parameter_dynamic_length_set_data(ParameterList * UNUSED (parms),PropertyRNA * parm,void * data,int length)7564 void RNA_parameter_dynamic_length_set_data(ParameterList *UNUSED(parms),
7565 PropertyRNA *parm,
7566 void *data,
7567 int length)
7568 {
7569 if (parm->flag & PROP_DYNAMIC) {
7570 ((ParameterDynAlloc *)data)->array_tot = (intptr_t)length;
7571 }
7572 }
7573
RNA_function_call(bContext * C,ReportList * reports,PointerRNA * ptr,FunctionRNA * func,ParameterList * parms)7574 int RNA_function_call(
7575 bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
7576 {
7577 if (func->call) {
7578 func->call(C, reports, ptr, parms);
7579
7580 return 0;
7581 }
7582
7583 return -1;
7584 }
7585
RNA_function_call_lookup(bContext * C,ReportList * reports,PointerRNA * ptr,const char * identifier,ParameterList * parms)7586 int RNA_function_call_lookup(bContext *C,
7587 ReportList *reports,
7588 PointerRNA *ptr,
7589 const char *identifier,
7590 ParameterList *parms)
7591 {
7592 FunctionRNA *func;
7593
7594 func = RNA_struct_find_function(ptr->type, identifier);
7595
7596 if (func) {
7597 return RNA_function_call(C, reports, ptr, func, parms);
7598 }
7599
7600 return -1;
7601 }
7602
RNA_function_call_direct(bContext * C,ReportList * reports,PointerRNA * ptr,FunctionRNA * func,const char * format,...)7603 int RNA_function_call_direct(
7604 bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, const char *format, ...)
7605 {
7606 va_list args;
7607 int ret;
7608
7609 va_start(args, format);
7610
7611 ret = RNA_function_call_direct_va(C, reports, ptr, func, format, args);
7612
7613 va_end(args);
7614
7615 return ret;
7616 }
7617
RNA_function_call_direct_lookup(bContext * C,ReportList * reports,PointerRNA * ptr,const char * identifier,const char * format,...)7618 int RNA_function_call_direct_lookup(bContext *C,
7619 ReportList *reports,
7620 PointerRNA *ptr,
7621 const char *identifier,
7622 const char *format,
7623 ...)
7624 {
7625 FunctionRNA *func;
7626
7627 func = RNA_struct_find_function(ptr->type, identifier);
7628
7629 if (func) {
7630 va_list args;
7631 int ret;
7632
7633 va_start(args, format);
7634
7635 ret = RNA_function_call_direct_va(C, reports, ptr, func, format, args);
7636
7637 va_end(args);
7638
7639 return ret;
7640 }
7641
7642 return -1;
7643 }
7644
rna_function_format_array_length(const char * format,int ofs,int flen)7645 static int rna_function_format_array_length(const char *format, int ofs, int flen)
7646 {
7647 char lenbuf[16];
7648 int idx = 0;
7649
7650 if (format[ofs++] == '[') {
7651 for (; ofs < flen && format[ofs] != ']' && idx < sizeof(lenbuf) - 1; idx++, ofs++) {
7652 lenbuf[idx] = format[ofs];
7653 }
7654 }
7655
7656 if (ofs < flen && format[ofs + 1] == ']') {
7657 /* XXX put better error reporting for (ofs >= flen) or idx over lenbuf capacity */
7658 lenbuf[idx] = '\0';
7659 return atoi(lenbuf);
7660 }
7661
7662 return 0;
7663 }
7664
rna_function_parameter_parse(PointerRNA * ptr,PropertyRNA * prop,PropertyType type,char ftype,int len,void * dest,const void * src,StructRNA * srna,const char * tid,const char * fid,const char * pid)7665 static int rna_function_parameter_parse(PointerRNA *ptr,
7666 PropertyRNA *prop,
7667 PropertyType type,
7668 char ftype,
7669 int len,
7670 void *dest,
7671 const void *src,
7672 StructRNA *srna,
7673 const char *tid,
7674 const char *fid,
7675 const char *pid)
7676 {
7677 /* ptr is always a function pointer, prop always a parameter */
7678
7679 switch (type) {
7680 case PROP_BOOLEAN: {
7681 if (ftype != 'b') {
7682 fprintf(
7683 stderr, "%s.%s: wrong type for parameter %s, a boolean was expected\n", tid, fid, pid);
7684 return -1;
7685 }
7686
7687 if (len == 0) {
7688 *((bool *)dest) = *((bool *)src);
7689 }
7690 else {
7691 memcpy(dest, src, len * sizeof(bool));
7692 }
7693
7694 break;
7695 }
7696 case PROP_INT: {
7697 if (ftype != 'i') {
7698 fprintf(stderr,
7699 "%s.%s: wrong type for parameter %s, an integer was expected\n",
7700 tid,
7701 fid,
7702 pid);
7703 return -1;
7704 }
7705
7706 if (len == 0) {
7707 *((int *)dest) = *((int *)src);
7708 }
7709 else {
7710 memcpy(dest, src, len * sizeof(int));
7711 }
7712
7713 break;
7714 }
7715 case PROP_FLOAT: {
7716 if (ftype != 'f') {
7717 fprintf(
7718 stderr, "%s.%s: wrong type for parameter %s, a float was expected\n", tid, fid, pid);
7719 return -1;
7720 }
7721
7722 if (len == 0) {
7723 *((float *)dest) = *((float *)src);
7724 }
7725 else {
7726 memcpy(dest, src, len * sizeof(float));
7727 }
7728
7729 break;
7730 }
7731 case PROP_STRING: {
7732 if (ftype != 's') {
7733 fprintf(
7734 stderr, "%s.%s: wrong type for parameter %s, a string was expected\n", tid, fid, pid);
7735 return -1;
7736 }
7737
7738 *((char **)dest) = *((char **)src);
7739
7740 break;
7741 }
7742 case PROP_ENUM: {
7743 if (ftype != 'e') {
7744 fprintf(
7745 stderr, "%s.%s: wrong type for parameter %s, an enum was expected\n", tid, fid, pid);
7746 return -1;
7747 }
7748
7749 *((int *)dest) = *((int *)src);
7750
7751 break;
7752 }
7753 case PROP_POINTER: {
7754 StructRNA *ptype;
7755
7756 if (ftype != 'O') {
7757 fprintf(
7758 stderr, "%s.%s: wrong type for parameter %s, an object was expected\n", tid, fid, pid);
7759 return -1;
7760 }
7761
7762 ptype = RNA_property_pointer_type(ptr, prop);
7763
7764 if (prop->flag_parameter & PARM_RNAPTR) {
7765 *((PointerRNA *)dest) = *((PointerRNA *)src);
7766 break;
7767 }
7768
7769 if (ptype != srna && !RNA_struct_is_a(srna, ptype)) {
7770 fprintf(stderr,
7771 "%s.%s: wrong type for parameter %s, "
7772 "an object of type %s was expected, passed an object of type %s\n",
7773 tid,
7774 fid,
7775 pid,
7776 RNA_struct_identifier(ptype),
7777 RNA_struct_identifier(srna));
7778 return -1;
7779 }
7780
7781 *((void **)dest) = *((void **)src);
7782
7783 break;
7784 }
7785 case PROP_COLLECTION: {
7786 StructRNA *ptype;
7787 ListBase *lb, *clb;
7788 Link *link;
7789 CollectionPointerLink *clink;
7790
7791 if (ftype != 'C') {
7792 fprintf(stderr,
7793 "%s.%s: wrong type for parameter %s, a collection was expected\n",
7794 tid,
7795 fid,
7796 pid);
7797 return -1;
7798 }
7799
7800 lb = (ListBase *)src;
7801 clb = (ListBase *)dest;
7802 ptype = RNA_property_pointer_type(ptr, prop);
7803
7804 if (ptype != srna && !RNA_struct_is_a(srna, ptype)) {
7805 fprintf(stderr,
7806 "%s.%s: wrong type for parameter %s, "
7807 "a collection of objects of type %s was expected, "
7808 "passed a collection of objects of type %s\n",
7809 tid,
7810 fid,
7811 pid,
7812 RNA_struct_identifier(ptype),
7813 RNA_struct_identifier(srna));
7814 return -1;
7815 }
7816
7817 for (link = lb->first; link; link = link->next) {
7818 clink = MEM_callocN(sizeof(CollectionPointerLink), "CCollectionPointerLink");
7819 RNA_pointer_create(NULL, srna, link, &clink->ptr);
7820 BLI_addtail(clb, clink);
7821 }
7822
7823 break;
7824 }
7825 default: {
7826 if (len == 0) {
7827 fprintf(stderr, "%s.%s: unknown type for parameter %s\n", tid, fid, pid);
7828 }
7829 else {
7830 fprintf(stderr, "%s.%s: unknown array type for parameter %s\n", tid, fid, pid);
7831 }
7832
7833 return -1;
7834 }
7835 }
7836
7837 return 0;
7838 }
7839
RNA_function_call_direct_va(bContext * C,ReportList * reports,PointerRNA * ptr,FunctionRNA * func,const char * format,va_list args)7840 int RNA_function_call_direct_va(bContext *C,
7841 ReportList *reports,
7842 PointerRNA *ptr,
7843 FunctionRNA *func,
7844 const char *format,
7845 va_list args)
7846 {
7847 PointerRNA funcptr;
7848 ParameterList parms;
7849 ParameterIterator iter;
7850 PropertyRNA *pret, *parm;
7851 PropertyType type;
7852 int i, ofs, flen, flag_parameter, len, alen, err = 0;
7853 const char *tid, *fid, *pid = NULL;
7854 char ftype;
7855 void **retdata = NULL;
7856
7857 RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
7858
7859 tid = RNA_struct_identifier(ptr->type);
7860 fid = RNA_function_identifier(func);
7861 pret = func->c_ret;
7862 flen = strlen(format);
7863
7864 RNA_parameter_list_create(&parms, ptr, func);
7865 RNA_parameter_list_begin(&parms, &iter);
7866
7867 for (i = 0, ofs = 0; iter.valid; RNA_parameter_list_next(&iter), i++) {
7868 parm = iter.parm;
7869 flag_parameter = RNA_parameter_flag(parm);
7870
7871 if (parm == pret) {
7872 retdata = iter.data;
7873 continue;
7874 }
7875 if (flag_parameter & PARM_OUTPUT) {
7876 continue;
7877 }
7878
7879 pid = RNA_property_identifier(parm);
7880
7881 if (ofs >= flen || format[ofs] == 'N') {
7882 if (parm->flag_parameter & PARM_REQUIRED) {
7883 err = -1;
7884 fprintf(stderr, "%s.%s: missing required parameter %s\n", tid, fid, pid);
7885 break;
7886 }
7887 ofs++;
7888 continue;
7889 }
7890
7891 type = RNA_property_type(parm);
7892 ftype = format[ofs++];
7893 len = RNA_property_array_length(&funcptr, parm);
7894 alen = rna_function_format_array_length(format, ofs, flen);
7895
7896 if (len != alen) {
7897 err = -1;
7898 fprintf(stderr,
7899 "%s.%s: for parameter %s, "
7900 "was expecting an array of %i elements, "
7901 "passed %i elements instead\n",
7902 tid,
7903 fid,
7904 pid,
7905 len,
7906 alen);
7907 break;
7908 }
7909
7910 switch (type) {
7911 case PROP_BOOLEAN:
7912 case PROP_INT:
7913 case PROP_ENUM: {
7914 int arg = va_arg(args, int);
7915 err = rna_function_parameter_parse(
7916 &funcptr, parm, type, ftype, len, iter.data, &arg, NULL, tid, fid, pid);
7917 break;
7918 }
7919 case PROP_FLOAT: {
7920 double arg = va_arg(args, double);
7921 err = rna_function_parameter_parse(
7922 &funcptr, parm, type, ftype, len, iter.data, &arg, NULL, tid, fid, pid);
7923 break;
7924 }
7925 case PROP_STRING: {
7926 const char *arg = va_arg(args, char *);
7927 err = rna_function_parameter_parse(
7928 &funcptr, parm, type, ftype, len, iter.data, &arg, NULL, tid, fid, pid);
7929 break;
7930 }
7931 case PROP_POINTER: {
7932 StructRNA *srna = va_arg(args, StructRNA *);
7933 void *arg = va_arg(args, void *);
7934 err = rna_function_parameter_parse(
7935 &funcptr, parm, type, ftype, len, iter.data, &arg, srna, tid, fid, pid);
7936 break;
7937 }
7938 case PROP_COLLECTION: {
7939 StructRNA *srna = va_arg(args, StructRNA *);
7940 ListBase *arg = va_arg(args, ListBase *);
7941 err = rna_function_parameter_parse(
7942 &funcptr, parm, type, ftype, len, iter.data, &arg, srna, tid, fid, pid);
7943 break;
7944 }
7945 default: {
7946 /* handle errors */
7947 err = rna_function_parameter_parse(
7948 &funcptr, parm, type, ftype, len, iter.data, NULL, NULL, tid, fid, pid);
7949 break;
7950 }
7951 }
7952
7953 if (err != 0) {
7954 break;
7955 }
7956 }
7957
7958 if (err == 0) {
7959 err = RNA_function_call(C, reports, ptr, func, &parms);
7960 }
7961
7962 /* XXX throw error when more parameters than those needed are passed or leave silent? */
7963 if (err == 0 && pret && ofs < flen && format[ofs++] == 'R') {
7964 parm = pret;
7965
7966 type = RNA_property_type(parm);
7967 ftype = format[ofs++];
7968 len = RNA_property_array_length(&funcptr, parm);
7969 alen = rna_function_format_array_length(format, ofs, flen);
7970
7971 if (len != alen) {
7972 err = -1;
7973 fprintf(stderr,
7974 "%s.%s: for return parameter %s, "
7975 "was expecting an array of %i elements, passed %i elements instead\n",
7976 tid,
7977 fid,
7978 pid,
7979 len,
7980 alen);
7981 }
7982 else {
7983 switch (type) {
7984 case PROP_BOOLEAN:
7985 case PROP_INT:
7986 case PROP_ENUM: {
7987 int *arg = va_arg(args, int *);
7988 err = rna_function_parameter_parse(
7989 &funcptr, parm, type, ftype, len, arg, retdata, NULL, tid, fid, pid);
7990 break;
7991 }
7992 case PROP_FLOAT: {
7993 float *arg = va_arg(args, float *);
7994 err = rna_function_parameter_parse(
7995 &funcptr, parm, type, ftype, len, arg, retdata, NULL, tid, fid, pid);
7996 break;
7997 }
7998 case PROP_STRING: {
7999 char **arg = va_arg(args, char **);
8000 err = rna_function_parameter_parse(
8001 &funcptr, parm, type, ftype, len, arg, retdata, NULL, tid, fid, pid);
8002 break;
8003 }
8004 case PROP_POINTER: {
8005 StructRNA *srna = va_arg(args, StructRNA *);
8006 void **arg = va_arg(args, void **);
8007 err = rna_function_parameter_parse(
8008 &funcptr, parm, type, ftype, len, arg, retdata, srna, tid, fid, pid);
8009 break;
8010 }
8011 case PROP_COLLECTION: {
8012 StructRNA *srna = va_arg(args, StructRNA *);
8013 ListBase **arg = va_arg(args, ListBase **);
8014 err = rna_function_parameter_parse(
8015 &funcptr, parm, type, ftype, len, arg, retdata, srna, tid, fid, pid);
8016 break;
8017 }
8018 default: {
8019 /* handle errors */
8020 err = rna_function_parameter_parse(
8021 &funcptr, parm, type, ftype, len, NULL, NULL, NULL, tid, fid, pid);
8022 break;
8023 }
8024 }
8025 }
8026 }
8027
8028 RNA_parameter_list_end(&iter);
8029 RNA_parameter_list_free(&parms);
8030
8031 return err;
8032 }
8033
RNA_function_call_direct_va_lookup(bContext * C,ReportList * reports,PointerRNA * ptr,const char * identifier,const char * format,va_list args)8034 int RNA_function_call_direct_va_lookup(bContext *C,
8035 ReportList *reports,
8036 PointerRNA *ptr,
8037 const char *identifier,
8038 const char *format,
8039 va_list args)
8040 {
8041 FunctionRNA *func;
8042
8043 func = RNA_struct_find_function(ptr->type, identifier);
8044
8045 if (func) {
8046 return RNA_function_call_direct_va(C, reports, ptr, func, format, args);
8047 }
8048
8049 return 0;
8050 }
8051
RNA_translate_ui_text(const char * text,const char * text_ctxt,StructRNA * type,PropertyRNA * prop,int translate)8052 const char *RNA_translate_ui_text(
8053 const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, int translate)
8054 {
8055 return rna_translate_ui_text(text, text_ctxt, type, prop, translate);
8056 }
8057
RNA_property_reset(PointerRNA * ptr,PropertyRNA * prop,int index)8058 bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
8059 {
8060 int len;
8061
8062 /* get the length of the array to work with */
8063 len = RNA_property_array_length(ptr, prop);
8064
8065 /* get and set the default values as appropriate for the various types */
8066 switch (RNA_property_type(prop)) {
8067 case PROP_BOOLEAN:
8068 if (len) {
8069 if (index == -1) {
8070 bool *tmparray = MEM_callocN(sizeof(bool) * len, "reset_defaults - boolean");
8071
8072 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
8073 RNA_property_boolean_set_array(ptr, prop, tmparray);
8074
8075 MEM_freeN(tmparray);
8076 }
8077 else {
8078 int value = RNA_property_boolean_get_default_index(ptr, prop, index);
8079 RNA_property_boolean_set_index(ptr, prop, index, value);
8080 }
8081 }
8082 else {
8083 int value = RNA_property_boolean_get_default(ptr, prop);
8084 RNA_property_boolean_set(ptr, prop, value);
8085 }
8086 return true;
8087 case PROP_INT:
8088 if (len) {
8089 if (index == -1) {
8090 int *tmparray = MEM_callocN(sizeof(int) * len, "reset_defaults - int");
8091
8092 RNA_property_int_get_default_array(ptr, prop, tmparray);
8093 RNA_property_int_set_array(ptr, prop, tmparray);
8094
8095 MEM_freeN(tmparray);
8096 }
8097 else {
8098 int value = RNA_property_int_get_default_index(ptr, prop, index);
8099 RNA_property_int_set_index(ptr, prop, index, value);
8100 }
8101 }
8102 else {
8103 int value = RNA_property_int_get_default(ptr, prop);
8104 RNA_property_int_set(ptr, prop, value);
8105 }
8106 return true;
8107 case PROP_FLOAT:
8108 if (len) {
8109 if (index == -1) {
8110 float *tmparray = MEM_callocN(sizeof(float) * len, "reset_defaults - float");
8111
8112 RNA_property_float_get_default_array(ptr, prop, tmparray);
8113 RNA_property_float_set_array(ptr, prop, tmparray);
8114
8115 MEM_freeN(tmparray);
8116 }
8117 else {
8118 float value = RNA_property_float_get_default_index(ptr, prop, index);
8119 RNA_property_float_set_index(ptr, prop, index, value);
8120 }
8121 }
8122 else {
8123 float value = RNA_property_float_get_default(ptr, prop);
8124 RNA_property_float_set(ptr, prop, value);
8125 }
8126 return true;
8127 case PROP_ENUM: {
8128 int value = RNA_property_enum_get_default(ptr, prop);
8129 RNA_property_enum_set(ptr, prop, value);
8130 return true;
8131 }
8132
8133 case PROP_STRING: {
8134 char *value = RNA_property_string_get_default_alloc(ptr, prop, NULL, 0);
8135 RNA_property_string_set(ptr, prop, value);
8136 MEM_freeN(value);
8137 return true;
8138 }
8139
8140 case PROP_POINTER: {
8141 PointerRNA value = RNA_property_pointer_get_default(ptr, prop);
8142 RNA_property_pointer_set(ptr, prop, value, NULL);
8143 return true;
8144 }
8145
8146 default:
8147 /* FIXME: are there still any cases that haven't been handled?
8148 * comment out "default" block to check :) */
8149 return false;
8150 }
8151 }
8152
RNA_property_assign_default(PointerRNA * ptr,PropertyRNA * prop)8153 bool RNA_property_assign_default(PointerRNA *ptr, PropertyRNA *prop)
8154 {
8155 if (!RNA_property_is_idprop(prop) || RNA_property_array_check(prop)) {
8156 return false;
8157 }
8158
8159 /* get and set the default values as appropriate for the various types */
8160 switch (RNA_property_type(prop)) {
8161 case PROP_INT: {
8162 int value = RNA_property_int_get(ptr, prop);
8163 return RNA_property_int_set_default(ptr, prop, value);
8164 }
8165
8166 case PROP_FLOAT: {
8167 float value = RNA_property_float_get(ptr, prop);
8168 return RNA_property_float_set_default(ptr, prop, value);
8169 }
8170
8171 default:
8172 return false;
8173 }
8174 }
8175
8176 /* use RNA_warning macro which includes __func__ suffix */
_RNA_warning(const char * format,...)8177 void _RNA_warning(const char *format, ...)
8178 {
8179 va_list args;
8180
8181 va_start(args, format);
8182 vprintf(format, args);
8183 va_end(args);
8184
8185 /* gcc macro adds '\n', but cant use for other compilers */
8186 #ifndef __GNUC__
8187 fputc('\n', stdout);
8188 #endif
8189
8190 #ifdef WITH_PYTHON
8191 {
8192 extern void PyC_LineSpit(void);
8193 PyC_LineSpit();
8194 }
8195 #endif
8196 }
8197
RNA_path_resolved_create(PointerRNA * ptr,struct PropertyRNA * prop,const int prop_index,PathResolvedRNA * r_anim_rna)8198 bool RNA_path_resolved_create(PointerRNA *ptr,
8199 struct PropertyRNA *prop,
8200 const int prop_index,
8201 PathResolvedRNA *r_anim_rna)
8202 {
8203 int array_len = RNA_property_array_length(ptr, prop);
8204
8205 if ((array_len == 0) || (prop_index < array_len)) {
8206 r_anim_rna->ptr = *ptr;
8207 r_anim_rna->prop = prop;
8208 r_anim_rna->prop_index = array_len ? prop_index : -1;
8209
8210 return true;
8211 }
8212 return false;
8213 }
8214
8215 static char rna_struct_state_owner[64];
RNA_struct_state_owner_set(const char * name)8216 void RNA_struct_state_owner_set(const char *name)
8217 {
8218 if (name) {
8219 BLI_strncpy(rna_struct_state_owner, name, sizeof(rna_struct_state_owner));
8220 }
8221 else {
8222 rna_struct_state_owner[0] = '\0';
8223 }
8224 }
8225
RNA_struct_state_owner_get(void)8226 const char *RNA_struct_state_owner_get(void)
8227 {
8228 if (rna_struct_state_owner[0]) {
8229 return rna_struct_state_owner;
8230 }
8231 return NULL;
8232 }
8233