Blender V2.61 - r43446

property.c

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