[dali_1.9.32] Merge branch 'devel/master' 16/245116/1
authorCheng-Shiun Tsai <cheng.tsai@samsung.com>
Fri, 2 Oct 2020 09:47:01 +0000 (10:47 +0100)
committerCheng-Shiun Tsai <cheng.tsai@samsung.com>
Fri, 2 Oct 2020 09:47:01 +0000 (10:47 +0100)
Change-Id: I273fcca7812387ae4d62a455aa69c43ea8f95c9f

16 files changed:
automated-tests/src/dali/utc-Dali-PropertyValue.cpp
dali/internal/event/common/demangler-unix.cpp
dali/internal/event/common/demangler-windows.cpp
dali/internal/event/common/demangler.h
dali/internal/event/common/property-metadata.cpp
dali/internal/event/common/scene-impl.cpp [changed mode: 0644->0755]
dali/internal/event/common/scene-impl.h [changed mode: 0644->0755]
dali/internal/event/rendering/shader-impl.cpp
dali/internal/render/common/render-algorithms.cpp [changed mode: 0644->0755]
dali/internal/render/common/render-item.cpp [changed mode: 0644->0755]
dali/internal/render/common/render-manager.cpp [changed mode: 0644->0755]
dali/public-api/actors/custom-actor-impl.h
dali/public-api/dali-core-version.cpp
dali/public-api/object/property-value.cpp
dali/public-api/object/property-value.h
packaging/dali.spec

index 762e99a..a3f8292 100644 (file)
@@ -478,6 +478,29 @@ int UtcDaliPropertyValueCopyConstructorStringP(void)
   END_TEST;
 }
 
