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