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