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