+int UtcDaliPropertyValueCopyAssignStringDifferentTypeP(void)
+{
+  Property::Value value1{Vector4(3.f, 2.f, 1.f, 2.0f)};
+  Property::Value value2{"very very long string ..................."};
+  value2 = value1;
+
+  Vector4 vec1, vec2;
+  value1.Get(vec1);
+  value2.Get(vec2);
+  DALI_TEST_EQUALS(value1.GetType(), value2.GetType(), TEST_LOCATION);
+  DALI_TEST_EQUALS(vec1, vec2, TEST_LOCATION);
+
+  Property::Value value3{Vector4(3.f, 2.f, 1.f, 2.0f)};
+  Property::Value value4{"very very long string ..................."};
+
+  value3 = value4;
+
+  DALI_TEST_EQUALS(value3.GetType(), value4.GetType(), TEST_LOCATION);
+  DALI_TEST_EQUALS(value3.Get<std::string>(), "very very long string ...................", TEST_LOCATION);
+  DALI_TEST_EQUALS(value3.Get<std::string>(), value4.Get<std::string>(), TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliPropertyValueCopyConstructorArrayP(void)
 {
   Property::Value  value1(Property::ARRAY);
index 07a63a1..773b653 100644 (file)
  *
  */
 
+// EXTERNAL HEADER
+#include <string_view>
+
 // FILE HEADER
 #include <dali/internal/event/common/demangler.h>
 
-// INTERNAL HEADERS
-#include <dali/public-api/common/vector-wrapper.h>
-
 namespace
 {
-
-// true if character represent a digit
-inline bool IsDigit(char c)
-{
-  return (c >= '0' && c <= '9');
-}
-
-// Gets the number of characters (number is in string)
-//   start The start position to look for a number
-//   result The number as an integer
-//   returns the number of characters used to define the number ie '12' is 2
-size_t GetNumberOfCharacters(const std::string& s, const size_t& start, int& result)
+// Extracts the number from the src view and update the view.
+size_t ExtractNumber(std::string_view& src)
 {
-  size_t size = s.size();
-
-  size_t i = start;
-
-  int number = 0;
+  auto   IsDigit = [](char c) { return (c >= '0' && c <= '9'); };
+  size_t number  = 0;
 
-  for( ; i < size; ++i )
+  for(auto i = 0u; i < src.size(); ++i)
   {
-    char c = s.at(i);
+    char c = src[i];
     if( !IsDigit( c ) )
     {
+      //update the src view.
+      src.remove_prefix(i);
       break;
     }
     else
@@ -55,53 +44,41 @@ size_t GetNumberOfCharacters(const std::string& s, const size_t& start, int& res
     }
   }
 
-  if( i - start )
-  {
-    result = number;
-  }
-
-  return i - start;
+  return number;
 }
 
 /**
- * @brief Demangle a nested typeid name into its component parts.
+ * @brief Demangle a nested typeid name into its component parts and return
+ * the last component.
  * A nested type name is one containing namespaces and class names only.
- *   eg DemangleNestedNames(typeid(Dali::Actor).name());
+ *   eg ExtractDemangleNestedName(typeid(Dali::Actor).name());
  * @param[in] typeIdName The type id name string to demangle.
- * @returns the demangled list of names ie ["Dali","Actor"] or an empty list
+ * @returns the last component "Actor" or an empty string_view
  */
-std::vector<std::string> DemangleNestedNames(const char *typeIdName)
+std::string_view ExtractDemangleNestedName(std::string_view mangledName)
 {
-  // Demangle class name mangled according to the Itanium C++ ABI
-  // Returns demangled names ie "N4Dali8Internal5ActorE" is ["Dali","Internal","Actor"]
-  std::vector<std::string> ret;
-
-  const std::string mangledName(typeIdName);
-
-
-  size_t size = mangledName.size();
-
-  if( size >= 2 )
+  if(mangledName.empty())
   {
-    int number = 0;
-    size_t start = 0;
-
-    // If the class isnt nested in a namespace then it just starts with the
-    // number of characters
-    if(mangledName[0] == 'N' && mangledName[size-1]  == 'E')
-    {
-      start = 1;
-    }
+    return {};
+  }
 
-    while( size_t chars = GetNumberOfCharacters(mangledName, start, number) )
-    {
-      ret.push_back( mangledName.substr( start + chars, number ) );
+  // classes nested inside a namespace starts with 'N' and ends with 'E'
+  // so trim those
+  if(mangledName.front() == 'N' && mangledName.back() == 'E')
+  {
+    mangledName.remove_prefix(1);
+    mangledName.remove_suffix(1);
+  }
 
-      start += chars + number;
-    }
+  std::string_view result;
+  while(!mangledName.empty())
+  {
+    auto length = ExtractNumber(mangledName);
+    result      = {mangledName.data(), length};
+    mangledName.remove_prefix(length);
   }
 
-  return ret;
+  return result;
 }
 
 } // anon namespace
@@ -111,18 +88,9 @@ namespace Dali
 
 namespace Internal
 {
-
-const std::string DemangleClassName(const char *typeIdName)
+std::string DemangleClassName(const char* typeIdName)
 {
-  std::string name;
-  std::vector<std::string> names = DemangleNestedNames(typeIdName);
-
-  if( names.size() )
-  {
-    name = names[ names.size() - 1 ];
-  }
-
-  return name;
+  return std::string(ExtractDemangleNestedName(typeIdName));
 }
 
 } // namespace Internal
index 9d6612a..cdfc58b 100644 (file)
@@ -23,8 +23,7 @@ namespace Dali
 
 namespace Internal
 {
-
-const std::string DemangleClassName(const char *typeIdName)
+std::string DemangleClassName(const char* typeIdName)
 {
   std::string name = typeIdName;
   int index = name.find_last_of(' ');
index 4d9790b..647e015 100644 (file)
@@ -32,7 +32,7 @@ namespace Internal
  * @param[in] typeIdName The type id name string to demangle.
  * @returns the class name ie "Actor" or an empty string
  */
-const std::string DemangleClassName(const char *typeIdName);
+std::string DemangleClassName(const char* typeIdName);
 
 } // namespace Internal
 
index aa4d607..1df9d5e 100644 (file)
@@ -86,7 +86,7 @@ void PropertyMetadata::SetPropertyValue( const Property::Value& propertyValue )
 
     case Property::ARRAY:
     {
-      Property::Array* array = propertyValue.GetArray();
+      const Property::Array* array = propertyValue.GetArray();
       if( array )
       {
         value = *array;
@@ -96,7 +96,7 @@ void PropertyMetadata::SetPropertyValue( const Property::Value& propertyValue )
 
     case Property::MAP:
     {
-      Property::Map* map = propertyValue.GetMap();
+      const Property::Map* map = propertyValue.GetMap();
       if( map )
       {
         value = *map;
old mode 100644 (file)
new mode 100755 (executable)
index 7f85aa1..496fba4
@@ -375,6 +375,11 @@ Integration::Scene::WheelEventSignalType& Scene::WheelEventSignal()
   return mWheelEventSignal;
 }
 
+std::vector<Dali::Internal::SceneGraph::DirtyRect>& Scene::GetItemsDirtyRects()
+{
+  return mItemsDirtyRects;
+}
+
 } // Internal
 
 } // Dali
old mode 100644 (file)
new mode 100755 (executable)
index 96b8a8f..67d08d5
@@ -44,6 +44,54 @@ namespace Internal
 namespace SceneGraph
 {
 class Scene;
+
+struct DirtyRect
+{
+  DirtyRect(Node* node, Render::Renderer* renderer, int frame, Rect<int>& rect)
+  : node(node),
+    renderer(renderer),
+    frame(frame),
+    rect(rect),
+    visited(true)
+  {
+  }
+
+  DirtyRect()
+  : node(nullptr),
+    renderer(nullptr),
+    frame(0),
+    rect(),
+    visited(true)
+  {
+  }
+
+  bool operator<(const DirtyRect& rhs) const
+  {
+    if (node == rhs.node)
+    {
+      if (renderer == rhs.renderer)
+      {
+        return frame > rhs.frame; // Most recent rects come first
+      }
+      else
+      {
+        return renderer < rhs.renderer;
+      }
+    }
+    else
+    {
+      return node < rhs.node;
+    }
+  }
+
+  Node* node;
+  Render::Renderer* renderer;
+  int frame;
+
+  Rect<int> rect;
+  bool visited;
+};
+
 }
 
 class EventProcessor;
@@ -260,6 +308,13 @@ public:
    */
   Integration::Scene::WheelEventSignalType& WheelEventSignal();
 
+  /**
+   * @brief Get ItemsDirtyRects
+   *
+   * @return the ItemsDirtyRects
+   */
+  std::vector<Dali::Internal::SceneGraph::DirtyRect>& GetItemsDirtyRects();
+
 public:
 
   /**
@@ -327,6 +382,8 @@ private:
 
   // The wheel event signal
   Integration::Scene::WheelEventSignalType mWheelEventSignal;
+
+  std::vector<Dali::Internal::SceneGraph::DirtyRect>                    mItemsDirtyRects;
 };
 
 } // Internal
index 1a7f11f..3c3dcf9 100644 (file)
@@ -124,7 +124,7 @@ void Shader::SetDefaultProperty( Property::Index index, const Property::Value& p
     {
       if( propertyValue.GetType() == Property::MAP )
       {
-        Dali::Property::Map* map = propertyValue.GetMap();
+        const Dali::Property::Map* map = propertyValue.GetMap();
         if( map )
         {
           std::string vertex;
old mode 100644 (file)
new mode 100755 (executable)
index 744ae86..f5d540c
@@ -418,6 +418,7 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
   if (!rootClippingRect.IsEmpty())
   {
     context.SetScissorTest( true );
+    context.Scissor( rootClippingRect.x, rootClippingRect.y, rootClippingRect.width, rootClippingRect.height );
     mScissorStack.push_back( rootClippingRect );
   }
   // We are not performing a layer clip and no clipping rect set. Add the viewport as the root scissor rectangle.
old mode 100644 (file)
new mode 100755 (executable)
index b795530..d0daa83
@@ -110,8 +110,8 @@ ClippingBox RenderItem::CalculateViewportSpaceAABB( const Vector3& size, const i
                         static_cast<float>( viewportWidth )  * 0.5f - aabb.x,
                         static_cast<float>( viewportHeight ) * 0.5f - aabb.y );
 
-  int x = static_cast< int >( roundf( aabbInScreen.x ) );
-  int y = static_cast< int >( roundf( aabbInScreen.y ) );
+  int x = static_cast< int >( floor( aabbInScreen.x ) );
+  int y = static_cast< int >( floor( aabbInScreen.y ) );
   int z = static_cast< int >( roundf( aabbInScreen.z ) );
   int w = static_cast< int >( roundf( aabbInScreen.w ) );
 
old mode 100644 (file)
new mode 100755 (executable)
index d3db8f3..e885c33
@@ -48,53 +48,6 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_REN
 } // unnamed namespace
 #endif
 
-struct DirtyRect
-{
-  DirtyRect(Node* node, Render::Renderer* renderer, int frame, Rect<int>& rect)
-  : node(node),
-    renderer(renderer),
-    frame(frame),
-    rect(rect),
-    visited(true)
-  {
-  }
-
-  DirtyRect()
-  : node(nullptr),
-    renderer(nullptr),
-    frame(0),
-    rect(),
-    visited(true)
-  {
-  }
-
-  bool operator<(const DirtyRect& rhs) const
-  {
-    if (node == rhs.node)
-    {
-      if (renderer == rhs.renderer)
-      {
-        return frame > rhs.frame; // Most recent rects come first
-      }
-      else
-      {
-        return renderer < rhs.renderer;
-      }
-    }
-    else
-    {
-      return node < rhs.node;
-    }
-  }
-
-  Node* node;
-  Render::Renderer* renderer;
-  int frame;
-
-  Rect<int> rect;
-  bool visited;
-};
-
 /**
  * Structure to contain internal data
  */
@@ -124,8 +77,7 @@ struct RenderManager::Impl
     programController( glAbstraction ),
     depthBufferAvailable( depthBufferAvailableParam ),
     stencilBufferAvailable( stencilBufferAvailableParam ),
-    partialUpdateAvailable( partialUpdateAvailableParam ),
-    itemsCheckSum(0)
+    partialUpdateAvailable( partialUpdateAvailableParam )
   {
      // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
     threadPool = std::unique_ptr<Dali::ThreadPool>( new Dali::ThreadPool() );
@@ -222,8 +174,6 @@ struct RenderManager::Impl
   std::unique_ptr<Dali::ThreadPool>         threadPool;               ///< The thread pool
   Vector<GLuint>                            boundTextures;            ///< The textures bound for rendering
   Vector<GLuint>                            textureDependencyList;    ///< The dependency list of binded textures
-  std::size_t                               itemsCheckSum;            ///< The damaged render items checksum from previous prerender phase.
-  std::vector<DirtyRect>                    itemsDirtyRects;
 };
 
 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
@@ -648,15 +598,19 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
   DamagedRectsCleaner damagedRectCleaner(damagedRects);
 
+
+
+  Internal::Scene& sceneInternal = GetImplementation(scene);
+  SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
+
   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
-  // so you don't need to sort: std::stable_sort(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end());
-  for (DirtyRect& dirtyRect : mImpl->itemsDirtyRects)
+  // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end());
+  std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
+  for (DirtyRect& dirtyRect : itemsDirtyRects)
   {
     dirtyRect.visited = false;
   }
 
-  Internal::Scene& sceneInternal = GetImplementation(scene);
-  SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
   for (uint32_t i = 0; i < count; ++i)
   {
@@ -759,11 +713,11 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
                 // 2. Mark the related dirty rects as visited so they will not be removed below.
                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
                 dirtyRect.rect = rect;
-                auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
-                dirtyRectPos = mImpl->itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
+                auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
+                dirtyRectPos = itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
 
                 int c = 1;
-                while (++dirtyRectPos != mImpl->itemsDirtyRects.end())
+                while (++dirtyRectPos != itemsDirtyRects.end())
                 {
                   if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
                   {
@@ -777,7 +731,7 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
                   c++;
                   if (c > 3) // no more then 3 previous rects
                   {
-                    mImpl->itemsDirtyRects.erase(dirtyRectPos);
+                    itemsDirtyRects.erase(dirtyRectPos);
                     break;
                   }
                 }
@@ -789,8 +743,8 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
             {
               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
               // 2. Mark the related dirty rects as visited so they will not be removed below.
-              auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
-              while (dirtyRectPos != mImpl->itemsDirtyRects.end())
+              auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
+              while (dirtyRectPos != itemsDirtyRects.end())
               {
                 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
                 {
@@ -808,9 +762,9 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
   }
 
   // Check removed nodes or removed renderers dirty rects
-  auto i = mImpl->itemsDirtyRects.begin();
-  auto j = mImpl->itemsDirtyRects.begin();
-  while (i != mImpl->itemsDirtyRects.end())
+  auto i = itemsDirtyRects.begin();
+  auto j = itemsDirtyRects.begin();
+  while (i != itemsDirtyRects.end())
   {
     if (i->visited)
     {
@@ -824,7 +778,7 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
     i++;
   }
 
-  mImpl->itemsDirtyRects.resize(j - mImpl->itemsDirtyRects.begin());
+  itemsDirtyRects.resize(j - itemsDirtyRects.begin());
   damagedRectCleaner.SetCleanOnReturn(false);
 }
 
index 11bb9e4..3afaa88 100644 (file)
@@ -288,6 +288,9 @@ protected: // For derived classes
   {
     ACTOR_BEHAVIOUR_DEFAULT  = 0,      ///< Use to provide default behaviour (size negotiation is on, event callbacks are not called). @SINCE_1_2_10
     DISABLE_SIZE_NEGOTIATION = 1 << 0, ///< True if control does not need size negotiation, i.e. it can be skipped in the algorithm @SINCE_1_0.0
+    NOT_IN_USE_1             = 1<<1,
+    NOT_IN_USE_2             = 1<<2,
+    NOT_IN_USE_3             = 1<<3,
 
     LAST_ACTOR_FLAG ///< Special marker for last actor flag @SINCE_1_0.0
   };
index 5d2c491..7ee6ca0 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const uint32_t    CORE_MAJOR_VERSION = 1;
 const uint32_t    CORE_MINOR_VERSION = 9;
-const uint32_t    CORE_MICRO_VERSION = 31;
+const uint32_t    CORE_MICRO_VERSION = 32;
 const char* const CORE_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 6c80133..09bb5c7 100644 (file)
 
 namespace Dali
 {
-namespace
-{
-/**
- * Helper to check if the property value can be read as int/bool
- */
-inline bool IsIntegerType(Property::Type type)
-{
-  return (Property::BOOLEAN == type) || (Property::INTEGER == type);
-}
-} // namespace
 
 struct Property::Value::Impl
 {
+  ~Impl()
+  {
+    // Destroy the current object stored in Data union memory.
+    Destroy();
+  }
+
+  Impl(const Impl&) = delete;
+
+  Impl(Impl&&) = delete;
+
+  Impl& operator=(Impl&&) = delete;
+
+  Impl()
+  {
+    static_assert(sizeof(Impl) == 16);
+    static_assert(alignof(Impl) == alignof(Impl*));
+
+    SetType(Property::NONE);
+  }
+
   Impl(bool booleanValue)
-  : type(Property::BOOLEAN),
-    integerValue(booleanValue)
   {
+    SetType(Property::BOOLEAN);
+    mData.mBool.member = booleanValue;
   }
 
   Impl(float floatValue)
-  : type(Property::FLOAT),
-    floatValue(floatValue)
   {
+    SetType(Property::FLOAT);
+    mData.mFloat.member = floatValue;
   }
 
   Impl(int32_t integerValue)
-  : type(Property::INTEGER),
-    integerValue(integerValue)
   {
+    SetType(Property::INTEGER);
+    mData.mInt.member = integerValue;
   }
 
-  Impl(const Vector2& vectorValue)
-  : type(Property::VECTOR2),
-    vector2Value(new Vector2(vectorValue))
+  Impl(Vector2 vectorValue)
   {
+    SetType(Property::VECTOR2);
+    ConstructInplace(mData.mVector2.member, std::move(vectorValue));
   }
 
-  Impl(const Vector3& vectorValue)
-  : type(Property::VECTOR3),
-    vector3Value(new Vector3(vectorValue))
+  Impl(Vector3 vectorValue)
   {
+    SetType(Property::VECTOR3);
+    ConstructInplace(mData.mVector3.member, std::move(vectorValue));
   }
 
-  Impl(const Vector4& vectorValue)
-  : type(Property::VECTOR4),
-    vector4Value(new Vector4(vectorValue))
+  Impl(Extents extentsValue)
   {
+    SetType(Property::EXTENTS);
+    ConstructInplace(mData.mExtents.member, std::move(extentsValue));
   }
 
-  Impl(const Matrix3& matrixValue)
-  : type(Property::MATRIX3),
-    matrix3Value(new Matrix3(matrixValue))
+  Impl(Property::Map mapValue)
   {
+    SetType(Property::MAP);
+    ConstructInplace(mData.mMap.member, std::move(mapValue));
   }
 
-  Impl(const Matrix& matrixValue)
-  : type(Property::MATRIX),
-    matrixValue(new Matrix(matrixValue))
+  Impl(Property::Array arrayValue)
   {
+    SetType(Property::ARRAY);
+    ConstructInplace(mData.mArray.member, std::move(arrayValue));
   }
 
-  Impl(const AngleAxis& angleAxisValue)
-  : type(Property::ROTATION),
-    angleAxisValue(new AngleAxis(angleAxisValue))
+  Impl(std::string stringValue)
   {
+    SetType(Property::STRING);
+    mData.mString.member = new std::string(std::move(stringValue));
   }
 
-  Impl(const Quaternion& quaternionValue)
-  : type(Property::ROTATION),
-    angleAxisValue(new AngleAxis())
+  Impl(Rect<int32_t> rectValue)
   {
-    quaternionValue.ToAxisAngle(angleAxisValue->axis, angleAxisValue->angle);
+    SetType(Property::RECTANGLE);
+    mData.mRect.member = new Rect<int32_t>(std::move(rectValue));
   }
 
-  Impl(const std::string& stringValue)
-  : type(Property::STRING),
-    stringValue(new std::string(stringValue))
+  Impl(Vector4 vectorValue)
   {
+    SetType(Property::VECTOR4);
+    mData.mVector4.member = new Vector4(std::move(vectorValue));
   }
 
-  Impl(const Rect<int32_t>& rectValue)
-  : type(Property::RECTANGLE),
-    rectValue(new Rect<int>(rectValue))
+  Impl(Matrix3 matrixValue)
   {
+    SetType(Property::MATRIX3);
+    mData.mMatrix3.member = new Matrix3(std::move(matrixValue));
   }
 
-  Impl(const Rect<float>& rectValue)
-  : type(Property::VECTOR4),
-    vector4Value(new Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height))
+  Impl(Matrix matrixValue)
   {
+    SetType(Property::MATRIX);
+    mData.mMatrix.member = new Matrix(std::move(matrixValue));
   }
 
-  Impl(const Property::Array& arrayValue)
-  : type(Property::ARRAY),
-    arrayValue(new Property::Array(arrayValue))
+  Impl(AngleAxis angleAxisValue)
   {
+    SetType(Property::ROTATION);
+    mData.mAngleAxis.member = new AngleAxis(std::move(angleAxisValue));
   }
 
-  Impl(Property::Array&& arrayValue)
-  : type(Property::ARRAY),
-    arrayValue(new Property::Array(std::move(arrayValue)))
+  Type GetType() const
   {
+    return mData.mType.type;
   }
 
-  Impl(const Property::Map& mapValue)
-  : type(Property::MAP),
-    mapValue(new Property::Map(mapValue))
+  bool GetBool() const
   {
+    return mData.mBool.member;
   }
 
-  Impl(Property::Map&& mapValue)
-  : type(Property::MAP),
-    mapValue(new Property::Map(std::move(mapValue)))
+  int32_t GetInt() const
   {
+    return mData.mInt.member;
   }
 
-  Impl(const Extents& extentsValue)
-  : type(Property::EXTENTS),
-    extentsValue(new Extents(extentsValue))
+  float GetFloat() const
   {
+    return mData.mFloat.member;
   }
 
-  Impl(const std::initializer_list<KeyValuePair>& values)
-  : type(Property::MAP),
-    mapValue(new Property::Map(values))
+  const Extents& GetExtents() const
   {
+    return mData.mExtents.member;
   }
 
-  /**
-   * Destructor, takes care of releasing the dynamically allocated types
-   */
-  ~Impl()
+  const Vector2& GetVector2() const
+  {
+    return mData.mVector2.member;
+  }
+
+  const Vector3& GetVector3() const
+  {
+    return mData.mVector3.member;
+  }
+
+  const Property::Map& GetMap() const
+  {
+    return mData.mMap.member;
+  }
+
+  const Property::Array& GetArray() const
+  {
+    return mData.mArray.member;
+  }
+
+  const Vector4& GetVector4() const
+  {
+    return *(mData.mVector4.member);
+  }
+
+  const Matrix3& GetMatrix3() const
+  {
+    return *(mData.mMatrix3.member);
+  }
+
+  const Matrix& GetMatrix() const
+  {
+    return *(mData.mMatrix.member);
+  }
+
+  const AngleAxis& GetAngleAxis() const
+  {
+    return *(mData.mAngleAxis.member);
+  }
+
+  const std::string& GetString() const
+  {
+    return *(mData.mString.member);
+  }
+
+  const Rect<int32_t>& GetRect() const
+  {
+    return *(mData.mRect.member);
+  }
+
+  Property::Map* GetMapPtr()
+  {
+    return &(mData.mMap.member);
+  }
+
+  Property::Array* GetArrayPtr()
   {
-    switch(type)
+    return &(mData.mArray.member);
+  }
+
+  Impl& operator=(const Impl& other)
+  {
+    const bool isSameType = GetType() == other.GetType();
+
+    if(!isSameType)
+    {
+      Destroy();
+      SetType(other.GetType());
+    }
+
+    switch(GetType())
     {
-      case Property::NONE:    // FALLTHROUGH
-      case Property::BOOLEAN: // FALLTHROUGH
-      case Property::FLOAT:   // FALLTHROUGH
+      case Property::NONE:
+      {
+        break;
+      }
+      case Property::BOOLEAN:
+      {
+        mData.mBool.member = other.GetBool();
+        break;
+      }
+      case Property::FLOAT:
+      {
+        mData.mFloat.member = other.GetFloat();
+        break;
+      }
       case Property::INTEGER:
       {
-        break; // nothing to do
+        mData.mInt.member = other.GetInt();
+        break;
+      }
+      case Property::EXTENTS:
+      {
+        auto obj = other.GetExtents();
+        ConstructInplace(mData.mExtents.member, std::move(obj));
+        break;
       }
       case Property::VECTOR2:
       {
-        delete vector2Value;
+        auto obj = other.GetVector2();
+        ConstructInplace(mData.mVector2.member, std::move(obj));
         break;
       }
       case Property::VECTOR3:
       {
-        delete vector3Value;
+        auto obj = other.GetVector3();
+        ConstructInplace(mData.mVector3.member, std::move(obj));
+        break;
+      }
+      case Property::ARRAY:
+      {
+        auto obj = other.GetArray();
+        ConstructInplace(mData.mArray.member, std::move(obj));
+        break;
+      }
+      case Property::MAP:
+      {
+        auto obj = other.GetMap();
+        ConstructInplace(mData.mMap.member, std::move(obj));
         break;
       }
       case Property::VECTOR4:
       {
-        delete vector4Value;
+        if(isSameType)
+        {
+          *mData.mVector4.member = other.GetVector4();
+        }
+        else
+        {
+          mData.mVector4.member = new Vector4(other.GetVector4());
+        }
         break;
       }
       case Property::MATRIX3:
       {
-        delete matrix3Value;
+        if(isSameType)
+        {
+          *mData.mMatrix3.member = other.GetMatrix3();
+        }
+        else
+        {
+          mData.mMatrix3.member = new Matrix3(other.GetMatrix3());
+        }
         break;
       }
       case Property::MATRIX:
       {
-        delete matrixValue;
+        if(isSameType)
+        {
+          *mData.mMatrix.member = other.GetMatrix();
+        }
+        else
+        {
+          mData.mMatrix.member = new Matrix(other.GetMatrix());
+        }
         break;
       }
       case Property::RECTANGLE:
       {
-        delete rectValue;
+        if(isSameType)
+        {
+          *mData.mRect.member = other.GetRect();
+        }
+        else
+        {
+          mData.mRect.member = new Rect<int32_t>(other.GetRect());
+        }
         break;
       }
       case Property::ROTATION:
       {
-        delete angleAxisValue;
+        if(isSameType)
+        {
+          *mData.mAngleAxis.member = other.GetAngleAxis();
+        }
+        else
+        {
+          mData.mAngleAxis.member = new AngleAxis(other.GetAngleAxis());
+        }
         break;
       }
       case Property::STRING:
       {
-        delete stringValue;
+        if(isSameType)
+        {
+          *mData.mString.member = other.GetString();
+        }
+        else
+        {
+          mData.mString.member = new std::string(other.GetString());
+        }
+        break;
+      }
+    }
+    return *this;
+  }
+
+private:
+  void SetType(Type typeValue)
+  {
+    mData.mType.type = typeValue;
+  }
+
+  /**
+   * This helper function takes a typed(Tp) memory location( member)
+   * and a object of same type( val ) and move constructs a new object of
+   * same type(Tp) in the memory location( member) using placement new.
+   * after this function call member location will have a object of type Tp.
+   */
+  template<typename Tp>
+  void ConstructInplace(Tp& member, Tp&& val)
+  {
+    new(&member) Tp(std::forward<Tp>(val));
+  }
+
+  /**
+  * Destroy the object created in the Data union memory by probing the
+  * type and calling the appropriate destructor.
+  * and also reset the type and memory location to reflect that .
+  */
+  void Destroy()
+  {
+    switch(GetType())
+    {
+      case Property::NONE:
+      case Property::BOOLEAN:
+      case Property::FLOAT:
+      case Property::INTEGER:
+      {
+        break; // nothing to do
+      }
+      case Property::EXTENTS:
+      {
+        mData.mExtents.member.~Extents();
+        break;
+      }
+      case Property::VECTOR2:
+      {
+        mData.mVector2.member.~Vector2();
+        break;
+      }
+      case Property::VECTOR3:
+      {
+        mData.mVector3.member.~Vector3();
         break;
       }
       case Property::ARRAY:
       {
-        delete arrayValue;
+        using array = Property::Array;
+        mData.mArray.member.~array();
         break;
       }
       case Property::MAP:
       {
-        delete mapValue;
+        using map = Property::Map;
+        mData.mMap.member.~map();
         break;
       }
-      case Property::EXTENTS:
+      case Property::VECTOR4:
       {
-        delete extentsValue;
+        delete mData.mVector4.member;
+        break;
+      }
+      case Property::MATRIX3:
+      {
+        delete mData.mMatrix3.member;
+        break;
+      }
+      case Property::MATRIX:
+      {
+        delete mData.mMatrix.member;
+        break;
+      }
+      case Property::RECTANGLE:
+      {
+        delete mData.mRect.member;
+        break;
+      }
+      case Property::ROTATION:
+      {
+        delete mData.mAngleAxis.member;
+        break;
+      }
+      case Property::STRING:
+      {
+        delete mData.mString.member;
         break;
       }
     }
   }
 
-public: // Data
-  Type type;
-  union
+  /*
+   * This wrapper struct is used for
+   * storing Type in every union member
+   * and can acess it from non active member
+   * of the uninon without invoking UB. this is
+   * possible because of CIS(common initial sequence)
+   * http://eel.is/c++draft/class.mem#general-25
+   */
+  template<typename T>
+  struct UnionMember
+  {
+    Type type;
+    T    member;
+  };
+
+  /**
+   * Tagged union implementation.
+   *
+   * This Data union contains non trivial data
+   * types Map and Array, the default constructor
+   * and destructors are deleted by the compiler
+   * so we provided empty constructor and destructor
+   * just to pacify the compiler.
+   * The only job of this union to give a typed memory buffer to the
+   * Impl class which can construct the appropriate object
+   * using placement new.
+   * As Impl class explicitly construct the object and keeps track of the
+   * object it creates and then destroys them in the ~Impl() this will not leak
+   * any memory.
+   */
+  union Data
   {
-    int32_t integerValue;
-    float   floatValue;
-    // must use pointers for any class value pre c++ 11
-    Vector2*         vector2Value;
-    Vector3*         vector3Value;
-    Vector4*         vector4Value;
-    Matrix3*         matrix3Value;
-    Matrix*          matrixValue;
-    AngleAxis*       angleAxisValue;
-    std::string*     stringValue;
-    Rect<int32_t>*   rectValue;
-    Property::Array* arrayValue;
-    Property::Map*   mapValue;
-    Extents*         extentsValue;
+    Data()
+    {
+    }
+    ~Data()
+    {
+    }
+
+    UnionMember<bool>            mBool;
+    UnionMember<int32_t>         mInt;
+    UnionMember<float>           mFloat;
+    UnionMember<Extents>         mExtents;
+    UnionMember<Vector2>         mVector2;
+    UnionMember<Vector3>         mVector3;
+    UnionMember<Property::Map>   mMap;
+    UnionMember<Property::Array> mArray;
+    UnionMember<Vector4*>        mVector4;
+    UnionMember<Matrix3*>        mMatrix3;
+    UnionMember<Matrix*>         mMatrix;
+    UnionMember<AngleAxis*>      mAngleAxis;
+    UnionMember<std::string*>    mString;
+    UnionMember<Rect<int32_t>*>  mRect;
+    struct
+    {
+      Type type;
+    } mType;
   };
 
-private:
-  // non-copyable
-  Impl(const Impl&) = delete;
-  Impl& operator=(const Impl&) = delete;
+  Data mData;
 };
 
 Property::Value::Value()
@@ -316,7 +575,7 @@ Property::Value::Value(const Rect<int32_t>& rectValue)
 }
 
 Property::Value::Value(const Rect<float>& rectValue)
-: mImpl(new Impl(rectValue))
+: mImpl(new Impl(Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height)))
 {
 }
 
@@ -326,12 +585,14 @@ Property::Value::Value(const AngleAxis& angleAxisValue)
 }
 
 Property::Value::Value(const Quaternion& quaternionValue)
-: mImpl(new Impl(quaternionValue))
 {
+  AngleAxis angleAxisValue;
+  quaternionValue.ToAxisAngle(angleAxisValue.axis, angleAxisValue.angle);
+  mImpl = new Impl(std::move(angleAxisValue));
 }
 
-Property::Value::Value(const std::string& stringValue)
-: mImpl(new Impl(stringValue))
+Property::Value::Value(std::string stringValue)
+: mImpl(new Impl(std::move(stringValue)))
 {
 }
 
@@ -348,22 +609,12 @@ Property::Value::Value(const char* stringValue)
   }
 }
 
-Property::Value::Value(Property::Array& arrayValue)
-: mImpl(new Impl(arrayValue))
-{
-}
-
-Property::Value::Value(Property::Array&& arrayValue)
+Property::Value::Value(Property::Array arrayValue)
 : mImpl(new Impl(std::move(arrayValue)))
 {
 }
 
-Property::Value::Value(Property::Map& mapValue)
-: mImpl(new Impl(mapValue))
-{
-}
-
-Property::Value::Value(Property::Map&& mapValue)
+Property::Value::Value(Property::Map mapValue)
 : mImpl(new Impl(std::move(mapValue)))
 {
 }
@@ -374,7 +625,7 @@ Property::Value::Value(const Extents& extentsValue)
 }
 
 Property::Value::Value(const std::initializer_list<KeyValuePair>& values)
-: mImpl(new Impl(values))
+: mImpl(new Impl(Property::Map(values)))
 {
 }
 
@@ -415,7 +666,7 @@ Property::Value::Value(Type type)
     }
     case Property::RECTANGLE:
     {
-      mImpl = new Impl(Rect<int32_t>(0, 0, 0, 0));
+      mImpl = new Impl(Rect<int32_t>());
       break;
     }
     case Property::ROTATION:
@@ -468,7 +719,7 @@ Property::Value::Value(const Property::Value& value)
   operator=(value);
 }
 
-Property::Value::Value(Property::Value&& value)
+Property::Value::Value(Property::Value&& value) noexcept
 : mImpl(value.mImpl)
 {
   value.mImpl = nullptr;
@@ -481,181 +732,26 @@ Property::Value& Property::Value::operator=(const Property::Value& value)
     // skip self assignment
     return *this;
   }
-  // if we are assigned an empty value, just drop impl
-  if(!value.mImpl)
-  {
-    delete mImpl;
-    mImpl = nullptr;
-    return *this;
-  }
-  // first check if the type is the same, no need to change impl, just assign
-  if(mImpl && (mImpl->type == value.mImpl->type))
+
+  if(value.mImpl)
   {
-    switch(mImpl->type)
+    if(!mImpl)
     {
-      case Property::BOOLEAN:
-      {
-        mImpl->integerValue = value.mImpl->integerValue;
-        break;
-      }
-      case Property::FLOAT:
-      {
-        mImpl->floatValue = value.mImpl->floatValue;
-        break;
-      }
-      case Property::INTEGER:
-      {
-        mImpl->integerValue = value.mImpl->integerValue;
-        break;
-      }
-      case Property::VECTOR2:
-      {
-        *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
-        break;
-      }
-      case Property::VECTOR3:
-      {
-        *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
-        break;
-      }
-      case Property::VECTOR4:
-      {
-        *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
-        break;
-      }
-      case Property::RECTANGLE:
-      {
-        *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
-        break;
-      }
-      case Property::ROTATION:
-      {
-        *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated
-        break;
-      }
-      case Property::STRING:
-      {
-        *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
-        break;
-      }
-      case Property::MATRIX:
-      {
-        *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
-        break;
-      }
-      case Property::MATRIX3:
-      {
-        *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
-        break;
-      }
-      case Property::ARRAY:
-      {
-        *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
-        break;
-      }
-      case Property::MAP:
-      {
-        *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
-        break;
-      }
-      case Property::EXTENTS:
-      {
-        *mImpl->extentsValue = *value.mImpl->extentsValue; // type cannot change in mImpl so extents is allocated
-        break;
-      }
-      case Property::NONE:
-      { // mImpl will be a nullptr, there's no way to get to this case
-      }
+      mImpl = new Impl();
     }
+
+    *mImpl = *(value.mImpl);
   }
   else
   {
-    // different type, release old impl and create new
-    Impl* newImpl(nullptr);
-    switch(value.mImpl->type)
-    {
-      case Property::BOOLEAN:
-      {
-        newImpl = new Impl(bool(value.mImpl->integerValue));
-        break;
-      }
-      case Property::FLOAT:
-      {
-        newImpl = new Impl(value.mImpl->floatValue);
-        break;
-      }
-      case Property::INTEGER:
-      {
-        newImpl = new Impl(value.mImpl->integerValue);
-        break;
-      }
-      case Property::VECTOR2:
-      {
-        newImpl = new Impl(*value.mImpl->vector2Value); // type cannot change in mImpl so vector is allocated
-        break;
-      }
-      case Property::VECTOR3:
-      {
-        newImpl = new Impl(*value.mImpl->vector3Value); // type cannot change in mImpl so vector is allocated
-        break;
-      }
-      case Property::VECTOR4:
-      {
-        newImpl = new Impl(*value.mImpl->vector4Value); // type cannot change in mImpl so vector is allocated
-        break;
-      }
-      case Property::RECTANGLE:
-      {
-        newImpl = new Impl(*value.mImpl->rectValue); // type cannot change in mImpl so rect is allocated
-        break;
-      }
-      case Property::ROTATION:
-      {
-        newImpl = new Impl(*value.mImpl->angleAxisValue); // type cannot change in mImpl so quaternion is allocated
-        break;
-      }
-      case Property::MATRIX3:
-      {
-        newImpl = new Impl(*value.mImpl->matrix3Value); // type cannot change in mImpl so matrix is allocated
-        break;
-      }
-      case Property::MATRIX:
-      {
-        newImpl = new Impl(*value.mImpl->matrixValue); // type cannot change in mImpl so matrix is allocated
-        break;
-      }
-      case Property::STRING:
-      {
-        newImpl = new Impl(*value.mImpl->stringValue); // type cannot change in mImpl so string is allocated
-        break;
-      }
-      case Property::ARRAY:
-      {
-        newImpl = new Impl(*value.mImpl->arrayValue); // type cannot change in mImpl so array is allocated
-        break;
-      }
-      case Property::MAP:
-      {
-        newImpl = new Impl(*value.mImpl->mapValue); // type cannot change in mImpl so map is allocated
-        break;
-      }
-      case Property::EXTENTS:
-      {
-        newImpl = new Impl(*value.mImpl->extentsValue); // type cannot change in mImpl so extents is allocated
-        break;
-      }
-      case Property::NONE:
-      { // nullptr value will be used for "empty" value
-      }
-    }
     delete mImpl;
-    mImpl = newImpl;
+    mImpl = nullptr;
   }
 
   return *this;
 }
 
