Blender  V2.59
property.c
Go to the documentation of this file.
00001 
00002 /*  property.c   june 2000
00003  * 
00004  *  ton roosendaal
00005  * $Id: property.c 35247 2011-02-27 20:40:57Z jesterking $
00006  *
00007  * ***** BEGIN GPL LICENSE BLOCK *****
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00024  * All rights reserved.
00025  *
00026  * The Original Code is: all of this file.
00027  *
00028  * Contributor(s): none yet.
00029  *
00030  * ***** END GPL LICENSE BLOCK *****
00031  */
00032 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <stddef.h>
00041 #include <string.h>
00042 #include <ctype.h>
00043 
00044 #include "MEM_guardedalloc.h"
00045 
00046 #include "DNA_property_types.h"
00047 #include "DNA_object_types.h"
00048 
00049 #include "BLI_blenlib.h"
00050 
00051 #include "BKE_property.h"
00052 
00053 void free_property(bProperty *prop)
00054 {
00055         
00056         if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
00057         MEM_freeN(prop);
00058         
00059 }
00060 
00061 void free_properties(ListBase *lb)
00062 {
00063         bProperty *prop;
00064         
00065         while( (prop= lb->first) ) {
00066                 BLI_remlink(lb, prop);
00067                 free_property(prop);
00068         }
00069 }
00070 
00071 bProperty *copy_property(bProperty *prop)
00072 {
00073         bProperty *propn;
00074         
00075         propn= MEM_dupallocN(prop);
00076         if(prop->poin && prop->poin != &prop->data) {
00077                 propn->poin= MEM_dupallocN(prop->poin);
00078         }
00079         else propn->poin= &propn->data;
00080         
00081         return propn;
00082 }
00083 
00084 void copy_properties(ListBase *lbn, ListBase *lbo)
00085 {
00086         bProperty *prop, *propn;
00087         free_properties( lbn ); /* incase we are copying to an object with props */
00088         prop= lbo->first;
00089         while(prop) {
00090                 propn= copy_property(prop);
00091                 BLI_addtail(lbn, propn);
00092                 prop= prop->next;
00093         }
00094         
00095         
00096 }
00097 
00098 void init_property(bProperty *prop)
00099 {
00100         /* also use when property changes type */
00101         
00102         if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
00103         prop->poin= NULL;
00104         
00105         prop->data= 0;
00106         
00107         switch(prop->type) {
00108         case GPROP_BOOL:
00109         case GPROP_INT:
00110         case GPROP_FLOAT:
00111         case GPROP_TIME:
00112                 prop->poin= &prop->data;
00113                 break;
00114         case GPROP_STRING:
00115                 prop->poin= MEM_callocN(MAX_PROPSTRING, "property string");
00116                 break;
00117         }
00118 }
00119 
00120 
00121 bProperty *new_property(int type)
00122 {
00123         bProperty *prop;
00124 
00125         prop= MEM_callocN(sizeof(bProperty), "property");
00126         prop->type= type;
00127 
00128         init_property(prop);
00129         
00130         strcpy(prop->name, "prop");
00131 
00132         return prop;
00133 }
00134 
00135 /* used by unique_property() only */
00136 static bProperty *get_property__internal(bProperty *first, bProperty *self, const char *name)
00137 {
00138         bProperty *p;
00139         for(p= first; p; p= p->next) {
00140                 if (p!=self && (strcmp(p->name, name)==0))
00141                         return p;
00142         }
00143         return NULL;
00144 }
00145 void unique_property(bProperty *first, bProperty *prop, int force)
00146 {
00147         bProperty *p;
00148 
00149         /* set the first if its not set */
00150         if(first==NULL) {
00151                 first= prop;
00152                 while(first->prev) {
00153                         first= first->prev;
00154                 }
00155         }
00156 
00157         if(force) {
00158                 /* change other names to make them unique */
00159                 while((p = get_property__internal(first, prop, prop->name))) {
00160                         unique_property(first, p, 0);
00161                 }
00162         }else {
00163                 /* change our own name until its unique */
00164                 if(get_property__internal(first, prop, prop->name)) {
00165                         /* there is a collision */
00166                         char new_name[sizeof(prop->name)];
00167                         char base_name[sizeof(prop->name)];
00168                         char num[sizeof(prop->name)];
00169                         int i= 0;
00170 
00171                         /* strip numbers */
00172                         strcpy(base_name, prop->name);
00173                         for(i= strlen(base_name)-1; (i>=0 && isdigit(base_name[i])); i--) {
00174                                 base_name[i]= '\0';
00175                         }
00176                         i= 0;
00177 
00178                         do { /* ensure we have enough chars for the new number in the name */
00179                                 sprintf(num, "%d", i++);
00180                                 BLI_strncpy(new_name, base_name, sizeof(prop->name) - strlen(num));
00181                                 strcat(new_name, num);
00182                         } while(get_property__internal(first, prop, new_name));
00183 
00184                         strcpy(prop->name, new_name);
00185                 }
00186         }
00187 }
00188 
00189 bProperty *get_ob_property(Object *ob, const char *name)
00190 {
00191         return BLI_findstring(&ob->prop, name, offsetof(bProperty, name));
00192 }
00193 
00194 void set_ob_property(Object *ob, bProperty *propc)
00195 {
00196         bProperty *prop;
00197         prop= get_ob_property(ob, propc->name);
00198         if(prop) {
00199                 free_property(prop);
00200                 BLI_remlink(&ob->prop, prop);
00201         }
00202         BLI_addtail(&ob->prop, copy_property(propc));
00203 }
00204 
00205 /* negative: prop is smaller
00206  * positive: prop is larger
00207  */
00208 int compare_property(bProperty *prop, char *str)
00209 {
00210 //      extern int Gdfra;               /* sector.c */
00211         float fvalue, ftest;
00212         
00213         switch(prop->type) {
00214         case GPROP_BOOL:
00215                 if(BLI_strcasecmp(str, "true")==0) {
00216                         if(prop->data==1) return 0;
00217                         else return 1;
00218                 }
00219                 else if(BLI_strcasecmp(str, "false")==0) {
00220                         if(prop->data==0) return 0;
00221                         else return 1;
00222                 }
00223                 /* no break, do GPROP_int too! */
00224                 
00225         case GPROP_INT:
00226                 return prop->data - atoi(str);
00227 
00228         case GPROP_FLOAT:
00229         case GPROP_TIME:
00230                 // WARNING: untested for GPROP_TIME
00231                 // function isn't used currently
00232                 fvalue= *((float *)&prop->data);
00233                 ftest= (float)atof(str);
00234                 if( fvalue > ftest) return 1;
00235                 else if( fvalue < ftest) return -1;
00236                 return 0;
00237 
00238         case GPROP_STRING:
00239                 return strcmp(prop->poin, str);
00240         }
00241         
00242         return 0;
00243 }
00244 
00245 void set_property(bProperty *prop, char *str)
00246 {
00247 //      extern int Gdfra;               /* sector.c */
00248 
00249         switch(prop->type) {
00250         case GPROP_BOOL:
00251                 if(BLI_strcasecmp(str, "true")==0) prop->data= 1;
00252                 else if(BLI_strcasecmp(str, "false")==0) prop->data= 0;
00253                 else prop->data= (atoi(str)!=0);
00254                 break;
00255         case GPROP_INT:
00256                 prop->data= atoi(str);
00257                 break;
00258         case GPROP_FLOAT:
00259         case GPROP_TIME:
00260                 *((float *)&prop->data)= (float)atof(str);
00261                 break;
00262         case GPROP_STRING:
00263                 strcpy(prop->poin, str);
00264                 break;
00265         }
00266         
00267 }
00268 
00269 void add_property(bProperty *prop, char *str)
00270 {
00271 //      extern int Gdfra;               /* sector.c */
00272 
00273         switch(prop->type) {
00274         case GPROP_BOOL:
00275         case GPROP_INT:
00276                 prop->data+= atoi(str);
00277                 break;
00278         case GPROP_FLOAT:
00279         case GPROP_TIME:
00280                 *((float *)&prop->data)+= (float)atof(str);
00281                 break;
00282         case GPROP_STRING:
00283                 /* strcpy(prop->poin, str); */
00284                 break;
00285         }
00286 }
00287 
00288 /* reads value of property, sets it in chars in str */
00289 void set_property_valstr(bProperty *prop, char *str)
00290 {
00291 //      extern int Gdfra;               /* sector.c */
00292 
00293         if(str == NULL) return;
00294 
00295         switch(prop->type) {
00296         case GPROP_BOOL:
00297         case GPROP_INT:
00298                 sprintf(str, "%d", prop->data);
00299                 break;
00300         case GPROP_FLOAT:
00301         case GPROP_TIME:
00302                 sprintf(str, "%f", *((float *)&prop->data));
00303                 break;
00304         case GPROP_STRING:
00305                 BLI_strncpy(str, prop->poin, MAX_PROPSTRING);
00306                 break;
00307         }
00308 }
00309 
00310 void cp_property(bProperty *prop1, bProperty *prop2)
00311 {
00312         char str[128];
00313 
00314         set_property_valstr(prop2, str);
00315 
00316         set_property(prop1, str);
00317 }