1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #include "CAttributes.h"
6 #include "fast_atof.h"
7 #include "ITexture.h"
8 #include "IVideoDriver.h"
9 
10 namespace irr
11 {
12 namespace io
13 {
14 
15 /*
16 	basic types
17 */
18 
19 // Attribute implemented for boolean values
20 class CBoolAttribute : public IAttribute
21 {
22 public:
23 
CBoolAttribute(const char * name,bool value)24 	CBoolAttribute(const char* name, bool value)
25 	{
26 		Name = name;
27 		setBool(value);
28 	}
29 
getInt()30 	virtual s32 getInt()
31 	{
32 		return BoolValue ? 1 : 0;
33 	}
34 
getFloat()35 	virtual f32 getFloat()
36 	{
37 		return BoolValue ? 1.0f : 0.0f;
38 	}
39 
getBool()40 	virtual bool getBool()
41 	{
42 		return BoolValue;
43 	}
44 
getStringW()45 	virtual core::stringw getStringW()
46 	{
47 		return core::stringw( BoolValue ? L"true" : L"false" );
48 	}
49 
setInt(s32 intValue)50 	virtual void setInt(s32 intValue)
51 	{
52 		BoolValue = (intValue != 0);
53 	}
54 
setFloat(f32 floatValue)55 	virtual void setFloat(f32 floatValue)
56 	{
57 		BoolValue = (floatValue != 0);
58 	}
59 
setBool(bool boolValue)60 	virtual void setBool(bool boolValue)
61 	{
62 		BoolValue = boolValue;
63 	}
64 
setString(const char * string)65 	virtual void setString(const char* string)
66 	{
67 		BoolValue = strcmp(string, "true") == 0;
68 	}
69 
getType()70 	virtual E_ATTRIBUTE_TYPE getType() const
71 	{
72 		return EAT_BOOL;
73 	}
74 
getTypeString()75 	virtual const wchar_t* getTypeString() const
76 	{
77 		return L"bool";
78 	}
79 
80 	bool BoolValue;
81 };
82 
83 // Attribute implemented for integers
84 class CIntAttribute : public IAttribute
85 {
86 public:
87 
CIntAttribute(const char * name,s32 value)88 	CIntAttribute(const char* name, s32 value)
89 	{
90 		Name = name;
91 		setInt(value);
92 	}
93 
getInt()94 	virtual s32 getInt()
95 	{
96 		return Value;
97 	}
98 
getFloat()99 	virtual f32 getFloat()
100 	{
101 		return (f32)Value;
102 	}
103 
getBool()104 	virtual bool getBool()
105 	{
106 		return (Value != 0);
107 	}
108 
getStringW()109 	virtual core::stringw getStringW()
110 	{
111 		return core::stringw(Value);
112 	}
113 
setInt(s32 intValue)114 	virtual void setInt(s32 intValue)
115 	{
116 		Value = intValue;
117 	}
118 
setFloat(f32 floatValue)119 	virtual void setFloat(f32 floatValue)
120 	{
121 		Value = (s32)floatValue;
122 	};
123 
setString(const char * text)124 	virtual void setString(const char* text)
125 	{
126 		Value = atoi(text);
127 	}
128 
getType()129 	virtual E_ATTRIBUTE_TYPE getType() const
130 	{
131 		return EAT_INT;
132 	}
133 
134 
getTypeString()135 	virtual const wchar_t* getTypeString() const
136 	{
137 		return L"int";
138 	}
139 
140 	s32 Value;
141 };
142 
143 // Attribute implemented for floats
144 class CFloatAttribute : public IAttribute
145 {
146 public:
147 
CFloatAttribute(const char * name,f32 value)148 	CFloatAttribute(const char* name, f32 value)
149 	{
150 		Name = name;
151 		setFloat(value);
152 	}
153 
getInt()154 	virtual s32 getInt()
155 	{
156 		return (s32)Value;
157 	}
158 
getFloat()159 	virtual f32 getFloat()
160 	{
161 		return Value;
162 	}
163 
getBool()164 	virtual bool getBool()
165 	{
166 		return (Value != 0);
167 	}
168 
getStringW()169 	virtual core::stringw getStringW()
170 	{
171 		return core::stringw((double)Value);
172 	}
173 
setInt(s32 intValue)174 	virtual void setInt(s32 intValue)
175 	{
176 		Value = (f32)intValue;
177 	}
178 
setFloat(f32 floatValue)179 	virtual void setFloat(f32 floatValue)
180 	{
181 		Value = floatValue;
182 	}
183 
setString(const char * text)184 	virtual void setString(const char* text)
185 	{
186 		Value = core::fast_atof(text);
187 	}
188 
getType()189 	virtual E_ATTRIBUTE_TYPE getType() const
190 	{
191 		return EAT_FLOAT;
192 	}
193 
194 
getTypeString()195 	virtual const wchar_t* getTypeString() const
196 	{
197 		return L"float";
198 	}
199 
200 	f32 Value;
201 };
202 
203 
204 
205 /*
206 	Types which can be represented as a list of numbers
207 */
208 
209 // Base class for all attributes which are a list of numbers-
210 // vectors, colors, positions, triangles, etc
211 class CNumbersAttribute : public IAttribute
212 {
213 public:
214 
CNumbersAttribute(const char * name,video::SColorf value)215 	CNumbersAttribute(const char* name, video::SColorf value) :
216 		ValueI(), ValueF(), Count(4), IsFloat(true)
217 	{
218 		Name = name;
219 		ValueF.push_back(value.r);
220 		ValueF.push_back(value.g);
221 		ValueF.push_back(value.b);
222 		ValueF.push_back(value.a);
223 	}
224 
CNumbersAttribute(const char * name,video::SColor value)225 	CNumbersAttribute(const char* name, video::SColor value) :
226 		ValueI(), ValueF(), Count(4), IsFloat(false)
227 	{
228 		Name = name;
229 		ValueI.push_back(value.getRed());
230 		ValueI.push_back(value.getGreen());
231 		ValueI.push_back(value.getBlue());
232 		ValueI.push_back(value.getAlpha());
233 	}
234 
235 
CNumbersAttribute(const char * name,core::vector3df value)236 	CNumbersAttribute(const char* name, core::vector3df value) :
237 		ValueI(), ValueF(), Count(3), IsFloat(true)
238 	{
239 		Name = name;
240 		ValueF.push_back(value.X);
241 		ValueF.push_back(value.Y);
242 		ValueF.push_back(value.Z);
243 	}
244 
CNumbersAttribute(const char * name,core::rect<s32> value)245 	CNumbersAttribute(const char* name, core::rect<s32> value) :
246 		ValueI(), ValueF(), Count(4), IsFloat(false)
247 	{
248 		Name = name;
249 		ValueI.push_back(value.UpperLeftCorner.X);
250 		ValueI.push_back(value.UpperLeftCorner.Y);
251 		ValueI.push_back(value.LowerRightCorner.X);
252 		ValueI.push_back(value.LowerRightCorner.Y);
253 	}
254 
CNumbersAttribute(const char * name,core::rect<f32> value)255 	CNumbersAttribute(const char* name, core::rect<f32> value) :
256 		ValueI(), ValueF(), Count(4), IsFloat(true)
257 	{
258 		Name = name;
259 		ValueF.push_back(value.UpperLeftCorner.X);
260 		ValueF.push_back(value.UpperLeftCorner.Y);
261 		ValueF.push_back(value.LowerRightCorner.X);
262 		ValueF.push_back(value.LowerRightCorner.Y);
263 	}
264 
CNumbersAttribute(const char * name,core::matrix4 value)265 	CNumbersAttribute(const char* name, core::matrix4 value) :
266 		ValueI(), ValueF(), Count(16), IsFloat(true)
267 	{
268 		Name = name;
269 		for (s32 r=0; r<4; ++r)
270 			for (s32 c=0; c<4; ++c)
271 				ValueF.push_back(value(r,c));
272 	}
273 
CNumbersAttribute(const char * name,core::quaternion value)274 	CNumbersAttribute(const char* name, core::quaternion value) :
275 		ValueI(), ValueF(), Count(4), IsFloat(true)
276 	{
277 		Name = name;
278 		ValueF.push_back(value.X);
279 		ValueF.push_back(value.Y);
280 		ValueF.push_back(value.Z);
281 		ValueF.push_back(value.W);
282 	}
283 
CNumbersAttribute(const char * name,core::aabbox3d<f32> value)284 	CNumbersAttribute(const char* name, core::aabbox3d<f32> value) :
285 		ValueI(), ValueF(), Count(6), IsFloat(true)
286 	{
287 		Name = name;
288 		ValueF.push_back(value.MinEdge.X);
289 		ValueF.push_back(value.MinEdge.Y);
290 		ValueF.push_back(value.MinEdge.Z);
291 		ValueF.push_back(value.MaxEdge.X);
292 		ValueF.push_back(value.MaxEdge.Y);
293 		ValueF.push_back(value.MaxEdge.Z);
294 	}
295 
CNumbersAttribute(const char * name,core::plane3df value)296 	CNumbersAttribute(const char* name, core::plane3df value) :
297 		ValueI(), ValueF(), Count(4), IsFloat(true)
298 	{
299 		Name = name;
300 		ValueF.push_back(value.Normal.X);
301 		ValueF.push_back(value.Normal.Y);
302 		ValueF.push_back(value.Normal.Z);
303 		ValueF.push_back(value.D);
304 	}
305 
CNumbersAttribute(const char * name,core::triangle3df value)306 	CNumbersAttribute(const char* name, core::triangle3df value) :
307 		ValueI(), ValueF(), Count(9), IsFloat(true)
308 	{
309 		Name = name;
310 		ValueF.push_back(value.pointA.X);
311 		ValueF.push_back(value.pointA.Y);
312 		ValueF.push_back(value.pointA.Z);
313 		ValueF.push_back(value.pointB.X);
314 		ValueF.push_back(value.pointB.Y);
315 		ValueF.push_back(value.pointB.Z);
316 		ValueF.push_back(value.pointC.X);
317 		ValueF.push_back(value.pointC.Y);
318 		ValueF.push_back(value.pointC.Z);
319 	}
320 
CNumbersAttribute(const char * name,core::vector2df value)321 	CNumbersAttribute(const char* name, core::vector2df value) :
322 		ValueI(), ValueF(), Count(2), IsFloat(true)
323 	{
324 		Name = name;
325 		ValueF.push_back(value.X);
326 		ValueF.push_back(value.Y);
327 	}
328 
CNumbersAttribute(const char * name,core::vector2di value)329 	CNumbersAttribute(const char* name, core::vector2di value) :
330 		ValueI(), ValueF(), Count(2), IsFloat(false)
331 	{
332 		Name = name;
333 		ValueI.push_back(value.X);
334 		ValueI.push_back(value.Y);
335 	}
336 
CNumbersAttribute(const char * name,core::line2di value)337 	CNumbersAttribute(const char* name, core::line2di value) :
338 		ValueI(), ValueF(), Count(4), IsFloat(false)
339 	{
340 		Name = name;
341 		ValueI.push_back(value.start.X);
342 		ValueI.push_back(value.start.Y);
343 		ValueI.push_back(value.end.X);
344 		ValueI.push_back(value.end.Y);
345 	}
346 
CNumbersAttribute(const char * name,core::line2df value)347 	CNumbersAttribute(const char* name, core::line2df value) :
348 		ValueI(), ValueF(), Count(4), IsFloat(true)
349 	{
350 		Name = name;
351 		ValueF.push_back(value.start.X);
352 		ValueF.push_back(value.start.Y);
353 		ValueF.push_back(value.end.X);
354 		ValueF.push_back(value.end.Y);
355 	}
356 
CNumbersAttribute(const char * name,core::line3df value)357 	CNumbersAttribute(const char* name, core::line3df value) :
358 		ValueI(), ValueF(), Count(6), IsFloat(true)
359 	{
360 		Name = name;
361 		ValueF.push_back(value.start.X);
362 		ValueF.push_back(value.start.Y);
363 		ValueF.push_back(value.start.Z);
364 		ValueF.push_back(value.end.X);
365 		ValueF.push_back(value.end.Y);
366 		ValueF.push_back(value.end.Z);
367 	}
368 
CNumbersAttribute(const char * name,core::dimension2du value)369 	CNumbersAttribute(const char* name, core::dimension2du value) :
370 		ValueI(), ValueF(), Count(2), IsFloat(false)
371 	{
372 		Name = name;
373 		ValueI.push_back(value.Width);
374 		ValueI.push_back(value.Height);
375 	}
376 
377 
CNumbersAttribute(const char * name,core::dimension2df value)378 	CNumbersAttribute(const char* name, core::dimension2df value) :
379 		ValueI(), ValueF(), Count(2), IsFloat(true)
380 	{
381 		Name = name;
382 		ValueF.push_back(value.Width);
383 		ValueF.push_back(value.Height);
384 	}
385 
386 
387 
388 	// getting values
getInt()389 	virtual s32 getInt()
390 	{
391 		if (Count==0)
392 			return 0;
393 
394 		if (IsFloat)
395 			return (s32)ValueF[0];
396 		else
397 			return ValueI[0];
398 	}
399 
getFloat()400 	virtual f32 getFloat()
401 	{
402 		if (Count==0)
403 			return 0.0f;
404 
405 		if (IsFloat)
406 			return ValueF[0];
407 		else
408 			return (f32)ValueI[0];
409 	}
410 
getBool()411 	virtual bool getBool()
412 	{
413 		// return true if any number is nonzero
414 		bool ret=false;
415 
416 		for (u32 i=0; i < Count; ++i)
417 			if ( IsFloat ? (ValueF[i] != 0) : (ValueI[i] != 0) )
418 			{
419 				ret=true;
420 				break;
421 			}
422 
423 		return ret;
424 
425 	}
426 
427 
getString()428 	virtual core::stringc getString()
429 	{
430 		core::stringc outstr;
431 
432 		for (u32 i=0; i <Count; ++i)
433 		{
434 			if (IsFloat)
435 				outstr += ValueF[i];
436 			else
437 				outstr += ValueI[i];
438 
439 			if (i < Count-1)
440 				outstr += ", ";
441 		}
442 		return outstr;
443 	}
getStringW()444 	virtual core::stringw getStringW()
445 	{
446 		core::stringw outstr;
447 
448 		for (u32 i=0; i <Count; ++i)
449 		{
450 			if (IsFloat)
451 				outstr += ValueF[i];
452 			else
453 				outstr += ValueI[i];
454 
455 			if (i < Count-1)
456 				outstr += L", ";
457 		}
458 		return outstr;
459 	}
460 
getPosition()461 	virtual core::position2di getPosition()
462 	{
463 		core::position2di p;
464 
465 		if (IsFloat)
466 		{
467 			p.X = (s32)(Count > 0 ? ValueF[0] : 0);
468 			p.Y = (s32)(Count > 1 ? ValueF[1] : 0);
469 		}
470 		else
471 		{
472 			p.X = Count > 0 ? ValueI[0] : 0;
473 			p.Y = Count > 1 ? ValueI[1] : 0;
474 		}
475 
476 		return p;
477 	}
478 
getVector()479 	virtual core::vector3df getVector()
480 	{
481 		core::vector3df v;
482 
483 		if (IsFloat)
484 		{
485 			v.X = Count > 0 ? ValueF[0] : 0;
486 			v.Y = Count > 1 ? ValueF[1] : 0;
487 			v.Z = Count > 2 ? ValueF[2] : 0;
488 		}
489 		else
490 		{
491 			v.X = (f32)(Count > 0 ? ValueI[0] : 0);
492 			v.Y = (f32)(Count > 1 ? ValueI[1] : 0);
493 			v.Z = (f32)(Count > 2 ? ValueI[2] : 0);
494 		}
495 
496 		return v;
497 	}
498 
getVector2d()499 	virtual core::vector2df getVector2d()
500 	{
501 		core::vector2df v;
502 
503 		if (IsFloat)
504 		{
505 			v.X = Count > 0 ? ValueF[0] : 0;
506 			v.Y = Count > 1 ? ValueF[1] : 0;
507 		}
508 		else
509 		{
510 			v.X = (f32)(Count > 0 ? ValueI[0] : 0);
511 			v.Y = (f32)(Count > 1 ? ValueI[1] : 0);
512 		}
513 
514 		return v;
515 	}
516 
getColorf()517 	virtual video::SColorf getColorf()
518 	{
519 		video::SColorf c;
520 		if (IsFloat)
521 		{
522 			c.setColorComponentValue(0, Count > 0 ? ValueF[0] : 0);
523 			c.setColorComponentValue(1, Count > 1 ? ValueF[1] : 0);
524 			c.setColorComponentValue(2, Count > 2 ? ValueF[2] : 0);
525 			c.setColorComponentValue(3, Count > 3 ? ValueF[3] : 0);
526 		}
527 		else
528 		{
529 			c.setColorComponentValue(0, Count > 0 ? (f32)(ValueI[0]) / 255.0f : 0);
530 			c.setColorComponentValue(1, Count > 1 ? (f32)(ValueI[1]) / 255.0f : 0);
531 			c.setColorComponentValue(2, Count > 2 ? (f32)(ValueI[2]) / 255.0f : 0);
532 			c.setColorComponentValue(3, Count > 3 ? (f32)(ValueI[3]) / 255.0f : 0);
533 		}
534 
535 		return c;
536 	}
537 
getColor()538 	virtual video::SColor getColor()
539 	{
540 		return getColorf().toSColor();
541 	}
542 
543 
getRect()544 	virtual core::rect<s32> getRect()
545 	{
546 		core::rect<s32> r;
547 
548 		if (IsFloat)
549 		{
550 			r.UpperLeftCorner.X  = (s32)(Count > 0 ? ValueF[0] : 0);
551 			r.UpperLeftCorner.Y  = (s32)(Count > 1 ? ValueF[1] : 0);
552 			r.LowerRightCorner.X = (s32)(Count > 2 ? ValueF[2] : r.UpperLeftCorner.X);
553 			r.LowerRightCorner.Y = (s32)(Count > 3 ? ValueF[3] : r.UpperLeftCorner.Y);
554 		}
555 		else
556 		{
557 			r.UpperLeftCorner.X  = Count > 0 ? ValueI[0] : 0;
558 			r.UpperLeftCorner.Y  = Count > 1 ? ValueI[1] : 0;
559 			r.LowerRightCorner.X = Count > 2 ? ValueI[2] : r.UpperLeftCorner.X;
560 			r.LowerRightCorner.Y = Count > 3 ? ValueI[3] : r.UpperLeftCorner.Y;
561 		}
562 		return r;
563 	}
564 
getDimension2d()565 	virtual core::dimension2du getDimension2d()
566 	{
567 		core::dimension2d<u32> dim;
568 
569 		if (IsFloat)
570 		{
571 			dim.Width = (u32)(Count > 0 ? ValueF[0] : 0);
572 			dim.Height = (u32)(Count > 1 ? ValueF[1] : 0);
573 		}
574 		else
575 		{
576 			dim.Width = (u32)(Count > 0 ? ValueI[0] : 0);
577 			dim.Height = (u32)(Count > 1 ? ValueI[1] : 0);
578 		}
579 		return dim;
580 	}
581 
getMatrix()582 	virtual core::matrix4 getMatrix()
583 	{
584 		core::matrix4 ret;
585 		if (IsFloat)
586 		{
587 			for (u32 r=0; r<4; ++r)
588 				for (u32 c=0; c<4; ++c)
589 					if (Count > c+r*4)
590 						ret(r,c) = ValueF[c+r*4];
591 		}
592 		else
593 		{
594 			for (u32 r=0; r<4; ++r)
595 				for (u32 c=0; c<4; ++c)
596 					if (Count > c+r*4)
597 						ret(r,c) = (f32)ValueI[c+r*4];
598 		}
599 		return ret;
600 	}
601 
getQuaternion()602 	virtual core::quaternion getQuaternion()
603 	{
604 		core::quaternion ret;
605 		if (IsFloat)
606 		{
607 			ret.X = Count > 0 ? ValueF[0] : 0.0f;
608 			ret.Y = Count > 1 ? ValueF[1] : 0.0f;
609 			ret.Z = Count > 2 ? ValueF[2] : 0.0f;
610 			ret.W = Count > 3 ? ValueF[3] : 0.0f;
611 		}
612 		else
613 		{
614 			ret.X = Count > 0 ? (f32)ValueI[0] : 0.0f;
615 			ret.Y = Count > 1 ? (f32)ValueI[1] : 0.0f;
616 			ret.Z = Count > 2 ? (f32)ValueI[2] : 0.0f;
617 			ret.W = Count > 3 ? (f32)ValueI[3] : 0.0f;
618 		}
619 		return ret;
620 	}
621 
getTriangle()622 	virtual core::triangle3df getTriangle()
623 	{
624 		core::triangle3df ret;
625 
626 		if (IsFloat)
627 		{
628 			ret.pointA.X = Count > 0 ? ValueF[0] : 0.0f;
629 			ret.pointA.Y = Count > 1 ? ValueF[1] : 0.0f;
630 			ret.pointA.Z = Count > 2 ? ValueF[2] : 0.0f;
631 			ret.pointB.X = Count > 3 ? ValueF[3] : 0.0f;
632 			ret.pointB.Y = Count > 4 ? ValueF[4] : 0.0f;
633 			ret.pointB.Z = Count > 5 ? ValueF[5] : 0.0f;
634 			ret.pointC.X = Count > 6 ? ValueF[6] : 0.0f;
635 			ret.pointC.Y = Count > 7 ? ValueF[7] : 0.0f;
636 			ret.pointC.Z = Count > 8 ? ValueF[8] : 0.0f;
637 		}
638 		else
639 		{
640 			ret.pointA.X = Count > 0 ? (f32)ValueI[0] : 0.0f;
641 			ret.pointA.Y = Count > 1 ? (f32)ValueI[1] : 0.0f;
642 			ret.pointA.Z = Count > 2 ? (f32)ValueI[2] : 0.0f;
643 			ret.pointB.X = Count > 3 ? (f32)ValueI[3] : 0.0f;
644 			ret.pointB.Y = Count > 4 ? (f32)ValueI[4] : 0.0f;
645 			ret.pointB.Z = Count > 5 ? (f32)ValueI[5] : 0.0f;
646 			ret.pointC.X = Count > 6 ? (f32)ValueI[6] : 0.0f;
647 			ret.pointC.Y = Count > 7 ? (f32)ValueI[7] : 0.0f;
648 			ret.pointC.Z = Count > 8 ? (f32)ValueI[8] : 0.0f;
649 		}
650 
651 		return ret;
652 	}
653 
getPlane()654 	virtual core::plane3df getPlane()
655 	{
656 		core::plane3df ret;
657 
658 		if (IsFloat)
659 		{
660 			ret.Normal.X = Count > 0 ? ValueF[0] : 0.0f;
661 			ret.Normal.Y = Count > 1 ? ValueF[1] : 0.0f;
662 			ret.Normal.Z = Count > 2 ? ValueF[2] : 0.0f;
663 			ret.D		 = Count > 3 ? ValueF[3] : 0.0f;
664 		}
665 		else
666 		{
667 			ret.Normal.X = Count > 0 ? (f32)ValueI[0] : 0.0f;
668 			ret.Normal.Y = Count > 1 ? (f32)ValueI[1] : 0.0f;
669 			ret.Normal.Z = Count > 2 ? (f32)ValueI[2] : 0.0f;
670 			ret.D		 = Count > 3 ? (f32)ValueI[3] : 0.0f;
671 		}
672 
673 		return ret;
674 	}
675 
getBBox()676 	virtual core::aabbox3df getBBox()
677 	{
678 		core::aabbox3df ret;
679 		if (IsFloat)
680 		{
681 			ret.MinEdge.X = Count > 0 ? ValueF[0] : 0.0f;
682 			ret.MinEdge.Y = Count > 1 ? ValueF[1] : 0.0f;
683 			ret.MinEdge.Z = Count > 2 ? ValueF[2] : 0.0f;
684 			ret.MaxEdge.X = Count > 3 ? ValueF[3] : 0.0f;
685 			ret.MaxEdge.Y = Count > 4 ? ValueF[4] : 0.0f;
686 			ret.MaxEdge.Z = Count > 5 ? ValueF[5] : 0.0f;
687 		}
688 		else
689 		{
690 			ret.MinEdge.X = Count > 0 ? (f32)ValueI[0] : 0.0f;
691 			ret.MinEdge.Y = Count > 1 ? (f32)ValueI[1] : 0.0f;
692 			ret.MinEdge.Z = Count > 2 ? (f32)ValueI[2] : 0.0f;
693 			ret.MaxEdge.X = Count > 3 ? (f32)ValueI[3] : 0.0f;
694 			ret.MaxEdge.Y = Count > 4 ? (f32)ValueI[4] : 0.0f;
695 			ret.MaxEdge.Z = Count > 5 ? (f32)ValueI[5] : 0.0f;
696 		}
697 		return ret;
698 
699 	}
700 
getLine2d()701 	virtual core::line2df getLine2d()
702 	{
703 		core::line2df ret;
704 		if (IsFloat)
705 		{
706 			ret.start.X = Count > 0 ? ValueF[0] : 0.0f;
707 			ret.start.Y = Count > 1 ? ValueF[1] : 0.0f;
708 			ret.end.X   = Count > 2 ? ValueF[2] : 0.0f;
709 			ret.end.Y   = Count > 3 ? ValueF[3] : 0.0f;
710 		}
711 		else
712 		{
713 			ret.start.X = Count > 0 ? (f32)ValueI[0] : 0.0f;
714 			ret.start.Y = Count > 1 ? (f32)ValueI[1] : 0.0f;
715 			ret.end.X   = Count > 2 ? (f32)ValueI[2] : 0.0f;
716 			ret.end.Y   = Count > 3 ? (f32)ValueI[3] : 0.0f;
717 		}
718 		return ret;
719 	}
720 
getLine3d()721 	virtual core::line3df getLine3d()
722 	{
723 		core::line3df ret;
724 		if (IsFloat)
725 		{
726 			ret.start.X = Count > 0 ? ValueF[0] : 0.0f;
727 			ret.start.Y = Count > 1 ? ValueF[1] : 0.0f;
728 			ret.start.Z = Count > 2 ? ValueF[2] : 0.0f;
729 			ret.end.X   = Count > 3 ? ValueF[3] : 0.0f;
730 			ret.end.Y   = Count > 4 ? ValueF[4] : 0.0f;
731 			ret.end.Z   = Count > 5 ? ValueF[5] : 0.0f;
732 		}
733 		else
734 		{
735 			ret.start.X = Count > 0 ? (f32)ValueI[0] : 0.0f;
736 			ret.start.Y = Count > 1 ? (f32)ValueI[1] : 0.0f;
737 			ret.start.Z = Count > 2 ? (f32)ValueI[2] : 0.0f;
738 			ret.end.X   = Count > 3 ? (f32)ValueI[3] : 0.0f;
739 			ret.end.Y   = Count > 4 ? (f32)ValueI[4] : 0.0f;
740 			ret.end.Z   = Count > 5 ? (f32)ValueI[5] : 0.0f;
741 		}
742 		return ret;
743 	}
744 
745 	//! get float array
getFloatArray()746 	virtual core::array<f32> getFloatArray()
747 	{
748 		if (!IsFloat)
749 		{
750 			ValueF.clear();
751 			for (u32 i=0; i<Count; ++i)
752 				ValueF.push_back( (f32) ValueI[i] );
753 		}
754 		return ValueF;
755 	}
756 
757 	//! get int array
getIntArray()758 	virtual core::array<s32> getIntArray()
759 	{
760 		if (IsFloat)
761 		{
762 			ValueI.clear();
763 			for (u32 i=0; i<Count; ++i)
764 				ValueI.push_back( (s32) ValueF[i] );
765 		}
766 		return ValueI;
767 	}
768 
769 
770 	// setting values
setInt(s32 intValue)771 	virtual void setInt(s32 intValue)
772 	{
773 		// set all values
774 		for (u32 i=0; i < Count; ++i)
775 			if (IsFloat)
776 				ValueF[i] = (f32)intValue;
777 			else
778 				ValueI[i] = intValue;
779 	}
780 
setFloat(f32 floatValue)781 	virtual void setFloat(f32 floatValue)
782 	{
783 		// set all values
784 		for (u32 i=0; i < Count; ++i)
785 			if (IsFloat)
786 				ValueF[i] = floatValue;
787 			else
788 				ValueI[i] = (s32)floatValue;
789 	}
790 
setBool(bool boolValue)791 	virtual void setBool(bool boolValue)
792 	{
793 		setInt( boolValue ? 1 : 0);
794 	}
795 
setString(const char * text)796 	virtual void setString(const char* text)
797 	{
798 		// parse text
799 
800 		const char* P = (const char*)text;
801 
802 		reset();
803 
804 		u32 i=0;
805 
806 		for ( i=0; i<Count && *P; ++i )
807 		{
808 			while(*P && P[0]!='-' && ( P[0]==' ' || (P[0] < '0' || P[0] > '9') ) )
809 				++P;
810 
811 			// set value
812 			if ( *P)
813 			{
814 				if (IsFloat)
815 				{
816 					f32 c = 0;
817 					P = core::fast_atof_move(P, c);
818 					ValueF[i] = c;
819 				}
820 				else
821 				{
822 					// todo: fix this to read ints properly
823 					f32 c = 0;
824 					P = core::fast_atof_move(P, c);
825 					ValueI[i] = (s32)c;
826 
827 				}
828 			}
829 		}
830 		// todo: warning message
831 		//if (i < Count-1)
832 		//{
833 		//
834 		//}
835 	}
836 
setPosition(core::position2di v)837 	virtual void setPosition(core::position2di v)
838 	{
839 		reset();
840 		if (IsFloat)
841 		{
842 			if (Count > 0) ValueF[0] = (f32)v.X;
843 			if (Count > 1) ValueF[1] = (f32)v.Y;
844 		}
845 		else
846 		{
847 			if (Count > 0) ValueI[0] = v.X;
848 			if (Count > 1) ValueI[1] = v.Y;
849 		}
850 	}
851 
setVector(core::vector3df v)852 	virtual void setVector(core::vector3df v)
853 	{
854 		reset();
855 		if (IsFloat)
856 		{
857 			if (Count > 0) ValueF[0] = v.X;
858 			if (Count > 1) ValueF[1] = v.Y;
859 			if (Count > 2) ValueF[2] = v.Z;
860 		}
861 		else
862 		{
863 			if (Count > 0) ValueI[0] = (s32)v.X;
864 			if (Count > 1) ValueI[1] = (s32)v.Y;
865 			if (Count > 2) ValueI[2] = (s32)v.Z;
866 		}
867 	}
868 
setColor(video::SColorf color)869 	virtual void setColor(video::SColorf color)
870 	{
871 		reset();
872 		if (IsFloat)
873 		{
874 			if (Count > 0) ValueF[0] = color.r;
875 			if (Count > 1) ValueF[1] = color.g;
876 			if (Count > 2) ValueF[2] = color.b;
877 			if (Count > 3) ValueF[3] = color.a;
878 		}
879 		else
880 		{
881 			if (Count > 0) ValueI[0] = (s32)(color.r * 255);
882 			if (Count > 1) ValueI[1] = (s32)(color.g * 255);
883 			if (Count > 2) ValueI[2] = (s32)(color.b * 255);
884 			if (Count > 3) ValueI[3] = (s32)(color.a * 255);
885 		}
886 
887 	}
888 
setColor(video::SColor color)889 	virtual void setColor(video::SColor color)
890 	{
891 		reset();
892 		if (IsFloat)
893 		{
894 			if (Count > 0) ValueF[0] = (f32)color.getRed() / 255.0f;
895 			if (Count > 1) ValueF[1] = (f32)color.getGreen() / 255.0f;
896 			if (Count > 2) ValueF[2] = (f32)color.getBlue() / 255.0f;
897 			if (Count > 3) ValueF[3] = (f32)color.getAlpha() / 255.0f;
898 		}
899 		else
900 		{
901 			if (Count > 0) ValueI[0] = color.getRed();
902 			if (Count > 1) ValueI[1] = color.getGreen();
903 			if (Count > 2) ValueI[2] = color.getBlue();
904 			if (Count > 3) ValueI[3] = color.getAlpha();
905 		}
906 	}
907 
setRect(core::rect<s32> value)908 	virtual void setRect(core::rect<s32> value)
909 	{
910 		reset();
911 		if (IsFloat)
912 		{
913 			if (Count > 0) ValueF[0] = (f32)value.UpperLeftCorner.X;
914 			if (Count > 1) ValueF[1] = (f32)value.UpperLeftCorner.Y;
915 			if (Count > 2) ValueF[2] = (f32)value.LowerRightCorner.X;
916 			if (Count > 3) ValueF[3] = (f32)value.LowerRightCorner.Y;
917 		}
918 		else
919 		{
920 			if (Count > 0) ValueI[0] = value.UpperLeftCorner.X;
921 			if (Count > 1) ValueI[1] = value.UpperLeftCorner.Y;
922 			if (Count > 2) ValueI[2] = value.LowerRightCorner.X;
923 			if (Count > 3) ValueI[3] = value.LowerRightCorner.Y;
924 		}
925 	}
926 
setMatrix(core::matrix4 value)927 	virtual void setMatrix(core::matrix4 value)
928 	{
929 		reset();
930 		if (IsFloat)
931 		{
932 			for (u32 r=0; r<4; ++r)
933 				for (u32 c=0; c<4; ++c)
934 					if (Count > c+r*4)
935 						ValueF[c+r*4] = value(r,c);
936 		}
937 		else
938 		{
939 			for (u32 r=0; r<4; ++r)
940 				for (u32 c=0; c<4; ++c)
941 					if (Count > c+r*4)
942 						ValueI[c+r*4] = (s32)value(r,c);
943 		}
944 	}
945 
setQuaternion(core::quaternion value)946 	virtual void setQuaternion(core::quaternion value)
947 	{
948 		reset();
949 		if (IsFloat)
950 		{
951 			if (Count > 0) ValueF[0] = value.X;
952 			if (Count > 1) ValueF[1] = value.Y;
953 			if (Count > 2) ValueF[2] = value.Z;
954 			if (Count > 3) ValueF[3] = value.W;
955 		}
956 		else
957 		{
958 			if (Count > 0) ValueI[0] = (s32)value.X;
959 			if (Count > 1) ValueI[1] = (s32)value.Y;
960 			if (Count > 2) ValueI[2] = (s32)value.Z;
961 			if (Count > 3) ValueI[3] = (s32)value.W;
962 		}
963 	}
964 
setBoundingBox(core::aabbox3d<f32> value)965 	virtual void setBoundingBox(core::aabbox3d<f32> value)
966 	{
967 		reset();
968 		if (IsFloat)
969 		{
970 			if (Count > 0) ValueF[0] = value.MinEdge.X;
971 			if (Count > 1) ValueF[1] = value.MinEdge.Y;
972 			if (Count > 2) ValueF[2] = value.MinEdge.Z;
973 			if (Count > 3) ValueF[3] = value.MaxEdge.X;
974 			if (Count > 4) ValueF[4] = value.MaxEdge.Y;
975 			if (Count > 5) ValueF[5] = value.MaxEdge.Z;
976 		}
977 		else
978 		{
979 			if (Count > 0) ValueI[0] = (s32)value.MinEdge.X;
980 			if (Count > 1) ValueI[1] = (s32)value.MinEdge.Y;
981 			if (Count > 2) ValueI[2] = (s32)value.MinEdge.Z;
982 			if (Count > 3) ValueI[3] = (s32)value.MaxEdge.X;
983 			if (Count > 4) ValueI[4] = (s32)value.MaxEdge.Y;
984 			if (Count > 5) ValueI[5] = (s32)value.MaxEdge.Z;
985 		}
986 	}
987 
setPlane(core::plane3df value)988 	virtual void setPlane(core::plane3df value)
989 	{
990 		reset();
991 		if (IsFloat)
992 		{
993 			if (Count > 0) ValueF[0] = value.Normal.X;
994 			if (Count > 1) ValueF[1] = value.Normal.Y;
995 			if (Count > 2) ValueF[2] = value.Normal.Z;
996 			if (Count > 3) ValueF[3] = value.D;
997 		}
998 		else
999 		{
1000 			if (Count > 0) ValueI[0] = (s32)value.Normal.X;
1001 			if (Count > 1) ValueI[1] = (s32)value.Normal.Y;
1002 			if (Count > 2) ValueI[2] = (s32)value.Normal.Z;
1003 			if (Count > 3) ValueI[3] = (s32)value.D;
1004 		}
1005 	}
1006 
setTriangle3d(core::triangle3df value)1007 	virtual void setTriangle3d(core::triangle3df value)
1008 	{
1009 		reset();
1010 		if (IsFloat)
1011 		{
1012 			if (Count > 0) ValueF[0] = value.pointA.X;
1013 			if (Count > 1) ValueF[1] = value.pointA.Y;
1014 			if (Count > 2) ValueF[2] = value.pointA.Z;
1015 			if (Count > 3) ValueF[3] = value.pointB.X;
1016 			if (Count > 4) ValueF[4] = value.pointB.Y;
1017 			if (Count > 5) ValueF[5] = value.pointB.Z;
1018 			if (Count > 6) ValueF[6] = value.pointC.X;
1019 			if (Count > 7) ValueF[7] = value.pointC.Y;
1020 			if (Count > 8) ValueF[8] = value.pointC.Z;
1021 		}
1022 		else
1023 		{
1024 			if (Count > 0) ValueI[0] = (s32)value.pointA.X;
1025 			if (Count > 1) ValueI[1] = (s32)value.pointA.Y;
1026 			if (Count > 2) ValueI[2] = (s32)value.pointA.Z;
1027 			if (Count > 3) ValueI[3] = (s32)value.pointB.X;
1028 			if (Count > 4) ValueI[4] = (s32)value.pointB.Y;
1029 			if (Count > 5) ValueI[5] = (s32)value.pointB.Z;
1030 			if (Count > 6) ValueI[6] = (s32)value.pointC.X;
1031 			if (Count > 7) ValueI[7] = (s32)value.pointC.Y;
1032 			if (Count > 8) ValueI[8] = (s32)value.pointC.Z;
1033 		}
1034 	}
1035 
setVector2d(core::vector2df v)1036 	virtual void setVector2d(core::vector2df v)
1037 	{
1038 		reset();
1039 		if (IsFloat)
1040 		{
1041 			if (Count > 0) ValueF[0] = v.X;
1042 			if (Count > 1) ValueF[1] = v.Y;
1043 		}
1044 		else
1045 		{
1046 			if (Count > 0) ValueI[0] = (s32)v.X;
1047 			if (Count > 1) ValueI[1] = (s32)v.Y;
1048 		}
1049 	}
1050 
setVector2d(core::vector2di v)1051 	virtual void setVector2d(core::vector2di v)
1052 	{
1053 		reset();
1054 		if (IsFloat)
1055 		{
1056 			if (Count > 0) ValueF[0] = (f32)v.X;
1057 			if (Count > 1) ValueF[1] = (f32)v.Y;
1058 		}
1059 		else
1060 		{
1061 			if (Count > 0) ValueI[0] = v.X;
1062 			if (Count > 1) ValueI[1] = v.Y;
1063 		}
1064 	}
1065 
setLine2d(core::line2di v)1066 	virtual void setLine2d(core::line2di v)
1067 	{
1068 		reset();
1069 		if (IsFloat)
1070 		{
1071 			if (Count > 0) ValueF[0] = (f32)v.start.X;
1072 			if (Count > 1) ValueF[1] = (f32)v.start.Y;
1073 			if (Count > 2) ValueF[2] = (f32)v.end.X;
1074 			if (Count > 3) ValueF[3] = (f32)v.end.Y;
1075 		}
1076 		else
1077 		{
1078 			if (Count > 0) ValueI[0] = v.start.X;
1079 			if (Count > 1) ValueI[1] = v.start.Y;
1080 			if (Count > 2) ValueI[2] = v.end.X;
1081 			if (Count > 3) ValueI[3] = v.end.Y;
1082 		}
1083 	}
1084 
setLine2d(core::line2df v)1085 	virtual void setLine2d(core::line2df v)
1086 	{
1087 		reset();
1088 		if (IsFloat)
1089 		{
1090 			if (Count > 0) ValueF[0] = v.start.X;
1091 			if (Count > 1) ValueF[1] = v.start.Y;
1092 			if (Count > 2) ValueF[2] = v.end.X;
1093 			if (Count > 3) ValueF[3] = v.end.Y;
1094 		}
1095 		else
1096 		{
1097 			if (Count > 0) ValueI[0] = (s32)v.start.X;
1098 			if (Count > 1) ValueI[1] = (s32)v.start.Y;
1099 			if (Count > 2) ValueI[2] = (s32)v.end.X;
1100 			if (Count > 3) ValueI[3] = (s32)v.end.Y;
1101 		}
1102 	}
1103 
setDimension2d(core::dimension2du v)1104 	virtual void setDimension2d(core::dimension2du v)
1105 	{
1106 		reset();
1107 		if (IsFloat)
1108 		{
1109 			if (Count > 0) ValueF[0] = (f32)v.Width;
1110 			if (Count > 1) ValueF[1] = (f32)v.Height;
1111 		}
1112 		else
1113 		{
1114 			if (Count > 0) ValueI[0] = (s32)v.Width;
1115 			if (Count > 1) ValueI[1] = (s32)v.Height;
1116 		}
1117 	}
1118 
1119 	//! set float array
setFloatArray(core::array<f32> & vals)1120 	virtual void setFloatArray(core::array<f32> &vals)
1121 	{
1122 		reset();
1123 
1124 		for (u32 i=0; i<vals.size() && i<Count; ++i)
1125 		{
1126 			if (IsFloat)
1127 				ValueF[i] = vals[i];
1128 			else
1129 				ValueI[i] = (s32)vals[i];
1130 		}
1131 	}
1132 
1133 	//! set int array
setIntArray(core::array<s32> & vals)1134 	virtual void setIntArray(core::array<s32> &vals)
1135 	{
1136 		reset();
1137 
1138 		for (u32 i=0; i<vals.size() && i<Count; ++i)
1139 		{
1140 			if (IsFloat)
1141 				ValueF[i] = (f32)vals[i];
1142 			else
1143 				ValueI[i] = vals[i];
1144 		}
1145 	}
1146 
1147 
1148 	//! is it a number list?
isNumberList()1149 	virtual bool isNumberList()
1150 	{
1151 		return true;
1152 	}
1153 
1154 	//! is it a float list?
isFloat()1155 	virtual bool isFloat()
1156 	{
1157 		return IsFloat;
1158 	}
1159 
getType()1160 	virtual E_ATTRIBUTE_TYPE getType() const
1161 	{
1162 		if (IsFloat)
1163 			return EAT_FLOATARRAY;
1164 		else
1165 			return EAT_INTARRAY;
1166 	}
1167 
getTypeString()1168 	virtual const wchar_t* getTypeString() const
1169 	{
1170 		if (IsFloat)
1171 			return L"floatlist";
1172 		else
1173 			return L"intlist";
1174 	}
1175 
1176 protected:
1177 
1178 	//! clear all values
reset()1179 	void reset()
1180 	{
1181 		if (IsFloat)
1182 			for (u32 i=0; i < Count ; ++i)
1183 				ValueF[i] = 0.0f;
1184 		else
1185 			for (u32 i=0; i < Count ; ++i)
1186 				ValueI[i] = 0;
1187 	}
1188 
1189 	core::array<s32> ValueI;
1190 	core::array<f32> ValueF;
1191 	u32 Count;
1192 	bool IsFloat;
1193 };
1194 
1195 
1196 // Attribute implemented for floating point colors
1197 class CColorfAttribute : public CNumbersAttribute
1198 {
1199 public:
1200 
CColorfAttribute(const char * name,video::SColorf value)1201 	CColorfAttribute(const char* name, video::SColorf value) : CNumbersAttribute(name, value) {}
1202 
getInt()1203 	virtual s32 getInt()
1204 	{
1205 		return getColor().color;
1206 	}
1207 
getFloat()1208 	virtual f32 getFloat()
1209 	{
1210 		return (f32)getColor().color;
1211 	}
1212 
setInt(s32 intValue)1213 	virtual void setInt(s32 intValue)
1214 	{
1215 		video::SColorf c = video::SColor(intValue);
1216 		ValueF[0] = c.r;
1217 		ValueF[1] = c.g;
1218 		ValueF[2] = c.b;
1219 		ValueF[3] = c.a;
1220 	}
1221 
setFloat(f32 floatValue)1222 	virtual void setFloat(f32 floatValue)
1223 	{
1224 		setInt((s32)floatValue);
1225 	}
1226 
getType()1227 	virtual E_ATTRIBUTE_TYPE getType() const
1228 	{
1229 		return EAT_COLORF;
1230 	}
1231 
getTypeString()1232 	virtual const wchar_t* getTypeString() const
1233 	{
1234 		return L"colorf";
1235 	}
1236 };
1237 
1238 
1239 
1240 // Attribute implemented for colors
1241 class CColorAttribute : public CNumbersAttribute
1242 {
1243 public:
1244 
CColorAttribute(const char * name,const video::SColorf & value)1245 	CColorAttribute(const char* name, const video::SColorf& value) : CNumbersAttribute(name, value) {}
1246 
CColorAttribute(const char * name,const video::SColor & value)1247 	CColorAttribute(const char* name, const video::SColor& value) : CNumbersAttribute(name, value) {}
1248 
getInt()1249 	virtual s32 getInt()
1250 	{
1251 		return getColor().color;
1252 	}
1253 
getFloat()1254 	virtual f32 getFloat()
1255 	{
1256 		return (f32)getColor().color;
1257 	}
1258 
setInt(s32 intValue)1259 	virtual void setInt(s32 intValue)
1260 	{
1261 		video::SColorf c = video::SColor(intValue);
1262 		ValueF[0] = c.r;
1263 		ValueF[1] = c.g;
1264 		ValueF[2] = c.b;
1265 		ValueF[3] = c.a;
1266 	}
1267 
setFloat(f32 floatValue)1268 	virtual void setFloat(f32 floatValue)
1269 	{
1270 		setInt((s32)floatValue);
1271 	}
1272 
getStringW()1273 	virtual core::stringw getStringW()
1274 	{
1275 		char tmp[10];
1276 		const video::SColor c = getColor();
1277 		sprintf(tmp, "%02x%02x%02x%02x", c.getAlpha(), c.getRed(), c.getGreen(), c.getBlue());
1278 		return core::stringw(tmp);
1279 	}
1280 
setString(const char * text)1281 	virtual void setString(const char* text)
1282 	{
1283 		u32 c;
1284 		if (sscanf(text, "%08x", &c)!=1)
1285 		{
1286 			CNumbersAttribute::setString(text);
1287 		}
1288 		else
1289 			setColor(c);
1290 	}
1291 
getType()1292 	virtual E_ATTRIBUTE_TYPE getType() const
1293 	{
1294 		return EAT_COLOR;
1295 	}
1296 
1297 
getTypeString()1298 	virtual const wchar_t* getTypeString() const
1299 	{
1300 		return L"color";
1301 	}
1302 
1303 };
1304 
1305 
1306 // Attribute implemented for 3d vectors
1307 class CVector3DAttribute : public CNumbersAttribute
1308 {
1309 public:
1310 
CVector3DAttribute(const char * name,core::vector3df value)1311 	CVector3DAttribute(const char* name, core::vector3df value) : CNumbersAttribute(name, value) {}
1312 
getType()1313 	virtual E_ATTRIBUTE_TYPE getType() const
1314 	{
1315 		return EAT_VECTOR3D;
1316 	}
1317 
getMatrix()1318 	virtual core::matrix4 getMatrix()
1319 	{
1320 		core::matrix4 ret;
1321 		ret.makeIdentity();
1322 		ret.setTranslation( core::vector3df(ValueF[0],ValueF[1],ValueF[2]) );
1323 		return ret;
1324 	}
1325 
getTypeString()1326 	virtual const wchar_t* getTypeString() const
1327 	{
1328 		return L"vector3d";
1329 	}
1330 };
1331 
1332 // Attribute implemented for 2d vectors
1333 class CVector2DAttribute : public CNumbersAttribute
1334 {
1335 public:
1336 
CVector2DAttribute(const char * name,core::vector2df value)1337 	CVector2DAttribute(const char* name, core::vector2df value) : CNumbersAttribute(name, value) {}
1338 
getType()1339 	virtual E_ATTRIBUTE_TYPE getType() const
1340 	{
1341 		return EAT_VECTOR2D;
1342 	}
1343 
getTypeString()1344 	virtual const wchar_t* getTypeString() const
1345 	{
1346 		return L"vector2d";
1347 	}
1348 };
1349 
1350 // Attribute implemented for 2d vectors
1351 class CPosition2DAttribute : public CNumbersAttribute
1352 {
1353 public:
1354 
CPosition2DAttribute(const char * name,core::position2di value)1355 	CPosition2DAttribute(const char* name, core::position2di value) : CNumbersAttribute(name, value) {}
1356 
getType()1357 	virtual E_ATTRIBUTE_TYPE getType() const
1358 	{
1359 		return EAT_POSITION2D;
1360 	}
1361 
getTypeString()1362 	virtual const wchar_t* getTypeString() const
1363 	{
1364 		return L"position";
1365 	}
1366 };
1367 
1368 
1369 
1370 // Attribute implemented for rectangles
1371 class CRectAttribute : public CNumbersAttribute
1372 {
1373 public:
1374 
CRectAttribute(const char * name,core::rect<s32> value)1375 	CRectAttribute(const char* name, core::rect<s32> value) : CNumbersAttribute(name, value) { }
1376 
getType()1377 	virtual E_ATTRIBUTE_TYPE getType() const
1378 	{
1379 		return EAT_RECT;
1380 	}
1381 
getTypeString()1382 	virtual const wchar_t* getTypeString() const
1383 	{
1384 		return L"rect";
1385 	}
1386 };
1387 
1388 
1389 // Attribute implemented for dimension
1390 class CDimension2dAttribute : public CNumbersAttribute
1391 {
1392 public:
1393 
CDimension2dAttribute(const char * name,core::dimension2d<u32> value)1394 	CDimension2dAttribute (const char* name, core::dimension2d<u32> value) : CNumbersAttribute(name, value) { }
1395 
getType()1396 	virtual E_ATTRIBUTE_TYPE getType() const
1397 	{
1398 		return EAT_DIMENSION2D;
1399 	}
1400 
getTypeString()1401 	virtual const wchar_t* getTypeString() const
1402 	{
1403 		return L"dimension2d";
1404 	}
1405 };
1406 
1407 // Attribute implemented for matrices
1408 class CMatrixAttribute : public CNumbersAttribute
1409 {
1410 public:
1411 
CMatrixAttribute(const char * name,core::matrix4 value)1412 	CMatrixAttribute(const char* name, core::matrix4 value) : CNumbersAttribute(name, value) { }
1413 
getType()1414 	virtual E_ATTRIBUTE_TYPE getType() const
1415 	{
1416 		return EAT_MATRIX;
1417 	}
1418 
getQuaternion()1419 	virtual core::quaternion getQuaternion()
1420 	{
1421 		return core::quaternion(getMatrix());
1422 	}
1423 
getTypeString()1424 	virtual const wchar_t* getTypeString() const
1425 	{
1426 		return L"matrix";
1427 	}
1428 };
1429 
1430 // Attribute implemented for quaternions
1431 class CQuaternionAttribute : public CNumbersAttribute
1432 {
1433 public:
1434 
CQuaternionAttribute(const char * name,core::quaternion value)1435 	CQuaternionAttribute(const char* name, core::quaternion value) : CNumbersAttribute(name, value) { }
1436 
getType()1437 	virtual E_ATTRIBUTE_TYPE getType() const
1438 	{
1439 		return EAT_QUATERNION;
1440 	}
1441 
getMatrix()1442 	virtual core::matrix4 getMatrix()
1443 	{
1444 		return getQuaternion().getMatrix();
1445 	}
1446 
getTypeString()1447 	virtual const wchar_t* getTypeString() const
1448 	{
1449 		return L"quaternion";
1450 	}
1451 };
1452 
1453 
1454 // Attribute implemented for bounding boxes
1455 class CBBoxAttribute : public CNumbersAttribute
1456 {
1457 public:
1458 
CBBoxAttribute(const char * name,core::aabbox3df value)1459 	CBBoxAttribute(const char* name, core::aabbox3df value) : CNumbersAttribute(name, value) { }
1460 
getType()1461 	virtual E_ATTRIBUTE_TYPE getType() const
1462 	{
1463 		return EAT_BBOX;
1464 	}
1465 
getTypeString()1466 	virtual const wchar_t* getTypeString() const
1467 	{
1468 		return L"box3d";
1469 	}
1470 };
1471 
1472 // Attribute implemented for planes
1473 class CPlaneAttribute : public CNumbersAttribute
1474 {
1475 public:
1476 
CPlaneAttribute(const char * name,core::plane3df value)1477 	CPlaneAttribute(const char* name, core::plane3df value) : CNumbersAttribute(name, value) { }
1478 
getType()1479 	virtual E_ATTRIBUTE_TYPE getType() const
1480 	{
1481 		return EAT_PLANE;
1482 	}
1483 
getTypeString()1484 	virtual const wchar_t* getTypeString() const
1485 	{
1486 		return L"plane";
1487 	}
1488 };
1489 
1490 // Attribute implemented for triangles
1491 class CTriangleAttribute : public CNumbersAttribute
1492 {
1493 public:
1494 
CTriangleAttribute(const char * name,core::triangle3df value)1495 	CTriangleAttribute(const char* name, core::triangle3df value) : CNumbersAttribute(name, value) { }
1496 
getType()1497 	virtual E_ATTRIBUTE_TYPE getType() const
1498 	{
1499 		return EAT_TRIANGLE3D;
1500 	}
1501 
getPlane()1502 	virtual core::plane3df getPlane()
1503 	{
1504 		return getTriangle().getPlane();
1505 	}
1506 
getTypeString()1507 	virtual const wchar_t* getTypeString() const
1508 	{
1509 		return L"triangle";
1510 	}
1511 };
1512 
1513 
1514 // Attribute implemented for 2d lines
1515 class CLine2dAttribute : public CNumbersAttribute
1516 {
1517 public:
1518 
CLine2dAttribute(const char * name,core::line2df value)1519 	CLine2dAttribute(const char* name, core::line2df value) : CNumbersAttribute(name, value) { }
1520 
getType()1521 	virtual E_ATTRIBUTE_TYPE getType() const
1522 	{
1523 		return EAT_LINE2D;
1524 	}
1525 
getTypeString()1526 	virtual const wchar_t* getTypeString() const
1527 	{
1528 		return L"line2d";
1529 	}
1530 };
1531 
1532 // Attribute implemented for 3d lines
1533 class CLine3dAttribute : public CNumbersAttribute
1534 {
1535 public:
1536 
CLine3dAttribute(const char * name,core::line3df value)1537 	CLine3dAttribute(const char* name, core::line3df value) : CNumbersAttribute(name, value) { }
1538 
getType()1539 	virtual E_ATTRIBUTE_TYPE getType() const
1540 	{
1541 		return EAT_LINE3D;
1542 	}
1543 
getTypeString()1544 	virtual const wchar_t* getTypeString() const
1545 	{
1546 		return L"line3d";
1547 	}
1548 };
1549 
1550 
1551 // vector2df
1552 // dimension2du
1553 
1554 /*
1555 	Special attributes
1556 */
1557 
1558 // Attribute implemented for enumeration literals
1559 class CEnumAttribute : public IAttribute
1560 {
1561 public:
1562 
CEnumAttribute(const char * name,const char * value,const char * const * literals)1563 	CEnumAttribute(const char* name, const char* value, const char* const* literals)
1564 	{
1565 		Name = name;
1566 		setEnum(value, literals);
1567 	}
1568 
setEnum(const char * enumValue,const char * const * enumerationLiterals)1569 	virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals)
1570 	{
1571 		int literalCount = 0;
1572 
1573 		if (enumerationLiterals)
1574 		{
1575 			s32 i;
1576 			for (i=0; enumerationLiterals[i]; ++i)
1577 				++literalCount;
1578 
1579 			EnumLiterals.reallocate(literalCount);
1580 			for (i=0; enumerationLiterals[i]; ++i)
1581 				EnumLiterals.push_back(enumerationLiterals[i]);
1582 		}
1583 
1584 		setString(enumValue);
1585 	}
1586 
getInt()1587 	virtual s32 getInt()
1588 	{
1589 		for (u32 i=0; i < EnumLiterals.size(); ++i)
1590 			if (Value.equals_ignore_case(EnumLiterals[i]))
1591 			{
1592 				return (s32)i;
1593 			}
1594 
1595 		return -1;
1596 	}
1597 
getFloat()1598 	virtual f32 getFloat()
1599 	{
1600 		return (f32)getInt();
1601 	}
1602 
getBool()1603 	virtual bool getBool()
1604 	{
1605 		return (getInt() != 0); // does not make a lot of sense, I know
1606 	}
1607 
getString()1608 	virtual core::stringc getString()
1609 	{
1610 		return Value;
1611 	}
1612 
getStringW()1613 	virtual core::stringw getStringW()
1614 	{
1615 		return core::stringw(Value.c_str());
1616 	}
1617 
setInt(s32 intValue)1618 	virtual void setInt(s32 intValue)
1619 	{
1620 		if (intValue>=0 && intValue<(s32)EnumLiterals.size())
1621 			Value = EnumLiterals[intValue];
1622 		else
1623 			Value = "";
1624 	}
1625 
setFloat(f32 floatValue)1626 	virtual void setFloat(f32 floatValue)
1627 	{
1628 		setInt((s32)floatValue);
1629 	};
1630 
setString(const char * text)1631 	virtual void setString(const char* text)
1632 	{
1633 		Value = text;
1634 	}
1635 
getEnum()1636 	virtual const char* getEnum()
1637 	{
1638 		return Value.c_str();
1639 	}
1640 
getType()1641 	virtual E_ATTRIBUTE_TYPE getType() const
1642 	{
1643 		return EAT_ENUM;
1644 	}
1645 
1646 
getTypeString()1647 	virtual const wchar_t* getTypeString() const
1648 	{
1649 		return L"enum";
1650 	}
1651 
1652 	core::stringc Value;
1653 	core::array<core::stringc> EnumLiterals;
1654 };
1655 
1656 
1657 
1658 
1659 
1660 // Attribute implemented for strings
1661 class CStringAttribute : public IAttribute
1662 {
1663 public:
1664 
CStringAttribute(const char * name,const char * value)1665 	CStringAttribute(const char* name, const char* value)
1666 	{
1667 		IsStringW=false;
1668 		Name = name;
1669 		setString(value);
1670 	}
1671 
CStringAttribute(const char * name,const wchar_t * value)1672 	CStringAttribute(const char* name, const wchar_t* value)
1673 	{
1674 		IsStringW = true;
1675 		Name = name;
1676 		setString(value);
1677 	}
1678 
CStringAttribute(const char * name,void * binaryData,s32 lenghtInBytes)1679 	CStringAttribute(const char* name, void* binaryData, s32 lenghtInBytes)
1680 	{
1681 		IsStringW=false;
1682 		Name = name;
1683 		setBinary(binaryData, lenghtInBytes);
1684 	}
1685 
getInt()1686 	virtual s32 getInt()
1687 	{
1688 		if (IsStringW)
1689 			return atoi(core::stringc(ValueW.c_str()).c_str());
1690 		else
1691 			return atoi(Value.c_str());
1692 	}
1693 
getFloat()1694 	virtual f32 getFloat()
1695 	{
1696 		if (IsStringW)
1697 			return core::fast_atof(core::stringc(ValueW.c_str()).c_str());
1698 		else
1699 			return core::fast_atof(Value.c_str());
1700 	}
1701 
getBool()1702 	virtual bool getBool()
1703 	{
1704 		if (IsStringW)
1705 			return ValueW.equals_ignore_case(L"true");
1706 		else
1707 			return Value.equals_ignore_case("true");
1708 	}
1709 
getString()1710 	virtual core::stringc getString()
1711 	{
1712 		if (IsStringW)
1713 			return core::stringc(ValueW.c_str());
1714 		else
1715 			return Value;
1716 	}
getStringW()1717 	virtual core::stringw getStringW()
1718 	{
1719 		if (IsStringW)
1720 			return ValueW;
1721 		else
1722 			return core::stringw(Value.c_str());
1723 	}
1724 
setInt(s32 intValue)1725 	virtual void setInt(s32 intValue)
1726 	{
1727 		if (IsStringW)
1728 			ValueW = core::stringw(intValue);
1729 		else
1730 			Value = core::stringc(intValue);
1731 	}
1732 
setFloat(f32 floatValue)1733 	virtual void setFloat(f32 floatValue)
1734 	{
1735 		if (IsStringW)
1736 		{
1737 			ValueW = core::stringw((double)floatValue);
1738 		}
1739 		else
1740 		{
1741 			Value = core::stringc((double)floatValue);
1742 		}
1743 	};
1744 
setString(const char * text)1745 	virtual void setString(const char* text)
1746 	{
1747 		if (IsStringW)
1748 			ValueW = core::stringw(text);
1749 		else
1750 			Value = text;
1751 	}
1752 
setString(const wchar_t * text)1753 	virtual void setString(const wchar_t* text)
1754 	{
1755 		if (IsStringW)
1756 			ValueW = text;
1757 		else
1758 			Value = core::stringc(text);
1759 	}
1760 
getType()1761 	virtual E_ATTRIBUTE_TYPE getType() const
1762 	{
1763 		return EAT_STRING;
1764 	}
1765 
1766 
getTypeString()1767 	virtual const wchar_t* getTypeString() const
1768 	{
1769 		return L"string";
1770 	}
1771 
getBinary(void * outdata,s32 maxLength)1772 	virtual void getBinary(void* outdata, s32 maxLength)
1773 	{
1774 		s32 dataSize = maxLength;
1775 		c8* datac8 = (c8*)(outdata);
1776 		s32 p = 0;
1777 		const c8* dataString = Value.c_str();
1778 
1779 		for (s32 i=0; i<dataSize; ++i)
1780 			datac8[i] = 0;
1781 
1782 		while(dataString[p] && p<dataSize)
1783 		{
1784 			s32 v = getByteFromHex((c8)dataString[p*2]) * 16;
1785 
1786 			if (dataString[(p*2)+1])
1787 				v += getByteFromHex((c8)dataString[(p*2)+1]);
1788 
1789 			datac8[p] = v;
1790 			++p;
1791 		}
1792 	};
1793 
setBinary(void * data,s32 maxLength)1794 	virtual void setBinary(void* data, s32 maxLength)
1795 	{
1796 		s32 dataSize = maxLength;
1797 		c8* datac8 = (c8*)(data);
1798 		char tmp[3];
1799 		tmp[2] = 0;
1800 		Value = "";
1801 
1802 		for (s32 b=0; b<dataSize; ++b)
1803 		{
1804 			getHexStrFromByte(datac8[b], tmp);
1805 			Value.append(tmp);
1806 		}
1807 	};
1808 
1809 	bool IsStringW;
1810 	core::stringc Value;
1811 	core::stringw ValueW;
1812 
1813 protected:
1814 
getByteFromHex(c8 h)1815 	static inline s32 getByteFromHex(c8 h)
1816 	{
1817 		if (h >= '0' && h <='9')
1818 			return h-'0';
1819 
1820 		if (h >= 'a' && h <='f')
1821 			return h-'a' + 10;
1822 
1823 		return 0;
1824 	}
1825 
getHexStrFromByte(c8 byte,c8 * out)1826 	static inline void getHexStrFromByte(c8 byte, c8* out)
1827 	{
1828 		s32 b = (byte & 0xf0) >> 4;
1829 
1830 		for (s32 i=0; i<2; ++i)
1831 		{
1832 			if (b >=0 && b <= 9)
1833 				out[i] = b+'0';
1834 			if (b >=10 && b <= 15)
1835 				out[i] = (b-10)+'a';
1836 
1837 			b = byte & 0x0f;
1838 		}
1839 	}
1840 };
1841 
1842 // Attribute implemented for binary data
1843 class CBinaryAttribute : public CStringAttribute
1844 {
1845 public:
1846 
CBinaryAttribute(const char * name,void * binaryData,s32 lenghtInBytes)1847 	CBinaryAttribute(const char* name, void* binaryData, s32 lenghtInBytes)
1848 		: CStringAttribute(name, binaryData, lenghtInBytes)
1849 	{
1850 
1851 	}
1852 
getType()1853 	virtual E_ATTRIBUTE_TYPE getType() const
1854 	{
1855 		return EAT_BINARY;
1856 	}
1857 
1858 
getTypeString()1859 	virtual const wchar_t* getTypeString() const
1860 	{
1861 		return L"binary";
1862 	}
1863 };
1864 
1865 
1866 
1867 // Attribute implemented for texture references
1868 class CTextureAttribute : public IAttribute
1869 {
1870 public:
1871 
CTextureAttribute(const char * name,video::ITexture * value,video::IVideoDriver * driver,const io::path & filename)1872 	CTextureAttribute(const char* name, video::ITexture* value, video::IVideoDriver* driver, const io::path& filename)
1873 		: Value(0), Driver(driver), OverrideName(filename)
1874 	{
1875 		if (Driver)
1876 			Driver->grab();
1877 
1878 		Name = name;
1879 		setTexture(value);
1880 	}
1881 
~CTextureAttribute()1882 	~CTextureAttribute()
1883 	{
1884 		if (Driver)
1885 			Driver->drop();
1886 
1887 		if (Value)
1888 			Value->drop();
1889 	}
1890 
getTexture()1891 	virtual video::ITexture* getTexture()
1892 	{
1893 		return Value;
1894 	}
1895 
getBool()1896 	virtual bool getBool()
1897 	{
1898 		return (Value != 0);
1899 	}
1900 
getStringW()1901 	virtual core::stringw getStringW()
1902 	{
1903 		// (note: don't try to put all this in some ?: operators, or c++ builder will choke)
1904 		if ( OverrideName.size() )
1905 			return core::stringw(OverrideName);
1906 
1907 		if ( Value )
1908 			return core::stringw(Value->getName().getPath().c_str());
1909 
1910 		return core::stringw(0);
1911 	}
1912 
getString()1913 	virtual core::stringc getString()
1914 	{
1915 		// since texture names can be stringw we are careful with the types
1916 		if ( OverrideName.size() )
1917 			return core::stringc(OverrideName);
1918 
1919 		if ( Value )
1920 			return core::stringc(Value->getName().getPath().c_str());
1921 
1922 		return core::stringc(0);
1923 	}
1924 
setString(const char * text)1925 	virtual void setString(const char* text)
1926 	{
1927 		if (Driver)
1928 		{
1929 			if (text && *text)
1930 			{
1931 				setTexture(Driver->getTexture(text));
1932 				OverrideName=text;
1933 			}
1934 			else
1935 				setTexture(0);
1936 		}
1937 	}
1938 
setTexture(video::ITexture * value)1939 	virtual void setTexture(video::ITexture* value)
1940 	{
1941 		if ( value == Value )
1942 			return;
1943 
1944 		if (Value)
1945 			Value->drop();
1946 
1947 		Value = value;
1948 
1949 		if (Value)
1950 			Value->grab();
1951 	}
1952 
getType()1953 	virtual E_ATTRIBUTE_TYPE getType() const
1954 	{
1955 		return EAT_TEXTURE;
1956 	}
1957 
1958 
getTypeString()1959 	virtual const wchar_t* getTypeString() const
1960 	{
1961 		return L"texture";
1962 	}
1963 
1964 	video::ITexture* Value;
1965 	video::IVideoDriver* Driver;
1966 	io::path OverrideName;
1967 };
1968 
1969 
1970 
1971 // Attribute implemented for array of stringw
1972 class CStringWArrayAttribute : public IAttribute
1973 {
1974 public:
1975 
CStringWArrayAttribute(const char * name,const core::array<core::stringw> & value)1976 	CStringWArrayAttribute(const char* name, const core::array<core::stringw>& value)
1977 	{
1978 		Name = name;
1979 		setArray(value);
1980 	}
1981 
getArray()1982 	virtual core::array<core::stringw> getArray()
1983 	{
1984 		return Value;
1985 	}
1986 
setArray(const core::array<core::stringw> & value)1987 	virtual void setArray(const core::array<core::stringw>& value)
1988 	{
1989 		Value = value;
1990 	}
1991 
getType()1992 	virtual E_ATTRIBUTE_TYPE getType() const
1993 	{
1994 		return EAT_STRINGWARRAY;
1995 	}
1996 
getTypeString()1997 	virtual const wchar_t* getTypeString() const
1998 	{
1999 		return L"stringwarray";
2000 	}
2001 
2002 	core::array<core::stringw> Value;
2003 };
2004 
2005 
2006 // Attribute implemented for user pointers
2007 class CUserPointerAttribute : public IAttribute
2008 {
2009 public:
2010 
CUserPointerAttribute(const char * name,void * value)2011 	CUserPointerAttribute(const char* name, void* value)
2012 	{
2013 		Name = name;
2014 		Value = value;
2015 	}
2016 
getInt()2017 	virtual s32 getInt()
2018 	{
2019 		return *static_cast<s32*>(Value);
2020 	}
2021 
getBool()2022 	virtual bool getBool()
2023 	{
2024 		return (Value != 0);
2025 	}
2026 
getStringW()2027 	virtual core::stringw getStringW()
2028 	{
2029 		wchar_t buf[32];
2030 		swprintf(buf, 32, L"%p", Value);
2031 
2032 		return core::stringw(buf);
2033 	}
2034 
setString(const char * text)2035 	virtual void setString(const char* text)
2036 	{
2037 		u32 tmp;
2038 		sscanf(text, "0x%x", &tmp);
2039 		Value = (void *) tmp;
2040 	}
2041 
getType()2042 	virtual E_ATTRIBUTE_TYPE getType() const
2043 	{
2044 		return EAT_USER_POINTER;
2045 	}
2046 
setUserPointer(void * v)2047 	virtual void setUserPointer(void* v)
2048 	{
2049 		Value = v;
2050 	}
2051 
getUserPointer()2052 	virtual void* getUserPointer()
2053 	{
2054 		return Value;
2055 	}
2056 
2057 
getTypeString()2058 	virtual const wchar_t* getTypeString() const
2059 	{
2060 		return L"userPointer";
2061 	}
2062 
2063 	void* Value;
2064 };
2065 
2066 
2067 
2068 // todo: CGUIFontAttribute
2069 
2070 } // end namespace io
2071 } // end namespace irr
2072