-Property::Value& Property::Value::operator=(Property::Value&& value)
+Property::Value& Property::Value::operator=(Property::Value&& value) noexcept
 {
   if(this != &value)
   {
@@ -674,21 +770,24 @@ Property::Value::~Value()
 
 Property::Type Property::Value::GetType() const
 {
-  Property::Type type(Property::NONE);
-  if(mImpl)
-  {
-    type = mImpl->type;
-  }
-  return type;
+  return mImpl ? mImpl->GetType() : Property::NONE;
 }
 
 bool Property::Value::Get(bool& booleanValue) const
 {
   bool converted = false;
-  if(mImpl && IsIntegerType(mImpl->type))
+  if(mImpl)
   {
-    booleanValue = mImpl->integerValue;
-    converted    = true;
+    if(mImpl->GetType() == BOOLEAN)
+    {
+      booleanValue = mImpl->GetBool();
+      converted    = true;
+    }
+    else if(mImpl->GetType() == INTEGER)
+    {
+      booleanValue = mImpl->GetInt();
+      converted    = true;
+    }
   }
   return converted;
 }
@@ -698,14 +797,19 @@ bool Property::Value::Get(float& floatValue) const
   bool converted = false;
   if(mImpl)
   {
-    if(mImpl->type == FLOAT)
+    if(mImpl->GetType() == FLOAT)
     {
-      floatValue = mImpl->floatValue;
+      floatValue = mImpl->GetFloat();
       converted  = true;
     }
-    else if(IsIntegerType(mImpl->type))
+    else if(mImpl->GetType() == BOOLEAN)
     {
-      floatValue = static_cast<float>(mImpl->integerValue);
+      floatValue = static_cast<float>(mImpl->GetBool());
+      converted  = true;
+    }
+    else if(mImpl->GetType() == INTEGER)
+    {
+      floatValue = static_cast<float>(mImpl->GetInt());
       converted  = true;
     }
   }
@@ -717,14 +821,19 @@ bool Property::Value::Get(int32_t& integerValue) const
   bool converted = false;
   if(mImpl)
   {
-    if(IsIntegerType(mImpl->type))
+    if(mImpl->GetType() == INTEGER)
+    {
+      integerValue = mImpl->GetInt();
+      converted    = true;
+    }
+    else if(mImpl->GetType() == BOOLEAN)
     {
-      integerValue = mImpl->integerValue;
+      integerValue = mImpl->GetBool();
       converted    = true;
     }
-    else if(mImpl->type == FLOAT)
+    else if(mImpl->GetType() == FLOAT)
     {
-      integerValue = static_cast<int32_t>(mImpl->floatValue);
+      integerValue = static_cast<int32_t>(mImpl->GetFloat());
       converted    = true;
     }
   }
@@ -736,10 +845,19 @@ bool Property::Value::Get(Vector2& vectorValue) const
   bool converted = false;
   if(mImpl)
   {
-    // type cannot change in mImpl so vector is allocated
-    if(mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4)
+    if(mImpl->GetType() == VECTOR4)
+    {
+      vectorValue = mImpl->GetVector4();
+      converted   = true;
+    }
+    else if(mImpl->GetType() == VECTOR2)
+    {
+      vectorValue = mImpl->GetVector2();
+      converted   = true;
+    }
+    else if(mImpl->GetType() == VECTOR3)
     {
-      vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned
+      vectorValue = mImpl->GetVector3();
       converted   = true;
     }
   }
@@ -751,15 +869,19 @@ bool Property::Value::Get(Vector3& vectorValue) const
   bool converted = false;
   if(mImpl)
   {
-    // type cannot change in mImpl so vector is allocated
-    if(mImpl->type == VECTOR3 || mImpl->type == VECTOR4)
+    if(mImpl->GetType() == VECTOR4)
+    {
+      vectorValue = mImpl->GetVector4();
+      converted   = true;
+    }
+    else if(mImpl->GetType() == VECTOR2)
     {
-      vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned
+      vectorValue = mImpl->GetVector2();
       converted   = true;
     }
-    else if(mImpl->type == VECTOR2)
+    else if(mImpl->GetType() == VECTOR3)
     {
-      vectorValue = *(mImpl->vector2Value);
+      vectorValue = mImpl->GetVector3();
       converted   = true;
     }
   }
@@ -771,19 +893,19 @@ bool Property::Value::Get(Vector4& vectorValue) const
   bool converted = false;
   if(mImpl)
   {
-    if(mImpl->type == VECTOR4) // type cannot change in mImpl so vector is allocated
+    if(mImpl->GetType() == VECTOR4)
     {
-      vectorValue = *(mImpl->vector4Value);
+      vectorValue = mImpl->GetVector4();
       converted   = true;
     }
-    else if(mImpl->type == VECTOR2)
+    else if(mImpl->GetType() == VECTOR2)
     {
-      vectorValue = *(mImpl->vector2Value);
+      vectorValue = mImpl->GetVector2();
       converted   = true;
     }
-    else if(mImpl->type == VECTOR3)
+    else if(mImpl->GetType() == VECTOR3)
     {
-      vectorValue = *(mImpl->vector3Value);
+      vectorValue = mImpl->GetVector3();
       converted   = true;
     }
   }
@@ -793,9 +915,9 @@ bool Property::Value::Get(Vector4& vectorValue) const
 bool Property::Value::Get(Matrix3& matrixValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == MATRIX3)) // type cannot change in mImpl so matrix is allocated
+  if(mImpl && (mImpl->GetType() == MATRIX3))
   {
-    matrixValue = *(mImpl->matrix3Value);
+    matrixValue = mImpl->GetMatrix3();
     converted   = true;
   }
   return converted;
@@ -804,9 +926,9 @@ bool Property::Value::Get(Matrix3& matrixValue) const
 bool Property::Value::Get(Matrix& matrixValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == MATRIX)) // type cannot change in mImpl so matrix is allocated
