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(&params, ptr, cprop->add);
4034       RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
4035       RNA_parameter_list_free(&params);
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(&params, ptr, cprop->remove);
4109       RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
4110       RNA_parameter_list_free(&params);
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(&current, 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(&current, 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