Cleanup: Split some code out of rna_access.c
[blender.git] / source / blender / makesrna / intern / rna_access.c
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 <stdlib.h>
22 #include <stddef.h>
23 #include <string.h>
24 #include <ctype.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "DNA_ID.h"
29 #include "DNA_scene_types.h"
30 #include "DNA_constraint_types.h"
31 #include "DNA_modifier_types.h"
32 #include "DNA_windowmanager_types.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_utildefines.h"
36 #include "BLI_dynstr.h"
37 #include "BLI_ghash.h"
38 #include "BLI_math.h"
39
40 #include "BLF_api.h"
41 #include "BLT_translation.h"
42
43 #include "BKE_animsys.h"
44 #include "BKE_context.h"
45 #include "BKE_idcode.h"
46 #include "BKE_idprop.h"
47 #include "BKE_fcurve.h"
48 #include "BKE_main.h"
49 #include "BKE_report.h"
50
51 #include "DEG_depsgraph.h"
52
53 #include "RNA_access.h"
54 #include "RNA_define.h"
55 #include "RNA_enum_types.h"
56
57 #include "WM_api.h"
58 #include "WM_message.h"
59
60 /* flush updates */
61 #include "DNA_object_types.h"
62 #include "WM_types.h"
63
64 #include "rna_internal.h"
65 #include "rna_access_internal.h"
66
67 const PointerRNA PointerRNA_NULL = {{NULL}};
68
69 /* Init/Exit */
70
71 void RNA_init(void)
72 {
73   StructRNA *srna;
74   PropertyRNA *prop;
75
76   BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
77   BLENDER_RNA.structs_len = 0;
78
79   for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
80     if (!srna->cont.prophash) {
81       srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
82
83       for (prop = srna->cont.properties.first; prop; prop = prop->next) {
84         if (!(prop->flag_internal & PROP_INTERN_BUILTIN)) {
85           BLI_ghash_insert(srna->cont.prophash, (void *)prop->identifier, prop);
86         }
87       }
88     }
89     BLI_assert(srna->flag & STRUCT_PUBLIC_NAMESPACE);
90     BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
91     BLENDER_RNA.structs_len += 1;
92   }
93 }
94
95 void RNA_exit(void)
96 {
97   StructRNA *srna;
98
99   RNA_property_update_cache_free();
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
113 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
114 {
115   r_ptr->id.data = NULL;
116   r_ptr->type = &RNA_BlendData;
117   r_ptr->data = main;
118 }
119
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       else {
136         idtype = type;
137       }
138     }
139   }
140
141   r_ptr->id.data = id;
142   r_ptr->type = idtype;
143   r_ptr->data = id;
144 }
145
146 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
147 {
148 #if 0 /* UNUSED */
149   StructRNA *idtype = NULL;
150
151   if (id) {
152     PointerRNA tmp = {{0}};
153     tmp.data = id;
154     idtype = rna_ID_refine(&tmp);
155   }
156 #endif
157
158   r_ptr->id.data = id;
159   r_ptr->type = type;
160   r_ptr->data = data;
161
162   if (data) {
163     while (r_ptr->type && r_ptr->type->refine) {
164       StructRNA *rtype = r_ptr->type->refine(r_ptr);
165
166       if (rtype == r_ptr->type) {
167         break;
168       }
169       else {
170         r_ptr->type = rtype;
171       }
172     }
173   }
174 }
175
176 bool RNA_pointer_is_null(const PointerRNA *ptr)
177 {
178   return !((ptr->data != NULL) && (ptr->id.data != NULL) && (ptr->type != NULL));
179 }
180
181 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
182 {
183   if (type && type->flag & STRUCT_ID) {
184     ptr->id.data = ptr->data;
185   }
186   else {
187     ptr->id.data = parent->id.data;
188   }
189 }
190
191 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
192 {
193   r_ptr->id.data = NULL;
194   r_ptr->type = &RNA_BlenderRNA;
195   r_ptr->data = &BLENDER_RNA;
196 }
197
198 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
199 {
200   if (data) {
201     PointerRNA result;
202     result.data = data;
203     result.type = type;
204     rna_pointer_inherit_id(type, ptr, &result);
205
206     while (result.type->refine) {
207       type = result.type->refine(&result);
208
209       if (type == result.type) {
210         break;
211       }
212       else {
213         result.type = type;
214       }
215     }
216     return result;
217   }
218   else {
219     return PointerRNA_NULL;
220   }
221 }
222
223 void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
224 {
225 #if 0 /* works but this case if covered by more general code below. */
226   if (RNA_struct_is_ID(ptr->type)) {
227     /* simple case */
228     RNA_id_pointer_create(ptr->id.data, r_ptr);
229   }
230   else
231 #endif
232   {
233     StructRNA *base;
234     PointerRNA t_ptr;
235     *r_ptr = *ptr; /* initialize as the same in case cant recast */
236
237     for (base = ptr->type->base; base; base = base->base) {
238       t_ptr = rna_pointer_inherit_refine(ptr, base, ptr->data);
239       if (t_ptr.type && t_ptr.type != ptr->type) {
240         *r_ptr = t_ptr;
241       }
242     }
243   }
244 }
245
246 /* ID Properties */
247
248 void rna_idproperty_touch(IDProperty *idprop)
249 {
250   /* so the property is seen as 'set' by rna */
251   idprop->flag &= ~IDP_FLAG_GHOST;
252 }
253
254 static IDProperty *rna_idproperty_ui_container(PropertyRNA *prop)
255 {
256   IDProperty *idprop;
257
258   for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
259     if (STREQ(RNA_IDP_UI, idprop->name)) {
260       break;
261     }
262   }
263
264   if (idprop == NULL) {
265     for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
266       if (STREQ(RNA_IDP_UI, idprop->name)) {
267         break;
268       }
269     }
270   }
271
272   return idprop;
273 }
274
275 /* return a UI local ID prop definition for this prop */
276 static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
277 {
278   IDProperty *idprop = rna_idproperty_ui_container(prop);
279
280   if (idprop) {
281     return IDP_GetPropertyTypeFromGroup(idprop, ((IDProperty *)prop)->name, IDP_GROUP);
282   }
283
284   return NULL;
285 }
286
287 /* return or create a UI local ID prop definition for this prop */
288 static IDProperty *rna_idproperty_ui_ensure(PointerRNA *ptr, PropertyRNA *prop, bool create)
289 {
290   IDProperty *idprop = rna_idproperty_ui_container(prop);
291   IDPropertyTemplate dummy = {0};
292
293   if (idprop == NULL && create) {
294     IDProperty *props = RNA_struct_idprops(ptr, false);
295
296     /* Sanity check: props is the actual container of this property. */
297     if (props != NULL && BLI_findindex(&props->data.group, prop) >= 0) {
298       idprop = IDP_New(IDP_GROUP, &dummy, RNA_IDP_UI);
299
300       if (!IDP_AddToGroup(props, idprop)) {
301         IDP_FreePropertyContent(idprop);
302         return NULL;
303       }
304     }
305   }
306
307   if (idprop) {
308     const char *name = ((IDProperty *)prop)->name;
309     IDProperty *rv = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_GROUP);
310
311     if (rv == NULL && create) {
312       rv = IDP_New(IDP_GROUP, &dummy, name);
313
314       if (!IDP_AddToGroup(idprop, rv)) {
315         IDP_FreePropertyContent(rv);
316         return NULL;
317       }
318     }
319
320     return rv;
321   }
322
323   return NULL;
324 }
325
326 static bool rna_idproperty_ui_set_default(PointerRNA *ptr,
327                                           PropertyRNA *prop,
328                                           const char type,
329                                           IDPropertyTemplate *value)
330 {
331   BLI_assert(ELEM(type, IDP_INT, IDP_DOUBLE));
332
333   if (prop->magic == RNA_MAGIC) {
334     return false;
335   }
336
337   /* attempt to get the local ID values */
338   IDProperty *idp_ui = rna_idproperty_ui_ensure(ptr, prop, value != NULL);
339
340   if (idp_ui == NULL) {
341     return (value == NULL);
342   }
343
344   IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", type);
345
346   if (value == NULL) {
347     if (item != NULL) {
348       IDP_RemoveFromGroup(idp_ui, item);
349     }
350   }
351   else {
352     if (item != NULL) {
353       switch (type) {
354         case IDP_INT:
355           IDP_Int(item) = value->i;
356           break;
357         case IDP_DOUBLE:
358           IDP_Double(item) = value->d;
359           break;
360         default:
361           BLI_assert(false);
362           return false;
363       }
364     }
365     else {
366       item = IDP_New(type, value, "default");
367
368       if (!IDP_AddToGroup(idp_ui, item)) {
369         IDP_FreePropertyContent(item);
370         return false;
371       }
372     }
373   }
374
375   return true;
376 }
377
378 IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
379 {
380   StructRNA *type = ptr->type;
381
382   if (type && type->idproperties) {
383     return type->idproperties(ptr, create);
384   }
385
386   return NULL;
387 }
388
389 bool RNA_struct_idprops_check(StructRNA *srna)
390 {
391   return (srna && srna->idproperties);
392 }
393
394 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
395 {
396   IDProperty *group = RNA_struct_idprops(ptr, 0);
397
398   if (group) {
399     if (group->type == IDP_GROUP) {
400       return IDP_GetPropertyFromGroup(group, name);
401     }
402     else {
403       /* Not sure why that happens sometimes, with nested properties... */
404       /* Seems to be actually array prop, name is usually "0"... To be sorted out later. */
405 #if 0
406       printf(
407           "Got unexpected IDProp container when trying to retrieve %s: %d\n", name, group->type);
408 #endif
409     }
410   }
411
412   return NULL;
413 }
414
415 static void rna_idproperty_free(PointerRNA *ptr, const char *name)
416 {
417   IDProperty *group = RNA_struct_idprops(ptr, 0);
418
419   if (group) {
420     IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
421     if (idprop) {
422       IDP_FreeFromGroup(group, idprop);
423     }
424   }
425 }
426
427 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
428 {
429   if (prop->magic == RNA_MAGIC) {
430     int arraylen[RNA_MAX_ARRAY_DIMENSION];
431     return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) : prop->totarraylength;
432   }
433   else {
434     IDProperty *idprop = (IDProperty *)prop;
435
436     if (idprop->type == IDP_ARRAY) {
437       return idprop->len;
438     }
439     else {
440       return 0;
441     }
442   }
443 }
444
445 static bool rna_ensure_property_array_check(PropertyRNA *prop)
446 {
447   if (prop->magic == RNA_MAGIC) {
448     return (prop->getlength || prop->totarraylength);
449   }
450   else {
451     IDProperty *idprop = (IDProperty *)prop;
452
453     return (idprop->type == IDP_ARRAY);
454   }
455 }
456
457 static void rna_ensure_property_multi_array_length(PointerRNA *ptr,
458                                                    PropertyRNA *prop,
459                                                    int length[])
460 {
461   if (prop->magic == RNA_MAGIC) {
462     if (prop->getlength) {
463       prop->getlength(ptr, length);
464     }
465     else {
466       memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
467     }
468   }
469   else {
470     IDProperty *idprop = (IDProperty *)prop;
471
472     if (idprop->type == IDP_ARRAY) {
473       length[0] = idprop->len;
474     }
475     else {
476       length[0] = 0;
477     }
478   }
479 }
480
481 static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
482 {
483   /* this verifies if the idproperty actually matches the property
484    * description and otherwise removes it. this is to ensure that
485    * rna property access is type safe, e.g. if you defined the rna
486    * to have a certain array length you can count on that staying so */
487
488   switch (idprop->type) {
489     case IDP_IDPARRAY:
490       if (prop->type != PROP_COLLECTION) {
491         return false;
492       }
493       break;
494     case IDP_ARRAY:
495       if (rna_ensure_property_array_length(ptr, prop) != idprop->len) {
496         return false;
497       }
498
499       if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT) {
500         return false;
501       }
502       if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) {
503         return false;
504       }
505
506       break;
507     case IDP_INT:
508       if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) {
509         return false;
510       }
511       break;
512     case IDP_FLOAT:
513     case IDP_DOUBLE:
514       if (prop->type != PROP_FLOAT) {
515         return false;
516       }
517       break;
518     case IDP_STRING:
519       if (prop->type != PROP_STRING) {
520         return false;
521       }
522       break;
523     case IDP_GROUP:
524     case IDP_ID:
525       if (prop->type != PROP_POINTER) {
526         return false;
527       }
528       break;
529     default:
530       return false;
531   }
532
533   return true;
534 }
535
536 static PropertyRNA *typemap[IDP_NUMTYPES] = {
537     (PropertyRNA *)&rna_PropertyGroupItem_string,
538     (PropertyRNA *)&rna_PropertyGroupItem_int,
539     (PropertyRNA *)&rna_PropertyGroupItem_float,
540     NULL,
541     NULL,
542     NULL,
543     (PropertyRNA *)&rna_PropertyGroupItem_group,
544     (PropertyRNA *)&rna_PropertyGroupItem_id,
545     (PropertyRNA *)&rna_PropertyGroupItem_double,
546     (PropertyRNA *)&rna_PropertyGroupItem_idp_array,
547 };
548
549 static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
550     NULL,
551     (PropertyRNA *)&rna_PropertyGroupItem_int_array,
552     (PropertyRNA *)&rna_PropertyGroupItem_float_array,
553     NULL,
554     NULL,
555     NULL,
556     (PropertyRNA *)&rna_PropertyGroupItem_collection,
557     NULL,
558     (PropertyRNA *)&rna_PropertyGroupItem_double_array,
559 };
560
561 static void *rna_idproperty_check_ex(PropertyRNA **prop,
562                                      PointerRNA *ptr,
563                                      const bool return_rnaprop)
564 {
565   /* This is quite a hack, but avoids some complexity in the API. we
566    * pass IDProperty structs as PropertyRNA pointers to the outside.
567    * We store some bytes in PropertyRNA structs that allows us to
568    * distinguish it from IDProperty structs. If it is an ID property,
569    * we look up an IDP PropertyRNA based on the type, and set the data
570    * pointer to the IDProperty. */
571
572   if ((*prop)->magic == RNA_MAGIC) {
573     if ((*prop)->flag & PROP_IDPROPERTY) {
574       IDProperty *idprop = rna_idproperty_find(ptr, (*prop)->identifier);
575
576       if (idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) {
577         IDProperty *group = RNA_struct_idprops(ptr, 0);
578
579         IDP_FreeFromGroup(group, idprop);
580         return NULL;
581       }
582
583       return idprop;
584     }
585     else {
586       return return_rnaprop ? *prop : NULL;
587     }
588   }
589
590   {
591     IDProperty *idprop = (IDProperty *)(*prop);
592
593     if (idprop->type == IDP_ARRAY) {
594       *prop = arraytypemap[(int)(idprop->subtype)];
595     }
596     else {
597       *prop = typemap[(int)(idprop->type)];
598     }
599
600     return idprop;
601   }
602 }
603
604 /* This function only returns an IDProperty,
605  * or NULL (in case IDProp could not be found, or prop is a real RNA property). */
606 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
607 {
608   return rna_idproperty_check_ex(prop, ptr, false);
609 }
610
611 /* This function always return the valid, real data pointer, be it a regular RNA property one,
612  * or an IDProperty one. */
613 PropertyRNA *rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr)
614 {
615   return rna_idproperty_check_ex(prop, ptr, true);
616 }
617
618 PropertyRNA *rna_ensure_property(PropertyRNA *prop)
619 {
620   /* the quick version if we don't need the idproperty */
621
622   if (prop->magic == RNA_MAGIC) {
623     return prop;
624   }
625
626   {
627     IDProperty *idprop = (IDProperty *)prop;
628
629     if (idprop->type == IDP_ARRAY) {
630       return arraytypemap[(int)(idprop->subtype)];
631     }
632     else {
633       return typemap[(int)(idprop->type)];
634     }
635   }
636 }
637
638 static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
639 {
640   if (prop->magic == RNA_MAGIC) {
641     return prop->identifier;
642   }
643   else {
644     return ((const IDProperty *)prop)->name;
645   }
646 }
647
648 static const char *rna_ensure_property_description(PropertyRNA *prop)
649 {
650   const char *description = NULL;
651
652   if (prop->magic == RNA_MAGIC) {
653     description = prop->description;
654   }
655   else {
656     /* attempt to get the local ID values */
657     IDProperty *idp_ui = rna_idproperty_ui(prop);
658
659     if (idp_ui) {
660       IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "description", IDP_STRING);
661       if (item) {
662         description = IDP_String(item);
663       }
664     }
665
666     if (description == NULL) {
667       description = ((IDProperty *)prop)->name; /* XXX - not correct */
668     }
669   }
670
671   return description;
672 }
673
674 static const char *rna_ensure_property_name(const PropertyRNA *prop)
675 {
676   const char *name;
677
678   if (prop->magic == RNA_MAGIC) {
679     name = prop->name;
680   }
681   else {
682     name = ((const IDProperty *)prop)->name;
683   }
684
685   return name;
686 }
687
688 /* Structs */
689
690 StructRNA *RNA_struct_find(const char *identifier)
691 {
692   return BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier);
693 }
694
695 const char *RNA_struct_identifier(const StructRNA *type)
696 {
697   return type->identifier;
698 }
699
700 const char *RNA_struct_ui_name(const StructRNA *type)
701 {
702   return CTX_IFACE_(type->translation_context, type->name);
703 }
704
705 const char *RNA_struct_ui_name_raw(const StructRNA *type)
706 {
707   return type->name;
708 }
709
710 int RNA_struct_ui_icon(const StructRNA *type)
711 {
712   if (type) {
713     return type->icon;
714   }
715   else {
716     return ICON_DOT;
717   }
718 }
719
720 const char *RNA_struct_ui_description(const StructRNA *type)
721 {
722   return TIP_(type->description);
723 }
724
725 const char *RNA_struct_ui_description_raw(const StructRNA *type)
726 {
727   return type->description;
728 }
729
730 const char *RNA_struct_translation_context(const StructRNA *type)
731 {
732   return type->translation_context;
733 }
734
735 PropertyRNA *RNA_struct_name_property(const StructRNA *type)
736 {
737   return type->nameproperty;
738 }
739
740 const EnumPropertyItem *RNA_struct_property_tag_defines(const StructRNA *type)
741 {
742   return type->prop_tag_defines;
743 }
744
745 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
746 {
747   return type->iteratorproperty;
748 }
749
750 StructRNA *RNA_struct_base(StructRNA *type)
751 {
752   return type->base;
753 }
754
755 /**
756  * Use to find the subtype directly below a base-type.
757  *
758  * So if type were `RNA_SpotLIght`, `RNA_struct_base_of(type, &RNA_ID)` would return `&RNA_Light`.
759  */
760 const StructRNA *RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
761 {
762   while (type) {
763     if (type->base == parent_type) {
764       return type;
765     }
766     type = type->base;
767   }
768   return NULL;
769 }
770
771 bool RNA_struct_is_ID(const StructRNA *type)
772 {
773   return (type->flag & STRUCT_ID) != 0;
774 }
775
776 bool RNA_struct_undo_check(const StructRNA *type)
777 {
778   return (type->flag & STRUCT_UNDO) != 0;
779 }
780
781 bool RNA_struct_idprops_register_check(const StructRNA *type)
782 {
783   return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
784 }
785
786 bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
787 {
788   return (type->flag & (STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_NO_IDPROPERTIES)) == 0;
789 }
790
791 /**
792  * Whether given type implies datablock usage by IDProperties.
793  * This is used to prevent classes allowed to have IDProperties,
794  * but not datablock ones, to indirectly use some
795  * (e.g. by assigning an IDP_GROUP containing some IDP_ID pointers...).
796  */
797 bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
798 {
799   return (type->flag & (STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES | STRUCT_ID)) != 0;
800 }
801
802 /* remove an id-property */
803 bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
804 {
805   IDProperty *group = RNA_struct_idprops(ptr, 0);
806
807   if (group) {
808     IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
809     if (idp) {
810       IDP_FreeFromGroup(group, idp);
811
812       return true;
813     }
814   }
815   return false;
816 }
817
818 bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
819 {
820   const StructRNA *base;
821
822   if (srna == &RNA_AnyType) {
823     return true;
824   }
825
826   if (!type) {
827     return false;
828   }
829
830   /* ptr->type is always maximally refined */
831   for (base = type; base; base = base->base) {
832     if (base == srna) {
833       return true;
834     }
835   }
836
837   return false;
838 }
839
840 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
841 {
842   if (identifier[0] == '[' && identifier[1] == '"') { /* "  (dummy comment to avoid confusing some
843                                                        * function lists in text editors) */
844     /* id prop lookup, not so common */
845     PropertyRNA *r_prop = NULL;
846     PointerRNA r_ptr; /* only support single level props */
847     if (RNA_path_resolve_property(ptr, identifier, &r_ptr, &r_prop) && (r_ptr.type == ptr->type) &&
848         (r_ptr.data == ptr->data)) {
849       return r_prop;
850     }
851   }
852   else {
853     /* most common case */
854     PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
855     PointerRNA propptr;
856
857     if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr)) {
858       return propptr.data;
859     }
860   }
861
862   return NULL;
863 }
864
865 /* Find the property which uses the given nested struct */
866 static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
867 {
868   PropertyRNA *prop = NULL;
869
870   RNA_STRUCT_BEGIN (ptr, iprop) {
871     /* This assumes that there can only be one user of this nested struct */
872     if (RNA_property_pointer_type(ptr, iprop) == srna) {
873       prop = iprop;
874       break;
875     }
876   }
877   RNA_PROP_END;
878
879   return prop;
880 }
881
882 bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
883 {
884   /* note, prop_test could be freed memory, only use for comparison */
885
886   /* validate the RNA is ok */
887   PropertyRNA *iterprop;
888   bool found = false;
889
890   iterprop = RNA_struct_iterator_property(ptr->type);
891
892   RNA_PROP_BEGIN (ptr, itemptr, iterprop) {
893     /* PropertyRNA *prop = itemptr.data; */
894     if (prop_test == (PropertyRNA *)itemptr.data) {
895       found = true;
896       break;
897     }
898   }
899   RNA_PROP_END;
900
901   return found;
902 }
903
904 unsigned int RNA_struct_count_properties(StructRNA *srna)
905 {
906   PointerRNA struct_ptr;
907   unsigned int counter = 0;
908
909   RNA_pointer_create(NULL, srna, NULL, &struct_ptr);
910
911   RNA_STRUCT_BEGIN (&struct_ptr, prop) {
912     counter++;
913     UNUSED_VARS(prop);
914   }
915   RNA_STRUCT_END;
916
917   return counter;
918 }
919
920 /* Low level direct access to type->properties,
921  * note this ignores parent classes so should be used with care. */
922 const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
923 {
924   return &srna->cont.properties;
925 }
926
927 PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
928 {
929   return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
930 }
931
932 FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
933 {
934 #if 1
935   FunctionRNA *func;
936   StructRNA *type;
937   for (type = srna; type; type = type->base) {
938     func = (FunctionRNA *)BLI_findstring_ptr(
939         &type->functions, identifier, offsetof(FunctionRNA, identifier));
940     if (func) {
941       return func;
942     }
943   }
944   return NULL;
945
946   /* functional but slow */
947 #else
948   PointerRNA tptr;
949   PropertyRNA *iterprop;
950   FunctionRNA *func;
951
952   RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr);
953   iterprop = RNA_struct_find_property(&tptr, "functions");
954
955   func = NULL;
956
957   RNA_PROP_BEGIN (&tptr, funcptr, iterprop) {
958     if (STREQ(identifier, RNA_function_identifier(funcptr.data))) {
959       func = funcptr.data;
960       break;
961     }
962   }
963   RNA_PROP_END;
964
965   return func;
966 #endif
967 }
968
969 const ListBase *RNA_struct_type_functions(StructRNA *srna)
970 {
971   return &srna->functions;
972 }
973
974 StructRegisterFunc RNA_struct_register(StructRNA *type)
975 {
976   return type->reg;
977 }
978
979 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
980 {
981   do {
982     if (type->unreg) {
983       return type->unreg;
984     }
985   } while ((type = type->base));
986
987   return NULL;
988 }
989
990 void **RNA_struct_instance(PointerRNA *ptr)
991 {
992   StructRNA *type = ptr->type;
993
994   do {
995     if (type->instance) {
996       return type->instance(ptr);
997     }
998   } while ((type = type->base));
999
1000   return NULL;
1001 }
1002
1003 void *RNA_struct_py_type_get(StructRNA *srna)
1004 {
1005   return srna->py_type;
1006 }
1007
1008 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
1009 {
1010   srna->py_type = py_type;
1011 }
1012
1013 void *RNA_struct_blender_type_get(StructRNA *srna)
1014 {
1015   return srna->blender_type;
1016 }
1017
1018 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
1019 {
1020   srna->blender_type = blender_type;
1021 }
1022
1023 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
1024 {
1025   PropertyRNA *nameprop;
1026
1027   if (ptr->data && (nameprop = RNA_struct_name_property(ptr->type))) {
1028     return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
1029   }
1030
1031   return NULL;
1032 }
1033
1034 /**
1035  * Use when registering structs with the #STRUCT_PUBLIC_NAMESPACE flag.
1036  */
1037 bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
1038 {
1039   const StructRNA *srna_exists = RNA_struct_find(identifier);
1040   if (UNLIKELY(srna_exists != NULL)) {
1041     /* Use comprehensive string construction since this is such a rare occurrence
1042      * and information here may cut down time troubleshooting. */
1043     DynStr *dynstr = BLI_dynstr_new();
1044     BLI_dynstr_appendf(dynstr, "Type identifier '%s' is already in use: '", identifier);
1045     BLI_dynstr_append(dynstr, srna_exists->identifier);
1046     int i = 0;
1047     if (srna_exists->base) {
1048       for (const StructRNA *base = srna_exists->base; base; base = base->base) {
1049         BLI_dynstr_append(dynstr, "(");
1050         BLI_dynstr_append(dynstr, base->identifier);
1051         i += 1;
1052       }
1053       while (i--) {
1054         BLI_dynstr_append(dynstr, ")");
1055       }
1056     }
1057     BLI_dynstr_append(dynstr, "'.");
1058     char *result = BLI_dynstr_get_cstring(dynstr);
1059     BLI_dynstr_free(dynstr);
1060     BKE_report(reports, RPT_ERROR, result);
1061     MEM_freeN(result);
1062     return false;
1063   }
1064   else {
1065     return true;
1066   }
1067 }
1068
1069 bool RNA_struct_bl_idname_ok_or_report(ReportList *reports,
1070                                        const char *identifier,
1071                                        const char *sep)
1072 {
1073   const int len_sep = strlen(sep);
1074   const int len_id = strlen(identifier);
1075   const char *p = strstr(identifier, sep);
1076   /* TODO: make error, for now warning until add-ons update. */
1077 #if 1
1078   const int report_level = RPT_WARNING;
1079   const bool failure = true;
1080 #else
1081   const int report_level = RPT_ERROR;
1082   const bool failure = false;
1083 #endif
1084   if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) {
1085     BKE_reportf(
1086         reports, report_level, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep);
1087     return failure;
1088   }
1089
1090   const char *c, *start, *end, *last;
1091   start = identifier;
1092   end = p;
1093   last = end - 1;
1094   for (c = start; c != end; c++) {
1095     if (((*c >= 'A' && *c <= 'Z') || ((c != start) && (*c >= '0' && *c <= '9')) ||
1096          ((c != start) && (c != last) && (*c == '_'))) == 0) {
1097       BKE_reportf(
1098           reports, report_level, "'%s' doesn't have upper case alpha-numeric prefix", identifier);
1099       return failure;
1100     }
1101   }
1102
1103   start = p + len_sep;
1104   end = identifier + len_id;
1105   last = end - 1;
1106   for (c = start; c != end; c++) {
1107     if (((*c >= 'A' && *c <= 'Z') || (*c >= 'a' && *c <= 'z') || (*c >= '0' && *c <= '9') ||
1108          ((c != start) && (c != last) && (*c == '_'))) == 0) {
1109       BKE_reportf(reports, report_level, "'%s' doesn't have an alpha-numeric suffix", identifier);
1110       return failure;
1111     }
1112   }
1113   return true;
1114 }
1115
1116 /* Property Information */
1117
1118 const char *RNA_property_identifier(const PropertyRNA *prop)
1119 {
1120   return rna_ensure_property_identifier(prop);
1121 }
1122
1123 const char *RNA_property_description(PropertyRNA *prop)
1124 {
1125   return TIP_(rna_ensure_property_description(prop));
1126 }
1127
1128 PropertyType RNA_property_type(PropertyRNA *prop)
1129 {
1130   return rna_ensure_property(prop)->type;
1131 }
1132
1133 PropertySubType RNA_property_subtype(PropertyRNA *prop)
1134 {
1135   PropertyRNA *rna_prop = rna_ensure_property(prop);
1136
1137   /* For custom properties, find and parse the 'subtype' metadata field. */
1138   if (prop->magic != RNA_MAGIC) {
1139     IDProperty *idprop = (IDProperty *)prop;
1140
1141     /* Restrict to arrays only for now for performance reasons. */
1142     if (idprop->type == IDP_ARRAY && ELEM(idprop->subtype, IDP_INT, IDP_FLOAT, IDP_DOUBLE)) {
1143       IDProperty *idp_ui = rna_idproperty_ui(prop);
1144
1145       if (idp_ui) {
1146         IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "subtype", IDP_STRING);
1147
1148         if (item) {
1149           int result = PROP_NONE;
1150           RNA_enum_value_from_id(rna_enum_property_subtype_items, IDP_String(item), &result);
1151           return (PropertySubType)result;
1152         }
1153       }
1154     }
1155   }
1156
1157   return rna_prop->subtype;
1158 }
1159
1160 PropertyUnit RNA_property_unit(PropertyRNA *prop)
1161 {
1162   return RNA_SUBTYPE_UNIT(RNA_property_subtype(prop));
1163 }
1164
1165 int RNA_property_flag(PropertyRNA *prop)
1166 {
1167   return rna_ensure_property(prop)->flag;
1168 }
1169
1170 /**
1171  * Get the tags set for \a prop as int bitfield.
1172  * \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this
1173  *       in debug builds (to avoid performance issues in non-debug builds), which should be
1174  *       the only way to set tags. Hence, at this point we assume the tag bitfield to be valid.
1175  */
1176 int RNA_property_tags(PropertyRNA *prop)
1177 {
1178   return rna_ensure_property(prop)->tags;
1179 }
1180
1181 bool RNA_property_builtin(PropertyRNA *prop)
1182 {
1183   return (rna_ensure_property(prop)->flag_internal & PROP_INTERN_BUILTIN) != 0;
1184 }
1185
1186 void *RNA_property_py_data_get(PropertyRNA *prop)
1187 {
1188   return prop->py_data;
1189 }
1190
1191 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
1192 {
1193   return rna_ensure_property_array_length(ptr, prop);
1194 }
1195
1196 bool RNA_property_array_check(PropertyRNA *prop)
1197 {
1198   return rna_ensure_property_array_check(prop);
1199 }
1200
1201 /* used by BPY to make an array from the python object */
1202 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
1203 {
1204   PropertyRNA *rprop = rna_ensure_property(prop);
1205
1206   if (length) {
1207     rna_ensure_property_multi_array_length(ptr, prop, length);
1208   }
1209
1210   return rprop->arraydimension;
1211 }
1212
1213 /* Return the size of Nth dimension. */
1214 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
1215 {
1216   int len[RNA_MAX_ARRAY_DIMENSION];
1217
1218   rna_ensure_property_multi_array_length(ptr, prop, len);
1219
1220   return len[dim];
1221 }
1222
1223 char RNA_property_array_item_char(PropertyRNA *prop, int index)
1224 {
1225   const char *vectoritem = "XYZW";
1226   const char *quatitem = "WXYZ";
1227   const char *coloritem = "RGBA";
1228   PropertySubType subtype = RNA_property_subtype(prop);
1229
1230   BLI_assert(index >= 0);
1231
1232   /* get string to use for array index */
1233   if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1234     return quatitem[index];
1235   }
1236   else if ((index < 4) && ELEM(subtype,
1237                                PROP_TRANSLATION,
1238                                PROP_DIRECTION,
1239                                PROP_XYZ,
1240                                PROP_XYZ_LENGTH,
1241                                PROP_EULER,
1242                                PROP_VELOCITY,
1243                                PROP_ACCELERATION,
1244                                PROP_COORDS)) {
1245     return vectoritem[index];
1246   }
1247   else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1248     return coloritem[index];
1249   }
1250
1251   return '\0';
1252 }
1253
1254 int RNA_property_array_item_index(PropertyRNA *prop, char name)
1255 {
1256   /* Don't use custom property subtypes in RNA path lookup. */
1257   PropertySubType subtype = rna_ensure_property(prop)->subtype;
1258
1259   /* get index based on string name/alias */
1260   /* maybe a function to find char index in string would be better than all the switches */
1261   if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1262     switch (name) {
1263       case 'w':
1264         return 0;
1265       case 'x':
1266         return 1;
1267       case 'y':
1268         return 2;
1269       case 'z':
1270         return 3;
1271     }
1272   }
1273   else if (ELEM(subtype,
1274                 PROP_TRANSLATION,
1275                 PROP_DIRECTION,
1276                 PROP_XYZ,
1277                 PROP_XYZ_LENGTH,
1278                 PROP_EULER,
1279                 PROP_VELOCITY,
1280                 PROP_ACCELERATION)) {
1281     switch (name) {
1282       case 'x':
1283         return 0;
1284       case 'y':
1285         return 1;
1286       case 'z':
1287         return 2;
1288       case 'w':
1289         return 3;
1290     }
1291   }
1292   else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1293     switch (name) {
1294       case 'r':
1295         return 0;
1296       case 'g':
1297         return 1;
1298       case 'b':
1299         return 2;
1300       case 'a':
1301         return 3;
1302     }
1303   }
1304
1305   return -1;
1306 }
1307
1308 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
1309 {
1310   IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1311   int softmin, softmax;
1312
1313   if (prop->magic != RNA_MAGIC) {
1314     /* attempt to get the local ID values */
1315     IDProperty *idp_ui = rna_idproperty_ui(prop);
1316
1317     if (idp_ui) {
1318       IDProperty *item;
1319
1320       item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
1321       *hardmin = item ? IDP_Int(item) : INT_MIN;
1322
1323       item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
1324       *hardmax = item ? IDP_Int(item) : INT_MAX;
1325
1326       return;
1327     }
1328   }
1329
1330   if (iprop->range) {
1331     *hardmin = INT_MIN;
1332     *hardmax = INT_MAX;
1333
1334     iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1335   }
1336   else if (iprop->range_ex) {
1337     *hardmin = INT_MIN;
1338     *hardmax = INT_MAX;
1339
1340     iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1341   }
1342   else {
1343     *hardmin = iprop->hardmin;
1344     *hardmax = iprop->hardmax;
1345   }
1346 }
1347
1348 void RNA_property_int_ui_range(
1349     PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
1350 {
1351   IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1352   int hardmin, hardmax;
1353
1354   if (prop->magic != RNA_MAGIC) {
1355     /* attempt to get the local ID values */
1356     IDProperty *idp_ui = rna_idproperty_ui(prop);
1357
1358     if (idp_ui) {
1359       IDProperty *item;
1360
1361       item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
1362       *softmin = item ? IDP_Int(item) : INT_MIN;
1363
1364       item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
1365       *softmax = item ? IDP_Int(item) : INT_MAX;
1366
1367       item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
1368       *step = item ? IDP_Int(item) : 1;
1369
1370       return;
1371     }
1372   }
1373
1374   *softmin = iprop->softmin;
1375   *softmax = iprop->softmax;
1376
1377   if (iprop->range) {
1378     hardmin = INT_MIN;
1379     hardmax = INT_MAX;
1380
1381     iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1382
1383     *softmin = max_ii(*softmin, hardmin);
1384     *softmax = min_ii(*softmax, hardmax);
1385   }
1386   else if (iprop->range_ex) {
1387     hardmin = INT_MIN;
1388     hardmax = INT_MAX;
1389
1390     iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1391
1392     *softmin = max_ii(*softmin, hardmin);
1393     *softmax = min_ii(*softmax, hardmax);
1394   }
1395
1396   *step = iprop->step;
1397 }
1398
1399 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1400 {
1401   FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1402   float softmin, softmax;
1403
1404   if (prop->magic != RNA_MAGIC) {
1405     /* attempt to get the local ID values */
1406     IDProperty *idp_ui = rna_idproperty_ui(prop);
1407
1408     if (idp_ui) {
1409       IDProperty *item;
1410
1411       item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
1412       *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1413
1414       item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1415       *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1416
1417       return;
1418     }
1419   }
1420
1421   if (fprop->range) {
1422     *hardmin = -FLT_MAX;
1423     *hardmax = FLT_MAX;
1424
1425     fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1426   }
1427   else if (fprop->range_ex) {
1428     *hardmin = -FLT_MAX;
1429     *hardmax = FLT_MAX;
1430
1431     fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1432   }
1433   else {
1434     *hardmin = fprop->hardmin;
1435     *hardmax = fprop->hardmax;
1436   }
1437 }
1438
1439 void RNA_property_float_ui_range(PointerRNA *ptr,
1440                                  PropertyRNA *prop,
1441                                  float *softmin,
1442                                  float *softmax,
1443                                  float *step,
1444                                  float *precision)
1445 {
1446   FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1447   float hardmin, hardmax;
1448
1449   if (prop->magic != RNA_MAGIC) {
1450     /* attempt to get the local ID values */
1451     IDProperty *idp_ui = rna_idproperty_ui(prop);
1452
1453     if (idp_ui) {
1454       IDProperty *item;
1455
1456       item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1457       *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1458
1459       item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1460       *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1461
1462       item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1463       *step = item ? (float)IDP_Double(item) : 1.0f;
1464
1465       item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1466       *precision = item ? (float)IDP_Double(item) : 3.0f;
1467
1468       return;
1469     }
1470   }
1471
1472   *softmin = fprop->softmin;
1473   *softmax = fprop->softmax;
1474
1475   if (fprop->range) {
1476     hardmin = -FLT_MAX;
1477     hardmax = FLT_MAX;
1478
1479     fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1480
1481     *softmin = max_ff(*softmin, hardmin);
1482     *softmax = min_ff(*softmax, hardmax);
1483   }
1484   else if (fprop->range_ex) {
1485     hardmin = -FLT_MAX;
1486     hardmax = FLT_MAX;
1487
1488     fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1489
1490     *softmin = max_ff(*softmin, hardmin);
1491     *softmax = min_ff(*softmax, hardmax);
1492   }
1493
1494   *step = fprop->step;
1495   *precision = (float)fprop->precision;
1496 }
1497
1498 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1499 {
1500   float min, max;
1501
1502   RNA_property_float_range(ptr, prop, &min, &max);
1503
1504   if (*value < min) {
1505     *value = min;
1506     return -1;
1507   }
1508   else if (*value > max) {
1509     *value = max;
1510     return 1;
1511   }
1512   else {
1513     return 0;
1514   }
1515 }
1516
1517 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1518 {
1519   int min, max;
1520
1521   RNA_property_int_range(ptr, prop, &min, &max);
1522
1523   if (*value < min) {
1524     *value = min;
1525     return -1;
1526   }
1527   else if (*value > max) {
1528     *value = max;
1529     return 1;
1530   }
1531   else {
1532     return 0;
1533   }
1534 }
1535
1536 /* this is the max length including \0 terminator.
1537  * '0' used when their is no maximum */
1538 int RNA_property_string_maxlength(PropertyRNA *prop)
1539 {
1540   StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1541   return sprop->maxlength;
1542 }
1543
1544 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1545 {
1546   prop = rna_ensure_property(prop);
1547
1548   if (prop->type == PROP_POINTER) {
1549     PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1550
1551     if (pprop->typef) {
1552       return pprop->typef(ptr);
1553     }
1554     else if (pprop->type) {
1555       return pprop->type;
1556     }
1557   }
1558   else if (prop->type == PROP_COLLECTION) {
1559     CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1560
1561     if (cprop->item_type) {
1562       return cprop->item_type;
1563     }
1564   }
1565   /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1566
1567   return &RNA_UnknownType;
1568 }
1569
1570 bool RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1571 {
1572   prop = rna_ensure_property(prop);
1573
1574   if (prop->type == PROP_POINTER) {
1575     PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1576
1577     if (pprop->poll) {
1578       if (rna_idproperty_check(&prop, ptr)) {
1579         return ((PropPointerPollFuncPy)pprop->poll)(ptr, *value, prop);
1580       }
1581       else {
1582         return pprop->poll(ptr, *value);
1583       }
1584     }
1585
1586     return 1;
1587   }
1588
1589   printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
1590   return 0;
1591 }
1592
1593 void RNA_property_enum_items_ex(bContext *C,
1594                                 PointerRNA *ptr,
1595                                 PropertyRNA *prop,
1596                                 const bool use_static,
1597                                 const EnumPropertyItem **r_item,
1598                                 int *r_totitem,
1599                                 bool *r_free)
1600 {
1601   EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1602
1603   *r_free = false;
1604
1605   if (!use_static && eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1606     const EnumPropertyItem *item;
1607
1608     if (prop->flag & PROP_ENUM_NO_CONTEXT) {
1609       item = eprop->itemf(NULL, ptr, prop, r_free);
1610     }
1611     else {
1612       item = eprop->itemf(C, ptr, prop, r_free);
1613     }
1614
1615     /* any callbacks returning NULL should be fixed */
1616     BLI_assert(item != NULL);
1617
1618     if (r_totitem) {
1619       int tot;
1620       for (tot = 0; item[tot].identifier; tot++) {
1621         /* pass */
1622       }
1623       *r_totitem = tot;
1624     }
1625
1626     *r_item = item;
1627   }
1628   else {
1629     *r_item = eprop->item;
1630     if (r_totitem) {
1631       *r_totitem = eprop->totitem;
1632     }
1633   }
1634 }
1635
1636 void RNA_property_enum_items(bContext *C,
1637                              PointerRNA *ptr,
1638                              PropertyRNA *prop,
1639                              const EnumPropertyItem **r_item,
1640                              int *r_totitem,
1641                              bool *r_free)
1642 {
1643   RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free);
1644 }
1645
1646 #ifdef WITH_INTERNATIONAL
1647 static void property_enum_translate(PropertyRNA *prop,
1648                                     EnumPropertyItem **r_item,
1649                                     int *r_totitem,
1650                                     bool *r_free)
1651 {
1652   if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1653     int i;
1654
1655     /* Note: Only do those tests once, and then use BLT_pgettext. */
1656     bool do_iface = BLT_translate_iface();
1657     bool do_tooltip = BLT_translate_tooltips();
1658     EnumPropertyItem *nitem;
1659
1660     if (!(do_iface || do_tooltip)) {
1661       return;
1662     }
1663
1664     if (*r_free) {
1665       nitem = *r_item;
1666     }
1667     else {
1668       const EnumPropertyItem *item = *r_item;
1669       int tot;
1670
1671       if (r_totitem) {
1672         tot = *r_totitem;
1673       }
1674       else {
1675         /* count */
1676         for (tot = 0; item[tot].identifier; tot++) {
1677           /* pass */
1678         }
1679       }
1680
1681       nitem = MEM_mallocN(sizeof(EnumPropertyItem) * (tot + 1), "enum_items_gettexted");
1682       memcpy(nitem, item, sizeof(EnumPropertyItem) * (tot + 1));
1683
1684       *r_free = true;
1685     }
1686
1687     for (i = 0; nitem[i].identifier; i++) {
1688       if (nitem[i].name && do_iface) {
1689         nitem[i].name = BLT_pgettext(prop->translation_context, nitem[i].name);
1690       }
1691       if (nitem[i].description && do_tooltip) {
1692         nitem[i].description = BLT_pgettext(NULL, nitem[i].description);
1693       }
1694     }
1695
1696     *r_item = nitem;
1697   }
1698 }
1699 #endif
1700
1701 void RNA_property_enum_items_gettexted(bContext *C,
1702                                        PointerRNA *ptr,
1703                                        PropertyRNA *prop,
1704                                        const EnumPropertyItem **r_item,
1705                                        int *r_totitem,
1706                                        bool *r_free)
1707 {
1708   RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
1709
1710 #ifdef WITH_INTERNATIONAL
1711   /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory
1712    * so allow the exception (callers are creating new arrays in this case). */
1713   property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free);
1714 #endif
1715 }
1716
1717 void RNA_property_enum_items_gettexted_all(bContext *C,
1718                                            PointerRNA *ptr,
1719                                            PropertyRNA *prop,
1720                                            const EnumPropertyItem **r_item,
1721                                            int *r_totitem,
1722                                            bool *r_free)
1723 {
1724   EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1725   int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
1726   /* first return all items */
1727   EnumPropertyItem *item_array = MEM_mallocN(mem_size, "enum_gettext_all");
1728   *r_free = true;
1729   memcpy(item_array, eprop->item, mem_size);
1730
1731   if (r_totitem) {
1732     *r_totitem = eprop->totitem;
1733   }
1734
1735   if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1736     const EnumPropertyItem *item;
1737     int i;
1738     bool free = false;
1739
1740     if (prop->flag & PROP_ENUM_NO_CONTEXT) {
1741       item = eprop->itemf(NULL, ptr, prop, &free);
1742     }
1743     else {
1744       item = eprop->itemf(C, ptr, prop, &free);
1745     }
1746
1747     /* any callbacks returning NULL should be fixed */
1748     BLI_assert(item != NULL);
1749
1750     for (i = 0; i < eprop->totitem; i++) {
1751       bool exists = false;
1752       int i_fixed;
1753
1754       /* Items that do not exist on list are returned,
1755        * but have their names/identifiers NULL'ed out. */
1756       for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
1757         if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
1758           exists = true;
1759           break;
1760         }
1761       }
1762
1763       if (!exists) {
1764         item_array[i].name = NULL;
1765         item_array[i].identifier = "";
1766       }
1767     }
1768
1769     if (free) {
1770       MEM_freeN((void *)item);
1771     }
1772   }
1773
1774 #ifdef WITH_INTERNATIONAL
1775   property_enum_translate(prop, &item_array, r_totitem, r_free);
1776 #endif
1777   *r_item = item_array;
1778 }
1779
1780 bool RNA_property_enum_value(
1781     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
1782 {
1783   const EnumPropertyItem *item;
1784   bool free;
1785   bool found;
1786
1787   RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1788
1789   if (item) {
1790     const int i = RNA_enum_from_identifier(item, identifier);
1791     if (i != -1) {
1792       *r_value = item[i].value;
1793       found = true;
1794     }
1795     else {
1796       found = false;
1797     }
1798
1799     if (free) {
1800       MEM_freeN((void *)item);
1801     }
1802   }
1803   else {
1804     found = false;
1805   }
1806   return found;
1807 }
1808
1809 bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
1810 {
1811   const int i = RNA_enum_from_value(item, value);
1812   if (i != -1) {
1813     *r_identifier = item[i].identifier;
1814     return true;
1815   }
1816   else {
1817     return false;
1818   }
1819 }
1820
1821 int RNA_enum_bitflag_identifiers(const EnumPropertyItem *item,
1822                                  const int value,
1823                                  const char **r_identifier)
1824 {
1825   int index = 0;
1826   for (; item->identifier; item++) {
1827     if (item->identifier[0] && item->value & value) {
1828       r_identifier[index++] = item->identifier;
1829     }
1830   }
1831   r_identifier[index] = NULL;
1832   return index;
1833 }
1834
1835 bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
1836 {
1837   const int i = RNA_enum_from_value(item, value);
1838   if (i != -1) {
1839     *r_name = item[i].name;
1840     return true;
1841   }
1842   else {
1843     return false;
1844   }
1845 }
1846
1847 bool RNA_enum_description(const EnumPropertyItem *item,
1848                           const int value,
1849                           const char **r_description)
1850 {
1851   const int i = RNA_enum_from_value(item, value);
1852   if (i != -1) {
1853     *r_description = item[i].description;
1854     return true;
1855   }
1856   else {
1857     return false;
1858   }
1859 }
1860
1861 int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
1862 {
1863   int i = 0;
1864   for (; item->identifier; item++, i++) {
1865     if (item->identifier[0] && STREQ(item->identifier, identifier)) {
1866       return i;
1867     }
1868   }
1869   return -1;
1870 }
1871
1872 /**
1873  * Take care using this with translated enums,
1874  * prefer #RNA_enum_from_identifier where possible.
1875  */
1876 int RNA_enum_from_name(const EnumPropertyItem *item, const char *name)
1877 {
1878   int i = 0;
1879   for (; item->identifier; item++, i++) {
1880     if (item->identifier[0] && STREQ(item->name, name)) {
1881       return i;
1882     }
1883   }
1884   return -1;
1885 }
1886
1887 int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
1888 {
1889   int i = 0;
1890   for (; item->identifier; item++, i++) {
1891     if (item->identifier[0] && item->value == value) {
1892       return i;
1893     }
1894   }
1895   return -1;
1896 }
1897
1898 unsigned int RNA_enum_items_count(const EnumPropertyItem *item)
1899 {
1900   unsigned int i = 0;
1901
1902   while (item->identifier) {
1903     item++;
1904     i++;
1905   }
1906
1907   return i;
1908 }
1909
1910 bool RNA_property_enum_identifier(
1911     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
1912 {
1913   const EnumPropertyItem *item = NULL;
1914   bool free;
1915
1916   RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1917   if (item) {
1918     bool result;
1919     result = RNA_enum_identifier(item, value, identifier);
1920     if (free) {
1921       MEM_freeN((void *)item);
1922     }
1923     return result;
1924   }
1925   return false;
1926 }
1927
1928 bool RNA_property_enum_name(
1929     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1930 {
1931   const EnumPropertyItem *item = NULL;
1932   bool free;
1933
1934   RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1935   if (item) {
1936     bool result;
1937     result = RNA_enum_name(item, value, name);
1938     if (free) {
1939       MEM_freeN((void *)item);
1940     }
1941
1942     return result;
1943   }
1944   return false;
1945 }
1946
1947 bool RNA_property_enum_name_gettexted(
1948     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1949 {
1950   bool result;
1951
1952   result = RNA_property_enum_name(C, ptr, prop, value, name);
1953
1954   if (result) {
1955     if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1956       if (BLT_translate_iface()) {
1957         *name = BLT_pgettext(prop->translation_context, *name);
1958       }
1959     }
1960   }
1961
1962   return result;
1963 }
1964
1965 bool RNA_property_enum_item_from_value(
1966     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
1967 {
1968   const EnumPropertyItem *item = NULL;
1969   bool free;
1970
1971   RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1972   if (item) {
1973     const int i = RNA_enum_from_value(item, value);
1974     bool result;
1975
1976     if (i != -1) {
1977       *r_item = item[i];
1978       result = true;
1979     }
1980     else {
1981       result = false;
1982     }
1983
1984     if (free) {
1985       MEM_freeN((void *)item);
1986     }
1987
1988     return result;
1989   }
1990   return false;
1991 }
1992
1993 bool RNA_property_enum_item_from_value_gettexted(
1994     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
1995 {
1996   bool result;
1997
1998   result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
1999
2000   if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
2001     if (BLT_translate_iface()) {
2002       r_item->name = BLT_pgettext(prop->translation_context, r_item->name);
2003     }
2004   }
2005
2006   return result;
2007 }
2008
2009 int RNA_property_enum_bitflag_identifiers(
2010     bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
2011 {
2012   const EnumPropertyItem *item = NULL;
2013   bool free;
2014
2015   RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
2016   if (item) {
2017     int result;
2018     result = RNA_enum_bitflag_identifiers(item, value, identifier);
2019     if (free) {
2020       MEM_freeN((void *)item);
2021     }
2022
2023     return result;
2024   }
2025   return 0;
2026 }
2027
2028 const char *RNA_property_ui_name(PropertyRNA *prop)
2029 {
2030   return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
2031 }
2032
2033 const char *RNA_property_ui_name_raw(PropertyRNA *prop)
2034 {
2035   return rna_ensure_property_name(prop);
2036 }
2037
2038 const char *RNA_property_ui_description(PropertyRNA *prop)
2039 {
2040   return TIP_(rna_ensure_property_description(prop));
2041 }
2042
2043 const char *RNA_property_ui_description_raw(PropertyRNA *prop)
2044 {
2045   return rna_ensure_property_description(prop);
2046 }
2047
2048 const char *RNA_property_translation_context(PropertyRNA *_prop)
2049 {
2050   PropertyRNA *prop = rna_ensure_property(_prop);
2051   return prop->translation_context;
2052 }
2053
2054 int RNA_property_ui_icon(PropertyRNA *prop)
2055 {
2056   return rna_ensure_property(prop)->icon;
2057 }
2058
2059 bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
2060 {
2061   ID *id = ptr->id.data;
2062   int flag;
2063   const char *dummy_info;
2064
2065   prop = rna_ensure_property(prop);
2066   flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
2067
2068   return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0 &&
2069           (!id || ((!ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)) &&
2070                    (!id->override_library || RNA_property_overridable_get(ptr, prop)))));
2071 }
2072
2073 /**
2074  * Version of #RNA_property_editable that tries to return additional info in \a r_info
2075  * that can be exposed in UI.
2076  */
2077 bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
2078 {
2079   ID *id = ptr->id.data;
2080   int flag;
2081
2082   prop = rna_ensure_property(prop);
2083   *r_info = "";
2084
2085   /* get flag */
2086   if (prop->editable) {
2087     flag = prop->editable(ptr, r_info);
2088   }
2089   else {
2090     flag = prop->flag;
2091     if ((flag & PROP_EDITABLE) == 0 || (flag & PROP_REGISTER)) {
2092       *r_info = N_("This property is for internal use only and can't be edited");
2093     }
2094   }
2095
2096   /* property from linked data-block */
2097   if (id) {
2098     if (ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
2099       if (!(*r_info)[0]) {
2100         *r_info = N_("Can't edit this property from a linked data-block");
2101       }
2102       return false;
2103     }
2104     if (id->override_library != NULL && !RNA_property_overridable_get(ptr, prop)) {
2105       if (!(*r_info)[0]) {
2106         *r_info = N_("Can't edit this property from an override data-block");
2107       }
2108       return false;
2109     }
2110   }
2111
2112   return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
2113 }
2114
2115 bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
2116 {
2117   int flag;
2118   const char *dummy_info;
2119
2120   prop = rna_ensure_property(prop);
2121   flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
2122   return (flag & PROP_EDITABLE) != 0;
2123 }
2124
2125 /* same as RNA_property_editable(), except this checks individual items in an array */
2126 bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2127 {
2128   ID *id;
2129   int flag;
2130
2131   BLI_assert(index >= 0);
2132
2133   prop = rna_ensure_property(prop);
2134
2135   flag = prop->flag;
2136
2137   if (prop->editable) {
2138     const char *dummy_info;
2139     flag &= prop->editable(ptr, &dummy_info);
2140   }
2141
2142   if (prop->itemeditable) {
2143     flag &= prop->itemeditable(ptr, index);
2144   }
2145
2146   id = ptr->id.data;
2147
2148   return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION));
2149 }
2150
2151 bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
2152 {
2153   /* check that base ID-block can support animation data */
2154   if (!id_can_have_animdata(ptr->id.data)) {
2155     return false;
2156   }
2157
2158   prop = rna_ensure_property(prop);
2159
2160   if (!(prop->flag & PROP_ANIMATABLE)) {
2161     return false;
2162   }
2163
2164   return (prop->flag & PROP_EDITABLE) != 0;
2165 }
2166
2167 bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
2168 {
2169   int len = 1, index;
2170   bool driven, special;
2171
2172   if (!prop) {
2173     return false;
2174   }
2175
2176   if (RNA_property_array_check(prop)) {
2177     len = RNA_property_array_length(ptr, prop);
2178   }
2179
2180   for (index = 0; index < len; index++) {
2181     if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special)) {
2182       return true;
2183     }
2184   }
2185
2186   return false;
2187 }
2188 /* this function is to check if its possible to create a valid path from the ID
2189  * its slow so don't call in a loop */
2190 bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
2191 {
2192   char *path = RNA_path_from_ID_to_property(ptr, prop);
2193   bool ret = false;
2194
2195   if (path) {
2196     PointerRNA id_ptr;
2197     PointerRNA r_ptr;
2198     PropertyRNA *r_prop;
2199
2200     RNA_id_pointer_create(ptr->id.data, &id_ptr);
2201     if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
2202       ret = (prop == r_prop);
2203     }
2204     MEM_freeN(path);
2205   }
2206
2207   return ret;
2208 }
2209
2210 static void rna_property_update(
2211     bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2212 {
2213   const bool is_rna = (prop->magic == RNA_MAGIC);
2214   prop = rna_ensure_property(prop);
2215
2216   if (is_rna) {
2217     if (prop->update) {
2218       /* ideally no context would be needed for update, but there's some
2219        * parts of the code that need it still, so we have this exception */
2220       if (prop->flag & PROP_CONTEXT_UPDATE) {
2221         if (C) {
2222           if ((prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) == PROP_CONTEXT_PROPERTY_UPDATE) {
2223             ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
2224           }
2225           else {
2226             ((ContextUpdateFunc)prop->update)(C, ptr);
2227           }
2228         }
2229       }
2230       else {
2231         prop->update(bmain, scene, ptr);
2232       }
2233     }
2234
2235 #if 1
2236     /* TODO(campbell): Should eventually be replaced entirely by message bus (below)
2237      * for now keep since COW, bugs are hard to track when we have other missing updates. */
2238     if (prop->noteflag) {
2239       WM_main_add_notifier(prop->noteflag, ptr->id.data);
2240     }
2241 #endif
2242
2243     /* if C is NULL, we're updating from animation.
2244      * avoid slow-down from f-curves by not publishing (for now). */
2245     if (C != NULL) {
2246       struct wmMsgBus *mbus = CTX_wm_message_bus(C);
2247       /* we could add NULL check, for now don't */
2248       WM_msg_publish_rna(mbus, ptr, prop);
2249     }
2250     if (ptr->id.data != NULL && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) {
2251       const short id_type = GS(((ID *)ptr->id.data)->name);
2252       if (ID_TYPE_IS_COW(id_type)) {
2253         DEG_id_tag_update(ptr->id.data, ID_RECALC_COPY_ON_WRITE);
2254       }
2255     }
2256     /* End message bus. */
2257   }
2258
2259   if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
2260     /* WARNING! This is so property drivers update the display!
2261      * not especially nice  */
2262     DEG_id_tag_update(ptr->id.data,
2263                       ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_PARAMETERS);
2264     WM_main_add_notifier(NC_WINDOW, NULL);
2265     /* Not nice as well, but the only way to make sure material preview
2266      * is updated with custom nodes.
2267      */
2268     if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->id.data != NULL) &&
2269         (GS(((ID *)ptr->id.data)->name) == ID_NT)) {
2270       WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
2271     }
2272   }
2273 }
2274
2275 /* must keep in sync with 'rna_property_update'
2276  * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
2277  * but this isn't likely to be a performance problem. */
2278 bool RNA_property_update_check(PropertyRNA *prop)
2279 {
2280   return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
2281 }
2282
2283 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
2284 {
2285   rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
2286 }
2287
2288 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2289 {
2290   rna_property_update(NULL, bmain, scene, ptr, prop);
2291 }
2292
2293 /* RNA Updates Cache ------------------------ */
2294 /* Overview of RNA Update cache system:
2295  *
2296  * RNA Update calls need to be cached in order to maintain reasonable performance
2297  * of the animation system (i.e. maintaining a somewhat interactive framerate)
2298  * while still allowing updates to be called (necessary in particular for modifier
2299  * property updates to actually work).
2300  *
2301  * The cache is structured with a dual-layer structure
2302  * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
2303  *        and most updates end up using just that anyways)
2304  * - L2 = Update functions to be called on those PointerRNA's
2305  */
2306
2307 /* cache element */
2308 typedef struct tRnaUpdateCacheElem {
2309   struct tRnaUpdateCacheElem *next, *prev;
2310
2311   PointerRNA ptr;   /* L1 key - id as primary, data secondary/ignored? */
2312   ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */
2313 } tRnaUpdateCacheElem;
2314
2315 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
2316 static ListBase rna_updates_cache = {NULL, NULL};
2317
2318 /* ........................... */
2319
2320 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
2321 {
2322   const bool is_rna = (prop->magic == RNA_MAGIC);
2323   tRnaUpdateCacheElem *uce = NULL;
2324   UpdateFunc fn = NULL;
2325   LinkData *ld;
2326
2327   /* sanity check */
2328   if (NULL == ptr) {
2329     return;
2330   }
2331
2332   prop = rna_ensure_property(prop);
2333
2334   /* we can only handle update calls with no context args for now (makes animsys updates easier) */
2335   if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) {
2336     return;
2337   }
2338   fn = prop->update;
2339
2340   /* find cache element for which key matches... */
2341   for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2342     /* Just match by id only for now,
2343      * since most update calls that we'll encounter only really care about this. */
2344     /* TODO: later, the cache might need to have some nesting on L1 to cope better
2345      * with these problems + some tagging to indicate we need this */
2346     if (uce->ptr.id.data == ptr->id.data) {
2347       break;
2348     }
2349   }
2350   if (uce == NULL) {
2351     /* create new instance */
2352     uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
2353     BLI_addtail(&rna_updates_cache, uce);
2354
2355     /* copy pointer */
2356     RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
2357   }
2358
2359   /* check on the update func */
2360   for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2361     /* stop on match - function already cached */
2362     if (fn == ld->data) {
2363       return;
2364     }
2365   }
2366   /* else... if still here, we need to add it */
2367   BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
2368 }
2369
2370 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
2371 {
2372   tRnaUpdateCacheElem *uce;
2373
2374   /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
2375
2376   /* execute the cached updates */
2377   for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2378     LinkData *ld;
2379
2380     for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2381       UpdateFunc fn = (UpdateFunc)ld->data;
2382       fn(bmain, scene, &uce->ptr);
2383     }
2384   }
2385 }
2386
2387 void RNA_property_update_cache_free(void)
2388 {
2389   tRnaUpdateCacheElem *uce, *ucn;
2390
2391   for (uce = rna_updates_cache.first; uce; uce = ucn) {
2392     ucn = uce->next;
2393
2394     /* free L2 cache */
2395     BLI_freelistN(&uce->L2Funcs);
2396
2397     /* remove self */
2398     BLI_freelinkN(&rna_updates_cache, uce);
2399   }
2400 }
2401
2402 /* ---------------------------------------------------------------------- */
2403
2404 /* Property Data */
2405
2406 bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
2407 {
2408   BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2409   IDProperty *idprop;
2410   bool value;
2411
2412   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2413   BLI_assert(RNA_property_array_check(prop) == false);
2414
2415   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2416     value = IDP_Int(idprop) != 0;
2417   }
2418   else if (bprop->get) {
2419     value = bprop->get(ptr);
2420   }
2421   else if (bprop->get_ex) {
2422     value = bprop->get_ex(ptr, prop);
2423   }
2424   else {
2425     value = bprop->defaultvalue;
2426   }
2427
2428   BLI_assert(ELEM(value, false, true));
2429
2430   return value;
2431 }
2432
2433 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
2434 {
2435   BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2436   IDProperty *idprop;
2437
2438   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2439   BLI_assert(RNA_property_array_check(prop) == false);
2440   BLI_assert(ELEM(value, false, true));
2441
2442   /* just in case other values are passed */
2443   BLI_assert(ELEM(value, true, false));
2444
2445   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2446     IDP_Int(idprop) = (int)value;
2447     rna_idproperty_touch(idprop);
2448   }
2449   else if (bprop->set) {
2450     bprop->set(ptr, value);
2451   }
2452   else if (bprop->set_ex) {
2453     bprop->set_ex(ptr, prop, value);
2454   }
2455   else if (prop->flag & PROP_EDITABLE) {
2456     IDPropertyTemplate val = {0};
2457     IDProperty *group;
2458
2459     val.i = value;
2460
2461     group = RNA_struct_idprops(ptr, 1);
2462     if (group) {
2463       IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2464     }
2465   }
2466 }
2467
2468 static void rna_property_boolean_fill_default_array_values(
2469     const bool *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values)
2470 {
2471   if (defarr && defarr_length > 0) {
2472     defarr_length = MIN2(defarr_length, out_length);
2473     memcpy(r_values, defarr, sizeof(bool) * defarr_length);
2474   }
2475   else {
2476     defarr_length = 0;
2477   }
2478
2479   for (int i = defarr_length; i < out_length; i++) {
2480     r_values[i] = defvalue;
2481   }
2482 }
2483
2484 static void rna_property_boolean_get_default_array_values(PointerRNA *ptr,
2485                                                           BoolPropertyRNA *bprop,
2486                                                           bool *r_values)
2487 {
2488   int length = bprop->property.totarraylength;
2489   int out_length = RNA_property_array_length(ptr, (PropertyRNA *)bprop);
2490
2491   rna_property_boolean_fill_default_array_values(
2492       bprop->defaultarray, length, bprop->defaultvalue, out_length, r_values);
2493 }
2494
2495 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
2496 {
2497   BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2498   IDProperty *idprop;
2499
2500   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2501   BLI_assert(RNA_property_array_check(prop) != false);
2502
2503   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2504     if (prop->arraydimension == 0) {
2505       values[0] = RNA_property_boolean_get(ptr, prop);
2506     }
2507     else {
2508       int *values_src = IDP_Array(idprop);
2509       for (uint i = 0; i < idprop->len; i++) {
2510         values[i] = (bool)values_src[i];
2511       }
2512     }
2513   }
2514   else if (prop->arraydimension == 0) {
2515     values[0] = RNA_property_boolean_get(ptr, prop);
2516   }
2517   else if (bprop->getarray) {
2518     bprop->getarray(ptr, values);
2519   }
2520   else if (bprop->getarray_ex) {
2521     bprop->getarray_ex(ptr, prop, values);
2522   }
2523   else {
2524     rna_property_boolean_get_default_array_values(ptr, bprop, values);
2525   }
2526 }
2527
2528 bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2529 {
2530   bool tmp[RNA_MAX_ARRAY_LENGTH];
2531   int len = rna_ensure_property_array_length(ptr, prop);
2532   bool value;
2533
2534   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2535   BLI_assert(RNA_property_array_check(prop) != false);
2536   BLI_assert(index >= 0);
2537   BLI_assert(index < len);
2538
2539   if (len <= RNA_MAX_ARRAY_LENGTH) {
2540     RNA_property_boolean_get_array(ptr, prop, tmp);
2541     value = tmp[index];
2542   }
2543   else {
2544     bool *tmparray;
2545
2546     tmparray = MEM_mallocN(sizeof(bool) * len, __func__);
2547     RNA_property_boolean_get_array(ptr, prop, tmparray);
2548     value = tmparray[index];
2549     MEM_freeN(tmparray);
2550   }
2551
2552   BLI_assert(ELEM(value, false, true));
2553
2554   return value;
2555 }
2556
2557 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
2558 {
2559   BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2560   IDProperty *idprop;
2561
2562   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2563   BLI_assert(RNA_property_array_check(prop) != false);
2564
2565   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2566     if (prop->arraydimension == 0) {
2567       IDP_Int(idprop) = values[0];
2568     }
2569     else {
2570       int *values_dst = IDP_Array(idprop);
2571       for (uint i = 0; i < idprop->len; i++) {
2572         values_dst[i] = (int)values[i];
2573       }
2574     }
2575     rna_idproperty_touch(idprop);
2576   }
2577   else if (prop->arraydimension == 0) {
2578     RNA_property_boolean_set(ptr, prop, values[0]);
2579   }
2580   else if (bprop->setarray) {
2581     bprop->setarray(ptr, values);
2582   }
2583   else if (bprop->setarray_ex) {
2584     bprop->setarray_ex(ptr, prop, values);
2585   }
2586   else if (prop->flag & PROP_EDITABLE) {
2587     IDPropertyTemplate val = {0};
2588     IDProperty *group;
2589
2590     val.array.len = prop->totarraylength;
2591     val.array.type = IDP_INT;
2592
2593     group = RNA_struct_idprops(ptr, 1);
2594     if (group) {
2595       idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2596       IDP_AddToGroup(group, idprop);
2597       int *values_dst = IDP_Array(idprop);
2598       for (uint i = 0; i < idprop->len; i++) {
2599         values_dst[i] = (int)values[i];
2600       }
2601     }
2602   }
2603 }
2604
2605 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
2606 {
2607   bool tmp[RNA_MAX_ARRAY_LENGTH];
2608   int len = rna_ensure_property_array_length(ptr, prop);
2609
2610   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2611   BLI_assert(RNA_property_array_check(prop) != false);
2612   BLI_assert(index >= 0);
2613   BLI_assert(index < len);
2614   BLI_assert(ELEM(value, false, true));
2615
2616   if (len <= RNA_MAX_ARRAY_LENGTH) {
2617     RNA_property_boolean_get_array(ptr, prop, tmp);
2618     tmp[index] = value;
2619     RNA_property_boolean_set_array(ptr, prop, tmp);
2620   }
2621   else {
2622     bool *tmparray;
2623
2624     tmparray = MEM_mallocN(sizeof(bool) * len, __func__);
2625     RNA_property_boolean_get_array(ptr, prop, tmparray);
2626     tmparray[index] = value;
2627     RNA_property_boolean_set_array(ptr, prop, tmparray);
2628     MEM_freeN(tmparray);
2629   }
2630 }
2631
2632 bool RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2633 {
2634   BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2635
2636   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2637   BLI_assert(RNA_property_array_check(prop) == false);
2638   BLI_assert(ELEM(bprop->defaultvalue, false, true));
2639
2640   return bprop->defaultvalue;
2641 }
2642
2643 void RNA_property_boolean_get_default_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
2644 {
2645   BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2646
2647   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2648   BLI_assert(RNA_property_array_check(prop) != false);
2649
2650   if (prop->arraydimension == 0) {
2651     values[0] = bprop->defaultvalue;
2652   }
2653   else {
2654     rna_property_boolean_get_default_array_values(ptr, bprop, values);
2655   }
2656 }
2657
2658 bool RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2659 {
2660   bool tmp[RNA_MAX_ARRAY_LENGTH];
2661   int len = rna_ensure_property_array_length(ptr, prop);
2662
2663   BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2664   BLI_assert(RNA_property_array_check(prop) != false);
2665   BLI_assert(index >= 0);
2666   BLI_assert(index < len);
2667
2668   if (len <= RNA_MAX_ARRAY_LENGTH) {
2669     RNA_property_boolean_get_default_array(ptr, prop, tmp);
2670     return tmp[index];
2671   }
2672   else {
2673     bool *tmparray, value;
2674
2675     tmparray = MEM_mallocN(sizeof(bool) * len, __func__);
2676     RNA_property_boolean_get_default_array(ptr, prop, tmparray);
2677     value = tmparray[index];
2678     MEM_freeN(tmparray);
2679
2680     return value;
2681   }
2682 }
2683
2684 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
2685 {
2686   IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2687   IDProperty *idprop;
2688
2689   BLI_assert(RNA_property_type(prop) == PROP_INT);
2690   BLI_assert(RNA_property_array_check(prop) == false);
2691
2692   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2693     return IDP_Int(idprop);
2694   }
2695   else if (iprop->get) {
2696     return iprop->get(ptr);
2697   }
2698   else if (iprop->get_ex) {
2699     return iprop->get_ex(ptr, prop);
2700   }
2701   else {
2702     return iprop->defaultvalue;
2703   }
2704 }
2705
2706 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2707 {
2708   IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2709   IDProperty *idprop;
2710
2711   BLI_assert(RNA_property_type(prop) == PROP_INT);
2712   BLI_assert(RNA_property_array_check(prop) == false);
2713   /* useful to check on bad values but set function should clamp */
2714   /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
2715
2716   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2717     RNA_property_int_clamp(ptr, prop, &value);
2718     IDP_Int(idprop) = value;
2719     rna_idproperty_touch(idprop);
2720   }
2721   else if (iprop->set) {
2722     iprop->set(ptr, value);
2723   }
2724   else if (iprop->set_ex) {
2725     iprop->set_ex(ptr, prop, value);
2726   }
2727   else if (prop->flag & PROP_EDITABLE) {
2728     IDPropertyTemplate val = {0};
2729     IDProperty *group;
2730
2731     RNA_property_int_clamp(ptr, prop, &value);
2732
2733     val.i = value;
2734
2735     group = RNA_struct_idprops(ptr, 1);
2736     if (group) {
2737       IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2738     }
2739   }
2740 }
2741
2742 static void rna_property_int_fill_default_array_values(
2743     const int *defarr, int defarr_length, int defvalue, int out_length, int *r_values)
2744 {
2745   if (defarr && defarr_length > 0) {
2746     defarr_length = MIN2(defarr_length, out_length);
2747     memcpy(r_values, defarr, sizeof(int) * defarr_length);
2748   }
2749   else {
2750     defarr_length = 0;
2751   }
2752
2753   for (int i = defarr_length; i < out_length; i++) {
2754     r_values[i] = defvalue;
2755   }
2756 }
2757
2758 static void rna_property_int_get_default_array_values(PointerRNA *ptr,
2759                                                       IntPropertyRNA *iprop,
2760                                                       int *r_values)
2761 {
2762   int length = iprop->property.totarraylength;
2763   int out_length = RNA_property_array_length(ptr, (PropertyRNA *)iprop);
2764
2765   rna_property_int_fill_default_array_values(
2766       iprop->defaultarray, length, iprop->defaultvalue, out_length, r_values);
2767 }
2768
2769 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2770 {
2771   IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2772   IDProperty *idprop;
2773
2774   BLI_assert(RNA_property_type(prop) == PROP_INT);
2775   BLI_assert(RNA_property_array_check(prop) != false);
2776
2777   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2778     BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
2779                (prop->flag & PROP_IDPROPERTY));
2780     if (prop->arraydimension == 0) {
2781       values[0] = RNA_property_int_get(ptr, prop);
2782     }
2783     else {
2784       memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2785     }
2786   }
2787   else if (prop->arraydimension == 0) {
2788     values[0] = RNA_property_int_get(ptr, prop);
2789   }
2790   else if (iprop->getarray) {
2791     iprop->getarray(ptr, values);
2792   }
2793   else if (iprop->getarray_ex) {
2794     iprop->getarray_ex(ptr, prop, values);
2795   }
2796   else {
2797     rna_property_int_get_default_array_values(ptr, iprop, values);
2798   }
2799 }
2800
2801 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
2802 {
2803   const int array_len = RNA_property_array_length(ptr, prop);
2804
2805   if (array_len <= 0) {
2806     values[0] = 0;
2807     values[1] = 0;
2808   }
2809   else if (array_len == 1) {
2810     RNA_property_int_get_array(ptr, prop, values);
2811     values[1] = values[0];
2812   }
2813   else {
2814     int arr_stack[32];
2815     int *arr;
2816     int i;
2817
2818     if (array_len > 32) {
2819       arr = MEM_mallocN(sizeof(int) * array_len, __func__);
2820     }
2821     else {
2822       arr = arr_stack;
2823     }
2824
2825     RNA_property_int_get_array(ptr, prop, arr);
2826     values[0] = values[1] = arr[0];
2827     for (i = 1; i < array_len; i++) {
2828       values[0] = MIN2(values[0], arr[i]);
2829       values[1] = MAX2(values[1], arr[i]);
2830     }
2831
2832     if (arr != arr_stack) {
2833       MEM_freeN(arr);
2834     }
2835   }
2836 }
2837
2838 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2839 {
2840   int tmp[RNA_MAX_ARRAY_LENGTH];
2841   int len = rna_ensure_property_array_length(ptr, prop);
2842
2843   BLI_assert(RNA_property_type(prop) == PROP_INT);
2844   BLI_assert(RNA_property_array_check(prop) != false);
2845   BLI_assert(index >= 0);
2846   BLI_assert(index < len);
2847
2848   if (len <= RNA_MAX_ARRAY_LENGTH) {
2849     RNA_property_int_get_array(ptr, prop, tmp);
2850     return tmp[index];
2851   }
2852   else {
2853     int *tmparray, value;
2854
2855     tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2856     RNA_property_int_get_array(ptr, prop, tmparray);
2857     value = tmparray[index];
2858     MEM_freeN(tmparray);
2859
2860     return value;
2861   }
2862 }
2863
2864 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2865 {
2866   IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2867   IDProperty *idprop;
2868
2869   BLI_assert(RNA_property_type(prop) == PROP_INT);
2870   BLI_assert(RNA_property_array_check(prop) != false);
2871
2872   if ((idprop = rna_idproperty_check(&prop, ptr))) {
2873     BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
2874                (prop->flag & PROP_IDPROPERTY));
2875     if (prop->arraydimension == 0) {
2876       IDP_Int(idprop) = values[0];
2877     }
2878     else {
2879       memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2880     }
2881
2882     rna_idproperty_touch(idprop);
2883   }
2884   else if (prop->arraydimension == 0) {
2885     RNA_property_int_set(ptr, prop, values[0]);
2886   }
2887   else if (iprop->setarray) {
2888     iprop->setarray(ptr, values);
2889   }
2890   else if (iprop->setarray_ex) {
2891     iprop->setarray_ex(ptr, prop, values);
2892   }
2893   else if (prop->flag & PROP_EDITABLE) {
2894     IDPropertyTemplate val = {0};
2895     IDProperty *group;
2896
2897     /* TODO: RNA_property_int_clamp_array(ptr, prop, &value); */
2898
2899     val.array.len = prop->totarraylength;
2900     val.array.type = IDP_INT;
2901
2902     group = RNA_struct_idprops(ptr, 1);
2903     if (group) {
2904       idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2905       IDP_AddToGroup(group, idprop);
2906       memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2907     }
2908   }
2909 }
2910
2911 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2912 {
2913   int tmp[RNA_MAX_ARRAY_LENGTH];
2914   int len = rna_ensure_property_array_length(ptr, prop);
2915
2916   BLI_assert(RNA_property_type(prop) == PROP_INT);
2917   BLI_assert(RNA_property_array_check(prop) != false);
2918   BLI_assert(index >= 0);
2919   BLI_assert(index < len);
2920
2921   if (len <= RNA_MAX_ARRAY_LENGTH) {
2922     RNA_property_int_get_array(ptr, prop, tmp);
2923     tmp[index] = value;
2924     RNA_property_int_set_array(ptr, prop, tmp);
2925   }
2926   else {
2927     int *tmparray;
2928
2929     tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2930     RNA_property_int_get_array(ptr, prop, tmparray);
2931     tmparray[index] = value;
2932     RNA_property_int_set_array(ptr, prop, tmparray);
2933     MEM_freeN(tmparray);
2934   }
2935 }
2936
2937 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2938 {
2939   IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2940
2941   if (prop->magic != RNA_MAGIC) {
2942     /* attempt to get the local ID values */
2943     IDProperty *idp_ui = rna_idproperty_ui(prop);
2944
2945     if (idp_ui) {
2946       IDProperty *item;
2947
2948       item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", IDP_INT);
2949       return item ? IDP_Int(item) : iprop->defaultvalue;
2950     }
2951   }
2952
2953   return iprop->defaultvalue;
2954 }
2955
2956 bool RNA_property_int_set_default(PointerRNA *ptr, PropertyRNA *prop, int value)
2957 {
2958   if (value != 0) {
2959     IDPropertyTemplate val = {
2960         .i = value,
2961     };
2962     return rna_idproperty_ui_set_default(ptr, prop, IDP_INT, &val);
2963   }
2964   else {
2965     return rna_idproperty_ui_set_default(ptr, prop, IDP_INT, NULL);
2966   }
2967 }
2968
2969 void RNA_property_int_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2970 {
2971   IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2972
2973   BLI_assert(RNA_property_type(prop) == PROP_INT);
2974   BLI_assert(RNA_property_array_check(prop) != false);
2975
2976   if (prop->magic != RNA_MAGIC) {
2977     int length = rna_ensure_property_array_length(ptr, prop);
2978
2979     IDProperty *idp_ui = rna_idproperty_ui(prop);
2980     IDProperty *item = idp_ui ? IDP_GetPropertyFromGroup(idp_ui, "default") : NULL;
2981
2982     int defval = (item && item->type == IDP_INT) ? IDP_Int(item) : iprop->defaultvalue;
2983
2984     if (item && item->type == IDP_ARRAY && item->subtype == IDP_INT) {
2985       rna_property_int_fill_default_array_values(
2986           IDP_Array(item), item->len, defval, length, values);
2987     }
2988     else {
2989       rna_property_int_fill_default_array_values(NULL, 0, defval, length, values);
2990     }
2991   }
2992   else if (prop->arraydimension == 0) {
2993     values[0] = iprop->defaultvalue;
2994   }
2995   else {
2996     rna_property_int_get_default_array_values(ptr, iprop, values);
2997   }
2998 }
2999
3000 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
3001 {
3002   int tmp[RNA_MAX_ARRAY_LENGTH];
3003   int len = rna_ensure_property_array_length(ptr, prop);
3004
3005   BLI_assert(RNA_property_type(prop) == PROP_INT);
3006   BLI_assert(RNA_property_array_check(prop) != false);
3007   BLI_assert(index >= 0);
3008   BLI_assert(index < len);
3009
3010   if (len <= RNA_MAX_ARRAY_LENGTH) {
3011     RNA_property_int_get_default_array(ptr, prop, tmp);
3012     return tmp[index];
3013   }
3014   else {
3015     int *tmparray, value;
3016
3017     tmparray = MEM_mallocN(sizeof(int) * len, __func__);
3018     RNA_property_int_get_default_array(ptr, prop, tmparray);
3019     value = tmparray[index];
3020     MEM_freeN(tmparray);
3021
3022     return value;
3023   }
3024 }
3025
3026 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
3027 {
3028   FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
3029   IDProperty *idprop;
3030
3031   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3032   BLI_assert(RNA_property_array_check(prop) == false);
3033
3034   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3035     if (idprop->type == IDP_FLOAT) {
3036       return IDP_Float(idprop);
3037     }
3038     else {
3039       return (float)IDP_Double(idprop);
3040     }
3041   }
3042   else if (fprop->get) {
3043     return fprop->get(ptr);
3044   }
3045   else if (fprop->get_ex) {
3046     return fprop->get_ex(ptr, prop);
3047   }
3048   else {
3049     return fprop->defaultvalue;
3050   }
3051 }
3052
3053 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
3054 {
3055   FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
3056   IDProperty *idprop;
3057
3058   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3059   BLI_assert(RNA_property_array_check(prop) == false);
3060   /* useful to check on bad values but set function should clamp */
3061   /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
3062
3063   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3064     RNA_property_float_clamp(ptr, prop, &value);
3065     if (idprop->type == IDP_FLOAT) {
3066       IDP_Float(idprop) = value;
3067     }
3068     else {
3069       IDP_Double(idprop) = value;
3070     }
3071
3072     rna_idproperty_touch(idprop);
3073   }
3074   else if (fprop->set) {
3075     fprop->set(ptr, value);
3076   }
3077   else if (fprop->set_ex) {
3078     fprop->set_ex(ptr, prop, value);
3079   }
3080   else if (prop->flag & PROP_EDITABLE) {
3081     IDPropertyTemplate val = {0};
3082     IDProperty *group;
3083
3084     RNA_property_float_clamp(ptr, prop, &value);
3085
3086     val.f = value;
3087
3088     group = RNA_struct_idprops(ptr, 1);
3089     if (group) {
3090       IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
3091     }
3092   }
3093 }
3094
3095 static void rna_property_float_fill_default_array_values(
3096     const float *defarr, int defarr_length, float defvalue, int out_length, float *r_values)
3097 {
3098   if (defarr && defarr_length > 0) {
3099     defarr_length = MIN2(defarr_length, out_length);
3100     memcpy(r_values, defarr, sizeof(float) * defarr_length);
3101   }
3102   else {
3103     defarr_length = 0;
3104   }
3105
3106   for (int i = defarr_length; i < out_length; i++) {
3107     r_values[i] = defvalue;
3108   }
3109 }
3110
3111 static void rna_property_float_get_default_array_values(PointerRNA *ptr,
3112                                                         FloatPropertyRNA *fprop,
3113                                                         float *r_values)
3114 {
3115   int length = fprop->property.totarraylength;
3116   int out_length = RNA_property_array_length(ptr, (PropertyRNA *)fprop);
3117
3118   rna_property_float_fill_default_array_values(
3119       fprop->defaultarray, length, fprop->defaultvalue, out_length, r_values);
3120 }
3121
3122 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
3123 {
3124   FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
3125   IDProperty *idprop;
3126   int i;
3127
3128   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3129   BLI_assert(RNA_property_array_check(prop) != false);
3130
3131   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3132     BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
3133                (prop->flag & PROP_IDPROPERTY));
3134     if (prop->arraydimension == 0) {
3135       values[0] = RNA_property_float_get(ptr, prop);
3136     }
3137     else if (idprop->subtype == IDP_FLOAT) {
3138       memcpy(values, IDP_Array(idprop), sizeof(float) * idprop->len);
3139     }
3140     else {
3141       for (i = 0; i < idprop->len; i++) {
3142         values[i] = (float)(((double *)IDP_Array(idprop))[i]);
3143       }
3144     }
3145   }
3146   else if (prop->arraydimension == 0) {
3147     values[0] = RNA_property_float_get(ptr, prop);
3148   }
3149   else if (fprop->getarray) {
3150     fprop->getarray(ptr, values);
3151   }
3152   else if (fprop->getarray_ex) {
3153     fprop->getarray_ex(ptr, prop, values);
3154   }
3155   else {
3156     rna_property_float_get_default_array_values(ptr, fprop, values);
3157   }
3158 }
3159
3160 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
3161 {
3162   const int array_len = RNA_property_array_length(ptr, prop);
3163
3164   if (array_len <= 0) {
3165     values[0] = 0.0f;
3166     values[1] = 0.0f;
3167   }
3168   else if (array_len == 1) {
3169     RNA_property_float_get_array(ptr, prop, values);
3170     values[1] = values[0];
3171   }
3172   else {
3173     float arr_stack[32];
3174     float *arr;
3175     int i;
3176
3177     if (array_len > 32) {
3178       arr = MEM_mallocN(sizeof(float) * array_len, __func__);
3179     }
3180     else {
3181       arr = arr_stack;
3182     }
3183
3184     RNA_property_float_get_array(ptr, prop, arr);
3185     values[0] = values[1] = arr[0];
3186     for (i = 1; i < array_len; i++) {
3187       values[0] = MIN2(values[0], arr[i]);
3188       values[1] = MAX2(values[1], arr[i]);
3189     }
3190
3191     if (arr != arr_stack) {
3192       MEM_freeN(arr);
3193     }
3194   }
3195 }
3196
3197 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
3198 {
3199   float tmp[RNA_MAX_ARRAY_LENGTH];
3200   int len = rna_ensure_property_array_length(ptr, prop);
3201
3202   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3203   BLI_assert(RNA_property_array_check(prop) != false);
3204   BLI_assert(index >= 0);
3205   BLI_assert(index < len);
3206
3207   if (len <= RNA_MAX_ARRAY_LENGTH) {
3208     RNA_property_float_get_array(ptr, prop, tmp);
3209     return tmp[index];
3210   }
3211   else {
3212     float *tmparray, value;
3213
3214     tmparray = MEM_mallocN(sizeof(float) * len, __func__);
3215     RNA_property_float_get_array(ptr, prop, tmparray);
3216     value = tmparray[index];
3217     MEM_freeN(tmparray);
3218
3219     return value;
3220   }
3221 }
3222
3223 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
3224 {
3225   FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
3226   IDProperty *idprop;
3227   int i;
3228
3229   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3230   BLI_assert(RNA_property_array_check(prop) != false);
3231
3232   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3233     BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) ||
3234                (prop->flag & PROP_IDPROPERTY));
3235     if (prop->arraydimension == 0) {
3236       if (idprop->type == IDP_FLOAT) {
3237         IDP_Float(idprop) = values[0];
3238       }
3239       else {
3240         IDP_Double(idprop) = values[0];
3241       }
3242     }
3243     else if (idprop->subtype == IDP_FLOAT) {
3244       memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
3245     }
3246     else {
3247       for (i = 0; i < idprop->len; i++) {
3248         ((double *)IDP_Array(idprop))[i] = values[i];
3249       }
3250     }
3251
3252     rna_idproperty_touch(idprop);
3253   }
3254   else if (prop->arraydimension == 0) {
3255     RNA_property_float_set(ptr, prop, values[0]);
3256   }
3257   else if (fprop->setarray) {
3258     fprop->setarray(ptr, values);
3259   }
3260   else if (fprop->setarray_ex) {
3261     fprop->setarray_ex(ptr, prop, values);
3262   }
3263   else if (prop->flag & PROP_EDITABLE) {
3264     IDPropertyTemplate val = {0};
3265     IDProperty *group;
3266
3267     /* TODO: RNA_property_float_clamp_array(ptr, prop, &value); */
3268
3269     val.array.len = prop->totarraylength;
3270     val.array.type = IDP_FLOAT;
3271
3272     group = RNA_struct_idprops(ptr, 1);
3273     if (group) {
3274       idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
3275       IDP_AddToGroup(group, idprop);
3276       memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
3277     }
3278   }
3279 }
3280
3281 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
3282 {
3283   float tmp[RNA_MAX_ARRAY_LENGTH];
3284   int len = rna_ensure_property_array_length(ptr, prop);
3285
3286   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3287   BLI_assert(RNA_property_array_check(prop) != false);
3288   BLI_assert(index >= 0);
3289   BLI_assert(index < len);
3290
3291   if (len <= RNA_MAX_ARRAY_LENGTH) {
3292     RNA_property_float_get_array(ptr, prop, tmp);
3293     tmp[index] = value;
3294     RNA_property_float_set_array(ptr, prop, tmp);
3295   }
3296   else {
3297     float *tmparray;
3298
3299     tmparray = MEM_mallocN(sizeof(float) * len, __func__);
3300     RNA_property_float_get_array(ptr, prop, tmparray);
3301     tmparray[index] = value;
3302     RNA_property_float_set_array(ptr, prop, tmparray);
3303     MEM_freeN(tmparray);
3304   }
3305 }
3306
3307 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3308 {
3309   FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
3310
3311   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3312   BLI_assert(RNA_property_array_check(prop) == false);
3313
3314   if (prop->magic != RNA_MAGIC) {
3315     /* attempt to get the local ID values */
3316     IDProperty *idp_ui = rna_idproperty_ui(prop);
3317
3318     if (idp_ui) {
3319       IDProperty *item;
3320
3321       item = IDP_GetPropertyTypeFromGroup(idp_ui, "default", IDP_DOUBLE);
3322       return item ? IDP_Double(item) : fprop->defaultvalue;
3323     }
3324   }
3325
3326   return fprop->defaultvalue;
3327 }
3328
3329 bool RNA_property_float_set_default(PointerRNA *ptr, PropertyRNA *prop, float value)
3330 {
3331   if (value != 0) {
3332     IDPropertyTemplate val = {
3333         .d = value,
3334     };
3335     return rna_idproperty_ui_set_default(ptr, prop, IDP_DOUBLE, &val);
3336   }
3337   else {
3338     return rna_idproperty_ui_set_default(ptr, prop, IDP_DOUBLE, NULL);
3339   }
3340 }
3341
3342 void RNA_property_float_get_default_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
3343 {
3344   FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
3345
3346   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3347   BLI_assert(RNA_property_array_check(prop) != false);
3348
3349   if (prop->magic != RNA_MAGIC) {
3350     int length = rna_ensure_property_array_length(ptr, prop);
3351
3352     IDProperty *idp_ui = rna_idproperty_ui(prop);
3353     IDProperty *item = idp_ui ? IDP_GetPropertyFromGroup(idp_ui, "default") : NULL;
3354
3355     float defval = (item && item->type == IDP_DOUBLE) ? IDP_Double(item) : fprop->defaultvalue;
3356
3357     if (item && item->type == IDP_ARRAY && item->subtype == IDP_DOUBLE) {
3358       double *defarr = IDP_Array(item);
3359       for (int i = 0; i < length; i++) {
3360         values[i] = (i < item->len) ? (float)defarr[i] : defval;
3361       }
3362     }
3363     else if (item && item->type == IDP_ARRAY && item->subtype == IDP_FLOAT) {
3364       rna_property_float_fill_default_array_values(
3365           IDP_Array(item), item->len, defval, length, values);
3366     }
3367     else {
3368       rna_property_float_fill_default_array_values(NULL, 0, defval, length, values);
3369     }
3370   }
3371   else if (prop->arraydimension == 0) {
3372     values[0] = fprop->defaultvalue;
3373   }
3374   else {
3375     rna_property_float_get_default_array_values(ptr, fprop, values);
3376   }
3377 }
3378
3379 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
3380 {
3381   float tmp[RNA_MAX_ARRAY_LENGTH];
3382   int len = rna_ensure_property_array_length(ptr, prop);
3383
3384   BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
3385   BLI_assert(RNA_property_array_check(prop) != false);
3386   BLI_assert(index >= 0);
3387   BLI_assert(index < len);
3388
3389   if (len <= RNA_MAX_ARRAY_LENGTH) {
3390     RNA_property_float_get_default_array(ptr, prop, tmp);
3391     return tmp[index];
3392   }
3393   else {
3394     float *tmparray, value;
3395
3396     tmparray = MEM_mallocN(sizeof(float) * len, __func__);
3397     RNA_property_float_get_default_array(ptr, prop, tmparray);
3398     value = tmparray[index];
3399     MEM_freeN(tmparray);
3400
3401     return value;
3402   }
3403 }
3404
3405 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
3406 {
3407   StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3408   IDProperty *idprop;
3409
3410   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3411
3412   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3413     /* editing bytes is not 100% supported
3414      * since they can contain NIL chars */
3415     if (idprop->subtype == IDP_STRING_SUB_BYTE) {
3416       memcpy(value, IDP_String(idprop), idprop->len);
3417       value[idprop->len] = '\0';
3418     }
3419     else {
3420       memcpy(value, IDP_String(idprop), idprop->len);
3421     }
3422   }
3423   else if (sprop->get) {
3424     sprop->get(ptr, value);
3425   }
3426   else if (sprop->get_ex) {
3427     sprop->get_ex(ptr, prop, value);
3428   }
3429   else {
3430     strcpy(value, sprop->defaultvalue);
3431   }
3432 }
3433
3434 char *RNA_property_string_get_alloc(
3435     PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
3436 {
3437   char *buf;
3438   int length;
3439
3440   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3441
3442   length = RNA_property_string_length(ptr, prop);
3443
3444   if (length + 1 < fixedlen) {
3445     buf = fixedbuf;
3446   }
3447   else {
3448     buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
3449   }
3450
3451 #ifndef NDEBUG
3452   /* safety check to ensure the string is actually set */
3453   buf[length] = 255;
3454 #endif
3455
3456   RNA_property_string_get(ptr, prop, buf);
3457
3458 #ifndef NDEBUG
3459   BLI_assert(buf[length] == '\0');
3460 #endif
3461
3462   if (r_len) {
3463     *r_len = length;
3464   }
3465
3466   return buf;
3467 }
3468
3469 /* this is the length without \0 terminator */
3470 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
3471 {
3472   StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3473   IDProperty *idprop;
3474
3475   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3476
3477   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3478     if (idprop->subtype == IDP_STRING_SUB_BYTE) {
3479       return idprop->len;
3480     }
3481     else {
3482 #ifndef NDEBUG
3483       /* these _must_ stay in sync */
3484       BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
3485 #endif
3486       return idprop->len - 1;
3487     }
3488   }
3489   else if (sprop->length) {
3490     return sprop->length(ptr);
3491   }
3492   else if (sprop->length_ex) {
3493     return sprop->length_ex(ptr, prop);
3494   }
3495   else {
3496     return strlen(sprop->defaultvalue);
3497   }
3498 }
3499
3500 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
3501 {
3502   StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3503   IDProperty *idprop;
3504
3505   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3506
3507   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3508     /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
3509     IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
3510     rna_idproperty_touch(idprop);
3511   }
3512   else if (sprop->set) {
3513     sprop->set(ptr, value); /* set function needs to clamp its self */
3514   }
3515   else if (sprop->set_ex) {
3516     sprop->set_ex(ptr, prop, value); /* set function needs to clamp its self */
3517   }
3518   else if (prop->flag & PROP_EDITABLE) {
3519     IDProperty *group;
3520
3521     group = RNA_struct_idprops(ptr, 1);
3522     if (group) {
3523       IDP_AddToGroup(group,
3524                      IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop)));
3525     }
3526   }
3527 }
3528
3529 void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const char *value, int len)
3530 {
3531   StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3532   IDProperty *idprop;
3533
3534   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3535   BLI_assert(RNA_property_subtype(prop) == PROP_BYTESTRING);
3536
3537   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3538     IDP_ResizeArray(idprop, len);
3539     memcpy(idprop->data.pointer, value, (size_t)len);
3540
3541     rna_idproperty_touch(idprop);
3542   }
3543   else if (sprop->set) {
3544     /* XXX, should take length argument (currently not used). */
3545     sprop->set(ptr, value); /* set function needs to clamp its self */
3546   }
3547   else if (sprop->set_ex) {
3548     /* XXX, should take length argument (currently not used). */
3549     sprop->set_ex(ptr, prop, value); /* set function needs to clamp its self */
3550   }
3551   else if (prop->flag & PROP_EDITABLE) {
3552     IDProperty *group;
3553
3554     group = RNA_struct_idprops(ptr, 1);
3555     if (group) {
3556       IDPropertyTemplate val = {0};
3557       val.string.str = value;
3558       val.string.len = len;
3559       val.string.subtype = IDP_STRING_SUB_BYTE;
3560       IDP_AddToGroup(group, IDP_New(IDP_STRING, &val, prop->identifier));
3561     }
3562   }
3563 }
3564
3565 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
3566 {
3567   StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
3568
3569   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3570
3571   strcpy(value, sprop->defaultvalue);
3572 }
3573
3574 char *RNA_property_string_get_default_alloc(PointerRNA *ptr,
3575                                             PropertyRNA *prop,
3576                                             char *fixedbuf,
3577                                             int fixedlen)
3578 {
3579   char *buf;
3580   int length;
3581
3582   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3583
3584   length = RNA_property_string_default_length(ptr, prop);
3585
3586   if (length + 1 < fixedlen) {
3587     buf = fixedbuf;
3588   }
3589   else {
3590     buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
3591   }
3592
3593   RNA_property_string_get_default(ptr, prop, buf);
3594
3595   return buf;
3596 }
3597
3598 /* this is the length without \0 terminator */
3599 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3600 {
3601   StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3602
3603   BLI_assert(RNA_property_type(prop) == PROP_STRING);
3604
3605   return strlen(sprop->defaultvalue);
3606 }
3607
3608 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
3609 {
3610   EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3611   IDProperty *idprop;
3612
3613   BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3614
3615   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3616     return IDP_Int(idprop);
3617   }
3618   else if (eprop->get) {
3619     return eprop->get(ptr);
3620   }
3621   else if (eprop->get_ex) {
3622     return eprop->get_ex(ptr, prop);
3623   }
3624   else {
3625     return eprop->defaultvalue;
3626   }
3627 }
3628
3629 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
3630 {
3631   EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3632   IDProperty *idprop;
3633
3634   BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3635
3636   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3637     IDP_Int(idprop) = value;
3638     rna_idproperty_touch(idprop);
3639   }
3640   else if (eprop->set) {
3641     eprop->set(ptr, value);
3642   }
3643   else if (eprop->set_ex) {
3644     eprop->set_ex(ptr, prop, value);
3645   }
3646   else if (prop->flag & PROP_EDITABLE) {
3647     IDPropertyTemplate val = {0};
3648     IDProperty *group;
3649
3650     val.i = value;
3651
3652     group = RNA_struct_idprops(ptr, 1);
3653     if (group) {
3654       IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
3655     }
3656   }
3657 }
3658
3659 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3660 {
3661   EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
3662
3663   BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3664
3665   return eprop->defaultvalue;
3666 }
3667
3668 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
3669 {
3670   EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3671
3672   BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3673
3674   return eprop->py_data;
3675 }
3676
3677 /**
3678  * Get the value of the item that is \a step items away from \a from_value.
3679  *
3680  * \param from_value: Item value to start stepping from.
3681  * \param step: Absolute value defines step size, sign defines direction.
3682  *              E.g to get the next item, pass 1, for the previous -1.
3683  */
3684 int RNA_property_enum_step(
3685     const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
3686 {
3687   const EnumPropertyItem *item_array;
3688   int totitem;
3689   bool free;
3690   int result_value = from_value;
3691   int i, i_init;
3692   int single_step = (step < 0) ? -1 : 1;
3693   int step_tot = 0;
3694
3695   RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
3696   i = RNA_enum_from_value(item_array, from_value);
3697   i_init = i;
3698
3699   do {
3700     i = mod_i(i + single_step, totitem);
3701     if (item_array[i].identifier[0]) {
3702       step_tot += single_step;
3703     }
3704   } while ((i != i_init) && (step_tot != step));
3705
3706   if (i != i_init) {
3707     result_value = item_array[i].value;
3708   }
3709
3710   if (free) {
3711     MEM_freeN((void *)item_array);
3712   }
3713
3714   return result_value;
3715 }
3716
3717 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
3718 {
3719   PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3720   IDProperty *idprop;
3721
3722   BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3723
3724   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3725     pprop = (PointerPropertyRNA *)prop;
3726
3727     if (RNA_struct_is_ID(pprop->type)) {
3728       return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop));
3729     }
3730
3731     /* for groups, data is idprop itself */
3732     if (pprop->typef) {
3733       return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
3734     }
3735     else {
3736       return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
3737     }
3738   }
3739   else if (pprop->get) {
3740     return pprop->get(ptr);
3741   }
3742   else if (prop->flag & PROP_IDPROPERTY) {
3743     /* XXX temporary hack to add it automatically, reading should
3744      * never do any write ops, to ensure thread safety etc .. */
3745     RNA_property_pointer_add(ptr, prop);
3746     return RNA_property_pointer_get(ptr, prop);
3747   }
3748   else {
3749     return PointerRNA_NULL;
3750   }
3751 }
3752
3753 void RNA_property_pointer_set(PointerRNA *ptr,
3754                               PropertyRNA *prop,
3755                               PointerRNA ptr_value,
3756                               ReportList *reports)
3757 {
3758   PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3759   BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3760
3761   /* Check types */
3762   if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
3763     BKE_reportf(reports,
3764                 RPT_ERROR,
3765                 "%s: expected %s type, not %s.\n",
3766                 __func__,
3767                 pprop->type->identifier,
3768                 ptr_value.type->identifier);
3769     return;
3770   }
3771
3772   /* RNA */
3773   if (pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
3774       !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) {
3775     pprop->set(ptr, ptr_value, reports);
3776   }
3777   /* IDProperty */
3778   else if (prop->flag & PROP_EDITABLE) {
3779     IDPropertyTemplate val = {0};
3780     IDProperty *group;
3781
3782     val.id = ptr_value.data;
3783
3784     group = RNA_struct_idprops(ptr, true);
3785     if (group) {
3786       IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier));
3787     }
3788   }
3789 }
3790
3791 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
3792 {
3793   /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
3794
3795   /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
3796
3797   return PointerRNA_NULL; /* FIXME: there has to be a way... */
3798 }
3799
3800 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
3801 {
3802   /*IDProperty *idprop;*/
3803
3804   BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3805
3806   if ((/*idprop=*/rna_idproperty_check(&prop, ptr))) {
3807     /* already exists */
3808   }
3809   else if (prop->flag & PROP_IDPROPERTY) {
3810     IDPropertyTemplate val = {0};
3811     IDProperty *group;
3812
3813     val.i = 0;
3814
3815     group = RNA_struct_idprops(ptr, 1);
3816     if (group) {
3817       IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
3818     }
3819   }
3820   else {
3821     printf("%s %s.%s: only supported for id properties.\n",
3822            __func__,
3823            ptr->type->identifier,
3824            prop->identifier);
3825   }
3826 }
3827
3828 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
3829 {
3830   IDProperty *idprop, *group;
3831
3832   BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3833
3834   if ((idprop = rna_idproperty_check(&prop, ptr))) {
3835     group = RNA_struct_idprops(ptr, 0);
3836
3837     if (group) {
3838       IDP_FreeFromGroup(group, idprop);
3839     }
3840   }
3841   else {
3842     printf("%s %s.%s: only supported for id properties.\n",
3843            __func__,
3844            ptr->type->identifier,
3845            prop->identifier);
3846   }
3847 }
3848
3849 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
3850 {
3851   CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
3852
3853   iter->ptr.data = rna_iterator_array_get(iter);
3854   iter->ptr.type = cprop->item_type;
3855   rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
3856 }
3857
3858 void RNA_property_collection_begin(PointerRNA *ptr,
3859                                    PropertyRNA *prop,
3860                                    CollectionPropertyIterator *iter)
3861 {
3862   IDProperty *idprop;
3863
3864   BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);<