+  if(mImpl && (mImpl->GetType() == MATRIX))
   {
-    matrixValue = *(mImpl->matrixValue);
+    matrixValue = mImpl->GetMatrix();
     converted   = true;
   }
   return converted;
@@ -815,9 +937,9 @@ bool Property::Value::Get(Matrix& matrixValue) const
 bool Property::Value::Get(Rect<int32_t>& rectValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == RECTANGLE)) // type cannot change in mImpl so rect is allocated
+  if(mImpl && (mImpl->GetType() == RECTANGLE))
   {
-    rectValue = *(mImpl->rectValue);
+    rectValue = mImpl->GetRect();
     converted = true;
   }
   return converted;
@@ -826,9 +948,9 @@ bool Property::Value::Get(Rect<int32_t>& rectValue) const
 bool Property::Value::Get(AngleAxis& angleAxisValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == ROTATION)) // type cannot change in mImpl so angleAxis is allocated
+  if(mImpl && (mImpl->GetType() == ROTATION))
   {
-    angleAxisValue = *(mImpl->angleAxisValue);
+    angleAxisValue = mImpl->GetAngleAxis();
     converted      = true;
   }
   return converted;
@@ -837,9 +959,10 @@ bool Property::Value::Get(AngleAxis& angleAxisValue) const
 bool Property::Value::Get(Quaternion& quaternionValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == ROTATION)) // type cannot change in mImpl so angleAxis is allocated
