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