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