+  if(mImpl && (mImpl->GetType() == ROTATION))
   {
-    quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis);
+    auto& obj       = mImpl->GetAngleAxis();
+    quaternionValue = Quaternion(obj.angle, obj.axis);
     converted       = true;
   }
   return converted;
@@ -848,9 +971,9 @@ bool Property::Value::Get(Quaternion& quaternionValue) const
 bool Property::Value::Get(std::string& stringValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == STRING)) // type cannot change in mImpl so string is allocated
+  if(mImpl && (mImpl->GetType() == STRING))
   {
-    stringValue.assign(*(mImpl->stringValue));
+    stringValue.assign(mImpl->GetString());
     converted = true;
   }
   return converted;
@@ -859,9 +982,9 @@ bool Property::Value::Get(std::string& stringValue) const
 bool Property::Value::Get(Property::Array& arrayValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == ARRAY)) // type cannot change in mImpl so array is allocated
+  if(mImpl && (mImpl->GetType() == ARRAY))
   {
-    arrayValue = *(mImpl->arrayValue);
+    arrayValue = mImpl->GetArray();
     converted  = true;
   }
   return converted;
@@ -870,50 +993,69 @@ bool Property::Value::Get(Property::Array& arrayValue) const
 bool Property::Value::Get(Property::Map& mapValue) const
 {
   bool converted = false;
-  if(mImpl && (mImpl->type == MAP)) // type cannot change in mImpl so map is allocated
+  if(mImpl && (mImpl->GetType() == MAP))
   {
-    mapValue  = *(mImpl->mapValue);
+    mapValue  = mImpl->GetMap();
     converted = true;
   }
   return converted;
 }
 
