- merged latest version of fluid solver
[blender.git] / intern / elbeem / intern / attributes.cpp
1 /******************************************************************************
2  *
3  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
4  * Copyright 2003,2004 Nils Thuerey
5  *
6  * configuration attribute storage class and attribute class
7  *
8  *****************************************************************************/
9
10 #include "attributes.h"
11 #include <sstream>
12
13
14 //! output attribute values? on=1/off=0
15 #define DEBUG_ATTRIBUTES 0
16
17
18 /******************************************************************************
19  * attribute conversion functions
20  *****************************************************************************/
21
22 // get value as string 
23 string Attribute::getAsString()
24 {
25         if(mValue.size()!=1) {
26                 //errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string has invalid value '"<< getCompleteString() <<"' ");
27                 // for directories etc. , this might be valid! cutoff "..." first
28                 string comp = getCompleteString();
29                 if(comp.size()<2) return string("");
30                 return comp.substr(1, comp.size()-2);
31         }
32         return mValue[0];
33 }
34
35 // get value as integer value
36 int Attribute::getAsInt()
37 {
38         bool success = true;
39         int ret = 0;
40         if(mValue.size()!=1) success = false;
41         else {
42                 const char *str = mValue[0].c_str();
43                 char *endptr;
44                 ret = strtol(str, &endptr, 10);
45                 if( (str==endptr) ||
46                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
47         }
48
49         if(!success) {
50                 errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as int has invalid value '"<< getCompleteString() <<"' ");
51                 errMsg("Attribute::getAsString", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
52                 errMsg("Attribute::getAsString", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
53                 return 0;
54         }
55         return ret;
56 }
57
58
59 // get value as integer value
60 bool Attribute::getAsBool() 
61 {
62         int val = getAsInt();
63         if(val==0) return false;
64         else                     return true;
65 }
66
67
68 // get value as double value
69 double Attribute::getAsFloat()
70 {
71         bool success = true;
72         double ret = 0.0;
73         if(mValue.size()!=1) success = false;
74         else {
75                 const char *str = mValue[0].c_str();
76                 char *endptr;
77                 ret = strtod(str, &endptr);
78                 if((str!=endptr) && (*endptr != '\0')) success = false;
79         }
80
81         if(!success) {
82                 errMsg("Attribute::getAsFloat", "Attribute \"" << mName << "\" used as double has invalid value '"<< getCompleteString() <<"' ");
83                 errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
84                 errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
85                 return 0.0;
86         }
87         return ret;
88 }
89
90 // get value as 3d vector 
91 ntlVec3d Attribute::getAsVec3d()
92 {
93         bool success = true;
94         ntlVec3d ret(0.0);
95         if(mValue.size()==1) {
96                 const char *str = mValue[0].c_str();
97                 char *endptr;
98                 double rval = strtod(str, &endptr);
99                 if( (str==endptr) ||
100                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
101                 if(success) ret = ntlVec3d( rval );
102         } else if(mValue.size()==3) {
103                 char *endptr;
104                 const char *str = NULL;
105
106                 str = mValue[0].c_str();
107                 double rval1 = strtod(str, &endptr);
108                 if( (str==endptr) ||
109                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
110
111                 str = mValue[1].c_str();
112                 double rval2 = strtod(str, &endptr);
113                 if( (str==endptr) ||
114                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
115
116                 str = mValue[2].c_str();
117                 double rval3 = strtod(str, &endptr);
118                 if( (str==endptr) ||
119                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
120
121                 if(success) ret = ntlVec3d( rval1, rval2, rval3 );
122         } else {
123                 success = false;
124         }
125
126         if(!success) {
127                 errMsg("Attribute::getAsVec3d", "Attribute \"" << mName << "\" used as Vec3d has invalid value '"<< getCompleteString() <<"' ");
128                 errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
129                 errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
130                 return ntlVec3d(0.0);
131         }
132         return ret;
133 }
134                 
135 // get value as 4x4 matrix 
136 ntlMat4Gfx Attribute::getAsMat4Gfx()
137 {
138         bool success = true;
139         ntlMat4Gfx ret(0.0);
140         char *endptr;
141
142         if(mValue.size()==1) {
143                 const char *str = mValue[0].c_str();
144                 double rval = strtod(str, &endptr);
145                 if( (str==endptr) ||
146                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
147                 if(success) {
148                         ret = ntlMat4Gfx( 0.0 );
149                         ret.value[0][0] = rval;
150                         ret.value[1][1] = rval;
151                         ret.value[2][2] = rval;
152                         ret.value[3][3] = 1.0;
153                 }
154         } else if(mValue.size()==9) {
155                 // 3x3
156                 for(int i=0; i<3;i++) {
157                         for(int j=0; j<3;j++) {
158                                 const char *str = mValue[i*3+j].c_str();
159                                 ret.value[i][j] = strtod(str, &endptr);
160                                 if( (str==endptr) ||
161                                                 ((str!=endptr) && (*endptr != '\0')) ) success = false;
162                         }
163                 }
164         } else if(mValue.size()==16) {
165                 // 4x4
166                 for(int i=0; i<4;i++) {
167                         for(int j=0; j<4;j++) {
168                                 const char *str = mValue[i*4+j].c_str();
169                                 ret.value[i][j] = strtod(str, &endptr);
170                                 if( (str==endptr) ||
171                                                 ((str!=endptr) && (*endptr != '\0')) ) success = false;
172                         }
173                 }
174
175         } else {
176                 success = false;
177         }
178
179         if(!success) {
180                 errMsg("Attribute::getAsMat4Gfx", "Attribute \"" << mName << "\" used as Mat4x4 has invalid value '"<< getCompleteString() <<"' ");
181                 errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
182                 errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
183                 return ntlMat4Gfx(0.0);
184         }
185         return ret;
186 }
187                 
188
189 // get the concatenated string of all value string
190 string Attribute::getCompleteString()
191 {
192         string ret;
193         for(size_t i=0;i<mValue.size();i++) {
194                 ret += mValue[i];
195                 if(i<mValue.size()-1) ret += " ";
196         }
197         return ret;
198 }
199
200
201 /******************************************************************************
202  * check if there were unknown params
203  *****************************************************************************/
204 bool AttributeList::checkUnusedParams()
205 {
206         bool found = false;
207         for(map<string, Attribute*>::iterator i=mAttrs.begin();
208                         i != mAttrs.end(); i++) {
209                 if((*i).second) {
210                         if(!(*i).second->getUsed()) {
211                                 errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString() <<"' ");
212                                 found = true;
213                         }
214                 }
215         }
216         return found;
217 }
218 //! set all params to used, for invisible objects
219 void AttributeList::setAllUsed() {
220         for(map<string, Attribute*>::iterator i=mAttrs.begin();
221                         i != mAttrs.end(); i++) {
222                 if((*i).second) {
223                         (*i).second->setUsed(true);
224                 }
225         }
226 }
227
228 /******************************************************************************
229  * Attribute list read functions
230  *****************************************************************************/
231 int AttributeList::readInt(string name, int defaultValue, string source,string target, bool needed) {
232         if(!exists(name)) {
233                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
234                 return defaultValue;
235         } 
236         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
237         find(name)->setUsed(true);
238         return find(name)->getAsInt(); 
239 }
240 bool AttributeList::readBool(string name, bool defaultValue, string source,string target, bool needed) {
241         if(!exists(name)) {
242                 if(needed) { errFatal("AttributeList::readBool","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
243                 return defaultValue;
244         } 
245         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
246         find(name)->setUsed(true);
247         return find(name)->getAsBool(); 
248 }
249 double AttributeList::readFloat(string name, double defaultValue, string source,string target, bool needed) {
250         if(!exists(name)) {
251                 if(needed) { errFatal("AttributeList::readFloat","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
252                 return defaultValue;
253         } 
254         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
255         find(name)->setUsed(true);
256         return find(name)->getAsFloat(); 
257 }
258 string AttributeList::readString(string name, string defaultValue, string source,string target, bool needed) {
259         if(!exists(name)) {
260                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
261                 return defaultValue;
262         } 
263         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
264         find(name)->setUsed(true);
265         return find(name)->getAsString(); 
266 }
267 ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed) {
268         if(!exists(name)) {
269                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
270                 return defaultValue;
271         } 
272         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
273         find(name)->setUsed(true);
274         return find(name)->getAsVec3d(); 
275 }
276
277 ntlMat4Gfx AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed) {
278         if(!exists(name)) {
279                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
280                 return defaultValue;
281         } 
282         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
283         find(name)->setUsed(true);
284         return find(name)->getAsMat4Gfx(); 
285 }
286
287 // set that a parameter can be given, and will be ignored...
288 bool AttributeList::ignoreParameter(string name, string source) {
289         if(!exists(name)) return false;
290         find(name)->setUsed(true);
291         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Param '"<< name <<"' set but ignored... " , 3); }
292         return true;
293 }
294                 
295 /******************************************************************************
296  * destructor
297  *****************************************************************************/
298 AttributeList::~AttributeList() { 
299         for(map<string, Attribute*>::iterator i=mAttrs.begin();
300                         i != mAttrs.end(); i++) {
301                 if((*i).second) {
302                         delete (*i).second;
303                         (*i).second = NULL;
304                 }
305         }
306 };
307
308
309 /******************************************************************************
310  * debugging
311  *****************************************************************************/
312
313 //! debug function, prints value 
314 void Attribute::print()
315 {
316         std::ostringstream ostr;
317         ostr << "  "<< mName <<"= ";
318         for(size_t i=0;i<mValue.size();i++) {
319                 ostr <<"'"<< mValue[i]<<"' ";
320         }
321         ostr <<" (at line "<<mLine<<") "; //<< std::endl;
322         debugOut( ostr.str(), 10);
323 }
324                 
325 //! debug function, prints all attribs 
326 void AttributeList::print()
327 {
328         debugOut("Attribute "<<mName<<" values:", 10);
329         for(map<string, Attribute*>::iterator i=mAttrs.begin();
330                         i != mAttrs.end(); i++) {
331                 if((*i).second) {
332                         (*i).second->print();
333                 }
334         }
335 }
336
337
338
339 /******************************************************************************
340  * import attributes from other attribute list
341  *****************************************************************************/
342 void AttributeList::import(AttributeList *oal)
343 {
344         for(map<string, Attribute*>::iterator i=oal->mAttrs.begin();
345                         i !=oal->mAttrs.end(); i++) {
346                 // FIXME - check freeing of copyied attributes
347                 if((*i).second) {
348                         Attribute *newAttr = new Attribute( *(*i).second );
349                         mAttrs[ (*i).first ] = newAttr;
350                 }
351         }
352 }
353
354
355
356