87c991424a795d9bb76355fa2d532f60e3da9cf1
[blender.git] / source / blender / makesrna / intern / rna_access.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Foundation (2008).
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/makesrna/intern/rna_access.c
24  *  \ingroup RNA
25  */
26
27
28 #include <stdlib.h>
29 #include <stddef.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_ID.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_windowmanager_types.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_dynstr.h"
42 #include "BLI_ghash.h"
43 #include "BLI_math.h"
44
45 #include "BLF_api.h"
46 #include "BLF_translation.h"
47
48 #include "BKE_animsys.h"
49 #include "BKE_context.h"
50 #include "BKE_idcode.h"
51 #include "BKE_idprop.h"
52 #include "BKE_main.h"
53 #include "BKE_report.h"
54
55
56 #include "WM_api.h"
57
58 #include "RNA_access.h"
59 #include "RNA_define.h"
60
61 /* flush updates */
62 #include "DNA_object_types.h"
63 #include "BKE_depsgraph.h"
64 #include "WM_types.h"
65
66 #include "rna_internal.h"
67
68 const PointerRNA PointerRNA_NULL = {{NULL}};
69
70 /* Init/Exit */
71
72 void RNA_init(void)
73 {
74         StructRNA *srna;
75         PropertyRNA *prop;
76
77         for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
78                 if (!srna->cont.prophash) {
79                         srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
80
81                         for (prop = srna->cont.properties.first; prop; prop = prop->next)
82                                 if (!(prop->flag & PROP_BUILTIN))
83                                         BLI_ghash_insert(srna->cont.prophash, (void *)prop->identifier, prop);
84                 }
85         }
86 }
87
88 void RNA_exit(void)
89 {
90         StructRNA *srna;
91         
92         RNA_property_update_cache_free();
93         
94         for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
95                 if (srna->cont.prophash) {
96                         BLI_ghash_free(srna->cont.prophash, NULL, NULL);
97                         srna->cont.prophash = NULL;
98                 }
99         }
100
101         RNA_free(&BLENDER_RNA);
102 }
103
104 /* Pointer */
105
106 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
107 {
108         r_ptr->id.data = NULL;
109         r_ptr->type = &RNA_BlendData;
110         r_ptr->data = main;
111 }
112
113 void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
114 {
115         StructRNA *type, *idtype = NULL;
116
117         if (id) {
118                 PointerRNA tmp = {{NULL}};
119                 tmp.data = id;
120                 idtype = rna_ID_refine(&tmp);
121                 
122                 while (idtype->refine) {
123                         type = idtype->refine(&tmp);
124
125                         if (type == idtype)
126                                 break;
127                         else
128                                 idtype = type;
129                 }
130         }
131         
132         r_ptr->id.data = id;
133         r_ptr->type = idtype;
134         r_ptr->data = id;
135 }
136
137 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
138 {
139 #if 0 /* UNUSED */
140         StructRNA *idtype = NULL;
141
142         if (id) {
143                 PointerRNA tmp = {{0}};
144                 tmp.data = id;
145                 idtype = rna_ID_refine(&tmp);
146         }
147 #endif
148
149         r_ptr->id.data = id;
150         r_ptr->type = type;
151         r_ptr->data = data;
152
153         if (data) {
154                 while (r_ptr->type && r_ptr->type->refine) {
155                         StructRNA *rtype = r_ptr->type->refine(r_ptr);
156
157                         if (rtype == r_ptr->type)
158                                 break;
159                         else
160                                 r_ptr->type = rtype;
161                 }
162         }
163 }
164
165 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
166 {
167         if (type && type->flag & STRUCT_ID) {
168                 ptr->id.data = ptr->data;
169         }
170         else {
171                 ptr->id.data = parent->id.data;
172         }
173 }
174
175 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
176 {
177         r_ptr->id.data = NULL;
178         r_ptr->type = &RNA_BlenderRNA;
179         r_ptr->data = &BLENDER_RNA;
180 }
181
182 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
183 {
184         if (data) {
185                 PointerRNA result;
186                 result.data = data;
187                 result.type = type;
188                 rna_pointer_inherit_id(type, ptr, &result);
189
190                 while (result.type->refine) {
191                         type = result.type->refine(&result);
192
193                         if (type == result.type)
194                                 break;
195                         else
196                                 result.type = type;
197                 }
198                 return result;
199         }
200         else {
201                 return PointerRNA_NULL;
202         }
203 }
204
205 /**/
206 void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
207 {
208 #if 0 /* works but this case if covered by more general code below. */
209         if (RNA_struct_is_ID(ptr->type)) {
210                 /* simple case */
211                 RNA_id_pointer_create(ptr->id.data, r_ptr);
212         }
213         else
214 #endif
215         {
216                 StructRNA *base;
217                 PointerRNA t_ptr;
218                 *r_ptr = *ptr; /* initialize as the same in case cant recast */
219
220                 for (base = ptr->type->base; base; base = base->base) {
221                         t_ptr = rna_pointer_inherit_refine(ptr, base, ptr->data);
222                         if (t_ptr.type && t_ptr.type != ptr->type) {
223                                 *r_ptr = t_ptr;
224                         }
225                 }
226         }
227 }
228
229 /* ID Properties */
230
231 static void rna_idproperty_touch(IDProperty *idprop)
232 {
233         /* so the property is seen as 'set' by rna */
234         idprop->flag &= ~IDP_FLAG_GHOST;
235 }
236
237 /* return a UI local ID prop definition for this prop */
238 static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
239 {
240         IDProperty *idprop;
241
242         for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
243                 if (strcmp(RNA_IDP_UI, idprop->name) == 0)
244                         break;
245         }
246
247         if (idprop == NULL) {
248                 for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
249                         if (strcmp(RNA_IDP_UI, idprop->name) == 0)
250                                 break;
251                 }
252         }
253
254         if (idprop) {
255                 return IDP_GetPropertyTypeFromGroup(idprop, ((IDProperty *)prop)->name, IDP_GROUP);
256         }
257
258         return NULL;
259 }
260
261 IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create)
262 {
263         StructRNA *type = ptr->type;
264
265         if (type && type->idproperties)
266                 return type->idproperties(ptr, create);
267         
268         return NULL;
269 }
270
271 int RNA_struct_idprops_check(StructRNA *srna)
272 {
273         return (srna && srna->idproperties) ? 1 : 0;
274 }
275
276 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
277 {
278         IDProperty *group = RNA_struct_idprops(ptr, 0);
279
280         if (group)
281                 return IDP_GetPropertyFromGroup(group, name);
282
283         return NULL;
284 }
285
286 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
287 {
288         if (prop->magic == RNA_MAGIC) {
289                 int arraylen[RNA_MAX_ARRAY_DIMENSION];
290                 return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) : prop->totarraylength;
291         }
292         else {
293                 IDProperty *idprop = (IDProperty *)prop;
294
295                 if (idprop->type == IDP_ARRAY)
296                         return idprop->len;
297                 else
298                         return 0;
299         }
300 }
301
302 static int rna_ensure_property_array_check(PropertyRNA *prop)
303 {
304         if (prop->magic == RNA_MAGIC) {
305                 return (prop->getlength || prop->totarraylength) ? 1 : 0;
306         }
307         else {
308                 IDProperty *idprop = (IDProperty *)prop;
309
310                 return idprop->type == IDP_ARRAY ? 1 : 0;
311         }
312 }
313
314 static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int length[])
315 {
316         if (prop->magic == RNA_MAGIC) {
317                 if (prop->getlength)
318                         prop->getlength(ptr, length);
319                 else
320                         memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
321         }
322         else {
323                 IDProperty *idprop = (IDProperty *)prop;
324
325                 if (idprop->type == IDP_ARRAY)
326                         length[0] = idprop->len;
327                 else
328                         length[0] = 0;
329         }
330 }
331
332 static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
333 {
334         /* this verifies if the idproperty actually matches the property
335          * description and otherwise removes it. this is to ensure that
336          * rna property access is type safe, e.g. if you defined the rna
337          * to have a certain array length you can count on that staying so */
338         
339         switch (idprop->type) {
340                 case IDP_IDPARRAY:
341                         if (prop->type != PROP_COLLECTION)
342                                 return 0;
343                         break;
344                 case IDP_ARRAY:
345                         if (rna_ensure_property_array_length(ptr, prop) != idprop->len)
346                                 return 0;
347
348                         if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
349                                 return 0;
350                         if (idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
351                                 return 0;
352
353                         break;
354                 case IDP_INT:
355                         if (!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
356                                 return 0;
357                         break;
358                 case IDP_FLOAT:
359                 case IDP_DOUBLE:
360                         if (prop->type != PROP_FLOAT)
361                                 return 0;
362                         break;
363                 case IDP_STRING:
364                         if (prop->type != PROP_STRING)
365                                 return 0;
366                         break;
367                 case IDP_GROUP:
368                         if (prop->type != PROP_POINTER)
369                                 return 0;
370                         break;
371                 default:
372                         return 0;
373         }
374
375         return 1;
376 }
377
378 static PropertyRNA *typemap[IDP_NUMTYPES] = {
379         (PropertyRNA *)&rna_PropertyGroupItem_string,
380         (PropertyRNA *)&rna_PropertyGroupItem_int,
381         (PropertyRNA *)&rna_PropertyGroupItem_float,
382         NULL, NULL, NULL,
383         (PropertyRNA *)&rna_PropertyGroupItem_group, NULL,
384         (PropertyRNA *)&rna_PropertyGroupItem_double,
385         (PropertyRNA *)&rna_PropertyGroupItem_idp_array
386 };
387
388 static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
389         NULL, (PropertyRNA *)&rna_PropertyGroupItem_int_array,
390         (PropertyRNA *)&rna_PropertyGroupItem_float_array,
391         NULL, NULL, NULL,
392         (PropertyRNA *)&rna_PropertyGroupItem_collection, NULL,
393         (PropertyRNA *)&rna_PropertyGroupItem_double_array
394 };
395
396 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
397 {
398         /* This is quite a hack, but avoids some complexity in the API. we
399          * pass IDProperty structs as PropertyRNA pointers to the outside.
400          * We store some bytes in PropertyRNA structs that allows us to
401          * distinguish it from IDProperty structs. If it is an ID property,
402          * we look up an IDP PropertyRNA based on the type, and set the data
403          * pointer to the IDProperty. */
404
405         if ((*prop)->magic == RNA_MAGIC) {
406                 if ((*prop)->flag & PROP_IDPROPERTY) {
407                         IDProperty *idprop = rna_idproperty_find(ptr, (*prop)->identifier);
408
409                         if (idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) {
410                                 IDProperty *group = RNA_struct_idprops(ptr, 0);
411
412                                 IDP_RemFromGroup(group, idprop);
413                                 IDP_FreeProperty(idprop);
414                                 MEM_freeN(idprop);
415                                 return NULL;
416                         }
417
418                         return idprop;
419                 }
420                 else
421                         return NULL;
422         }
423
424         {
425                 IDProperty *idprop = (IDProperty *)(*prop);
426
427                 if (idprop->type == IDP_ARRAY)
428                         *prop = arraytypemap[(int)(idprop->subtype)];
429                 else
430                         *prop = typemap[(int)(idprop->type)];
431
432                 return idprop;
433         }
434 }
435
436 static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
437 {
438         /* the quick version if we don't need the idproperty */
439
440         if (prop->magic == RNA_MAGIC)
441                 return prop;
442
443         {
444                 IDProperty *idprop = (IDProperty *)prop;
445
446                 if (idprop->type == IDP_ARRAY)
447                         return arraytypemap[(int)(idprop->subtype)];
448                 else
449                         return typemap[(int)(idprop->type)];
450         }
451 }
452
453 static const char *rna_ensure_property_identifier(PropertyRNA *prop)
454 {
455         if (prop->magic == RNA_MAGIC)
456                 return prop->identifier;
457         else
458                 return ((IDProperty *)prop)->name;
459 }
460
461 static const char *rna_ensure_property_description(PropertyRNA *prop)
462 {
463         const char *description = NULL;
464
465         if (prop->magic == RNA_MAGIC)
466                 description = prop->description;
467         else {
468                 /* attempt to get the local ID values */
469                 IDProperty *idp_ui = rna_idproperty_ui(prop);
470
471                 if (idp_ui) {
472                         IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "description", IDP_STRING);
473                         if (item)
474                                 description = IDP_String(item);
475                 }
476
477                 if (description == NULL)
478                         description = ((IDProperty *)prop)->name;  /* XXX - not correct */
479         }
480
481         return TIP_(description);
482 }
483
484 static const char *rna_ensure_property_name(PropertyRNA *prop)
485 {
486         const char *name;
487
488         if (prop->magic == RNA_MAGIC)
489                 name = prop->name;
490         else
491                 name = ((IDProperty *)prop)->name;
492
493         return CTX_IFACE_(prop->translation_context, name);
494 }
495
496 /* Structs */
497
498 StructRNA *RNA_struct_find(const char *identifier)
499 {
500         StructRNA *type;
501         if (identifier) {
502                 for (type = BLENDER_RNA.structs.first; type; type = type->cont.next)
503                         if (strcmp(type->identifier, identifier) == 0)
504                                 return type;
505         }
506         return NULL;
507 }
508
509 const char *RNA_struct_identifier(StructRNA *type)
510 {
511         return type->identifier;
512 }
513
514 const char *RNA_struct_ui_name(StructRNA *type)
515 {
516         return CTX_IFACE_(type->translation_context, type->name);
517 }
518
519 int RNA_struct_ui_icon(StructRNA *type)
520 {
521         if (type)
522                 return type->icon;
523         else
524                 return ICON_DOT;
525 }
526
527 const char *RNA_struct_ui_description(StructRNA *type)
528 {
529         return TIP_(type->description);
530 }
531
532 const char *RNA_struct_translation_context(StructRNA *type)
533 {
534         return type->translation_context ? type->translation_context : BLF_I18NCONTEXT_DEFAULT;
535 }
536
537 PropertyRNA *RNA_struct_name_property(StructRNA *type)
538 {
539         return type->nameproperty;
540 }
541
542 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
543 {
544         return type->iteratorproperty;
545 }
546
547 StructRNA *RNA_struct_base(StructRNA *type)
548 {
549         return type->base;
550 }
551
552 int RNA_struct_is_ID(StructRNA *type)
553 {
554         return (type->flag & STRUCT_ID) != 0;
555 }
556
557 int RNA_struct_undo_check(StructRNA *type)
558 {
559         return (type->flag & STRUCT_UNDO) != 0;
560 }
561
562 int RNA_struct_idprops_register_check(StructRNA *type)
563 {
564         return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
565 }
566
567 /* remove an id-property */
568 int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
569 {
570         IDProperty *group = RNA_struct_idprops(ptr, 0);
571
572         if (group) {
573                 IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
574                 if (idp) {
575                         IDP_RemFromGroup(group, idp);
576                         IDP_FreeProperty(idp);
577                         MEM_freeN(idp);
578
579                         return 1;
580                 }
581         }
582         return 0;
583 }
584
585 int RNA_struct_is_a(StructRNA *type, StructRNA *srna)
586 {
587         StructRNA *base;
588
589         if (!type)
590                 return 0;
591
592         /* ptr->type is always maximally refined */
593         for (base = type; base; base = base->base)
594                 if (base == srna)
595                         return 1;
596         
597         return 0;
598 }
599
600 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
601 {
602         if (identifier[0] == '[' && identifier[1] == '"') { /* "  (dummy comment to avoid confusing some
603                                                                  * function lists in text editors) */
604                 /* id prop lookup, not so common */
605                 PropertyRNA *r_prop = NULL;
606                 PointerRNA r_ptr; /* only support single level props */
607                 if (RNA_path_resolve(ptr, identifier, &r_ptr, &r_prop) && r_ptr.type == ptr->type && r_ptr.data == ptr->data)
608                         return r_prop;
609         }
610         else {
611                 /* most common case */
612                 PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
613                 PointerRNA propptr;
614
615                 if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr))
616                         return propptr.data;
617         }
618         
619         return NULL;
620 }
621
622 /* Find the property which uses the given nested struct */
623 static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
624 {
625         PropertyRNA *prop = NULL;
626
627         RNA_STRUCT_BEGIN(ptr, iprop)
628         {
629                 /* This assumes that there can only be one user of this nested struct */
630                 if (RNA_property_pointer_type(ptr, iprop) == srna) {
631                         prop = iprop;
632                         break;
633                 }
634         }
635         RNA_PROP_END;
636
637         return prop;
638 }
639
640 int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
641 {
642         /* note, prop_test could be freed memory, only use for comparison */
643
644         /* validate the RNA is ok */
645         PropertyRNA *iterprop;
646         int found = FALSE;
647
648         iterprop = RNA_struct_iterator_property(ptr->type);
649
650         RNA_PROP_BEGIN(ptr, itemptr, iterprop)
651         {
652                 /* PropertyRNA *prop = itemptr.data; */
653                 if (prop_test == (PropertyRNA *)itemptr.data) {
654                         found = TRUE;
655                         break;
656                 }
657         }
658         RNA_PROP_END;
659
660         return found;
661 }
662
663 /* low level direct access to type->properties, note this ignores parent classes so should be used with care */
664 const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
665 {
666         return &srna->cont.properties;
667 }
668
669 PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
670 {
671         return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
672 }
673
674 FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
675 {
676 #if 1
677         FunctionRNA *func;
678         StructRNA *type;
679         for (type = srna; type; type = type->base) {
680                 func = (FunctionRNA *)BLI_findstring_ptr(&type->functions, identifier, offsetof(FunctionRNA, identifier));
681                 if (func) {
682                         return func;
683                 }
684         }
685         return NULL;
686
687         /* funcitonal but slow */
688 #else
689         PointerRNA tptr;
690         PropertyRNA *iterprop;
691         FunctionRNA *func;
692
693         RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr);
694         iterprop = RNA_struct_find_property(&tptr, "functions");
695
696         func = NULL;
697
698         RNA_PROP_BEGIN(&tptr, funcptr, iterprop)
699         {
700                 if (strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
701                         func = funcptr.data;
702                         break;
703                 }
704         }
705         RNA_PROP_END;
706
707         return func;
708 #endif
709 }
710
711 const ListBase *RNA_struct_type_functions(StructRNA *srna)
712 {
713         return &srna->functions;
714 }
715
716 StructRegisterFunc RNA_struct_register(StructRNA *type)
717 {
718         return type->reg;
719 }
720
721 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
722 {
723         do {
724                 if (type->unreg)
725                         return type->unreg;
726         } while ((type = type->base));
727
728         return NULL;
729 }
730
731 void **RNA_struct_instance(PointerRNA *ptr)
732 {
733         StructRNA *type = ptr->type;
734
735         do {
736                 if (type->instance)
737                         return type->instance(ptr);
738         } while ((type = type->base));
739
740         return NULL;
741 }
742
743 void *RNA_struct_py_type_get(StructRNA *srna)
744 {
745         return srna->py_type;
746 }
747
748 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
749 {
750         srna->py_type = py_type;
751 }
752
753 void *RNA_struct_blender_type_get(StructRNA *srna)
754 {
755         return srna->blender_type;
756 }
757
758 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
759 {
760         srna->blender_type = blender_type;
761 }
762
763 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
764 {
765         PropertyRNA *nameprop;
766
767         if (ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
768                 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
769
770         return NULL;
771 }
772
773 /* Property Information */
774
775 const char *RNA_property_identifier(PropertyRNA *prop)
776 {
777         return rna_ensure_property_identifier(prop);
778 }
779
780 const char *RNA_property_description(PropertyRNA *prop)
781 {
782         return rna_ensure_property_description(prop);
783 }
784
785 PropertyType RNA_property_type(PropertyRNA *prop)
786 {
787         return rna_ensure_property(prop)->type;
788 }
789
790 PropertySubType RNA_property_subtype(PropertyRNA *prop)
791 {
792         return rna_ensure_property(prop)->subtype;
793 }
794
795 PropertyUnit RNA_property_unit(PropertyRNA *prop)
796 {
797         return RNA_SUBTYPE_UNIT(rna_ensure_property(prop)->subtype);
798 }
799
800 int RNA_property_flag(PropertyRNA *prop)
801 {
802         return rna_ensure_property(prop)->flag;
803 }
804
805 void *RNA_property_py_data_get(PropertyRNA *prop)
806 {
807         return prop->py_data;
808 }
809
810 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
811 {
812         return rna_ensure_property_array_length(ptr, prop);
813 }
814
815 int RNA_property_array_check(PropertyRNA *prop)
816 {
817         return rna_ensure_property_array_check(prop);
818 }
819
820 /* used by BPY to make an array from the python object */
821 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
822 {
823         PropertyRNA *rprop = rna_ensure_property(prop);
824
825         if (length)
826                 rna_ensure_property_multi_array_length(ptr, prop, length);
827
828         return rprop->arraydimension;
829 }
830
831 /* Return the size of Nth dimension. */
832 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
833 {
834         int len[RNA_MAX_ARRAY_DIMENSION];
835
836         rna_ensure_property_multi_array_length(ptr, prop, len);
837
838         return len[dim];
839 }
840
841 char RNA_property_array_item_char(PropertyRNA *prop, int index)
842 {
843         const char *vectoritem = "XYZW";
844         const char *quatitem = "WXYZ";
845         const char *coloritem = "RGBA";
846         PropertySubType subtype = rna_ensure_property(prop)->subtype;
847
848         BLI_assert(index >= 0);
849
850         /* get string to use for array index */
851         if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
852                 return quatitem[index];
853         }
854         else if ((index < 4) && ELEM8(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
855                                       PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
856         {
857                 return vectoritem[index];
858         }
859         else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
860                 return coloritem[index];
861         }
862
863         return '\0';
864 }
865
866 int RNA_property_array_item_index(PropertyRNA *prop, char name)
867 {
868         PropertySubType subtype = rna_ensure_property(prop)->subtype;
869
870         /* get index based on string name/alias */
871         /* maybe a function to find char index in string would be better than all the switches */
872         if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
873                 switch (name) {
874                         case 'w':
875                                 return 0;
876                         case 'x':
877                                 return 1;
878                         case 'y':
879                                 return 2;
880                         case 'z':
881                                 return 3;
882                 }
883         }
884         else if (ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
885                        PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
886         {
887                 switch (name) {
888                         case 'x':
889                                 return 0;
890                         case 'y':
891                                 return 1;
892                         case 'z':
893                                 return 2;
894                         case 'w':
895                                 return 3;
896                 }
897         }
898         else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
899                 switch (name) {
900                         case 'r':
901                                 return 0;
902                         case 'g':
903                                 return 1;
904                         case 'b':
905                                 return 2;
906                         case 'a':
907                                 return 3;
908                 }
909         }
910
911         return -1;
912 }
913
914
915 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
916 {
917         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
918         int softmin, softmax;
919
920         if (prop->magic != RNA_MAGIC) {
921                 /* attempt to get the local ID values */
922                 IDProperty *idp_ui = rna_idproperty_ui(prop);
923
924                 if (idp_ui) {
925                         IDProperty *item;
926
927                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
928                         *hardmin = item ? IDP_Int(item) : INT_MIN;
929
930                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
931                         *hardmax = item ? IDP_Int(item) : INT_MAX;
932
933                         return;
934                 }
935         }
936
937         if (iprop->range) {
938                 *hardmin = INT_MIN;
939                 *hardmax = INT_MAX;
940
941                 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
942         }
943         else if (iprop->range_ex) {
944                 *hardmin = INT_MIN;
945                 *hardmax = INT_MAX;
946
947                 iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
948         }
949         else {
950                 *hardmin = iprop->hardmin;
951                 *hardmax = iprop->hardmax;
952         }
953 }
954
955 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
956 {
957         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
958         int hardmin, hardmax;
959         
960         if (prop->magic != RNA_MAGIC) {
961                 /* attempt to get the local ID values */
962                 IDProperty *idp_ui = rna_idproperty_ui(prop);
963
964                 if (idp_ui) {
965                         IDProperty *item;
966
967                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
968                         *softmin = item ? IDP_Int(item) : INT_MIN;
969
970                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
971                         *softmax = item ? IDP_Int(item) : INT_MAX;
972
973                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
974                         *step = item ? IDP_Int(item) : 1;
975
976                         return;
977                 }
978         }
979
980         *softmin = iprop->softmin;
981         *softmax = iprop->softmax;
982
983         if (iprop->range) {
984                 hardmin = INT_MIN;
985                 hardmax = INT_MAX;
986
987                 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
988
989                 *softmin = max_ii(*softmin, hardmin);
990                 *softmax = min_ii(*softmax, hardmax);
991         }
992         else if (iprop->range_ex) {
993                 hardmin = INT_MIN;
994                 hardmax = INT_MAX;
995
996                 iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
997
998                 *softmin = max_ii(*softmin, hardmin);
999                 *softmax = min_ii(*softmax, hardmax);
1000         }
1001
1002         *step = iprop->step;
1003 }
1004
1005 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1006 {
1007         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1008         float softmin, softmax;
1009
1010         if (prop->magic != RNA_MAGIC) {
1011                 /* attempt to get the local ID values */
1012                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1013
1014                 if (idp_ui) {
1015                         IDProperty *item;
1016
1017                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
1018                         *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1019
1020                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1021                         *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1022
1023                         return;
1024                 }
1025         }
1026
1027         if (fprop->range) {
1028                 *hardmin = -FLT_MAX;
1029                 *hardmax = FLT_MAX;
1030
1031                 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1032         }
1033         else if (fprop->range_ex) {
1034                 *hardmin = -FLT_MAX;
1035                 *hardmax = FLT_MAX;
1036
1037                 fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1038         }
1039         else {
1040                 *hardmin = fprop->hardmin;
1041                 *hardmax = fprop->hardmax;
1042         }
1043 }
1044
1045 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax,
1046                                  float *step, float *precision)
1047 {
1048         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1049         float hardmin, hardmax;
1050
1051         if (prop->magic != RNA_MAGIC) {
1052                 /* attempt to get the local ID values */
1053                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1054
1055                 if (idp_ui) {
1056                         IDProperty *item;
1057
1058                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1059                         *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1060
1061                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1062                         *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1063
1064                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1065                         *step = item ? (float)IDP_Double(item) : 1.0f;
1066
1067                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1068                         *precision = item ? (float)IDP_Double(item) : 3.0f;
1069
1070                         return;
1071                 }
1072         }
1073
1074         *softmin = fprop->softmin;
1075         *softmax = fprop->softmax;
1076
1077         if (fprop->range) {
1078                 hardmin = -FLT_MAX;
1079                 hardmax = FLT_MAX;
1080
1081                 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1082
1083                 *softmin = max_ff(*softmin, hardmin);
1084                 *softmax = min_ff(*softmax, hardmax);
1085         }
1086         else if (fprop->range_ex) {
1087                 hardmin = -FLT_MAX;
1088                 hardmax = FLT_MAX;
1089
1090                 fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1091
1092                 *softmin = max_ff(*softmin, hardmin);
1093                 *softmax = min_ff(*softmax, hardmax);
1094         }
1095
1096         *step = fprop->step;
1097         *precision = (float)fprop->precision;
1098 }
1099
1100 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1101 {
1102         float min, max;
1103
1104         RNA_property_float_range(ptr, prop, &min, &max);
1105
1106         if (*value < min) {
1107                 *value = min;
1108                 return -1;
1109         }
1110         else if (*value > max) {
1111                 *value = max;
1112                 return 1;
1113         }
1114         else {
1115                 return 0;
1116         }
1117 }
1118
1119 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1120 {
1121         int min, max;
1122
1123         RNA_property_int_range(ptr, prop, &min, &max);
1124
1125         if (*value < min) {
1126                 *value = min;
1127                 return -1;
1128         }
1129         else if (*value > max) {
1130                 *value = max;
1131                 return 1;
1132         }
1133         else {
1134                 return 0;
1135         }
1136 }
1137
1138 /* this is the max length including \0 terminator.
1139  * '0' used when their is no maximum */
1140 int RNA_property_string_maxlength(PropertyRNA *prop)
1141 {
1142         StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1143         return sprop->maxlength;
1144 }
1145
1146 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1147 {
1148         prop = rna_ensure_property(prop);
1149
1150         if (prop->type == PROP_POINTER) {
1151                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1152
1153                 if (pprop->typef)
1154                         return pprop->typef(ptr);
1155                 else if (pprop->type)
1156                         return pprop->type;
1157         }
1158         else if (prop->type == PROP_COLLECTION) {
1159                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1160
1161                 if (cprop->item_type)
1162                         return cprop->item_type;
1163         }
1164         /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1165
1166         return &RNA_UnknownType;
1167 }
1168
1169 int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1170 {
1171         prop = rna_ensure_property(prop);
1172
1173         if (prop->type == PROP_POINTER) {
1174                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1175                 if (pprop->poll)
1176                         return pprop->poll(ptr, *value);
1177
1178                 return 1;
1179         }
1180
1181         printf("%s %s: is not a pointer property.\n", __func__, prop->identifier);
1182         return 0;
1183 }
1184
1185 /* Reuse for dynamic types  */
1186 EnumPropertyItem DummyRNA_NULL_items[] = {
1187         {0, NULL, 0, NULL, NULL}
1188 };
1189
1190 /* Reuse for dynamic types with default value */
1191 EnumPropertyItem DummyRNA_DEFAULT_items[] = {
1192         {0, "DEFAULT", 0, "Default", ""},
1193         {0, NULL, 0, NULL, NULL}
1194 };
1195
1196 void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item,
1197                              int *totitem, int *free)
1198 {
1199         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1200
1201         *free = 0;
1202
1203         if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1204                 int tot = 0;
1205
1206                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1207                         *item = eprop->itemf(NULL, ptr, prop, free);
1208                 else
1209                         *item = eprop->itemf(C, ptr, prop, free);
1210
1211                 if (totitem) {
1212                         if (*item) {
1213                                 for (; (*item)[tot].identifier; tot++) ;
1214                         }
1215
1216                         *totitem = tot;
1217                 }
1218
1219         }
1220         else {
1221                 *item = eprop->item;
1222                 if (totitem)
1223                         *totitem = eprop->totitem;
1224         }
1225 }
1226
1227 void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1228                                        EnumPropertyItem **item, int *totitem, int *free)
1229 {
1230         RNA_property_enum_items(C, ptr, prop, item, totitem, free);
1231
1232 #ifdef WITH_INTERNATIONAL
1233         {
1234                 int i;
1235                 /* Note: Only do those tests once, and then use BLF_pgettext. */
1236                 int do_iface = BLF_translate_iface();
1237                 int do_tooltip = BLF_translate_tooltips();
1238                 EnumPropertyItem *nitem;
1239
1240                 if (!(do_iface || do_tooltip))
1241                         return;
1242
1243                 if (*free) {
1244                         nitem = *item;
1245                 }
1246                 else {
1247                         int totitem = 0;
1248
1249                         /* count */
1250                         for (i = 0; (*item)[i].identifier; i++)
1251                                 totitem++;
1252
1253                         nitem = MEM_callocN(sizeof(EnumPropertyItem) * (totitem + 1), "enum_items_gettexted");
1254
1255                         for (i = 0; (*item)[i].identifier; i++)
1256                                 nitem[i] = (*item)[i];
1257
1258                         *free = TRUE;
1259                 }
1260
1261                 for (i = 0; nitem[i].identifier; i++) {
1262                         if (nitem[i].name && do_iface) {
1263                                 /* note: prop->translation_context may be NULL, this just means we use the default "" context */
1264                                 nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name);
1265                         }
1266                         if (nitem[i].description && do_tooltip) {
1267                                 nitem[i].description = BLF_pgettext(NULL, nitem[i].description);
1268                         }
1269                 }
1270
1271                 *item = nitem;
1272         }
1273 #endif
1274 }
1275
1276
1277 int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
1278 {
1279         EnumPropertyItem *item, *item_array;
1280         int free, found;
1281
1282         RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free);
1283
1284         if (item_array) {
1285                 for (item = item_array; item->identifier; item++) {
1286                         if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
1287                                 *value = item->value;
1288                                 break;
1289                         }
1290                 }
1291
1292                 found = (item->identifier != NULL); /* could be alloc'd, assign before free */
1293
1294                 if (free) {
1295                         MEM_freeN(item_array);
1296                 }
1297         }
1298         else {
1299                 found = 0;
1300         }
1301         return found;
1302 }
1303
1304 int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier)
1305 {
1306         for (; item->identifier; item++) {
1307                 if (item->identifier[0] && item->value == value) {
1308                         *identifier = item->identifier;
1309                         return 1;
1310                 }
1311         }
1312         return 0;
1313 }
1314
1315 int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier)
1316 {
1317         int index = 0;
1318         for (; item->identifier; item++) {
1319                 if (item->identifier[0] && item->value & value) {
1320                         identifier[index++] = item->identifier;
1321                 }
1322         }
1323         identifier[index] = NULL;
1324         return index;
1325 }
1326
1327 int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name)
1328 {
1329         for (; item->identifier; item++) {
1330                 if (item->identifier[0] && item->value == value) {
1331                         *name = item->name;
1332                         return 1;
1333                 }
1334         }
1335         return 0;
1336 }
1337
1338 int RNA_enum_description(EnumPropertyItem *item, const int value, const char **description)
1339 {
1340         for (; item->identifier; item++) {
1341                 if (item->identifier[0] && item->value == value) {
1342                         *description = item->description;
1343                         return 1;
1344                 }
1345         }
1346         return 0;
1347 }
1348
1349 int RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1350                                  const char **identifier)
1351 {
1352         EnumPropertyItem *item = NULL;
1353         int result, free;
1354         
1355         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1356         if (item) {
1357                 result = RNA_enum_identifier(item, value, identifier);
1358                 if (free)
1359                         MEM_freeN(item);
1360
1361                 return result;
1362         }
1363         return 0;
1364 }
1365
1366 int RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1367 {
1368         EnumPropertyItem *item = NULL;
1369         int result, free;
1370         
1371         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1372         if (item) {
1373                 result = RNA_enum_name(item, value, name);
1374                 if (free)
1375                         MEM_freeN(item);
1376                 
1377                 return result;
1378         }
1379         return 0;
1380 }
1381
1382 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1383                                           const char **identifier)
1384 {
1385         EnumPropertyItem *item = NULL;
1386         int result, free;
1387
1388         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1389         if (item) {
1390                 result = RNA_enum_bitflag_identifiers(item, value, identifier);
1391                 if (free)
1392                         MEM_freeN(item);
1393
1394                 return result;
1395         }
1396         return 0;
1397 }
1398
1399 const char *RNA_property_ui_name(PropertyRNA *prop)
1400 {
1401         return rna_ensure_property_name(prop);
1402 }
1403
1404 const char *RNA_property_ui_description(PropertyRNA *prop)
1405 {
1406         return rna_ensure_property_description(prop);
1407 }
1408
1409 const char *RNA_property_translation_context(PropertyRNA *_prop)
1410 {
1411         PropertyRNA *prop = rna_ensure_property(_prop);
1412         return prop->translation_context ? prop->translation_context : BLF_I18NCONTEXT_DEFAULT;
1413 }
1414
1415 int RNA_property_ui_icon(PropertyRNA *prop)
1416 {
1417         return rna_ensure_property(prop)->icon;
1418 }
1419
1420 int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1421 {
1422         ID *id = ptr->id.data;
1423         int flag;
1424
1425         prop = rna_ensure_property(prop);
1426         flag = prop->editable ? prop->editable(ptr) : prop->flag;
1427         return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
1428 }
1429
1430 int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
1431 {
1432         int flag;
1433
1434         prop = rna_ensure_property(prop);
1435         flag = prop->editable ? prop->editable(ptr) : prop->flag;
1436         return (flag & PROP_EDITABLE);
1437 }
1438
1439 /* same as RNA_property_editable(), except this checks individual items in an array */
1440 int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1441 {
1442         ID *id;
1443         int flag;
1444
1445         BLI_assert(index >= 0);
1446
1447         prop = rna_ensure_property(prop);
1448
1449         flag = prop->flag;
1450         
1451         if (prop->editable)
1452                 flag &= prop->editable(ptr);
1453
1454         if (prop->itemeditable)
1455                 flag &= prop->itemeditable(ptr, index);
1456
1457         id = ptr->id.data;
1458
1459         return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
1460 }
1461
1462 int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1463 {
1464         /* check that base ID-block can support animation data */
1465         if (!id_type_can_have_animdata(ptr->id.data))
1466                 return 0;
1467         
1468         prop = rna_ensure_property(prop);
1469
1470         if (!(prop->flag & PROP_ANIMATABLE))
1471                 return 0;
1472
1473         return (prop->flag & PROP_EDITABLE);
1474 }
1475
1476 int RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
1477 {
1478         /* would need to ask animation system */
1479
1480         return 0;
1481 }
1482
1483
1484 /* this function is to check if its possible to create a valid path from the ID
1485  * its slow so don't call in a loop */
1486 int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
1487 {
1488         char *path = RNA_path_from_ID_to_property(ptr, prop);
1489         int ret = 0;
1490
1491         if (path) {
1492                 PointerRNA id_ptr;
1493                 PointerRNA r_ptr;
1494                 PropertyRNA *r_prop;
1495
1496                 RNA_id_pointer_create(ptr->id.data, &id_ptr);
1497                 if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == TRUE) {
1498                         ret = (prop == r_prop);
1499                 }
1500                 else {
1501                         ret = FALSE;
1502                 }
1503                 MEM_freeN(path);
1504         }
1505
1506         return ret;
1507 }
1508
1509
1510 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1511 {
1512         const bool is_rna = (prop->magic == RNA_MAGIC);
1513         prop = rna_ensure_property(prop);
1514
1515         if (is_rna) {
1516                 if (prop->update) {
1517                         /* ideally no context would be needed for update, but there's some
1518                          * parts of the code that need it still, so we have this exception */
1519                         if (prop->flag & PROP_CONTEXT_UPDATE) {
1520                                 if (C) {
1521                                         if (prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) {
1522                                                 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
1523                                         }
1524                                         else {
1525                                                 ((ContextUpdateFunc)prop->update)(C, ptr);
1526                                         }
1527                                 }
1528                         }
1529                         else
1530                                 prop->update(bmain, scene, ptr);
1531                 }
1532                 if (prop->noteflag)
1533                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1534         }
1535         
1536         if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
1537                 /* WARNING! This is so property drivers update the display!
1538                  * not especially nice  */
1539                 DAG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
1540                 WM_main_add_notifier(NC_WINDOW, NULL);
1541         }
1542 }
1543
1544 /* must keep in sync with 'rna_property_update'
1545  * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
1546  * but this isn't likely to be a performance problem. */
1547 int RNA_property_update_check(PropertyRNA *prop)
1548 {
1549         return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
1550 }
1551
1552 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1553 {
1554         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
1555 }
1556
1557 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1558 {
1559         rna_property_update(NULL, bmain, scene, ptr, prop);
1560 }
1561
1562
1563 /* RNA Updates Cache ------------------------ */
1564 /* Overview of RNA Update cache system:
1565  *
1566  * RNA Update calls need to be cached in order to maintain reasonable performance
1567  * of the animation system (i.e. maintaining a somewhat interactive framerate)
1568  * while still allowing updates to be called (necessary in particular for modifier
1569  * property updates to actually work).
1570  *
1571  * The cache is structured with a dual-layer structure
1572  * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
1573  *        and most updates end up using just that anyways)
1574  * - L2 = Update functions to be called on those PointerRNA's
1575  */
1576
1577 /* cache element */
1578 typedef struct tRnaUpdateCacheElem {
1579         struct tRnaUpdateCacheElem *next, *prev;
1580         
1581         PointerRNA ptr;     /* L1 key - id as primary, data secondary/ignored? */
1582         ListBase L2Funcs;   /* L2 functions (LinkData<RnaUpdateFuncRef>) */
1583 } tRnaUpdateCacheElem;
1584
1585 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
1586 static ListBase rna_updates_cache = {NULL, NULL};
1587
1588 /* ........................... */
1589
1590 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
1591 {
1592         const bool is_rna = (prop->magic == RNA_MAGIC);
1593         tRnaUpdateCacheElem *uce = NULL;
1594         UpdateFunc fn = NULL;
1595         LinkData *ld;
1596         
1597         /* sanity check */
1598         if (NULL == ptr)
1599                 return;
1600                 
1601         prop = rna_ensure_property(prop);
1602         
1603         /* we can only handle update calls with no context args for now (makes animsys updates easier) */
1604         if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
1605                 return;
1606         fn = prop->update;
1607                 
1608         /* find cache element for which key matches... */
1609         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1610                 /* just match by id only for now, since most update calls that we'll encounter only really care about this */
1611                 /* TODO: later, the cache might need to have some nesting on L1 to cope better
1612                  * with these problems + some tagging to indicate we need this */
1613                 if (uce->ptr.id.data == ptr->id.data)
1614                         break;
1615         }
1616         if (uce == NULL) {
1617                 /* create new instance */
1618                 uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
1619                 BLI_addtail(&rna_updates_cache, uce);
1620                 
1621                 /* copy pointer */
1622                 RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
1623         }
1624         
1625         /* check on the update func */
1626         for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
1627                 /* stop on match - function already cached */
1628                 if (fn == ld->data)
1629                         return;
1630         }
1631         /* else... if still here, we need to add it */
1632         BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
1633 }
1634
1635 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
1636 {
1637         tRnaUpdateCacheElem *uce;
1638         
1639         /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
1640         
1641         /* execute the cached updates */
1642         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1643                 LinkData *ld;
1644                 
1645                 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
1646                         UpdateFunc fn = (UpdateFunc)ld->data;
1647                         fn(bmain, scene, &uce->ptr);
1648                 }
1649         }
1650 }
1651
1652 void RNA_property_update_cache_free(void)
1653 {
1654         tRnaUpdateCacheElem *uce, *ucn;
1655         
1656         for (uce = rna_updates_cache.first; uce; uce = ucn) {
1657                 ucn = uce->next;
1658                 
1659                 /* free L2 cache */
1660                 BLI_freelistN(&uce->L2Funcs);
1661                 
1662                 /* remove self */
1663                 BLI_freelinkN(&rna_updates_cache, uce);
1664         }
1665 }
1666
1667 /* ---------------------------------------------------------------------- */
1668
1669 /* Property Data */
1670
1671 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
1672 {
1673         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1674         IDProperty *idprop;
1675
1676         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1677         BLI_assert(RNA_property_array_check(prop) == 0);
1678
1679         if ((idprop = rna_idproperty_check(&prop, ptr)))
1680                 return IDP_Int(idprop);
1681         else if (bprop->get)
1682                 return bprop->get(ptr);
1683         else if (bprop->get_ex)
1684                 return bprop->get_ex(ptr, prop);
1685         else
1686                 return bprop->defaultvalue;
1687 }
1688
1689 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1690 {
1691         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1692         IDProperty *idprop;
1693
1694         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1695         BLI_assert(RNA_property_array_check(prop) == 0);
1696
1697         /* just in case other values are passed */
1698         if (value) value = 1;
1699
1700         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1701                 IDP_Int(idprop) = value;
1702                 rna_idproperty_touch(idprop);
1703         }
1704         else if (bprop->set) {
1705                 bprop->set(ptr, value);
1706         }
1707         else if (bprop->set_ex) {
1708                 bprop->set_ex(ptr, prop, value);
1709         }
1710         else if (prop->flag & PROP_EDITABLE) {
1711                 IDPropertyTemplate val = {0};
1712                 IDProperty *group;
1713
1714                 val.i = value;
1715
1716                 group = RNA_struct_idprops(ptr, 1);
1717                 if (group)
1718                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
1719         }
1720 }
1721
1722 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1723 {
1724         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1725         IDProperty *idprop;
1726
1727         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1728         BLI_assert(RNA_property_array_check(prop) != 0);
1729
1730         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1731                 if (prop->arraydimension == 0)
1732                         values[0] = RNA_property_boolean_get(ptr, prop);
1733                 else
1734                         memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
1735         }
1736         else if (prop->arraydimension == 0)
1737                 values[0] = RNA_property_boolean_get(ptr, prop);
1738         else if (bprop->getarray)
1739                 bprop->getarray(ptr, values);
1740         else if (bprop->getarray_ex)
1741                 bprop->getarray_ex(ptr, prop, values);
1742         else if (bprop->defaultarray)
1743                 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
1744         else
1745                 memset(values, 0, sizeof(int) * prop->totarraylength);
1746 }
1747
1748 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1749 {
1750         int tmp[RNA_MAX_ARRAY_LENGTH];
1751         int len = rna_ensure_property_array_length(ptr, prop);
1752
1753         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1754         BLI_assert(RNA_property_array_check(prop) != 0);
1755         BLI_assert(index >= 0);
1756
1757         if (len <= RNA_MAX_ARRAY_LENGTH) {
1758                 RNA_property_boolean_get_array(ptr, prop, tmp);
1759                 return tmp[index];
1760         }
1761         else {
1762                 int *tmparray, value;
1763
1764                 tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_boolean_get_index");
1765                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1766                 value = tmparray[index];
1767                 MEM_freeN(tmparray);
1768
1769                 return value;
1770         }
1771 }
1772
1773 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1774 {
1775         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1776         IDProperty *idprop;
1777
1778         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1779         BLI_assert(RNA_property_array_check(prop) != 0);
1780
1781         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1782                 if (prop->arraydimension == 0)
1783                         IDP_Int(idprop) = values[0];
1784                 else
1785                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
1786
1787                 rna_idproperty_touch(idprop);
1788         }
1789         else if (prop->arraydimension == 0)
1790                 RNA_property_boolean_set(ptr, prop, values[0]);
1791         else if (bprop->setarray)
1792                 bprop->setarray(ptr, values);
1793         else if (bprop->setarray_ex)
1794                 bprop->setarray_ex(ptr, prop, values);
1795         else if (prop->flag & PROP_EDITABLE) {
1796                 IDPropertyTemplate val = {0};
1797                 IDProperty *group;
1798
1799                 val.array.len = prop->totarraylength;
1800                 val.array.type = IDP_INT;
1801
1802                 group = RNA_struct_idprops(ptr, 1);
1803                 if (group) {
1804                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
1805                         IDP_AddToGroup(group, idprop);
1806                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
1807                 }
1808         }
1809 }
1810
1811 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1812 {
1813         int tmp[RNA_MAX_ARRAY_LENGTH];
1814         int len = rna_ensure_property_array_length(ptr, prop);
1815
1816         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1817         BLI_assert(RNA_property_array_check(prop) != 0);
1818         BLI_assert(index >= 0);
1819
1820         if (len <= RNA_MAX_ARRAY_LENGTH) {
1821                 RNA_property_boolean_get_array(ptr, prop, tmp);
1822                 tmp[index] = value;
1823                 RNA_property_boolean_set_array(ptr, prop, tmp);
1824         }
1825         else {
1826                 int *tmparray;
1827
1828                 tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_boolean_get_index");
1829                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1830                 tmparray[index] = value;
1831                 RNA_property_boolean_set_array(ptr, prop, tmparray);
1832                 MEM_freeN(tmparray);
1833         }
1834 }
1835
1836 int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
1837 {
1838         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1839
1840         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1841         BLI_assert(RNA_property_array_check(prop) == 0);
1842
1843         return bprop->defaultvalue;
1844 }
1845
1846 void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
1847 {
1848         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1849         
1850         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1851         BLI_assert(RNA_property_array_check(prop) != 0);
1852
1853         if (prop->arraydimension == 0)
1854                 values[0] = bprop->defaultvalue;
1855         else if (bprop->defaultarray)
1856                 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
1857         else
1858                 memset(values, 0, sizeof(int) * prop->totarraylength);
1859 }
1860
1861 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1862 {
1863         int tmp[RNA_MAX_ARRAY_LENGTH];
1864         int len = rna_ensure_property_array_length(ptr, prop);
1865
1866         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1867         BLI_assert(RNA_property_array_check(prop) != 0);
1868         BLI_assert(index >= 0);
1869
1870         if (len <= RNA_MAX_ARRAY_LENGTH) {
1871                 RNA_property_boolean_get_default_array(ptr, prop, tmp);
1872                 return tmp[index];
1873         }
1874         else {
1875                 int *tmparray, value;
1876
1877                 tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_boolean_get_default_index");
1878                 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
1879                 value = tmparray[index];
1880                 MEM_freeN(tmparray);
1881
1882                 return value;
1883         }
1884 }
1885
1886 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
1887 {
1888         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
1889         IDProperty *idprop;
1890
1891         BLI_assert(RNA_property_type(prop) == PROP_INT);
1892         BLI_assert(RNA_property_array_check(prop) == 0);
1893
1894         if ((idprop = rna_idproperty_check(&prop, ptr)))
1895                 return IDP_Int(idprop);
1896         else if (iprop->get)
1897                 return iprop->get(ptr);
1898         else if (iprop->get_ex)
1899                 return iprop->get_ex(ptr, prop);
1900         else
1901                 return iprop->defaultvalue;
1902 }
1903
1904 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1905 {
1906         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
1907         IDProperty *idprop;
1908
1909         BLI_assert(RNA_property_type(prop) == PROP_INT);
1910         BLI_assert(RNA_property_array_check(prop) == 0);
1911         /* useful to check on bad values but set function should clamp */
1912         /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
1913
1914         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1915                 IDP_Int(idprop) = value;
1916                 rna_idproperty_touch(idprop);
1917         }
1918         else if (iprop->set)
1919                 iprop->set(ptr, value);
1920         else if (iprop->set_ex)
1921                 iprop->set_ex(ptr, prop, value);
1922         else if (prop->flag & PROP_EDITABLE) {
1923                 IDPropertyTemplate val = {0};
1924                 IDProperty *group;
1925
1926                 RNA_property_int_clamp(ptr, prop, &value);
1927
1928                 val.i = value;
1929
1930                 group = RNA_struct_idprops(ptr, 1);
1931                 if (group)
1932                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
1933         }
1934 }
1935
1936 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1937 {
1938         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
1939         IDProperty *idprop;
1940
1941         BLI_assert(RNA_property_type(prop) == PROP_INT);
1942         BLI_assert(RNA_property_array_check(prop) != 0);
1943
1944         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1945                 if (prop->arraydimension == 0)
1946                         values[0] = RNA_property_int_get(ptr, prop);
1947                 else
1948                         memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
1949         }
1950         else if (prop->arraydimension == 0)
1951                 values[0] = RNA_property_int_get(ptr, prop);
1952         else if (iprop->getarray)
1953                 iprop->getarray(ptr, values);
1954         else if (iprop->getarray_ex)
1955                 iprop->getarray_ex(ptr, prop, values);
1956         else if (iprop->defaultarray)
1957                 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
1958         else
1959                 memset(values, 0, sizeof(int) * prop->totarraylength);
1960 }
1961
1962 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
1963 {
1964         const int array_len = RNA_property_array_length(ptr, prop);
1965
1966         if (array_len <= 0) {
1967                 values[0] = 0;
1968                 values[1] = 0;
1969         }
1970         else if (array_len == 1) {
1971                 RNA_property_int_get_array(ptr, prop, values);
1972                 values[1] = values[0];
1973         }
1974         else {
1975                 int arr_stack[32];
1976                 int *arr;
1977                 int i;
1978
1979                 if (array_len > 32) {
1980                         arr = MEM_mallocN(sizeof(int) * array_len, "RNA_property_int_get_array_range");
1981                 }
1982                 else {
1983                         arr = arr_stack;
1984                 }
1985
1986                 RNA_property_int_get_array(ptr, prop, arr);
1987                 values[0] = values[1] = arr[0];
1988                 for (i = 1; i < array_len; i++) {
1989                         values[0] = MIN2(values[0], arr[i]);
1990                         values[1] = MAX2(values[1], arr[i]);
1991                 }
1992
1993                 if (arr != arr_stack) {
1994                         MEM_freeN(arr);
1995                 }
1996         }
1997 }
1998
1999 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2000 {
2001         int tmp[RNA_MAX_ARRAY_LENGTH];
2002         int len = rna_ensure_property_array_length(ptr, prop);
2003
2004         BLI_assert(RNA_property_type(prop) == PROP_INT);
2005         BLI_assert(RNA_property_array_check(prop) != 0);
2006         BLI_assert(index >= 0);
2007
2008         if (len <= RNA_MAX_ARRAY_LENGTH) {
2009                 RNA_property_int_get_array(ptr, prop, tmp);
2010                 return tmp[index];
2011         }
2012         else {
2013                 int *tmparray, value;
2014
2015                 tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_int_get_index");
2016                 RNA_property_int_get_array(ptr, prop, tmparray);
2017                 value = tmparray[index];
2018                 MEM_freeN(tmparray);
2019
2020                 return value;
2021         }
2022 }
2023
2024 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2025 {
2026         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2027         IDProperty *idprop;
2028
2029         BLI_assert(RNA_property_type(prop) == PROP_INT);
2030         BLI_assert(RNA_property_array_check(prop) != 0);
2031
2032         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2033                 if (prop->arraydimension == 0)
2034                         IDP_Int(idprop) = values[0];
2035                 else
2036                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2037
2038                 rna_idproperty_touch(idprop);
2039         }
2040         else if (prop->arraydimension == 0)
2041                 RNA_property_int_set(ptr, prop, values[0]);
2042         else if (iprop->setarray)
2043                 iprop->setarray(ptr, values);
2044         else if (iprop->setarray_ex)
2045                 iprop->setarray_ex(ptr, prop, values);
2046         else if (prop->flag & PROP_EDITABLE) {
2047                 IDPropertyTemplate val = {0};
2048                 IDProperty *group;
2049
2050                 /* TODO: RNA_property_int_clamp_array(ptr, prop, &value); */
2051
2052                 val.array.len = prop->totarraylength;
2053                 val.array.type = IDP_INT;
2054
2055                 group = RNA_struct_idprops(ptr, 1);
2056                 if (group) {
2057                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2058                         IDP_AddToGroup(group, idprop);
2059                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2060                 }
2061         }
2062 }
2063
2064 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2065 {
2066         int tmp[RNA_MAX_ARRAY_LENGTH];
2067         int len = rna_ensure_property_array_length(ptr, prop);
2068
2069         BLI_assert(RNA_property_type(prop) == PROP_INT);
2070         BLI_assert(RNA_property_array_check(prop) != 0);
2071         BLI_assert(index >= 0);
2072
2073         if (len <= RNA_MAX_ARRAY_LENGTH) {
2074                 RNA_property_int_get_array(ptr, prop, tmp);
2075                 tmp[index] = value;
2076                 RNA_property_int_set_array(ptr, prop, tmp);
2077         }
2078         else {
2079                 int *tmparray;
2080
2081                 tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_int_get_index");
2082                 RNA_property_int_get_array(ptr, prop, tmparray);
2083                 tmparray[index] = value;
2084                 RNA_property_int_set_array(ptr, prop, tmparray);
2085                 MEM_freeN(tmparray);
2086         }
2087 }
2088
2089 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2090 {
2091         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2092         return iprop->defaultvalue;
2093 }
2094
2095 void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2096 {
2097         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2098         
2099         BLI_assert(RNA_property_type(prop) == PROP_INT);
2100         BLI_assert(RNA_property_array_check(prop) != 0);
2101
2102         if (prop->arraydimension == 0)
2103                 values[0] = iprop->defaultvalue;
2104         else if (iprop->defaultarray)
2105                 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2106         else
2107                 memset(values, 0, sizeof(int) * prop->totarraylength);
2108 }
2109
2110 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2111 {
2112         int tmp[RNA_MAX_ARRAY_LENGTH];
2113         int len = rna_ensure_property_array_length(ptr, prop);
2114
2115         BLI_assert(RNA_property_type(prop) == PROP_INT);
2116         BLI_assert(RNA_property_array_check(prop) != 0);
2117         BLI_assert(index >= 0);
2118
2119         if (len <= RNA_MAX_ARRAY_LENGTH) {
2120                 RNA_property_int_get_default_array(ptr, prop, tmp);
2121                 return tmp[index];
2122         }
2123         else {
2124                 int *tmparray, value;
2125
2126                 tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_int_get_default_index");
2127                 RNA_property_int_get_default_array(ptr, prop, tmparray);
2128                 value = tmparray[index];
2129                 MEM_freeN(tmparray);
2130
2131                 return value;
2132         }
2133 }
2134
2135 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
2136 {
2137         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2138         IDProperty *idprop;
2139
2140         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2141         BLI_assert(RNA_property_array_check(prop) == 0);
2142
2143         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2144                 if (idprop->type == IDP_FLOAT)
2145                         return IDP_Float(idprop);
2146                 else
2147                         return (float)IDP_Double(idprop);
2148         }
2149         else if (fprop->get)
2150                 return fprop->get(ptr);
2151         else if (fprop->get_ex)
2152                 return fprop->get_ex(ptr, prop);
2153         else
2154                 return fprop->defaultvalue;
2155 }
2156
2157 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
2158 {
2159         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2160         IDProperty *idprop;
2161
2162         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2163         BLI_assert(RNA_property_array_check(prop) == 0);
2164         /* useful to check on bad values but set function should clamp */
2165         /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
2166
2167         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2168                 if (idprop->type == IDP_FLOAT)
2169                         IDP_Float(idprop) = value;
2170                 else
2171                         IDP_Double(idprop) = value;
2172
2173                 rna_idproperty_touch(idprop);
2174         }
2175         else if (fprop->set) {
2176                 fprop->set(ptr, value);
2177         }
2178         else if (fprop->set_ex) {
2179                 fprop->set_ex(ptr, prop, value);
2180         }
2181         else if (prop->flag & PROP_EDITABLE) {
2182                 IDPropertyTemplate val = {0};
2183                 IDProperty *group;
2184
2185                 RNA_property_float_clamp(ptr, prop, &value);
2186
2187                 val.f = value;
2188
2189                 group = RNA_struct_idprops(ptr, 1);
2190                 if (group)
2191                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
2192         }
2193 }
2194
2195 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
2196 {
2197         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2198         IDProperty *idprop;
2199         int i;
2200
2201         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2202         BLI_assert(RNA_property_array_check(prop) != 0);
2203
2204         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2205                 if (prop->arraydimension == 0)
2206                         values[0] = RNA_property_float_get(ptr, prop);
2207                 else if (idprop->subtype == IDP_FLOAT) {
2208                         memcpy(values, IDP_Array(idprop), sizeof(float) * idprop->len);
2209                 }
2210                 else {
2211                         for (i = 0; i < idprop->len; i++)
2212                                 values[i] =  (float)(((double *)IDP_Array(idprop))[i]);
2213                 }
2214         }
2215         else if (prop->arraydimension == 0)
2216                 values[0] = RNA_property_float_get(ptr, prop);
2217         else if (fprop->getarray)
2218                 fprop->getarray(ptr, values);
2219         else if (fprop->getarray_ex)
2220                 fprop->getarray_ex(ptr, prop, values);
2221         else if (fprop->defaultarray)
2222                 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2223         else
2224                 memset(values, 0, sizeof(float) * prop->totarraylength);
2225 }
2226
2227 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
2228 {
2229         const int array_len = RNA_property_array_length(ptr, prop);
2230
2231         if (array_len <= 0) {
2232                 values[0] = 0.0f;
2233                 values[1] = 0.0f;
2234         }
2235         else if (array_len == 1) {
2236                 RNA_property_float_get_array(ptr, prop, values);
2237                 values[1] = values[0];
2238         }
2239         else {
2240                 float arr_stack[32];
2241                 float *arr;
2242                 int i;
2243
2244                 if (array_len > 32) {
2245                         arr = MEM_mallocN(sizeof(float) * array_len, "RNA_property_float_get_array_range");
2246                 }
2247                 else {
2248                         arr = arr_stack;
2249                 }
2250
2251                 RNA_property_float_get_array(ptr, prop, arr);
2252                 values[0] = values[1] = arr[0];
2253                 for (i = 1; i < array_len; i++) {
2254                         values[0] = MIN2(values[0], arr[i]);
2255                         values[1] = MAX2(values[1], arr[i]);
2256                 }
2257
2258                 if (arr != arr_stack) {
2259                         MEM_freeN(arr);
2260                 }
2261         }
2262 }
2263
2264 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2265 {
2266         float tmp[RNA_MAX_ARRAY_LENGTH];
2267         int len = rna_ensure_property_array_length(ptr, prop);
2268
2269         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2270         BLI_assert(RNA_property_array_check(prop) != 0);
2271         BLI_assert(index >= 0);
2272
2273         if (len <= RNA_MAX_ARRAY_LENGTH) {
2274                 RNA_property_float_get_array(ptr, prop, tmp);
2275                 return tmp[index];
2276         }
2277         else {
2278                 float *tmparray, value;
2279
2280                 tmparray = MEM_callocN(sizeof(float) * len, "RNA_property_float_get_index");
2281                 RNA_property_float_get_array(ptr, prop, tmparray);
2282                 value = tmparray[index];
2283                 MEM_freeN(tmparray);
2284
2285                 return value;
2286         }
2287 }
2288
2289 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
2290 {
2291         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2292         IDProperty *idprop;
2293         int i;
2294
2295         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2296         BLI_assert(RNA_property_array_check(prop) != 0);
2297
2298         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2299                 if (prop->arraydimension == 0) {
2300                         if (idprop->type == IDP_FLOAT)
2301                                 IDP_Float(idprop) = values[0];
2302                         else
2303                                 IDP_Double(idprop) = values[0];
2304                 }
2305                 else if (idprop->subtype == IDP_FLOAT) {
2306                         memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2307                 }
2308                 else {
2309                         for (i = 0; i < idprop->len; i++)
2310                                 ((double *)IDP_Array(idprop))[i] = values[i];
2311                 }
2312
2313                 rna_idproperty_touch(idprop);
2314         }
2315         else if (prop->arraydimension == 0)
2316                 RNA_property_float_set(ptr, prop, values[0]);
2317         else if (fprop->setarray) {
2318                 fprop->setarray(ptr, values);
2319         }
2320         else if (fprop->setarray_ex) {
2321                 fprop->setarray_ex(ptr, prop, values);
2322         }
2323         else if (prop->flag & PROP_EDITABLE) {
2324                 IDPropertyTemplate val = {0};
2325                 IDProperty *group;
2326
2327                 /* TODO: RNA_property_float_clamp_array(ptr, prop, &value); */
2328
2329                 val.array.len = prop->totarraylength;
2330                 val.array.type = IDP_FLOAT;
2331
2332                 group = RNA_struct_idprops(ptr, 1);
2333                 if (group) {
2334                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2335                         IDP_AddToGroup(group, idprop);
2336                         memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2337                 }
2338         }
2339 }
2340
2341 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
2342 {
2343         float tmp[RNA_MAX_ARRAY_LENGTH];
2344         int len = rna_ensure_property_array_length(ptr, prop);
2345
2346         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2347         BLI_assert(RNA_property_array_check(prop) != 0);
2348         BLI_assert(index >= 0);
2349
2350         if (len <= RNA_MAX_ARRAY_LENGTH) {
2351                 RNA_property_float_get_array(ptr, prop, tmp);
2352                 tmp[index] = value;
2353                 RNA_property_float_set_array(ptr, prop, tmp);
2354         }
2355         else {
2356                 float *tmparray;
2357
2358                 tmparray = MEM_callocN(sizeof(float) * len, "RNA_property_float_get_index");
2359                 RNA_property_float_get_array(ptr, prop, tmparray);
2360                 tmparray[index] = value;
2361                 RNA_property_float_set_array(ptr, prop, tmparray);
2362                 MEM_freeN(tmparray);
2363         }
2364 }
2365
2366 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2367 {
2368         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2369
2370         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2371         BLI_assert(RNA_property_array_check(prop) == 0);
2372
2373         return fprop->defaultvalue;
2374 }
2375
2376 void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, float *values)
2377 {
2378         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2379         
2380         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2381         BLI_assert(RNA_property_array_check(prop) != 0);
2382
2383         if (prop->arraydimension == 0)
2384                 values[0] = fprop->defaultvalue;
2385         else if (fprop->defaultarray)
2386                 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2387         else
2388                 memset(values, 0, sizeof(float) * prop->totarraylength);
2389 }
2390
2391 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2392 {
2393         float tmp[RNA_MAX_ARRAY_LENGTH];
2394         int len = rna_ensure_property_array_length(ptr, prop);
2395
2396         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2397         BLI_assert(RNA_property_array_check(prop) != 0);
2398         BLI_assert(index >= 0);
2399
2400         if (len <= RNA_MAX_ARRAY_LENGTH) {
2401                 RNA_property_float_get_default_array(ptr, prop, tmp);
2402                 return tmp[index];
2403         }
2404         else {
2405                 float *tmparray, value;
2406
2407                 tmparray = MEM_callocN(sizeof(float) * len, "RNA_property_float_get_default_index");
2408                 RNA_property_float_get_default_array(ptr, prop, tmparray);
2409                 value = tmparray[index];
2410                 MEM_freeN(tmparray);
2411
2412                 return value;
2413         }
2414 }
2415
2416 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
2417 {
2418         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2419         IDProperty *idprop;
2420
2421         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2422
2423         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2424                 /* editing bytes is not 100% supported
2425                  * since they can contain NIL chars */
2426                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2427                         memcpy(value, IDP_String(idprop), idprop->len);
2428                         value[idprop->len] = '\0';
2429                 }
2430                 else {
2431                         memcpy(value, IDP_String(idprop), idprop->len);
2432                 }
2433         }
2434         else if (sprop->get) {
2435                 sprop->get(ptr, value);
2436         }
2437         else if (sprop->get_ex) {
2438                 sprop->get_ex(ptr, prop, value);
2439         }
2440         else {
2441                 strcpy(value, sprop->defaultvalue);
2442         }
2443 }
2444
2445 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop,
2446                                     char *fixedbuf, int fixedlen, int *r_len)
2447 {
2448         char *buf;
2449         int length;
2450
2451         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2452
2453         length = RNA_property_string_length(ptr, prop);
2454
2455         if (length + 1 < fixedlen)
2456                 buf = fixedbuf;
2457         else
2458                 buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
2459
2460 #ifndef NDEBUG
2461         /* safety check to ensure the string is actually set */
2462         buf[length] = 255;
2463 #endif
2464
2465         RNA_property_string_get(ptr, prop, buf);
2466
2467 #ifndef NDEBUG
2468         BLI_assert(buf[length] == '\0');
2469 #endif
2470
2471         if (r_len) {
2472                 *r_len = length;
2473         }
2474
2475         return buf;
2476 }
2477
2478 /* this is the length without \0 terminator */
2479 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
2480 {
2481         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2482         IDProperty *idprop;
2483
2484         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2485
2486         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2487                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2488                         return idprop->len;
2489                 }
2490                 else {
2491 #ifndef NDEBUG
2492                         /* these _must_ stay in sync */
2493                         BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
2494 #endif
2495                         return idprop->len - 1;
2496                 }
2497         }
2498         else if (sprop->length)
2499                 return sprop->length(ptr);
2500         else if (sprop->length_ex)
2501                 return sprop->length_ex(ptr, prop);
2502         else
2503                 return strlen(sprop->defaultvalue);
2504 }
2505
2506 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
2507 {
2508         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2509         IDProperty *idprop;
2510
2511         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2512
2513         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2514                 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
2515                 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
2516                 rna_idproperty_touch(idprop);
2517         }
2518         else if (sprop->set)
2519                 sprop->set(ptr, value);  /* set function needs to clamp its self */
2520         else if (sprop->set_ex)
2521                 sprop->set_ex(ptr, prop, value);  /* set function needs to clamp its self */
2522         else if (prop->flag & PROP_EDITABLE) {
2523                 IDProperty *group;
2524
2525                 group = RNA_struct_idprops(ptr, 1);
2526                 if (group)
2527                         IDP_AddToGroup(group, IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop) - 1));
2528         }
2529 }
2530
2531 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
2532 {
2533         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2534
2535         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2536
2537         strcpy(value, sprop->defaultvalue);
2538 }
2539
2540 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
2541 {
2542         char *buf;
2543         int length;
2544
2545         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2546
2547         length = RNA_property_string_default_length(ptr, prop);
2548
2549         if (length + 1 < fixedlen)
2550                 buf = fixedbuf;
2551         else
2552                 buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
2553
2554         RNA_property_string_get_default(ptr, prop, buf);
2555
2556         return buf;
2557 }
2558
2559 /* this is the length without \0 terminator */
2560 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2561 {
2562         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2563
2564         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2565
2566         return strlen(sprop->defaultvalue);
2567 }
2568
2569 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
2570 {
2571         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
2572         IDProperty *idprop;
2573
2574         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2575
2576         if ((idprop = rna_idproperty_check(&prop, ptr)))
2577                 return IDP_Int(idprop);
2578         else if (eprop->get)
2579                 return eprop->get(ptr);
2580         else if (eprop->get_ex)
2581                 return eprop->get_ex(ptr, prop);
2582         else
2583                 return eprop->defaultvalue;
2584 }
2585
2586 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2587 {
2588         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
2589         IDProperty *idprop;
2590
2591         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2592
2593         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2594                 IDP_Int(idprop) = value;
2595                 rna_idproperty_touch(idprop);
2596         }
2597         else if (eprop->set) {
2598                 eprop->set(ptr, value);
2599         }
2600         else if (eprop->set_ex) {
2601                 eprop->set_ex(ptr, prop, value);
2602         }
2603         else if (prop->flag & PROP_EDITABLE) {
2604                 IDPropertyTemplate val = {0};
2605                 IDProperty *group;
2606
2607                 val.i = value;
2608
2609                 group = RNA_struct_idprops(ptr, 1);
2610                 if (group)
2611                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2612         }
2613 }
2614
2615 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2616 {
2617         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
2618
2619         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2620
2621         return eprop->defaultvalue;
2622 }
2623
2624 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
2625 {
2626         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
2627
2628         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2629
2630         return eprop->py_data;
2631 }
2632
2633 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
2634 {
2635         PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
2636         IDProperty *idprop;
2637
2638         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2639
2640         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2641                 pprop = (PointerPropertyRNA *)prop;
2642
2643                 /* for groups, data is idprop itself */
2644                 if (pprop->typef)
2645                         return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
2646                 else
2647                         return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
2648         }
2649         else if (pprop->get) {
2650                 return pprop->get(ptr);
2651         }
2652         else if (prop->flag & PROP_IDPROPERTY) {
2653                 /* XXX temporary hack to add it automatically, reading should
2654                  * never do any write ops, to ensure thread safety etc .. */
2655                 RNA_property_pointer_add(ptr, prop);
2656                 return RNA_property_pointer_get(ptr, prop);
2657         }
2658         else {
2659                 return PointerRNA_NULL;
2660         }
2661 }
2662
2663 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
2664 {
2665         /*IDProperty *idprop;*/
2666
2667         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2668
2669         if ((/*idprop = */ rna_idproperty_check(&prop, ptr))) {
2670                 /* not supported */
2671                 /* rna_idproperty_touch(idprop); */
2672         }
2673         else {
2674                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
2675
2676                 if (pprop->set &&
2677                     !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
2678                     !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
2679                 {
2680                         pprop->set(ptr, ptr_value);
2681                 }
2682         }
2683 }
2684
2685 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
2686 {
2687         /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
2688
2689         /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
2690
2691         return PointerRNA_NULL; /* FIXME: there has to be a way... */
2692 }
2693
2694 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
2695 {
2696         /*IDProperty *idprop;*/
2697
2698         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2699
2700         if ((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
2701                 /* already exists */
2702         }
2703         else if (prop->flag & PROP_IDPROPERTY) {
2704                 IDPropertyTemplate val = {0};
2705                 IDProperty *group;
2706
2707                 val.i = 0;
2708
2709                 group = RNA_struct_idprops(ptr, 1);
2710                 if (group)
2711                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
2712         }
2713         else
2714                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2715 }
2716
2717 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
2718 {
2719         IDProperty *idprop, *group;
2720
2721         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2722
2723         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2724                 group = RNA_struct_idprops(ptr, 0);
2725                 
2726                 if (group) {
2727                         IDP_RemFromGroup(group, idprop);
2728                         IDP_FreeProperty(idprop);
2729                         MEM_freeN(idprop);
2730                 }
2731         }
2732         else
2733                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2734 }
2735
2736 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
2737 {
2738         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
2739
2740         iter->ptr.data = rna_iterator_array_get(iter);
2741         iter->ptr.type = cprop->item_type;
2742         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
2743 }
2744
2745 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
2746 {
2747         IDProperty *idprop;
2748
2749         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2750
2751         memset(iter, 0, sizeof(*iter));
2752
2753         if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
2754                 iter->parent = *ptr;
2755                 iter->prop = prop;
2756
2757                 if (idprop)
2758                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
2759                 else
2760                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
2761
2762                 if (iter->valid)
2763                         rna_property_collection_get_idp(iter);
2764
2765                 iter->idprop = 1;
2766         }
2767         else {
2768                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
2769                 cprop->begin(iter, ptr);
2770         }
2771 }
2772
2773 void RNA_property_collection_next(CollectionPropertyIterator *iter)
2774 {
2775         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
2776
2777         if (iter->idprop) {
2778                 rna_iterator_array_next(iter);
2779
2780                 if (iter->valid)
2781                         rna_property_collection_get_idp(iter);
2782         }
2783         else
2784                 cprop->next(iter);
2785 }
2786
2787 void RNA_property_collection_end(CollectionPropertyIterator *iter)
2788 {
2789         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
2790
2791         if (iter->idprop)
2792                 rna_iterator_array_end(iter);
2793         else
2794                 cprop->end(iter);
2795 }
2796
2797 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
2798 {
2799         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
2800         IDProperty *idprop;
2801
2802         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2803
2804         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2805                 return idprop->len;
2806         }
2807         else if (cprop->length) {
2808                 return cprop->length(ptr);
2809         }
2810         else {
2811                 CollectionPropertyIterator iter;
2812                 int length = 0;
2813
2814                 RNA_property_collection_begin(ptr, prop, &iter);
2815                 for (; iter.valid; RNA_property_collection_next(&iter))
2816                         length++;
2817                 RNA_property_collection_end(&iter);
2818
2819                 return length;
2820         }
2821 }
2822
2823 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2824 {
2825         IDProperty *idprop;
2826 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
2827
2828         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2829
2830         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2831                 IDPropertyTemplate val = {0};
2832                 IDProperty *item;
2833
2834                 item = IDP_New(IDP_GROUP, &val, "");
2835                 IDP_AppendArray(idprop, item);
2836                 /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory  */
2837                 MEM_freeN(item);
2838         }
2839         else if (prop->flag & PROP_IDPROPERTY) {
2840                 IDProperty *group, *item;
2841                 IDPropertyTemplate val = {0};
2842
2843                 group = RNA_struct_idprops(ptr, 1);
2844                 if (group) {
2845                         idprop = IDP_NewIDPArray(prop->identifier);
2846                         IDP_AddToGroup(group, idprop);
2847
2848                         item = IDP_New(IDP_GROUP, &val, "");
2849                         IDP_AppendArray(idprop, item);
2850                         /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory */
2851                         MEM_freeN(item);
2852                 }
2853         }
2854
2855         /* py api calls directly */
2856 #if 0
2857         else if (cprop->add) {
2858                 if (!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2859                         ParameterList params;
2860                         RNA_parameter_list_create(&params, ptr, cprop->add);
2861                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
2862                         RNA_parameter_list_free(&params);
2863                 }
2864         }
2865         /*else
2866             printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/
2867 #endif
2868
2869         if (r_ptr) {
2870                 if (idprop) {
2871                         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
2872
2873                         r_ptr->data = IDP_GetIndexArray(idprop, idprop->len - 1);
2874                         r_ptr->type = cprop->item_type;
2875                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
2876                 }
2877                 else
2878                         memset(r_ptr, 0, sizeof(*r_ptr));
2879         }
2880 }
2881
2882 int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
2883 {
2884         IDProperty *idprop;
2885 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
2886
2887         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2888
2889         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2890                 IDProperty tmp, *array;
2891                 int len;
2892
2893                 len = idprop->len;
2894                 array = IDP_IDPArray(idprop);
2895
2896                 if (key >= 0 && key < len) {
2897                         if (key + 1 < len) {
2898                                 /* move element to be removed to the back */
2899                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
2900                                 memmove(array + key, array + key + 1, sizeof(IDProperty) * (len - (key + 1)));
2901                                 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
2902                         }
2903
2904                         IDP_ResizeIDPArray(idprop, len - 1);
2905                 }
2906
2907                 return 1;
2908         }
2909         else if (prop->flag & PROP_IDPROPERTY)
2910                 return 1;
2911
2912         /* py api calls directly */
2913 #if 0
2914         else if (cprop->remove) {
2915                 if (!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2916                         ParameterList params;
2917                         RNA_parameter_list_create(&params, ptr, cprop->remove);
2918                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
2919                         RNA_parameter_list_free(&params);
2920                 }
2921
2922                 return 0;
2923         }
2924         /*else
2925             printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/
2926 #endif
2927         return 0;
2928 }
2929
2930 int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
2931 {
2932         IDProperty *idprop;
2933
2934         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2935
2936         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2937                 IDProperty tmp, *array;
2938                 int len;
2939
2940                 len = idprop->len;
2941                 array = IDP_IDPArray(idprop);
2942
2943                 if (key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
2944                         memcpy(&tmp, &array[key], sizeof(IDProperty));
2945                         if (pos < key)
2946                                 memmove(array + pos + 1, array + pos, sizeof(IDProperty) * (key - pos));
2947                         else
2948                                 memmove(array + key, array + key + 1, sizeof(IDProperty) * (pos - key));
2949                         memcpy(&array[pos], &tmp, sizeof(IDProperty));
2950                 }
2951
2952                 return 1;
2953         }
2954         else if (prop->flag & PROP_IDPROPERTY)
2955                 return 1;
2956
2957         return 0;
2958 }
2959
2960 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
2961 {
2962         IDProperty *idprop;
2963
2964         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2965
2966         if ((idprop = rna_idproperty_check(&prop, ptr)))
2967                 IDP_ResizeIDPArray(idprop, 0);
2968 }
2969
2970 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
2971 {
2972         CollectionPropertyIterator iter;
2973         int index = 0;
2974         
2975         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2976
2977         RNA_property_collection_begin(ptr, prop, &iter);
2978         for (index = 0; iter.valid; RNA_property_collection_next(&iter), index++) {
2979                 if (iter.ptr.data == t_ptr->data)
2980                         break;
2981         }
2982         RNA_property_collection_end(&iter);
2983         
2984         /* did we find it? */
2985         if (iter.valid)
2986                 return index;
2987         else
2988                 return -1;
2989 }
2990
2991 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
2992 {
2993         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
2994
2995         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2996
2997         if (cprop->lookupint) {
2998                 /* we have a callback defined, use it */
2999                 return cprop->lookupint(ptr, key, r_ptr);
3000         }
3001         else {
3002                 /* no callback defined, just iterate and find the nth item */
3003                 CollectionPropertyIterator iter;
3004                 int i;
3005
3006                 RNA_property_collection_begin(ptr, prop, &iter);
3007                 for (i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
3008                         if (i == key) {
3009                                 *r_ptr = iter.ptr;
3010                                 break;
3011                         }
3012                 }
3013                 RNA_property_collection_end(&iter);
3014
3015                 if (!iter.valid)
3016                         memset(r_ptr, 0, sizeof(*r_ptr));
3017
3018                 return iter.valid;
3019         }
3020 }
3021
3022 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
3023 {
3024         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
3025
3026         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3027
3028         if (cprop->lookupstring) {
3029                 /* we have a callback defined, use it */
3030                 return cprop->lookupstring(ptr, key, r_ptr);
3031         }
3032         else {
3033                 /* no callback defined, compare with name properties if they exist */
3034                 CollectionPropertyIterator iter;
3035                 PropertyRNA *nameprop;
3036                 char name[256], *nameptr;
3037                 int found = 0;
3038                 int keylen = strlen(key);
3039                 int namelen;
3040
3041                 RNA_property_collection_begin(ptr, prop, &iter);
3042                 for (; iter.valid; RNA_property_collection_next(&iter)) {
3043                         if (iter.ptr.data && iter.ptr.type->nameproperty) {
3044                                 nameprop = iter.ptr.type->nameproperty;
3045
3046                                 nameptr = RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name), &namelen);
3047
3048                                 if ((keylen == namelen) && (strcmp(nameptr, key) == 0)) {
3049                                         *r_ptr = iter.ptr;
3050                                         found = 1;
3051                                 }
3052
3053                                 if ((char *)&name != nameptr)
3054                                         MEM_freeN(nameptr);
3055
3056                                 if (found)
3057                                         break;
3058                         }
3059                 }
3060                 RNA_property_collection_end(&iter);
3061
3062                 if (!iter.valid)
3063                         memset(r_ptr, 0, sizeof(*r_ptr));
3064
3065                 return iter.valid;
3066         }
3067 }
3068
3069 /* zero return is an assignment error */
3070 int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
3071 {
3072         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
3073
3074         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3075
3076         if (cprop->assignint) {
3077                 /* we have a callback defined, use it */
3078                 return cprop->assignint(ptr, key, assign_ptr);
3079         }
3080
3081         return 0;
3082 }
3083
3084 int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
3085 {
3086         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3087
3088         *r_ptr = *ptr;
3089         return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1 : 0);
3090 }
3091
3092 int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
3093 {
3094         CollectionPropertyIterator iter;
3095         ArrayIterator *internal;
3096         char *arrayp;
3097
3098         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3099
3100         if (!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
3101                 return 0;
3102
3103         RNA_property_collection_begin(ptr, prop, &iter);
3104
3105         if (iter.valid) {
3106                 /* get data from array iterator and item property */
3107                 internal = iter.internal;
3108                 arrayp = (iter.valid) ? iter.ptr.data : NULL;
3109
3110                 if (internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
3111                         /* we might skip some items, so it's not a proper array */
3112                         RNA_property_collection_end(&iter);
3113                         return 0;
3114                 }
3115
3116                 array->array = arrayp + itemprop->rawoffset;
3117                 array->stride = internal->itemsize;
3118                 array->len = ((char *)internal->endptr - arrayp) / internal->itemsize;
3119                 array->type = itemprop->rawtype;
3120         }
3121         else
3122                 memset(array, 0, sizeof(RawArray));
3123
3124         RNA_property_collection_end(&iter);
3125
3126         return 1;
3127 }
3128
3129 #define RAW_GET(dtype, var, raw, a)                                           \
3130 {                                                                             \
3131         switch (raw.type) {                                                       \
3132                 case PROP_RAW_CHAR: var = (dtype)((char *)raw.array)[a]; break;       \
3133                 case PROP_RAW_SHORT: var = (dtype)((short *)raw.array)[a]; break;     \
3134                 case PROP_RAW_INT: var = (dtype)((int *)raw.array)[a]; break;         \
3135                 case PROP_RAW_FLOAT: var = (dtype)((float *)raw.array)[a]; break;     \
3136                 case PROP_RAW_DOUBLE: var = (dtype)((double *)raw.array)[a]; break;   \
3137                 default: var = (dtype)0;                                              \
3138         }                                                                         \
3139 } (void)0
3140
3141 #define RAW_SET(dtype, raw, a, var)                                           \
3142 {                                                                             \
3143         switch (raw.type) {                                                       \
3144                 case PROP_RAW_CHAR: ((char *)raw.array)[a] = (char)var; break;        \
3145                 case PROP_RAW_SHORT: ((short *)raw.array)[a] = (short)var; break;     \
3146                 case PROP_RAW_INT: ((int *)raw.array)[a] = (int)var; break;           \
3147                 case PROP_RAW_FLOAT: ((float *)raw.array)[a] = (float)var; break;     \
3148                 case PROP_RAW_DOUBLE: ((double *)raw.array)[a] = (double)var; break;  \
3149                 default: break;                                                       \
3150         }                                                                         \
3151 } (void)0
3152
3153 int RNA_raw_type_sizeof(RawPropertyType type)
3154 {
3155         switch (type) {
3156                 case PROP_RAW_CHAR: return sizeof(char);
3157                 case PROP_RAW_SHORT: return sizeof(short);
3158                 case PROP_RAW_INT: return sizeof(int);
3159                 case PROP_RAW_FLOAT: return sizeof(float);
3160                 case PROP_RAW_DOUBLE: return sizeof(double);
3161                 default: return 0;
3162         }
3163 }
3164
3165 static int rna_property_array_length_all_dimensions(PointerRNA *ptr, PropertyRNA *prop)
3166 {
3167         int i, len[RNA_MAX_ARRAY_DIMENSION];
3168         const int dim = RNA_property_array_dimension(ptr, prop, len);
3169         int size;
3170
3171         if (dim == 0)
3172                 return 0;
3173
3174         for (size = 1, i = 0; i < dim; i++)
3175                 size *= len[i];
3176         
3177         return size;
3178 }
3179
3180 static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname,
3181                           void *inarray, RawPropertyType intype, int inlen, int set)
3182 {
3183         StructRNA *ptype;
3184         PointerRNA itemptr;
3185         PropertyRNA *itemprop, *iprop;
3186         PropertyType itemtype = 0;
3187         RawArray in;
3188         int itemlen = 0;
3189
3190         /* initialize in array, stride assumed 0 in following code */
3191         in.array = inarray;
3192         in.type = intype;
3193         in.len = inlen;
3194         in.stride = 0;
3195
3196         ptype = RNA_property_pointer_type(ptr, prop);
3197
3198         /* try to get item property pointer */
3199         RNA_pointer_create(NULL, ptype, NULL, &itemptr);
3200         itemprop = RNA_struct_find_property(&itemptr, propname);
3201
3202         if (itemprop) {
3203                 /* we have item property pointer */
3204                 RawArray out;
3205
3206                 /* check type */
3207                 itemtype = RNA_property_type(itemprop);
3208
3209                 if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3210                         BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3211                         return 0;
3212                 }
3213
3214                 /* check item array */
3215                 itemlen = RNA_property_array_length(&itemptr, itemprop);
3216
3217                 /* dynamic array? need to get length per item */
3218                 if (itemprop->getlength) {
3219                         itemprop = NULL;
3220                 }
3221                 /* try to access as raw array */
3222                 else if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
3223                         int arraylen = (itemlen == 0) ? 1 : itemlen;
3224                         if (in.len != arraylen * out.len) {
3225                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d)",
3226                                             out.len * arraylen, in.len);
3227                                 return 0;
3228                         }
3229                         
3230                         /* matching raw types */
3231                         if (out.type == in.type) {
3232                                 void *inp = in.array;
3233                                 void *outp = out.array;
3234                                 int a, size;
3235
3236                                 size = RNA_raw_type_sizeof(out.type) * arraylen;
3237
3238                                 for (a = 0; a < out.len; a++) {
3239                                         if (set) memcpy(outp, inp, size);
3240                                         else memcpy(inp, outp, size);
3241
3242                                         inp = (char *)inp + size;
3243                                         outp = (char *)outp + out.stride;
3244                                 }
3245
3246                                 return 1;
3247                         }
3248
3249                         /* could also be faster with non-matching types,
3250                          * for now we just do slower loop .. */
3251                 }
3252         }
3253
3254         {
3255                 void *tmparray = NULL;
3256                 int tmplen = 0;
3257                 int err = 0, j, a = 0;
3258                 int needconv = 1;
3259
3260                 if (((itemtype == PROP_BOOLEAN || itemtype == PROP_INT) && in.type == PROP_RAW_INT) ||
3261                     (itemtype == PROP_FLOAT && in.type == PROP_RAW_FLOAT))
3262                 {
3263                         /* avoid creating temporary buffer if the data type match */
3264                         needconv = 0;
3265                 }
3266                 /* no item property pointer, can still be id property, or
3267                  * property of a type derived from the collection pointer type */
3268                 RNA_PROP_BEGIN(ptr, itemptr, prop)
3269                 {
3270                         if (itemptr.data) {
3271                                 if (itemprop) {
3272                                         /* we got the property already */
3273                                         iprop = itemprop;
3274                                 }
3275                                 else {
3276                                         /* not yet, look it up and verify if it is valid */
3277                                         iprop = RNA_struct_find_property(&itemptr, propname);
3278
3279                                         if (iprop) {
3280                                                 itemlen = rna_property_array_length_all_dimensions(&itemptr, iprop);
3281                                                 itemtype = RNA_property_type(iprop);
3282                                         }
3283                                         else {
3284                                                 BKE_reportf(reports, RPT_ERROR, "Property named '%s' not found", propname);
3285                                                 err = 1;
3286                                                 break;
3287                                         }
3288
3289                                         if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3290                                                 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3291                                                 err = 1;
3292                                                 break;
3293                                         }
3294                                 }
3295
3296                                 /* editable check */
3297                                 if (!set || RNA_property_editable(&itemptr, iprop)) {
3298                                         if (a + itemlen > in.len) {
3299                                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more)", in.len);
3300                                                 err = 1;
3301                                                 break;
3302                                         }
3303
3304                                         if (itemlen == 0) {
3305                                                 /* handle conversions */
3306                                                 if (set) {
3307                                                         switch (itemtype) {
3308                                                                 case PROP_BOOLEAN:
3309                                                                 {
3310                                                                         int b;
3311                                                                         RAW_GET(int, b, in, a);
3312                                                                         RNA_property_boolean_set(&itemptr, iprop, b);
3313                                                                         break;
3314                                                                 }
3315                                                                 case PROP_INT:
3316                                                                 {
3317                                                                         int i;
3318                                                                         RAW_GET(int, i, in, a);
3319                                                                         RNA_property_int_set(&itemptr, iprop, i);
3320                                                                         break;
3321                                                                 }
3322                                                                 case PROP_FLOAT:
3323                                                                 {
3324                                                                         float f;
3325                                                                         RAW_GET(float, f, in, a);
3326                                                                         RNA_property_float_set(&itemptr, iprop, f);
3327                                                                         break;
3328                                                                 }
3329                                                                 default:
3330                                                                         break;
3331                                                         }
3332                                                 }
3333                         &