-Property::Array* Property::Value::GetArray() const
+Property::Array const* Property::Value::GetArray() const
+{
+  if(mImpl && (mImpl->GetType() == ARRAY))
+  {
+    return mImpl->GetArrayPtr();
+  }
+  return nullptr;
+}
+
+Property::Array* Property::Value::GetArray()
 {
   Property::Array* array = nullptr;
-  if(mImpl && (mImpl->type == ARRAY)) // type cannot change in mImpl so array is allocated
+  if(mImpl && (mImpl->GetType() == ARRAY)) // type cannot change in mImpl so array is allocated
   {
-    array = mImpl->arrayValue;
+    array = mImpl->GetArrayPtr();
   }
   return array;
 }
 
-Property::Map* Property::Value::GetMap() const
+Property::Map const* Property::Value::GetMap() const
 {
   Property::Map* map = nullptr;
-  if(mImpl && (mImpl->type == MAP)) // type cannot change in mImpl so map is allocated
+  if(mImpl && (mImpl->GetType() == MAP)) // type cannot change in mImpl so map is allocated
   {
-    map = mImpl->mapValue;
+    map = mImpl->GetMapPtr();
   }
   return map;
 }
 
+Property::Map* Property::Value::GetMap()
+{
+  if(mImpl && (mImpl->GetType() == MAP))
+  {
+    return mImpl->GetMapPtr();
+  }
+  return nullptr;
+}
+
 bool Property::Value::Get(Extents& extentsValue) const
 {
   bool converted = false;
   if(mImpl)
   {
-    if(mImpl->type == EXTENTS)
+    if(mImpl->GetType() == EXTENTS)
     {
-      extentsValue = *(mImpl->extentsValue);
+      extentsValue = mImpl->GetExtents();
       converted    = true;
     }
-    else if(mImpl->type == VECTOR4)
+    else if(mImpl->GetType() == VECTOR4)
     {
-      extentsValue.start  = static_cast<uint16_t>(mImpl->vector4Value->x);
-      extentsValue.end    = static_cast<uint16_t>(mImpl->vector4Value->y);
-      extentsValue.top    = static_cast<uint16_t>(mImpl->vector4Value->z);
-      extentsValue.bottom = static_cast<uint16_t>(mImpl->vector4Value->w);
+      auto& obj           = mImpl->GetVector4();
+      extentsValue.start  = static_cast<uint16_t>(obj.x);
+      extentsValue.end    = static_cast<uint16_t>(obj.y);
+      extentsValue.top    = static_cast<uint16_t>(obj.z);
+      extentsValue.bottom = static_cast<uint16_t>(obj.w);
       converted           = true;
     }
   }
@@ -924,78 +1066,78 @@ std::ostream& operator<<(std::ostream& stream, const Property::Value& value)
 {
   if(value.mImpl)
   {
-    const Property::Value::Impl& impl(*value.mImpl);
+    auto obj = value.mImpl;
 
-    switch(impl.type)
+    switch(obj->GetType())
     {
       case Dali::Property::BOOLEAN:
       {
-        stream << impl.integerValue;
+        stream << obj->GetBool();
         break;
       }
       case Dali::Property::FLOAT:
       {
-        stream << impl.floatValue;
+        stream << obj->GetFloat();
         break;
       }
       case Dali::Property::INTEGER:
       {
-        stream << impl.integerValue;
+        stream << obj->GetInt();
         break;
       }
       case Dali::Property::VECTOR2:
       {
-        stream << *impl.vector2Value;
+        stream << obj->GetVector2();
         break;
       }
       case Dali::Property::VECTOR3:
       {
-        stream << *impl.vector3Value;
+        stream << obj->GetVector3();
         break;
       }
       case Dali::Property::VECTOR4:
       {
-        stream << *impl.vector4Value;
+        stream << obj->GetVector4();
         break;
       }
       case Dali::Property::MATRIX3:
       {
-        stream << *impl.matrix3Value;
+        stream << obj->GetMatrix3();
         break;
       }
       case Dali::Property::MATRIX:
       {
-        stream << *impl.matrixValue;
+        stream << obj->GetMatrix();
         break;
       }
       case Dali::Property::RECTANGLE:
       {
-        stream << *impl.rectValue;
+        stream << obj->GetRect();
         break;
       }
       case Dali::Property::ROTATION:
       {
-        stream << *impl.angleAxisValue;
+        stream << obj->GetAngleAxis();
         break;
       }
       case Dali::Property::STRING:
       {
-        stream << *impl.stringValue;
+        stream << obj->GetString();
         break;
       }
       case Dali::Property::ARRAY:
       {
-        stream << *(value.GetArray());
+        stream << obj->GetArray();
         break;
       }
       case Dali::Property::MAP:
       {
-        stream << *(value.GetMap());
+        stream << obj->GetMap();
         break;
       }
       case Dali::Property::EXTENTS:
       {
-        stream << *impl.extentsValue;
+        stream << obj->GetExtents();
         break;
       }
       case Dali::Property::NONE:
index d04c9e9..d9e6f7d 100644 (file)
@@ -163,7 +163,7 @@ public:
    * @SINCE_1_0.0
    * @param[in] stringValue A string
    */
-  Value(const std::string& stringValue);
+  Value(std::string stringValue);
 
   /**
    * @brief Creates a string property value.
@@ -176,34 +176,18 @@ public:
   /**
    * @brief Creates an array property value.
    *
-   * @SINCE_1_0.0
-   * @param[in] arrayValue An array
-   */
-  Value(Property::Array& arrayValue);
-
-  /**
-   * @brief Creates an array property value.
-   *
-   * @SINCE_1_4.16
-   * @param[in] arrayValue An r-value array
+   * @SINCE_1_9.30
+   * @param[in] arrayValue A property array
    */
-  Value(Property::Array&& arrayValue);
+  Value(Property::Array arrayValue);
 
   /**
    * @brief Creates a map property value.
    *
-   * @SINCE_1_0.0
-   * @param[in] mapValue A map
-   */
-  Value(Property::Map& mapValue);
-
-  /**
-   * @brief Creates a map property value.
-   *
-   * @SINCE_1_4.16
-   * @param[in] mapValue An r-value map
+   * @SINCE_1_9.30
+   * @param[in] mapValue A property map
    */
-  Value(Property::Map&& mapValue);
+  Value(Property::Map mapValue);
 
   /**
    * @brief Create a map property value from an initializer_list.
@@ -256,7 +240,7 @@ public:
    * @SINCE_1_4.16
    * @param[in] value The property value to move from
    */
-  Value(Value&& value);
+  Value(Value&& value) noexcept;
 
   /**
    * @brief Assigns a property value.
@@ -274,7 +258,7 @@ public:
    * @param[in] value The property value to move from
    * @return a reference to this
    */
-  Value& operator=(Value&& value);
+  Value& operator=(Value&& value) noexcept;
 
   /**
    * @brief Non-virtual destructor.
@@ -486,20 +470,36 @@ public:
   bool Get(Property::Map& mapValue) const;
 
   /**
-   * @brief Retrieves the Array API of the Property::Value without copying the contents of the map.
+   * @brief Retrieves the Array API of the Property::Value without copying the contents of the array.
    *
-   * @SINCE_1_0.0
+   * @SINCE_1_9.32
    * @return The Array API of the Property::Value or NULL if not a Property::Array
    */
-  Property::Array* GetArray() const;
+  const Property::Array* GetArray() const;
+
+  /**
+   * @brief Retrieves the Array API of the Property::Value without copying the contents of the array.
+   *
+   * @SINCE_1_9.32
+   * @return The Array API of the Property::Value or NULL if not a Property::Array
+   */
+  Property::Array* GetArray();
 
   /**
    * @brief Retrieves the Map API of the Property::Value without copying the contents of the map.
    *
-   * @SINCE_1_0.0
+   * @SINCE_1_9.32
+   * @return The Map API of the Property::Value or NULL if not a Property::Map
+   */
+  const Property::Map* GetMap() const;
+
+  /**
+   * @brief Retrieves the Map API of the Property::Value without copying the contents of the map.
+   *
+   * @SINCE_1_9.32
    * @return The Map API of the Property::Value or NULL if not a Property::Map
    */
-  Property::Map* GetMap() const;
+  Property::Map* GetMap();
 
   /**
    * @brief Retrieves an extents.
index a3f82bc..25b5042 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2
 Summary:    DALi 3D Engine
-Version:    1.9.31
+Version:    1.9.32
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT