2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/public-api/object/property-value.h>
25 #include <dali/public-api/math/angle-axis.h>
26 #include <dali/public-api/math/radian.h>
27 #include <dali/public-api/math/vector2.h>
28 #include <dali/public-api/math/vector3.h>
29 #include <dali/public-api/math/vector4.h>
30 #include <dali/public-api/math/matrix3.h>
31 #include <dali/public-api/math/matrix.h>
32 #include <dali/public-api/math/rect.h>
33 #include <dali/public-api/math/quaternion.h>
34 #include <dali/public-api/object/property-map.h>
35 #include <dali/public-api/object/property-array.h>
36 #include <dali/public-api/object/property-types.h>
37 #include <dali/integration-api/debug.h>
45 * Helper to check if the property value can be read as int/unsigned int/bool
47 inline bool IsIntegerType( Property::Type type )
49 return ( Property::BOOLEAN == type )||( Property::INTEGER == type )||(Property::UNSIGNED_INTEGER == type );
53 struct Property::Value::Impl
56 : type( Property::NONE ),
60 Impl( bool booleanValue )
61 : type( Property::BOOLEAN ),
62 integerValue( booleanValue )
65 Impl( float floatValue )
66 : type( Property::FLOAT ),
67 floatValue( floatValue )
70 Impl( int integerValue )
71 : type( Property::INTEGER ),
72 integerValue( integerValue )
75 Impl( unsigned int unsignedIntegerValue )
76 : type( Property::UNSIGNED_INTEGER ),
77 unsignedIntegerValue( unsignedIntegerValue )
80 Impl( const Vector2& vectorValue )
81 : type( Property::VECTOR2 ),
82 vector2Value( new Vector2( vectorValue ) )
85 Impl( const Vector3& vectorValue )
86 : type( Property::VECTOR3 ),
87 vector3Value( new Vector3( vectorValue ) )
90 Impl( const Vector4& vectorValue )
91 : type( Property::VECTOR4 ),
92 vector4Value( new Vector4( vectorValue ) )
95 Impl( const Matrix3& matrixValue )
96 : type( Property::MATRIX3 ),
97 matrix3Value( new Matrix3( matrixValue ) )
101 Impl( const Matrix& matrixValue )
102 : type( Property::MATRIX ),
103 matrixValue( new Matrix( matrixValue ) )
107 Impl( const AngleAxis& angleAxisValue )
108 : type( Property::ROTATION ),
109 quaternionValue( new Quaternion( angleAxisValue.angle, angleAxisValue.axis ) )
113 Impl( const Quaternion& quaternionValue )
114 : type( Property::ROTATION ),
115 quaternionValue( new Quaternion( quaternionValue ) )
119 Impl(const std::string& stringValue)
120 : type( Property::STRING ),
121 stringValue( new std::string( stringValue ) )
125 Impl( const Rect<int>& rectValue )
126 : type( Property::RECTANGLE ),
127 rectValue( new Rect<int>( rectValue ) )
131 Impl( const Property::Array& arrayValue )
132 : type( Property::ARRAY ),
133 arrayValue( new Property::Array( arrayValue ) )
137 Impl( const Property::Map& mapValue )
138 : type( Property::MAP ),
139 mapValue( new Property::Map( mapValue ) )
144 * Destructor, takes care of releasing the dynamically allocated types
150 case Property::NONE : // FALLTHROUGH
151 case Property::TYPE_COUNT : // FALLTHROUGH
152 case Property::BOOLEAN : // FALLTHROUGH
153 case Property::FLOAT : // FALLTHROUGH
154 case Property::INTEGER : // FALLTHROUGH
155 case Property::UNSIGNED_INTEGER :
157 break; // nothing to do
159 case Property::VECTOR2 :
164 case Property::VECTOR3:
169 case Property::VECTOR4:
174 case Property::MATRIX3:
179 case Property::MATRIX:
184 case Property::RECTANGLE:
189 case Property::ROTATION:
191 delete quaternionValue;
194 case Property::STRING:
199 case Property::ARRAY:
219 unsigned int unsignedIntegerValue;
220 // must use pointers for any class value pre c++ 11
221 Vector2* vector2Value;
222 Vector3* vector3Value;
223 Vector4* vector4Value;
224 Matrix3* matrix3Value;
226 Quaternion* quaternionValue;
227 std::string* stringValue;
228 Rect<int>* rectValue;
229 Property::Array* arrayValue;
230 Property::Map* mapValue;
234 Property::Value::Value()
239 Property::Value::Value( bool booleanValue )
240 : mImpl( new Impl( booleanValue ) )
244 Property::Value::Value( float floatValue )
245 : mImpl( new Impl( floatValue ) )
249 Property::Value::Value( int integerValue )
250 : mImpl( new Impl( integerValue ) )
254 Property::Value::Value( unsigned int unsignedIntegerValue )
255 : mImpl( new Impl( unsignedIntegerValue ) )
259 Property::Value::Value( const Vector2& vectorValue )
260 : mImpl( new Impl( vectorValue ) )
264 Property::Value::Value( const Vector3& vectorValue )
265 : mImpl( new Impl( vectorValue ) )
269 Property::Value::Value( const Vector4& vectorValue )
270 : mImpl( new Impl( vectorValue ) )
274 Property::Value::Value( const Matrix3& matrixValue )
275 : mImpl( new Impl( matrixValue ) )
279 Property::Value::Value( const Matrix& matrixValue )
280 : mImpl( new Impl( matrixValue ) )
284 Property::Value::Value( const Rect<int>& rectValue )
285 : mImpl( new Impl( rectValue ) )
289 Property::Value::Value( const AngleAxis& angleAxisValue )
290 : mImpl( new Impl( angleAxisValue ) )
294 Property::Value::Value( const Quaternion& quaternionValue )
295 : mImpl( new Impl( quaternionValue ) )
299 Property::Value::Value( const std::string& stringValue )
300 : mImpl( new Impl( stringValue ) )
304 Property::Value::Value( const char* stringValue )
305 : mImpl( new Impl( std::string(stringValue) ) )
309 Property::Value::Value( Property::Array& arrayValue )
310 : mImpl( new Impl( arrayValue ) )
314 Property::Value::Value( Property::Map& mapValue )
315 : mImpl( new Impl( mapValue ) )
320 Property::Value::~Value()
325 Property::Value::Value( const Property::Value& value )
328 // reuse assignment operator
332 Property::Value::Value( Type type )
336 case Property::BOOLEAN:
338 mImpl = new Impl( false );
341 case Property::FLOAT:
343 mImpl = new Impl( 0.f );
346 case Property::INTEGER:
348 mImpl = new Impl( 0 );
351 case Property::UNSIGNED_INTEGER:
353 mImpl = new Impl( 0U );
356 case Property::VECTOR2:
358 mImpl = new Impl( Vector2::ZERO );
361 case Property::VECTOR3:
363 mImpl = new Impl( Vector3::ZERO );
366 case Property::VECTOR4:
368 mImpl = new Impl( Vector4::ZERO );
371 case Property::RECTANGLE:
373 mImpl = new Impl( Rect<int>(0,0,0,0) );
376 case Property::ROTATION:
378 mImpl = new Impl( Quaternion() );
381 case Property::STRING:
383 mImpl = new Impl( std::string() );
386 case Property::MATRIX:
388 mImpl = new Impl( Matrix() );
391 case Property::MATRIX3:
393 mImpl = new Impl( Matrix3() );
396 case Property::ARRAY:
398 mImpl = new Impl( Property::Array() );
403 mImpl = new Impl( Property::Map() );
407 case Property::TYPE_COUNT:
415 Property::Value& Property::Value::operator=( const Property::Value& value )
417 if ( this == &value )
419 // skip self assignment
422 // if we are assigned an empty value, just drop impl
429 // first check if the type is the same, no need to change impl, just assign
430 if( mImpl && ( mImpl->type == value.mImpl->type ) )
432 switch( mImpl->type )
434 case Property::BOOLEAN:
436 mImpl->integerValue = value.mImpl->integerValue;
439 case Property::FLOAT:
441 mImpl->floatValue = value.mImpl->floatValue;
444 case Property::INTEGER:
446 mImpl->integerValue = value.mImpl->integerValue;
449 case Property::UNSIGNED_INTEGER:
451 mImpl->unsignedIntegerValue = value.mImpl->unsignedIntegerValue;
454 case Property::VECTOR2:
456 *mImpl->vector2Value = *value.mImpl->vector2Value;
459 case Property::VECTOR3:
461 *mImpl->vector3Value = *value.mImpl->vector3Value;
464 case Property::VECTOR4:
466 *mImpl->vector4Value = *value.mImpl->vector4Value;
469 case Property::RECTANGLE:
471 *mImpl->rectValue = *value.mImpl->rectValue;
474 case Property::ROTATION:
476 *mImpl->quaternionValue = *value.mImpl->quaternionValue;
479 case Property::STRING:
481 *mImpl->stringValue = *value.mImpl->stringValue;
484 case Property::MATRIX:
486 *mImpl->matrixValue = *value.mImpl->matrixValue;
489 case Property::MATRIX3:
491 *mImpl->matrix3Value = *value.mImpl->matrix3Value;
494 case Property::ARRAY:
496 *mImpl->arrayValue = *value.mImpl->arrayValue;
501 *mImpl->mapValue = *value.mImpl->mapValue;
505 case Property::TYPE_COUNT:
506 { // mImpl will be NULL, there's no way to get to this case
512 // different type, release old impl and create new
513 Impl* newImpl( NULL );
514 switch ( value.mImpl->type )
516 case Property::BOOLEAN:
518 newImpl = new Impl( bool( value.mImpl->integerValue ) );
521 case Property::FLOAT:
523 newImpl = new Impl( value.mImpl->floatValue );
526 case Property::INTEGER:
528 newImpl = new Impl( value.mImpl->integerValue );
531 case Property::UNSIGNED_INTEGER:
533 newImpl = new Impl( value.mImpl->unsignedIntegerValue );
536 case Property::VECTOR2:
538 newImpl = new Impl( *value.mImpl->vector2Value );
541 case Property::VECTOR3:
543 newImpl = new Impl( *value.mImpl->vector3Value );
546 case Property::VECTOR4:
548 newImpl = new Impl( *value.mImpl->vector4Value );
551 case Property::RECTANGLE:
553 newImpl = new Impl( *value.mImpl->rectValue );
556 case Property::ROTATION:
558 newImpl = new Impl( *value.mImpl->quaternionValue );
561 case Property::MATRIX3:
563 newImpl = new Impl( *value.mImpl->matrix3Value );
566 case Property::MATRIX:
568 newImpl = new Impl( *value.mImpl->matrixValue );
571 case Property::STRING:
573 newImpl = new Impl( *value.mImpl->stringValue );
576 case Property::ARRAY:
578 newImpl = new Impl( *value.mImpl->arrayValue );
583 newImpl = new Impl( *value.mImpl->mapValue );
587 case Property::TYPE_COUNT:
588 { // NULL value will be used for "empty" value
598 Property::Type Property::Value::GetType() const
600 Property::Type type( Property::NONE );
608 void Property::Value::Get( bool& booleanValue ) const
610 if( mImpl && IsIntegerType( mImpl->type ) )
612 booleanValue = mImpl->integerValue;
616 booleanValue = false;
620 void Property::Value::Get( float& floatValue ) const
622 if( mImpl && mImpl->type == FLOAT )
624 floatValue = mImpl->floatValue;
632 void Property::Value::Get( int& integerValue ) const
634 if( mImpl && IsIntegerType( mImpl->type ) )
636 integerValue = mImpl->integerValue;
644 void Property::Value::Get( unsigned int& unsignedIntegerValue ) const
646 if( mImpl && IsIntegerType( mImpl->type ) )
648 unsignedIntegerValue = mImpl->unsignedIntegerValue;
652 unsignedIntegerValue = 0u;
656 void Property::Value::Get( Vector2& vectorValue ) const
658 if( mImpl && mImpl->type == VECTOR2 && mImpl->vector2Value )
660 vectorValue = *(mImpl->vector2Value);
664 vectorValue.x = vectorValue.y = 0.f;
668 void Property::Value::Get( Vector3& vectorValue ) const
670 if( mImpl && mImpl->type == VECTOR3 && mImpl->vector3Value )
672 vectorValue = *(mImpl->vector3Value);
676 vectorValue.x = vectorValue.y = vectorValue.z = 0.f;
680 void Property::Value::Get( Vector4& vectorValue ) const
682 if( mImpl && mImpl->type == VECTOR4 && mImpl->vector4Value )
684 vectorValue = *(mImpl->vector4Value);
688 vectorValue.x = vectorValue.y = vectorValue.z = vectorValue.w = 0.f;
692 void Property::Value::Get( Matrix3& matrixValue ) const
694 if( mImpl && mImpl->type == MATRIX3 && mImpl->matrix3Value )
696 matrixValue = *(mImpl->matrix3Value);
700 matrixValue.SetIdentity();
704 void Property::Value::Get( Matrix& matrixValue ) const
706 if( mImpl && mImpl->type == MATRIX && mImpl->matrixValue )
708 matrixValue = *(mImpl->matrixValue);
712 matrixValue.SetIdentity();
716 void Property::Value::Get( Rect<int>& rectValue ) const
718 if( mImpl && mImpl->type == RECTANGLE && mImpl->rectValue )
720 rectValue = *(mImpl->rectValue);
724 rectValue.x = rectValue.y = rectValue.width = rectValue.height = 0.f;
728 void Property::Value::Get( AngleAxis& angleAxisValue ) const
730 if( mImpl && mImpl->type == ROTATION && mImpl->quaternionValue )
732 mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
736 angleAxisValue.angle = 0.f;
737 angleAxisValue.axis = Vector3::ZERO; // identity quaternion
741 void Property::Value::Get( Quaternion& quaternionValue ) const
743 if( mImpl && mImpl->type == ROTATION && mImpl->quaternionValue )
745 quaternionValue = *(mImpl->quaternionValue);
749 quaternionValue = Quaternion::IDENTITY;
753 void Property::Value::Get( std::string& stringValue ) const
755 if( mImpl && mImpl->type == STRING && mImpl->stringValue )
757 stringValue.assign( *(mImpl->stringValue) );
765 void Property::Value::Get( Property::Array& arrayValue ) const
767 if( mImpl && mImpl->type == ARRAY && mImpl->arrayValue )
769 arrayValue = *(mImpl->arrayValue);
777 void Property::Value::Get( Property::Map& mapValue ) const
779 if( mImpl && mImpl->type == MAP && mImpl->mapValue )
781 mapValue = *(mImpl->mapValue);
789 Property::Map* Property::Value::GetMap() const
791 Property::Map* map = NULL;
792 if( mImpl && mImpl->type == MAP && mImpl->mapValue )
794 map = mImpl->mapValue;
799 Property::Array* Property::Value::GetArray() const
801 Property::Array* array = NULL;
802 if( mImpl && mImpl->type == ARRAY && mImpl->arrayValue )
804 array = mImpl->arrayValue;
809 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
813 const Property::Value::Impl& impl( *value.mImpl );
817 case Dali::Property::BOOLEAN:
819 stream << impl.integerValue;
822 case Dali::Property::FLOAT:
824 stream << impl.floatValue;
827 case Dali::Property::INTEGER:
829 stream << impl.integerValue;
832 case Dali::Property::UNSIGNED_INTEGER:
834 stream << impl.unsignedIntegerValue;
837 case Dali::Property::VECTOR2:
839 stream << *impl.vector2Value;
842 case Dali::Property::VECTOR3:
844 stream << *impl.vector3Value;
847 case Dali::Property::VECTOR4:
849 stream << *impl.vector4Value;
852 case Dali::Property::MATRIX3:
854 stream << *impl.matrix3Value;
857 case Dali::Property::MATRIX:
859 stream << *impl.matrixValue;
862 case Dali::Property::RECTANGLE:
864 stream << *impl.rectValue;
867 case Dali::Property::ROTATION:
869 stream << *impl.quaternionValue;
872 case Dali::Property::STRING:
874 stream << *impl.stringValue;
877 case Dali::Property::ARRAY:
879 stream << "Array containing" << impl.arrayValue->Count() << " elements"; // TODO add ostream<< operator in array
882 case Dali::Property::MAP:
884 stream << "Map containing " << impl.mapValue->Count() << " elements"; // TODO add ostream<< operator in map
887 case Dali::Property::NONE:
888 case Dali::Property::TYPE_COUNT:
890 stream << "undefined type";
897 stream << "empty type";