synched with trunk at revision 32129
[blender.git] / source / blender / blenkernel / intern / property.c
1
2 /*  property.c   june 2000
3  * 
4  *  ton roosendaal
5  * $Id$
6  *
7  * ***** BEGIN GPL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stddef.h>
36 #include <string.h>
37 #include <ctype.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_property_types.h"
42 #include "DNA_object_types.h"
43
44 #include "BLI_blenlib.h"
45
46 void free_property(bProperty *prop)
47 {
48         
49         if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
50         MEM_freeN(prop);
51         
52 }
53
54 void free_properties(ListBase *lb)
55 {
56         bProperty *prop;
57         
58         while( (prop= lb->first) ) {
59                 BLI_remlink(lb, prop);
60                 free_property(prop);
61         }
62 }
63
64 bProperty *copy_property(bProperty *prop)
65 {
66         bProperty *propn;
67         
68         propn= MEM_dupallocN(prop);
69         if(prop->poin && prop->poin != &prop->data) {
70                 propn->poin= MEM_dupallocN(prop->poin);
71         }
72         else propn->poin= &propn->data;
73         
74         return propn;
75 }
76
77 void copy_properties(ListBase *lbn, ListBase *lbo)
78 {
79         bProperty *prop, *propn;
80         free_properties( lbn ); /* incase we are copying to an object with props */
81         prop= lbo->first;
82         while(prop) {
83                 propn= copy_property(prop);
84                 BLI_addtail(lbn, propn);
85                 prop= prop->next;
86         }
87         
88         
89 }
90
91 void init_property(bProperty *prop)
92 {
93         /* also use when property changes type */
94         
95         if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
96         prop->poin= 0;
97         
98         prop->data= 0;
99         
100         switch(prop->type) {
101         case GPROP_BOOL:
102         case GPROP_INT:
103         case GPROP_FLOAT:
104         case GPROP_TIME:
105                 prop->poin= &prop->data;
106                 break;
107         case GPROP_STRING:
108                 prop->poin= MEM_callocN(MAX_PROPSTRING, "property string");
109                 break;
110         }
111 }
112
113
114 bProperty *new_property(int type)
115 {
116         bProperty *prop;
117
118         prop= MEM_callocN(sizeof(bProperty), "property");
119         prop->type= type;
120
121         init_property(prop);
122         
123         strcpy(prop->name, "prop");
124
125         return prop;
126 }
127
128 /* used by unique_property() only */
129 static bProperty *get_property__internal(bProperty *first, bProperty *self, const char *name)
130 {
131         bProperty *p;
132         for(p= first; p; p= p->next) {
133                 if (p!=self && (strcmp(p->name, name)==0))
134                         return p;
135         }
136         return NULL;
137 }
138 void unique_property(bProperty *first, bProperty *prop, int force)
139 {
140         bProperty *p;
141
142         /* set the first if its not set */
143         if(first==NULL) {
144                 first= prop;
145                 while(first->prev) {
146                         first= first->prev;
147                 }
148         }
149
150         if(force) {
151                 /* change other names to make them unique */
152                 while((p = get_property__internal(first, prop, prop->name))) {
153                         unique_property(first, p, 0);
154                 }
155         }else {
156                 /* change our own name until its unique */
157                 if(get_property__internal(first, prop, prop->name)) {
158                         /* there is a collision */
159                         char new_name[sizeof(prop->name)];
160                         char base_name[sizeof(prop->name)];
161                         char num[sizeof(prop->name)];
162                         int i= 0;
163
164                         /* strip numbers */
165                         strcpy(base_name, prop->name);
166                         for(i= strlen(base_name)-1; (i>=0 && isdigit(base_name[i])); i--) {
167                                 base_name[i]= '\0';
168                         }
169                         i= 0;
170
171                         do { /* ensure we have enough chars for the new number in the name */
172                                 sprintf(num, "%d", i++);
173                                 BLI_strncpy(new_name, base_name, sizeof(prop->name) - strlen(num));
174                                 strcat(new_name, num);
175                         } while(get_property__internal(first, prop, new_name));
176
177                         strcpy(prop->name, new_name);
178                 }
179         }
180 }
181
182 bProperty *get_ob_property(Object *ob, char *name)
183 {
184         return BLI_findstring(&ob->prop, name, offsetof(bProperty, name));
185 }
186
187 void set_ob_property(Object *ob, bProperty *propc)
188 {
189         bProperty *prop;
190         prop= get_ob_property(ob, propc->name);
191         if(prop) {
192                 free_property(prop);
193                 BLI_remlink(&ob->prop, prop);
194         }
195         BLI_addtail(&ob->prop, copy_property(propc));
196 }
197
198 /* negative: prop is smaller
199  * positive: prop is larger
200  */
201 int compare_property(bProperty *prop, char *str)
202 {
203 //      extern int Gdfra;               /* sector.c */
204         float fvalue, ftest;
205         
206         switch(prop->type) {
207         case GPROP_BOOL:
208                 if(BLI_strcasecmp(str, "true")==0) {
209                         if(prop->data==1) return 0;
210                         else return 1;
211                 }
212                 else if(BLI_strcasecmp(str, "false")==0) {
213                         if(prop->data==0) return 0;
214                         else return 1;
215                 }
216                 /* no break, do GPROP_int too! */
217                 
218         case GPROP_INT:
219                 return prop->data - atoi(str);
220
221         case GPROP_FLOAT:
222         case GPROP_TIME:
223                 // WARNING: untested for GPROP_TIME
224                 // function isn't used currently
225                 fvalue= *((float *)&prop->data);
226                 ftest= (float)atof(str);
227                 if( fvalue > ftest) return 1;
228                 else if( fvalue < ftest) return -1;
229                 return 0;
230
231         case GPROP_STRING:
232                 return strcmp(prop->poin, str);
233         }
234         
235         return 0;
236 }
237
238 void set_property(bProperty *prop, char *str)
239 {
240 //      extern int Gdfra;               /* sector.c */
241
242         switch(prop->type) {
243         case GPROP_BOOL:
244                 if(BLI_strcasecmp(str, "true")==0) prop->data= 1;
245                 else if(BLI_strcasecmp(str, "false")==0) prop->data= 0;
246                 else prop->data= (atoi(str)!=0);
247                 break;
248         case GPROP_INT:
249                 prop->data= atoi(str);
250                 break;
251         case GPROP_FLOAT:
252         case GPROP_TIME:
253                 *((float *)&prop->data)= (float)atof(str);
254                 break;
255         case GPROP_STRING:
256                 strcpy(prop->poin, str);
257                 break;
258         }
259         
260 }
261
262 void add_property(bProperty *prop, char *str)
263 {
264 //      extern int Gdfra;               /* sector.c */
265
266         switch(prop->type) {
267         case GPROP_BOOL:
268         case GPROP_INT:
269                 prop->data+= atoi(str);
270                 break;
271         case GPROP_FLOAT:
272         case GPROP_TIME:
273                 *((float *)&prop->data)+= (float)atof(str);
274                 break;
275         case GPROP_STRING:
276                 /* strcpy(prop->poin, str); */
277                 break;
278         }
279 }
280
281 /* reads value of property, sets it in chars in str */
282 void set_property_valstr(bProperty *prop, char *str)
283 {
284 //      extern int Gdfra;               /* sector.c */
285
286         if(str == NULL) return;
287
288         switch(prop->type) {
289         case GPROP_BOOL:
290         case GPROP_INT:
291                 sprintf(str, "%d", prop->data);
292                 break;
293         case GPROP_FLOAT:
294         case GPROP_TIME:
295                 sprintf(str, "%f", *((float *)&prop->data));
296                 break;
297         case GPROP_STRING:
298                 BLI_strncpy(str, prop->poin, MAX_PROPSTRING);
299                 break;
300         }
301 }
302
303 void cp_property(bProperty *prop1, bProperty *prop2)
304 {
305         char str[128];
306
307         set_property_valstr(prop2, str);
308
309         set_property(prop1, str);
310 }