2 * Copyright (c) 2020 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/integration-api/debug.h>
26 #include <dali/public-api/common/extents.h>
27 #include <dali/public-api/math/angle-axis.h>
28 #include <dali/public-api/math/matrix.h>
29 #include <dali/public-api/math/matrix3.h>
30 #include <dali/public-api/math/quaternion.h>
31 #include <dali/public-api/math/radian.h>
32 #include <dali/public-api/math/rect.h>
33 #include <dali/public-api/math/vector2.h>
34 #include <dali/public-api/math/vector3.h>
35 #include <dali/public-api/math/vector4.h>
36 #include <dali/public-api/object/property-array.h>
37 #include <dali/public-api/object/property-map.h>
38 #include <dali/public-api/object/property-types.h>
45 * Helper to check if the property value can be read as int/bool
47 inline bool IsIntegerType(Property::Type type)
49 return (Property::BOOLEAN == type) || (Property::INTEGER == type);
53 struct Property::Value::Impl
55 Impl(bool booleanValue)
56 : type(Property::BOOLEAN),
57 integerValue(booleanValue)
61 Impl(float floatValue)
62 : type(Property::FLOAT),
63 floatValue(floatValue)
67 Impl(int32_t integerValue)
68 : type(Property::INTEGER),
69 integerValue(integerValue)
73 Impl(const Vector2& vectorValue)
74 : type(Property::VECTOR2),
75 vector2Value(new Vector2(vectorValue))
79 Impl(const Vector3& vectorValue)
80 : type(Property::VECTOR3),
81 vector3Value(new Vector3(vectorValue))
85 Impl(const Vector4& vectorValue)
86 : type(Property::VECTOR4),
87 vector4Value(new Vector4(vectorValue))
91 Impl(const Matrix3& matrixValue)
92 : type(Property::MATRIX3),
93 matrix3Value(new Matrix3(matrixValue))
97 Impl(const Matrix& matrixValue)
98 : type(Property::MATRIX),
99 matrixValue(new Matrix(matrixValue))
103 Impl(const AngleAxis& angleAxisValue)
104 : type(Property::ROTATION),
105 angleAxisValue(new AngleAxis(angleAxisValue))
109 Impl(const Quaternion& quaternionValue)
110 : type(Property::ROTATION),
111 angleAxisValue(new AngleAxis())
113 quaternionValue.ToAxisAngle(angleAxisValue->axis, angleAxisValue->angle);
116 Impl(const std::string& stringValue)
117 : type(Property::STRING),
118 stringValue(new std::string(stringValue))
122 Impl(const Rect<int32_t>& rectValue)
123 : type(Property::RECTANGLE),
124 rectValue(new Rect<int>(rectValue))
128 Impl(const Rect<float>& rectValue)
129 : type(Property::VECTOR4),
130 vector4Value(new Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height))
134 Impl(const Property::Array& arrayValue)
135 : type(Property::ARRAY),
136 arrayValue(new Property::Array(arrayValue))
140 Impl(Property::Array&& arrayValue)
141 : type(Property::ARRAY),
142 arrayValue(new Property::Array(std::move(arrayValue)))
146 Impl(const Property::Map& mapValue)
147 : type(Property::MAP),
148 mapValue(new Property::Map(mapValue))
152 Impl(Property::Map&& mapValue)
153 : type(Property::MAP),
154 mapValue(new Property::Map(std::move(mapValue)))
158 Impl(const Extents& extentsValue)
159 : type(Property::EXTENTS),
160 extentsValue(new Extents(extentsValue))
164 Impl(const std::initializer_list<KeyValuePair>& values)
165 : type(Property::MAP),
166 mapValue(new Property::Map(values))
171 * Destructor, takes care of releasing the dynamically allocated types
177 case Property::NONE: // FALLTHROUGH
178 case Property::BOOLEAN: // FALLTHROUGH
179 case Property::FLOAT: // FALLTHROUGH
180 case Property::INTEGER:
182 break; // nothing to do
184 case Property::VECTOR2:
189 case Property::VECTOR3:
194 case Property::VECTOR4:
199 case Property::MATRIX3:
204 case Property::MATRIX:
209 case Property::RECTANGLE:
214 case Property::ROTATION:
216 delete angleAxisValue;
219 case Property::STRING:
224 case Property::ARRAY:
234 case Property::EXTENTS:
246 int32_t integerValue;
248 // must use pointers for any class value pre c++ 11
249 Vector2* vector2Value;
250 Vector3* vector3Value;
251 Vector4* vector4Value;
252 Matrix3* matrix3Value;
254 AngleAxis* angleAxisValue;
255 std::string* stringValue;
256 Rect<int32_t>* rectValue;
257 Property::Array* arrayValue;
258 Property::Map* mapValue;
259 Extents* extentsValue;
264 Impl(const Impl&) = delete;
265 Impl& operator=(const Impl&) = delete;
268 Property::Value::Value()
273 Property::Value::Value(bool booleanValue)
274 : mImpl(new Impl(booleanValue))
278 Property::Value::Value(float floatValue)
279 : mImpl(new Impl(floatValue))
283 Property::Value::Value(int32_t integerValue)
284 : mImpl(new Impl(integerValue))
288 Property::Value::Value(const Vector2& vectorValue)
289 : mImpl(new Impl(vectorValue))
293 Property::Value::Value(const Vector3& vectorValue)
294 : mImpl(new Impl(vectorValue))
298 Property::Value::Value(const Vector4& vectorValue)
299 : mImpl(new Impl(vectorValue))
303 Property::Value::Value(const Matrix3& matrixValue)
304 : mImpl(new Impl(matrixValue))
308 Property::Value::Value(const Matrix& matrixValue)
309 : mImpl(new Impl(matrixValue))
313 Property::Value::Value(const Rect<int32_t>& rectValue)
314 : mImpl(new Impl(rectValue))
318 Property::Value::Value(const Rect<float>& rectValue)
319 : mImpl(new Impl(rectValue))
323 Property::Value::Value(const AngleAxis& angleAxisValue)
324 : mImpl(new Impl(angleAxisValue))
328 Property::Value::Value(const Quaternion& quaternionValue)
329 : mImpl(new Impl(quaternionValue))
333 Property::Value::Value(const std::string& stringValue)
334 : mImpl(new Impl(stringValue))
338 Property::Value::Value(const char* stringValue)
341 if(stringValue) // string constructor is undefined with nullptr
343 mImpl = new Impl(std::string(stringValue));
347 mImpl = new Impl(std::string());
351 Property::Value::Value(Property::Array& arrayValue)
352 : mImpl(new Impl(arrayValue))
356 Property::Value::Value(Property::Array&& arrayValue)
357 : mImpl(new Impl(std::move(arrayValue)))
361 Property::Value::Value(Property::Map& mapValue)
362 : mImpl(new Impl(mapValue))
366 Property::Value::Value(Property::Map&& mapValue)
367 : mImpl(new Impl(std::move(mapValue)))
371 Property::Value::Value(const Extents& extentsValue)
372 : mImpl(new Impl(extentsValue))
376 Property::Value::Value(const std::initializer_list<KeyValuePair>& values)
377 : mImpl(new Impl(values))
381 Property::Value::Value(Type type)
386 case Property::BOOLEAN:
388 mImpl = new Impl(false);
391 case Property::FLOAT:
393 mImpl = new Impl(0.f);
396 case Property::INTEGER:
401 case Property::VECTOR2:
403 mImpl = new Impl(Vector2::ZERO);
406 case Property::VECTOR3:
408 mImpl = new Impl(Vector3::ZERO);
411 case Property::VECTOR4:
413 mImpl = new Impl(Vector4::ZERO);
416 case Property::RECTANGLE:
418 mImpl = new Impl(Rect<int32_t>(0, 0, 0, 0));
421 case Property::ROTATION:
423 mImpl = new Impl(AngleAxis());
426 case Property::STRING:
428 mImpl = new Impl(std::string());
431 case Property::MATRIX:
433 mImpl = new Impl(Matrix());
436 case Property::MATRIX3:
438 mImpl = new Impl(Matrix3());
441 case Property::ARRAY:
443 mImpl = new Impl(Property::Array());
448 mImpl = new Impl(Property::Map());
451 case Property::EXTENTS:
453 mImpl = new Impl(Extents());
458 // No need to create an Impl
464 Property::Value::Value(const Property::Value& value)
467 // reuse assignment operator
471 Property::Value::Value(Property::Value&& value)
474 value.mImpl = nullptr;
477 Property::Value& Property::Value::operator=(const Property::Value& value)
481 // skip self assignment
484 // if we are assigned an empty value, just drop impl
491 // first check if the type is the same, no need to change impl, just assign
492 if(mImpl && (mImpl->type == value.mImpl->type))
496 case Property::BOOLEAN:
498 mImpl->integerValue = value.mImpl->integerValue;
501 case Property::FLOAT:
503 mImpl->floatValue = value.mImpl->floatValue;
506 case Property::INTEGER:
508 mImpl->integerValue = value.mImpl->integerValue;
511 case Property::VECTOR2:
513 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
516 case Property::VECTOR3:
518 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
521 case Property::VECTOR4:
523 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
526 case Property::RECTANGLE:
528 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
531 case Property::ROTATION:
533 *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated
536 case Property::STRING:
538 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
541 case Property::MATRIX:
543 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
546 case Property::MATRIX3:
548 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
551 case Property::ARRAY:
553 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
558 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
561 case Property::EXTENTS:
563 *mImpl->extentsValue = *value.mImpl->extentsValue; // type cannot change in mImpl so extents is allocated
567 { // mImpl will be a nullptr, there's no way to get to this case
573 // different type, release old impl and create new
574 Impl* newImpl(nullptr);
575 switch(value.mImpl->type)
577 case Property::BOOLEAN:
579 newImpl = new Impl(bool(value.mImpl->integerValue));
582 case Property::FLOAT:
584 newImpl = new Impl(value.mImpl->floatValue);
587 case Property::INTEGER:
589 newImpl = new Impl(value.mImpl->integerValue);
592 case Property::VECTOR2:
594 newImpl = new Impl(*value.mImpl->vector2Value); // type cannot change in mImpl so vector is allocated
597 case Property::VECTOR3:
599 newImpl = new Impl(*value.mImpl->vector3Value); // type cannot change in mImpl so vector is allocated
602 case Property::VECTOR4:
604 newImpl = new Impl(*value.mImpl->vector4Value); // type cannot change in mImpl so vector is allocated
607 case Property::RECTANGLE:
609 newImpl = new Impl(*value.mImpl->rectValue); // type cannot change in mImpl so rect is allocated
612 case Property::ROTATION:
614 newImpl = new Impl(*value.mImpl->angleAxisValue); // type cannot change in mImpl so quaternion is allocated
617 case Property::MATRIX3:
619 newImpl = new Impl(*value.mImpl->matrix3Value); // type cannot change in mImpl so matrix is allocated
622 case Property::MATRIX:
624 newImpl = new Impl(*value.mImpl->matrixValue); // type cannot change in mImpl so matrix is allocated
627 case Property::STRING:
629 newImpl = new Impl(*value.mImpl->stringValue); // type cannot change in mImpl so string is allocated
632 case Property::ARRAY:
634 newImpl = new Impl(*value.mImpl->arrayValue); // type cannot change in mImpl so array is allocated
639 newImpl = new Impl(*value.mImpl->mapValue); // type cannot change in mImpl so map is allocated
642 case Property::EXTENTS:
644 newImpl = new Impl(*value.mImpl->extentsValue); // type cannot change in mImpl so extents is allocated
648 { // nullptr value will be used for "empty" value
658 Property::Value& Property::Value::operator=(Property::Value&& value)
664 value.mImpl = nullptr;
670 Property::Value::~Value()
675 Property::Type Property::Value::GetType() const
677 Property::Type type(Property::NONE);
685 bool Property::Value::Get(bool& booleanValue) const
687 bool converted = false;
688 if(mImpl && IsIntegerType(mImpl->type))
690 booleanValue = mImpl->integerValue;
696 bool Property::Value::Get(float& floatValue) const
698 bool converted = false;
701 if(mImpl->type == FLOAT)
703 floatValue = mImpl->floatValue;
706 else if(IsIntegerType(mImpl->type))
708 floatValue = static_cast<float>(mImpl->integerValue);
715 bool Property::Value::Get(int32_t& integerValue) const
717 bool converted = false;
720 if(IsIntegerType(mImpl->type))
722 integerValue = mImpl->integerValue;
725 else if(mImpl->type == FLOAT)
727 integerValue = static_cast<int32_t>(mImpl->floatValue);
734 bool Property::Value::Get(Vector2& vectorValue) const
736 bool converted = false;
739 // type cannot change in mImpl so vector is allocated
740 if(mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4)
742 vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned
749 bool Property::Value::Get(Vector3& vectorValue) const
751 bool converted = false;
754 // type cannot change in mImpl so vector is allocated
755 if(mImpl->type == VECTOR3 || mImpl->type == VECTOR4)
757 vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned
760 else if(mImpl->type == VECTOR2)
762 vectorValue = *(mImpl->vector2Value);
769 bool Property::Value::Get(Vector4& vectorValue) const
771 bool converted = false;
774 if(mImpl->type == VECTOR4) // type cannot change in mImpl so vector is allocated
776 vectorValue = *(mImpl->vector4Value);
779 else if(mImpl->type == VECTOR2)
781 vectorValue = *(mImpl->vector2Value);
784 else if(mImpl->type == VECTOR3)
786 vectorValue = *(mImpl->vector3Value);
793 bool Property::Value::Get(Matrix3& matrixValue) const
795 bool converted = false;
796 if(mImpl && (mImpl->type == MATRIX3)) // type cannot change in mImpl so matrix is allocated
798 matrixValue = *(mImpl->matrix3Value);
804 bool Property::Value::Get(Matrix& matrixValue) const
806 bool converted = false;
807 if(mImpl && (mImpl->type == MATRIX)) // type cannot change in mImpl so matrix is allocated
809 matrixValue = *(mImpl->matrixValue);
815 bool Property::Value::Get(Rect<int32_t>& rectValue) const
817 bool converted = false;
818 if(mImpl && (mImpl->type == RECTANGLE)) // type cannot change in mImpl so rect is allocated
820 rectValue = *(mImpl->rectValue);
826 bool Property::Value::Get(AngleAxis& angleAxisValue) const
828 bool converted = false;
829 if(mImpl && (mImpl->type == ROTATION)) // type cannot change in mImpl so angleAxis is allocated
831 angleAxisValue = *(mImpl->angleAxisValue);
837 bool Property::Value::Get(Quaternion& quaternionValue) const
839 bool converted = false;
840 if(mImpl && (mImpl->type == ROTATION)) // type cannot change in mImpl so angleAxis is allocated
842 quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis);
848 bool Property::Value::Get(std::string& stringValue) const
850 bool converted = false;
851 if(mImpl && (mImpl->type == STRING)) // type cannot change in mImpl so string is allocated
853 stringValue.assign(*(mImpl->stringValue));
859 bool Property::Value::Get(Property::Array& arrayValue) const
861 bool converted = false;
862 if(mImpl && (mImpl->type == ARRAY)) // type cannot change in mImpl so array is allocated
864 arrayValue = *(mImpl->arrayValue);
870 bool Property::Value::Get(Property::Map& mapValue) const
872 bool converted = false;
873 if(mImpl && (mImpl->type == MAP)) // type cannot change in mImpl so map is allocated
875 mapValue = *(mImpl->mapValue);
881 Property::Array* Property::Value::GetArray() const
883 Property::Array* array = nullptr;
884 if(mImpl && (mImpl->type == ARRAY)) // type cannot change in mImpl so array is allocated
886 array = mImpl->arrayValue;
891 Property::Map* Property::Value::GetMap() const
893 Property::Map* map = nullptr;
894 if(mImpl && (mImpl->type == MAP)) // type cannot change in mImpl so map is allocated
896 map = mImpl->mapValue;
901 bool Property::Value::Get(Extents& extentsValue) const
903 bool converted = false;
906 if(mImpl->type == EXTENTS)
908 extentsValue = *(mImpl->extentsValue);
911 else if(mImpl->type == VECTOR4)
913 extentsValue.start = static_cast<uint16_t>(mImpl->vector4Value->x);
914 extentsValue.end = static_cast<uint16_t>(mImpl->vector4Value->y);
915 extentsValue.top = static_cast<uint16_t>(mImpl->vector4Value->z);
916 extentsValue.bottom = static_cast<uint16_t>(mImpl->vector4Value->w);
923 std::ostream& operator<<(std::ostream& stream, const Property::Value& value)
927 const Property::Value::Impl& impl(*value.mImpl);
931 case Dali::Property::BOOLEAN:
933 stream << impl.integerValue;
936 case Dali::Property::FLOAT:
938 stream << impl.floatValue;
941 case Dali::Property::INTEGER:
943 stream << impl.integerValue;
946 case Dali::Property::VECTOR2:
948 stream << *impl.vector2Value;
951 case Dali::Property::VECTOR3:
953 stream << *impl.vector3Value;
956 case Dali::Property::VECTOR4:
958 stream << *impl.vector4Value;
961 case Dali::Property::MATRIX3:
963 stream << *impl.matrix3Value;
966 case Dali::Property::MATRIX:
968 stream << *impl.matrixValue;
971 case Dali::Property::RECTANGLE:
973 stream << *impl.rectValue;
976 case Dali::Property::ROTATION:
978 stream << *impl.angleAxisValue;
981 case Dali::Property::STRING:
983 stream << *impl.stringValue;
986 case Dali::Property::ARRAY:
988 stream << *(value.GetArray());
991 case Dali::Property::MAP:
993 stream << *(value.GetMap());
996 case Dali::Property::EXTENTS:
998 stream << *impl.extentsValue;
1001 case Dali::Property::NONE:
1002 { // mImpl will be a nullptr, there's no way to get to this case
1008 stream << "undefined type";