Merge "Add UserInteractionEnabled property on actor for controlling user interaction...
authorSangHyeon Lee <sh10233.lee@samsung.com>
Thu, 17 Mar 2022 10:46:02 +0000 (10:46 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 17 Mar 2022 10:46:02 +0000 (10:46 +0000)
43 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-buffer.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-reflection.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-reflection.h
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-BaseHandle.cpp
automated-tests/src/dali/utc-Dali-Context.cpp [deleted file]
automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp
automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp
automated-tests/src/dali/utc-Dali-RotationGestureRecognizer.cpp
automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp
automated-tests/src/dali/utc-Dali-VisualRenderer.cpp [new file with mode: 0644]
dali/devel-api/actors/actor-devel.cpp [changed mode: 0755->0644]
dali/devel-api/actors/actor-devel.h
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/events/gesture-processor.cpp
dali/internal/event/events/gesture-processor.h
dali/internal/event/events/hit-test-algorithm-impl.cpp
dali/internal/event/events/hit-test-algorithm-impl.h
dali/internal/event/events/hover-event-processor.cpp
dali/internal/event/events/touch-event-processor.cpp
dali/internal/event/rendering/renderer-impl.cpp
dali/internal/event/rendering/renderer-impl.h
dali/internal/event/rendering/visual-renderer-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/visual-renderer-impl.h [new file with mode: 0644]
dali/internal/file.list
dali/internal/update/rendering/scene-graph-renderer.h
dali/public-api/common/intrusive-ptr.h
dali/public-api/dali-core-version.cpp
dali/public-api/dali-core.h
dali/public-api/file.list
dali/public-api/object/property-index-ranges.h
dali/public-api/rendering/renderer.h
dali/public-api/rendering/visual-renderer.cpp [new file with mode: 0644]
dali/public-api/rendering/visual-renderer.h [new file with mode: 0644]
packaging/dali.spec

index a352f26..a6c8ac8 100644 (file)
@@ -22,7 +22,6 @@ SET(TC_SOURCES
         utc-Dali-ConstraintFunction.cpp
         utc-Dali-Constraints.cpp
         utc-Dali-ConstraintSource.cpp
-        utc-Dali-Context.cpp
         utc-Dali-Core.cpp
         utc-Dali-CustomActor.cpp
         utc-Dali-Degree.cpp
@@ -68,6 +67,7 @@ SET(TC_SOURCES
         utc-Dali-Random.cpp
         utc-Dali-Rect.cpp
         utc-Dali-Renderer.cpp
+        utc-Dali-VisualRenderer.cpp
         utc-Dali-RenderTask.cpp
         utc-Dali-RenderTaskList.cpp
         utc-Dali-RotationGestureDetector.cpp
index e99de5c..e6416e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -140,6 +140,8 @@ void TestGlAbstraction::Initialize()
     {"uViewMatrix", GL_FLOAT_MAT4, 1},
     {"uLightCameraProjectionMatrix", GL_FLOAT_MAT4, 1},
     {"uLightCameraViewMatrix", GL_FLOAT_MAT4, 1}};
+
+  // WARNING: IF YOU CHANGE THIS LIST, ALSO CHANGE UNIFORMS IN test-graphics-reflection.cpp
 }
 
 void TestGlAbstraction::PreRender()
index aec9f5d..cc7fac4 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_GL_ABSTRACTION_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -913,8 +913,8 @@ public:
     if(it2 == uniformIDs.end())
     {
       // Uniform not found, so add it...
-      uniformIDs[name] = mLastUniformIdUsed++;
-      return mLastUniformIdUsed;
+      uniformIDs[name] = ++mLastUniformIdUsed;
+      return uniformIDs[name];
     }
 
     return it2->second;
@@ -991,7 +991,23 @@ public:
 
     for(const auto& uniform : mCustomUniformData)
     {
-      GetUniformLocation(program, uniform.name.c_str());
+      auto iter = uniform.name.find("[");
+      auto name = uniform.name;
+      if(iter != std::string::npos)
+      {
+        name            = uniform.name.substr(0, iter);
+        auto arrayCount = std::stoi(uniform.name.substr(iter + 1));
+        for(int i = 0; i < arrayCount; ++i)
+        {
+          std::stringstream nss;
+          nss << name << "[" << i << "]";
+          GetUniformLocation(program, nss.str().c_str()); // Generate a GL loc per element
+        }
+      }
+      else
+      {
+        GetUniformLocation(program, name.c_str());
+      }
     }
   }
 
index 83b7899..27f0dce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ TestGraphicsBuffer::TestGraphicsBuffer(TraceCallStack& callStack, TestGlAbstract
   mUsage(usage)
 {
   memory.resize(size);
-  mGl.GetBufferTrace().EnableLogging(true);
+  mGl.GetBufferTrace().EnableLogging(false);
 }
 
 void TestGraphicsBuffer::Bind()
@@ -82,65 +82,67 @@ GLenum TestGraphicsBuffer::GetTarget()
 
 void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const
 {
-  auto* reflection = static_cast<const TestGraphicsReflection*>(&program->GetReflection());
-
-  Graphics::UniformBlockInfo uboInfo{};
-  reflection->GetUniformBlock(0, uboInfo);
+  auto*       reflection = static_cast<const TestGraphicsReflection*>(&program->GetReflection());
+  const auto& uboInfo    = reflection->GetTestUniformBlock(0u);
 
   auto  offset = uboBinding.offset;
   auto* data   = memory.data() + offset;
 
   for(const auto& member : uboInfo.members)
   {
-    auto type = reflection->GetMemberType(0, member.location);
-    switch(type)
+    uint32_t numElements = member.numElements > 0 ? member.numElements : 1;
+
+    for(uint32_t i = 0; i < numElements; ++i)
     {
-      case Property::VECTOR4:
-      {
-        auto value = *reinterpret_cast<const Dali::Vector4*>(data + member.offset);
-        mGl.Uniform4f(member.location, value.x, value.y, value.z, value.w);
-        break;
-      }
-      case Property::VECTOR3:
-      {
-        auto value = *reinterpret_cast<const Dali::Vector3*>(data + member.offset);
-        mGl.Uniform3f(member.location, value.x, value.y, value.z);
-        break;
-      }
-      case Property::VECTOR2:
-      {
-        auto value = *reinterpret_cast<const Dali::Vector2*>(data + member.offset);
-        mGl.Uniform2f(member.location, value.x, value.y);
-        break;
-      }
-      case Property::FLOAT:
-      {
-        auto value = *reinterpret_cast<const float*>(data + member.offset);
-        mGl.Uniform1f(member.location, value);
-        break;
-      }
-      case Property::INTEGER:
-      {
-        auto ptr   = reinterpret_cast<const GLint*>(data + member.offset);
-        auto value = *ptr;
-        mGl.Uniform1i(member.location, value);
-        break;
-      }
-      case Property::MATRIX:
-      {
-        auto value = reinterpret_cast<const float*>(data + member.offset);
-        mGl.UniformMatrix4fv(member.location, 1, GL_FALSE, value);
-        break;
-      }
-      case Property::MATRIX3:
-      {
-        auto value = reinterpret_cast<const float*>(data + member.offset);
-        mGl.UniformMatrix3fv(member.location, 1, GL_FALSE, value);
-        break;
-      }
-      default:
+      switch(member.type)
       {
-        fprintf(stderr, "\n%s type not found\n", member.name.c_str());
+        case Property::VECTOR4:
+        {
+          auto value = *reinterpret_cast<const Dali::Vector4*>(data + member.offsets[i]);
+          mGl.Uniform4f(member.locations[i], value.x, value.y, value.z, value.w);
+          break;
+        }
+        case Property::VECTOR3:
+        {
+          auto value = *reinterpret_cast<const Dali::Vector3*>(data + member.offsets[i]);
+          mGl.Uniform3f(member.locations[i], value.x, value.y, value.z);
+          break;
+        }
+        case Property::VECTOR2:
+        {
+          auto value = *reinterpret_cast<const Dali::Vector2*>(data + member.offsets[i]);
+          mGl.Uniform2f(member.locations[i], value.x, value.y);
+          break;
+        }
+        case Property::FLOAT:
+        {
+          auto value = *reinterpret_cast<const float*>(data + member.offsets[i]);
+          mGl.Uniform1f(member.locations[i], value);
+          break;
+        }
+        case Property::INTEGER:
+        {
+          auto ptr   = reinterpret_cast<const GLint*>(data + member.offsets[i]);
+          auto value = *ptr;
+          mGl.Uniform1i(member.locations[i], value);
+          break;
+        }
+        case Property::MATRIX:
+        {
+          auto value = reinterpret_cast<const float*>(data + member.offsets[i]);
+          mGl.UniformMatrix4fv(member.locations[i], 1, GL_FALSE, value);
+          break;
+        }
+        case Property::MATRIX3:
+        {
+          auto value = reinterpret_cast<const float*>(data + member.offsets[i]);
+          mGl.UniformMatrix3fv(member.locations[i], 1, GL_FALSE, value);
+          break;
+        }
+        default:
+        {
+          fprintf(stderr, "\n%s type not found\n", member.name.c_str());
+        }
       }
     }
   }
index 3ed6b56..bedce18 100644 (file)
@@ -584,15 +584,15 @@ public:
 };
 
 TestGraphicsController::TestGraphicsController()
-: mCallStack(true, "TestGraphicsController."),
-  mCommandBufferCallStack(true, "TestCommandBuffer."),
-  mFrameBufferCallStack(true, "TestFrameBuffer.")
+: mCallStack(false, "TestGraphicsController."),
+  mCommandBufferCallStack(false, "TestCommandBuffer."),
+  mFrameBufferCallStack(false, "TestFrameBuffer.")
 {
   mCallStack.Enable(true);
   mCommandBufferCallStack.Enable(true);
   auto& trace = mGl.GetTextureTrace();
   trace.Enable(true);
-  trace.EnableLogging(true);
+  trace.EnableLogging(false);
 }
 
 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
index a994157..8f2e0c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,14 +20,15 @@ namespace Dali
 {
 TestGraphicsProgramImpl::TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector<UniformData>& customUniforms)
 : mGl(gl),
+  mId(gl.CreateProgram()),
   mCreateInfo(createInfo),
-  mReflection(gl, vertexFormats, createInfo, customUniforms)
+  mReflection(gl, mId, vertexFormats, createInfo, customUniforms)
 {
-  mId = mGl.CreateProgram();
-
   // Ensure active sampler uniforms are set
   mGl.SetCustomUniforms(customUniforms);
-  mGl.LinkProgram(mId);
+
+  // Don't need to re-register uniforms in GL side - now done in creation of mReflection.
+  // Was previously done in mGl.LinkProgram(mId);
 }
 
 bool TestGraphicsProgramImpl::GetParameter(uint32_t parameterId, void* outData)
index 25c09b5..5b3da8c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -50,10 +50,60 @@ static const std::vector<UniformData> UNIFORMS =
     UniformData("uViewMatrix", Property::Type::MATRIX),
     UniformData("uLightCameraProjectionMatrix", Property::Type::MATRIX),
     UniformData("uLightCameraViewMatrix", Property::Type::MATRIX),
+
+    // WARNING: IF YOU CHANGE THIS LIST, ALSO CHANGE mActiveUniforms IN test-gl-abstraction, Initialize
 };
+
+/**
+ * Helper function that returns size of uniform datatypes based
+ * on property type.
+ */
+constexpr int GetSizeForType(Property::Type type)
+{
+  switch(type)
+  {
+    case Property::Type::BOOLEAN:
+    {
+      return sizeof(bool);
+    }
+    case Property::Type::FLOAT:
+    {
+      return sizeof(float);
+    }
+    case Property::Type::INTEGER:
+    {
+      return sizeof(int);
+    }
+    case Property::Type::VECTOR2:
+    {
+      return sizeof(Vector2);
+    }
+    case Property::Type::VECTOR3:
+    {
+      return sizeof(Vector3);
+    }
+    case Property::Type::VECTOR4:
+    {
+      return sizeof(Vector4);
+    }
+    case Property::Type::MATRIX3:
+    {
+      return sizeof(Matrix3);
+    }
+    case Property::Type::MATRIX:
+    {
+      return sizeof(Matrix);
+    }
+    default:
+    {
+      return 0;
+    }
+  };
 }
 
-TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vfs, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms)
+} // namespace
+
+TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, uint32_t programId, Property::Array& vfs, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms)
 : mGl(gl),
   mCustomUniforms(customUniforms)
 {
@@ -76,34 +126,72 @@ TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, Property::
   mDefaultUniformBlock.name          = "";
   mDefaultUniformBlock.members       = {};
   mDefaultUniformBlock.binding       = 0;
-  mDefaultUniformBlock.size          = 64 * (UNIFORMS.size() + mCustomUniforms.size());
   mDefaultUniformBlock.descriptorSet = 0;
   mDefaultUniformBlock.members.clear();
-  int loc = 0;
+
+  int offset = 0;
   for(const auto& data : UNIFORMS)
   {
     mDefaultUniformBlock.members.emplace_back();
-    auto& item        = mDefaultUniformBlock.members.back();
-    item.name         = data.name;
-    item.binding      = 0;
-    item.offset       = loc * 64;
-    item.location     = loc++;
+    auto& item   = mDefaultUniformBlock.members.back();
+    item.name    = data.name;
+    item.binding = 0;
+    item.offsets.push_back(offset);
+    item.locations.push_back(gl.GetUniformLocation(programId, data.name.c_str()));
     item.bufferIndex  = 0;
     item.uniformClass = Graphics::UniformClass::UNIFORM;
+    item.type         = data.type;
+    offset += GetSizeForType(data.type);
   }
 
   for(const auto& data : mCustomUniforms)
   {
     fprintf(stderr, "\ncustom uniforms: %s\n", data.name.c_str());
     mDefaultUniformBlock.members.emplace_back();
-    auto& item        = mDefaultUniformBlock.members.back();
-    item.name         = data.name;
-    item.binding      = 0;
-    item.offset       = loc * 64;
-    item.location     = loc++;
-    item.bufferIndex  = 0;
-    item.uniformClass = Graphics::UniformClass::UNIFORM;
+    auto& item = mDefaultUniformBlock.members.back();
+
+    auto iter        = data.name.find("[", 0);
+    int  numElements = 1;
+    if(iter != std::string::npos)
+    {
+      auto baseName = data.name.substr(0, iter);
+      iter++;
+      numElements = std::stoi(data.name.substr(iter));
+      if(numElements == 0)
+      {
+        numElements = 1;
+      }
+
+      item.name         = baseName;
+      item.binding      = 0;
+      item.bufferIndex  = 0;
+      item.uniformClass = Graphics::UniformClass::UNIFORM;
+      item.type         = data.type;
+      item.numElements  = numElements;
+
+      for(int i = 0; i < numElements; ++i)
+      {
+        std::stringstream elementNameStream;
+        elementNameStream << baseName << "[" << i << "]";
+
+        item.locations.push_back(gl.GetUniformLocation(programId, elementNameStream.str().c_str()));
+        item.offsets.push_back(offset);
+        offset += GetSizeForType(data.type);
+      }
+    }
+    else
+    {
+      item.name    = data.name;
+      item.binding = 0;
+      item.offsets.push_back(offset);
+      item.locations.push_back(gl.GetUniformLocation(programId, item.name.c_str()));
+      item.bufferIndex  = 0;
+      item.uniformClass = Graphics::UniformClass::UNIFORM;
+      item.type         = data.type;
+      offset += GetSizeForType(data.type);
+    }
   }
+  mDefaultUniformBlock.size = offset;
 
   mUniformBlocks.push_back(mDefaultUniformBlock);
 }
@@ -157,9 +245,13 @@ uint32_t TestGraphicsReflection::GetUniformBlockBinding(uint32_t index) const
 
 uint32_t TestGraphicsReflection::GetUniformBlockSize(uint32_t index) const
 {
-  // 64 bytes per uniform (64 = 4x4 matrix)
-  // TODO: fix if array will be used
-  return 64 * (UNIFORMS.size() + mCustomUniforms.size());
+  if(index >= mUniformBlocks.size())
+  {
+    return 0;
+  }
+
+  const auto& block = mUniformBlocks[index];
+  return block.size;
 }
 
 bool TestGraphicsReflection::GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const
@@ -183,8 +275,8 @@ bool TestGraphicsReflection::GetUniformBlock(uint32_t index, Dali::Graphics::Uni
     out.members[i].name         = memberUniform.name;
     out.members[i].binding      = block.binding;
     out.members[i].uniformClass = Graphics::UniformClass::UNIFORM;
-    out.members[i].offset       = memberUniform.offset;
-    out.members[i].location     = memberUniform.location;
+    out.members[i].offset       = memberUniform.offsets[0];
+    out.members[i].location     = memberUniform.locations[0];
   }
 
   return true;
@@ -228,7 +320,7 @@ uint32_t TestGraphicsReflection::GetUniformBlockMemberOffset(uint32_t blockIndex
 {
   if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
   {
-    return mUniformBlocks[blockIndex].members[memberLocation].offset;
+    return mUniformBlocks[blockIndex].members[memberLocation].offsets[0];
   }
   else
   {
@@ -252,9 +344,4 @@ Graphics::ShaderLanguage TestGraphicsReflection::GetLanguage() const
   return Graphics::ShaderLanguage::GLSL_3_1;
 }
 
-Dali::Property::Type TestGraphicsReflection::GetMemberType(int blockIndex, int location) const
-{
-  return location < static_cast<int>(UNIFORMS.size()) ? UNIFORMS[location].type : mCustomUniforms[location - UNIFORMS.size()].type;
-}
-
 } // namespace Dali
index 2147cae..e968bd5 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_GRAPHICS_REFLECTION_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ namespace Dali
 class TestGraphicsReflection : public Graphics::Reflection
 {
 public:
-  TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vertexFormats, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms);
+  TestGraphicsReflection(TestGlAbstraction& gl, uint32_t program_id, Property::Array& vertexFormats, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms);
 
   uint32_t                                        GetVertexAttributeLocation(const std::string& name) const override;
   Dali::Graphics::VertexInputAttributeFormat      GetVertexAttributeFormat(uint32_t location) const override;
@@ -46,6 +46,27 @@ public:
   Graphics::ShaderLanguage                        GetLanguage() const override;
 
 public: // Test methods
+  struct TestUniformInfo
+  {
+    std::string            name{""}; // baseName in the case of arrays
+    Graphics::UniformClass uniformClass{Graphics::UniformClass::UNDEFINED};
+    uint32_t               binding{0u};
+    uint32_t               bufferIndex{0u};
+    std::vector<uint32_t>  offsets{};
+    std::vector<uint32_t>  locations{};
+    uint32_t               numElements{0u}; // 0 elements means this isn't an array; 1 element means this is an array of size 1
+    Property::Type         type;
+  };
+
+  struct TestUniformBlockInfo
+  {
+    std::string                  name{""};
+    uint32_t                     descriptorSet{0u};
+    uint32_t                     binding{0u};
+    uint32_t                     size{0u};
+    std::vector<TestUniformInfo> members{};
+  };
+
   void SetAttributes(std::vector<std::string> locations)
   {
     mAttributes.clear();
@@ -56,14 +77,17 @@ public: // Test methods
     }
   }
 
-  Dali::Property::Type GetMemberType(int blockIndex, int location) const;
+  const TestUniformBlockInfo& GetTestUniformBlock(uint32_t index) const
+  {
+    return mUniformBlocks[index];
+  }
 
   TestGlAbstraction&               mGl;
   mutable std::vector<std::string> mAttributes;
   std::vector<UniformData>         mCustomUniforms;
 
-  Graphics::UniformBlockInfo              mDefaultUniformBlock{}; ///< The emulated UBO containing all the standalone uniforms
-  std::vector<Graphics::UniformBlockInfo> mUniformBlocks{};       ///< List of uniform blocks
+  TestUniformBlockInfo              mDefaultUniformBlock{}; ///< The emulated UBO containing all the standalone uniforms
+  std::vector<TestUniformBlockInfo> mUniformBlocks{};       ///< List of uniform blocks
 };
 
 } // namespace Dali
index 7f2de63..2316036 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -146,7 +146,26 @@ bool TraceCallStack::FindMethodAndGetParameters(std::string method, std::string&
   }
   if(!found)
   {
-    fprintf(stderr, "Search for %s(%s) failed\n", method.c_str(), params.c_str());
+    fprintf(stderr, "Search for %s() failed\n", method.c_str());
+  }
+  return found;
+}
+
+bool TraceCallStack::FindMethodAndGetParameters(std::string method, NamedParams& params) const
+{
+  bool found = false;
+  for(size_t i = 0; i < mCallStack.size(); i++)
+  {
+    if(0 == mCallStack[i].method.compare(method))
+    {
+      found  = true;
+      params = mCallStack[i].namedParams;
+      break;
+    }
+  }
+  if(!found)
+  {
+    fprintf(stderr, "Search for %s() failed\n", method.c_str());
   }
   return found;
 }
index 6f720c5..c2d0a49 100644 (file)
@@ -207,6 +207,14 @@ public:
   bool FindMethodAndGetParameters(std::string method, std::string& params) const;
 
   /**
+   * Search for a method in the stack and return its parameters if found
+   * @param[in] method The name of the method
+   * @param[out] params of the method
+   * @return true if the method was in the stack
+   */
+  bool FindMethodAndGetParameters(std::string method, NamedParams& params) const;
+
+  /**
    * Count how many times a method was called
    * @param[in] method The name of the method
    * @return The number of times it was called
index a897ae1..9873aa7 100644 (file)
@@ -53,6 +53,7 @@ namespace
 bool gTouchCallBackCalled  = false;
 bool gTouchCallBackCalled2 = false;
 bool gTouchCallBackCalled3 = false;
+bool gHitTestTouchCallBackCalled = false;
 
 bool gHoverCallBackCalled = false;
 
@@ -112,6 +113,13 @@ static bool TestTouchCallback3(Actor, const TouchEvent&)
   END_TEST;
 }
 
+static bool TestHitTestTouchCallback(Actor, const TouchEvent&)
+{
+  gHitTestTouchCallBackCalled = true;
+  return false;
+  END_TEST;
+}
+
 static void ResetTouchCallbacks()
 {
   gTouchCallBackCalled  = false;
@@ -4968,8 +4976,6 @@ int UtcDaliActorPropertyClippingActorWithRendererOverride(void)
 
   // Check stencil functions are not called.
   DALI_TEST_CHECK(!stencilTrace.FindMethod("StencilFunc"));
-  // TODO: Temporarily commented out the line below when caching is disabled. Will need to add it back.
-  //  DALI_TEST_CHECK(!stencilTrace.FindMethod("StencilMask"));
   DALI_TEST_CHECK(!stencilTrace.FindMethod("StencilOp"));
 
   // Check that scissor clipping is overriden by the renderer properties.
@@ -10304,3 +10310,108 @@ int UtcDaliActorRegisterProperty(void)
 
   END_TEST;
 }
+
+int UtcDaliActorDoesWantedHitTest(void)
+{
+  struct HitTestData
+  {
+  public:
+    HitTestData(const Vector3& scale, const Vector2& touchPoint, bool result)
+    : mScale(scale),
+      mTouchPoint(touchPoint),
+      mResult(result)
+    {
+    }
+
+    Vector3 mScale;
+    Vector2 mTouchPoint;
+    bool    mResult;
+  };
+
+  TestApplication application;
+  tet_infoline(" UtcDaliActorDoesWantedHitTest");
+
+  // Fill a vector with different hit tests.
+  struct HitTestData* hitTestData[] = {
+    //                    scale                     touch point           result
+    new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(289.f, 400.f), true),  // touch point close to the right edge (inside)
+    new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(291.f, 400.f), false), // touch point close to the right edge (outside)
+    new HitTestData(Vector3(110.f, 100.f, 1.f), Vector2(291.f, 400.f), true),  // same point as above with a wider scale. Should be inside.
+    new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(200.f, 451.f), false), // touch point close to the down edge (outside)
+    new HitTestData(Vector3(100.f, 110.f, 1.f), Vector2(200.f, 451.f), true),  // same point as above with a wider scale. Should be inside.
+    NULL,
+  };
+
+  // get the root layer
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  Actor lowerActor = Actor::New();
+  lowerActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  lowerActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  // actor and lowerActor have no relationship.
+  application.GetScene().Add(lowerActor);
+  application.GetScene().Add(actor);
+
+  ResetTouchCallbacks();
+  gHitTestTouchCallBackCalled = false;
+
+  unsigned int index = 0;
+  while(NULL != hitTestData[index])
+  {
+    actor.SetProperty(Actor::Property::SIZE, Vector2(1.f, 1.f));
+    actor.SetProperty(Actor::Property::SCALE, Vector3(hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z));
+
+    lowerActor.SetProperty(Actor::Property::SIZE, Vector2(1.f, 1.f));
+    lowerActor.SetProperty(Actor::Property::SCALE, Vector3(hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z));
+
+    // flush the queue and render once
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_CHECK(!gTouchCallBackCalled);
+    DALI_TEST_CHECK(!gTouchCallBackCalled2);
+    DALI_TEST_CHECK(!gHitTestTouchCallBackCalled);
+
+    // connect to its touch signal
+    actor.TouchedSignal().Connect(TestTouchCallback);
+    lowerActor.TouchedSignal().Connect(TestTouchCallback2);
+
+    // connect to its hit-test signal
+    Dali::DevelActor::HitTestResultSignal(actor).Connect(TestHitTestTouchCallback);
+
+    Dali::Integration::Point point;
+    point.SetState(PointState::DOWN);
+    point.SetScreenPosition(Vector2(hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y));
+    Dali::Integration::TouchEvent event;
+    event.AddPoint(point);
+
+    // flush the queue and render once
+    application.SendNotification();
+    application.Render();
+    application.ProcessEvent(event);
+
+    // check hit-test events
+    DALI_TEST_CHECK(gHitTestTouchCallBackCalled == hitTestData[index]->mResult);
+    // Passed all hit-tests of actor.
+    DALI_TEST_CHECK(gTouchCallBackCalled == false);
+    // The lowerActor was hit-tested.
+    DALI_TEST_CHECK(gTouchCallBackCalled2 == hitTestData[index]->mResult);
+
+    if(gTouchCallBackCalled2 != hitTestData[index]->mResult)
+      tet_printf("Test failed:\nScale %f %f %f\nTouchPoint %f, %f\nResult %d\n",
+                 hitTestData[index]->mScale.x,
+                 hitTestData[index]->mScale.y,
+                 hitTestData[index]->mScale.z,
+                 hitTestData[index]->mTouchPoint.x,
+                 hitTestData[index]->mTouchPoint.y,
+                 hitTestData[index]->mResult);
+
+    ResetTouchCallbacks();
+    gHitTestTouchCallBackCalled = false;
+    ++index;
+  }
+  END_TEST;
+}
index b55478a..5b2061b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -308,6 +308,30 @@ int UtcDaliBaseHandleInequalityOperator02(void)
   END_TEST;
 }
 
+int UtcDaliBaseHandleInequalityWithNullptr(void)
+{
+  TestApplication application;
+  tet_infoline("Test for Dali::BaseHandle::operator == nullptr");
+
+  BaseHandle object;
+
+  // object is nullptr.
+  DALI_TEST_CHECK(object == nullptr);
+  DALI_TEST_CHECK(nullptr == object);
+  DALI_TEST_CHECK(!(object != nullptr));
+  DALI_TEST_CHECK(!(nullptr != object));
+
+  object = Actor::New();
+
+  // object is not nullptr.
+  DALI_TEST_CHECK(!(object == nullptr));
+  DALI_TEST_CHECK(!(nullptr == object));
+  DALI_TEST_CHECK(object != nullptr);
+  DALI_TEST_CHECK(nullptr != object);
+
+  END_TEST;
+}
+
 int UtcDaliBaseHandleStlVector(void)
 {
   TestApplication application;
diff --git a/automated-tests/src/dali/utc-Dali-Context.cpp b/automated-tests/src/dali/utc-Dali-Context.cpp
deleted file mode 100644 (file)
index a5e20a9..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <dali-test-suite-utils.h>
-#include <dali/public-api/dali-core.h>
-#include <stdlib.h>
-
-#include <iostream>
-
-using namespace Dali;
-
-namespace
-{
-// Size of the VertexAttributeArray enables
-// GLES specification states that there's a minimum of 8
-const unsigned int TEST_MAX_ATTRIBUTE_CACHE_SIZE = 8;
-
-enum TestAttribType
-{
-  ATTRIB_UNKNOWN = -1,
-  ATTRIB_POSITION,
-  ATTRIB_NORMAL,
-  ATTRIB_TEXCOORD,
-  ATTRIB_COLOR,
-  ATTRIB_BONE_WEIGHTS,
-  ATTRIB_BONE_INDICES,
-  ATTRIB_TYPE_LAST
-};
-
-// Create bitmap actor
-static Actor CreateBitmapActor()
-{
-  Actor actor = CreateRenderableActor();
-  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
-  actor.SetProperty(Actor::Property::NAME, "Test Image Rendering Actor");
-  return actor;
-}
-
-} // anonymous namespace
-
-// Positive test case for a method
-int UtcDaliContextVertexAttribStartup(void)
-{
-  tet_infoline("Testing vertex attrib initial state in context");
-
-  TestApplication application;
-
-  // start up
-  application.SendNotification();
-  application.Render();
-  application.Render();
-
-  // check the locations
-  for(unsigned int i = 0; i < TEST_MAX_ATTRIBUTE_CACHE_SIZE; i++)
-  {
-    DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayState(i) == false);
-  }
-
-  tet_result(TET_PASS);
-  END_TEST;
-}
-
-// Tests to make the attribs only get set once when continually rendering an image actor
-int UtcDaliContextVertexAttribImageRendering(void)
-{
-  tet_infoline("Testing vertex attrib rendering state in context with images");
-
-  TestApplication application;
-
-  // start up
-  application.SendNotification();
-  application.Render();
-  application.Render();
-
-  // the vertex attribs get modified on startup to set them to disabled
-  // clear the flag to say they've changed
-  application.GetGlAbstraction().ClearVertexAttribArrayChanged();
-
-  // create a test bitmap actor
-  Actor actor(CreateBitmapActor());
-  application.GetScene().Add(actor);
-
-  application.SendNotification();
-  application.Render();
-  application.Render();
-
-  // check to make sure the state has changed (the image renderer will enable some
-  // locations).
-  DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged());
-
-#ifdef REMOVE_CACHE_TESTING_TEMPORARILY
-  // Now check to make sure the state is cached, and isn't being set each frame.
-  application.GetGlAbstraction().ClearVertexAttribArrayChanged();
-
-  application.Render();
-  application.Render();
-  application.Render();
-
-  // if it has changed then the caching has failed
-  DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged() == false);
-
-  //tet_result(TET_PASS);
-#endif
-
-  END_TEST;
-}
index 2abc74e..1bac5af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
  */
 
 #include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/events/hit-test-algorithm.h>
 #include <dali/integration-api/events/touch-event-integ.h>
 #include <dali/public-api/dali-core.h>
@@ -27,6 +28,14 @@ using namespace Dali;
 
 namespace
 {
+bool        gHitTestTouchCallBackCalled = false;
+static bool TestHitTestTouchCallback(Actor, const TouchEvent&)
+{
+  gHitTestTouchCallBackCalled = true;
+  return false;
+  END_TEST;
+}
+
 /**
  * The functor to be used in the hit-test algorithm to check whether the actor is hittable.
  */
@@ -372,3 +381,57 @@ int UtcDaliHitTestAlgorithmOverlay(void)
   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
   END_TEST;
 }
+
+int UtcDaliHitTestAlgorithmDoesWantedHitTest(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm with does wanted to HitTest");
+
+  Stage             stage             = Stage::GetCurrent();
+  RenderTaskList    renderTaskList    = stage.GetRenderTaskList();
+  RenderTask        defaultRenderTask = renderTaskList.GetTask(0u);
+  Dali::CameraActor cameraActor       = defaultRenderTask.GetCameraActor();
+
+  Vector2 stageSize(stage.GetSize());
+  cameraActor.SetOrthographicProjection(stageSize);
+  cameraActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 1600.0f));
+
+  Vector2 actorSize(stageSize * 0.5f);
+  // Create two actors with half the size of the stage and set them to be overlapping
+  Actor blue = Actor::New();
+  blue.SetProperty(Actor::Property::NAME, "Blue");
+  blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  blue.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+  blue.SetProperty(Actor::Property::SIZE, actorSize);
+
+  Actor green = Actor::New();
+  green.SetProperty(Actor::Property::NAME, "Green");
+  green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  green.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+  green.SetProperty(Actor::Property::SIZE, actorSize);
+
+  // Add the actors to the view
+  stage.Add(blue);
+  stage.Add(green);
+
+  // connect to its hit-test signal
+  Dali::DevelActor::HitTestResultSignal(green).Connect(TestHitTestTouchCallback);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(0);
+  application.Render(10);
+
+  gHitTestTouchCallBackCalled = false;
+
+  HitTestAlgorithm::Results results;
+  HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction);
+
+  // check hit-test events
+  // The green actor received an event that the green actor was hit.
+  DALI_TEST_CHECK(gHitTestTouchCallBackCalled == true);
+  // The green actor passed the hit-test. So blue was the final hit.
+  DALI_TEST_CHECK(results.actor == blue);
+
+  END_TEST;
+}
index 77454af..9e838a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -608,3 +608,27 @@ int UtcDaliIntrusivePtrMoveAssignment(void)
 
   END_TEST;
 }
+
+/** Equality with nullptr */
+int UtcDaliIntrusivePtrOperatorEqualWithNullptr(void)
+{
+  tet_infoline("Test for Dali::IntrusivePtr::operator == nullptr");
+
+  IntrusivePtr<Counted> counted1(new Counted);
+
+  // counted1 is not nullptr.
+  DALI_TEST_CHECK(!(counted1 == nullptr));
+  DALI_TEST_CHECK(!(nullptr == counted1));
+  DALI_TEST_CHECK(counted1 != nullptr);
+  DALI_TEST_CHECK(nullptr != counted1);
+
+  counted1 = nullptr;
+
+  // counted1 is nullptr.
+  DALI_TEST_CHECK(counted1 == nullptr);
+  DALI_TEST_CHECK(nullptr == counted1);
+  DALI_TEST_CHECK(!(counted1 != nullptr));
+  DALI_TEST_CHECK(!(nullptr != counted1));
+
+  END_TEST;
+}
index c8d07d0..1aa7101 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -179,8 +179,6 @@ int UtcDaliRotationGestureRecognizerBasicInterrupted(void)
   GestureReceivedFunctor functor(data);
   detector.DetectedSignal().Connect(&application, functor);
 
-  // application.ProcessEvent( GenerateSingleTouch( PointState::DOWN, Vector2( 20.0f, 20.0f ), 150 ) );
-  // application.ProcessEvent( GenerateSingleTouch( PointState::MOTION, Vector2( 20.0f, 25.0f ), 151 ) );
   application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(20.0f, 30.0f), 152));
 
   application.SendNotification();
index 714c146..24921c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -40,6 +40,13 @@ void utc_dali_tap_gesture_detector_cleanup(void)
 ///////////////////////////////////////////////////////////////////////////////
 namespace
 {
+bool        gHitTestTouchCallBackCalled = false;
+static bool TestHitTestTouchCallback(Actor, const TouchEvent&)
+{
+  gHitTestTouchCallBackCalled = true;
+  return false;
+  END_TEST;
+}
 // Stores data that is populated in the callback and will be read by the TET cases
 struct SignalData
 {
@@ -1144,4 +1151,60 @@ int UtcDaliTapGestureReceiveAllTapEvents(void)
   data.Reset();
 
   END_TEST;
+}
+
+int UtcDaliTapGestureDoesWantedHitTest(void)
+{
+  TestApplication application;
+
+  Actor blue = Actor::New();
+  blue.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  Actor green = Actor::New();
+  green.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  application.GetScene().Add(blue);
+  application.GetScene().Add(green);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData             blueData;
+  GestureReceivedFunctor blueFunctor(blueData);
+
+  TapGestureDetector blueDetector = TapGestureDetector::New();
+  blueDetector.Attach(blue);
+  blueDetector.DetectedSignal().Connect(&application, blueFunctor);
+
+  SignalData             greenData;
+  GestureReceivedFunctor greenFunctor(greenData);
+
+  TapGestureDetector greenDetector = TapGestureDetector::New();
+  greenDetector.Attach(green);
+  greenDetector.DetectedSignal().Connect(&application, greenFunctor);
+
+  // connect to its hit-test signal
+  gHitTestTouchCallBackCalled = false;
+  Dali::DevelActor::HitTestResultSignal(green).Connect(TestHitTestTouchCallback);
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 0, 100));
+  application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 0, 120));
+  application.SendNotification();
+
+  // check hit-test events
+  // The green actor received an event that the green actor was hit.
+  DALI_TEST_EQUALS(true, gHitTestTouchCallBackCalled, TEST_LOCATION);
+
+  // The green actor passed the hit-test. So blue was the final hit.
+  DALI_TEST_EQUALS(false, greenData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, blueData.functorCalled, TEST_LOCATION);
+
+  blueData.Reset();
+  greenData.Reset();
+
+  END_TEST;
 }
\ No newline at end of file
diff --git a/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp b/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp
new file mode 100644 (file)
index 0000000..2b589e9
--- /dev/null
@@ -0,0 +1,673 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/common/capabilities.h>
+#include <dali/devel-api/common/stage.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/public-api/dali-core.h>
+#include <cstdio>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-test-suite-utils.h>
+#include <mesh-builder.h>
+#include <test-trace-call-stack.h>
+#include "test-graphics-command-buffer.h"
+
+using namespace Dali;
+
+void visual_renderer_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void visual_renderer_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliVisualRendererNew01(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  DALI_TEST_EQUALS((bool)renderer, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererNew02(void)
+{
+  TestApplication application;
+  VisualRenderer  renderer;
+  DALI_TEST_EQUALS((bool)renderer, false, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererCopyConstructor(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  VisualRenderer rendererCopy(renderer);
+  DALI_TEST_EQUALS((bool)rendererCopy, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  VisualRenderer renderer2;
+  DALI_TEST_EQUALS((bool)renderer2, false, TEST_LOCATION);
+
+  renderer2 = renderer;
+  DALI_TEST_EQUALS((bool)renderer2, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererMoveConstructor(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = Shader::New("vertexSrc", "fragmentSrc");
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+  DALI_TEST_CHECK(renderer);
+  DALI_TEST_EQUALS(1, renderer.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3::ONE, TEST_LOCATION);
+
+  auto testColor = Vector3(1.0f, 0.0f, 1.0f);
+  renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, testColor);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), testColor, TEST_LOCATION);
+
+  VisualRenderer move = std::move(renderer);
+  DALI_TEST_CHECK(move);
+  DALI_TEST_EQUALS(1, move.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(move.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), testColor, TEST_LOCATION);
+  DALI_TEST_CHECK(!renderer);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererMoveAssignment(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = Shader::New("vertexSrc", "fragmentSrc");
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+  DALI_TEST_CHECK(renderer);
+  DALI_TEST_EQUALS(1, renderer.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3::ONE, TEST_LOCATION);
+
+  renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, Vector3(1.0f, 0.0f, 1.0f));
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3(1.0f, 0.0f, 1.0f), TEST_LOCATION);
+
+  VisualRenderer move;
+  move = std::move(renderer);
+  DALI_TEST_CHECK(move);
+  DALI_TEST_EQUALS(1, move.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(move.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR), Vector3(1.0f, 0.0f, 1.0f), TEST_LOCATION);
+  DALI_TEST_CHECK(!renderer);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererDownCast01(void)
+{
+  TestApplication application;
+
+  Geometry       geometry = CreateQuadGeometry();
+  Shader         shader   = CreateShader();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  BaseHandle     handle(renderer);
+  VisualRenderer renderer2 = VisualRenderer::DownCast(handle);
+  DALI_TEST_EQUALS((bool)renderer2, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVisualRendererDownCast02(void)
+{
+  TestApplication application;
+
+  Handle         handle   = Handle::New(); // Create a custom object
+  VisualRenderer renderer = VisualRenderer::DownCast(handle);
+  DALI_TEST_EQUALS((bool)renderer, false, TEST_LOCATION);
+  END_TEST;
+}
+
+// using a template to auto deduce the parameter types
+template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
+void TEST_RENDERER_PROPERTY(P1 renderer, P2 stringName, P3 type, P4 isWriteable, P5 isAnimateable, P6 isConstraintInput, P7 enumName, P8 LOCATION)
+{
+  DALI_TEST_EQUALS(renderer.GetPropertyName(enumName), stringName, LOCATION);
+  DALI_TEST_EQUALS(renderer.GetPropertyIndex(stringName), static_cast<Property::Index>(enumName), LOCATION);
+  DALI_TEST_EQUALS(renderer.GetPropertyType(enumName), type, LOCATION);
+  DALI_TEST_EQUALS(renderer.IsPropertyWritable(enumName), isWriteable, LOCATION);
+  DALI_TEST_EQUALS(renderer.IsPropertyAnimatable(enumName), isAnimateable, LOCATION);
+  DALI_TEST_EQUALS(renderer.IsPropertyAConstraintInput(enumName), isConstraintInput, LOCATION);
+}
+
+int UtcDaliVisualRendererDefaultProperties(void)
+{
+  TestApplication application;
+  Geometry        geometry     = CreateQuadGeometry();
+  Shader          shader       = CreateShader();
+  VisualRenderer  renderer     = VisualRenderer::New(geometry, shader);
+  Renderer        baseRenderer = Renderer::New(geometry, shader);
+
+  DALI_TEST_EQUALS(baseRenderer.GetPropertyCount(), 27, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetPropertyCount(), 27 + 8, TEST_LOCATION);
+
+  TEST_RENDERER_PROPERTY(renderer, "transformOffset", Property::VECTOR2, true, true, true, VisualRenderer::Property::TRANSFORM_OFFSET, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformSize", Property::VECTOR2, true, true, true, VisualRenderer::Property::TRANSFORM_SIZE, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformOrigin", Property::VECTOR2, true, false, false, VisualRenderer::Property::TRANSFORM_ORIGIN, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformAnchorPoint", Property::VECTOR2, true, false, false, VisualRenderer::Property::TRANSFORM_ANCHOR_POINT, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "transformOffsetSizeMode", Property::VECTOR4, true, false, false, VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "extraSize", Property::VECTOR2, true, true, true, VisualRenderer::Property::EXTRA_SIZE, TEST_LOCATION);
+
+  TEST_RENDERER_PROPERTY(renderer, "visualMixColor", Property::VECTOR3, true, true, true, VisualRenderer::Property::VISUAL_MIX_COLOR, TEST_LOCATION);
+  TEST_RENDERER_PROPERTY(renderer, "preMultipliedAlpha", Property::FLOAT, true, false, false, VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index colorIndex = VisualRenderer::Property::VISUAL_MIX_COLOR;
+  renderer.SetProperty(colorIndex, Vector3(1.0f, 1.0f, 1.0f));
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(colorIndex), Vector3(1.0f, 1.0f, 1.0f), 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector3(1.0f, 0.0f, 1.0f));
+  keyFrames.Add(1.0f, Vector3(0.0f, 0.0f, 0.0f));
+  animation.AnimateBetween(Property(renderer, colorIndex), keyFrames);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector3>(colorIndex), Vector3(0.5f, 0.f, 0.5f), TEST_LOCATION);
+
+  application.Render(400);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector3>(colorIndex), Vector3(0.1f, 0.f, 0.1f), TEST_LOCATION);
+
+  application.Render(100);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector3>(colorIndex), Vector3(0.f, 0.f, 0.f), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector3>(colorIndex), Vector3(0.f, 0.f, 0.f), TEST_LOCATION);
+
+  // Can we test to see if the actor has stopped being drawn?
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = VisualRenderer::Property::TRANSFORM_OFFSET;
+  renderer.SetProperty(index, Vector2(1.0f, 0.0f));
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(1.0f, 0.0f), 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector2(1.0f, 0.0f));
+  keyFrames.Add(1.0f, Vector2(0.0f, 1.0f));
+  animation.AnimateBetween(Property(renderer, index), keyFrames);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.5f, 0.5f), TEST_LOCATION);
+
+  application.Render(400);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.1f, 0.9f), TEST_LOCATION);
+
+  application.Render(100);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<Vector2>(index), Vector2(0.f, 1.0f), TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(0.f, 1.f), TEST_LOCATION);
+
+  END_TEST;
+}
+
+struct VisualProperties
+{
+  VisualProperties() = default;
+
+  VisualProperties(Vector2 offset, Vector2 size, Vector2 origin, Vector2 pivot, Vector4 modes, Vector2 extraSize, Vector3 mixColor)
+  : mTransformOffset(offset),
+    mTransformSize(size),
+    mTransformOrigin(origin),
+    mTransformAnchorPoint(pivot),
+    mTransformOffsetSizeMode(modes),
+    mExtraSize(extraSize),
+    mMixColor(mixColor)
+  {
+  }
+
+  Vector2 mTransformOffset{Vector2::ZERO};
+  Vector2 mTransformSize{Vector2::ZERO};
+  Vector2 mTransformOrigin{Vector2::ZERO};
+  Vector2 mTransformAnchorPoint{Vector2::ZERO};
+  Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
+  Vector2 mExtraSize{Vector2::ZERO};
+  Vector3 mMixColor{Vector3::ONE};
+
+  static VisualProperties GetPropsAt(float alpha, const VisualProperties& start, const VisualProperties& end)
+  {
+    VisualProperties progress;
+    progress.mTransformOffset         = start.mTransformOffset + (end.mTransformOffset - start.mTransformOffset) * alpha;
+    progress.mTransformSize           = start.mTransformSize + (end.mTransformSize - start.mTransformSize) * alpha;
+    progress.mExtraSize               = start.mExtraSize + (end.mExtraSize - start.mExtraSize) * alpha;
+    progress.mMixColor                = start.mMixColor + (end.mMixColor - start.mMixColor) * alpha;
+    progress.mTransformOffsetSizeMode = end.mTransformOffsetSizeMode;
+    progress.mTransformOrigin         = end.mTransformOrigin;
+    progress.mTransformAnchorPoint    = end.mTransformAnchorPoint;
+    return progress;
+  }
+};
+
+void PrintVisualProperties(const VisualProperties& props, const std::string& prefix)
+{
+  tet_printf(
+    "%s: offset:(%5.3f, %5.3f)\n"
+    "%*c size:(%5.3f, %5.3f)\n"
+    "%*c origin:(%5.3f, %5.3f)\n"
+    "%*c anchorPoint:(%5.3f, %5.3f)\n"
+    "%*c offsetSizeMode:(%5.3f, %5.3f, %5.3f, %5.3f)\n"
+    "%*c extraSize:(%5.3f, %5.3f)\n"
+    "%*c mixColor:(%5.3f, %5.3f, %5.3f, %5.3f)\n",
+    prefix.c_str(),
+    props.mTransformOffset.x,
+    props.mTransformOffset.y,
+    prefix.length(),
+    ' ',
+    props.mTransformSize.x,
+    props.mTransformSize.y,
+    prefix.length(),
+    ' ',
+    props.mTransformOrigin.x,
+    props.mTransformOrigin.y,
+    prefix.length(),
+    ' ',
+    props.mTransformAnchorPoint.x,
+    props.mTransformAnchorPoint.y,
+    prefix.length(),
+    ' ',
+    props.mTransformOffsetSizeMode.x,
+    props.mTransformOffsetSizeMode.y,
+    props.mTransformOffsetSizeMode.z,
+    props.mTransformOffsetSizeMode.w,
+    prefix.length(),
+    ' ',
+    props.mExtraSize.x,
+    props.mExtraSize.y,
+    prefix.length(),
+    ' ',
+    props.mMixColor.x,
+    props.mMixColor.y,
+    props.mMixColor.z);
+}
+
+void SetVisualProperties(VisualRenderer renderer, VisualProperties props)
+{
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET, props.mTransformOffset);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_SIZE, props.mTransformSize);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_ORIGIN, props.mTransformOrigin);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT, props.mTransformAnchorPoint);
+  renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, props.mTransformOffsetSizeMode);
+  renderer.SetProperty(VisualRenderer::Property::EXTRA_SIZE, props.mExtraSize);
+  renderer.SetProperty(VisualRenderer::Property::VISUAL_MIX_COLOR, props.mMixColor);
+}
+
+void CheckEventVisualProperties(VisualRenderer renderer, VisualProperties expectedProps)
+{
+  tet_infoline("CheckEventVisualProperties\n");
+
+  VisualProperties actualProps;
+  actualProps.mTransformOffset         = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_OFFSET);
+  actualProps.mTransformSize           = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE);
+  actualProps.mTransformOrigin         = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ORIGIN);
+  actualProps.mTransformAnchorPoint    = renderer.GetProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT);
+  actualProps.mTransformOffsetSizeMode = renderer.GetProperty<Vector4>(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE);
+  actualProps.mExtraSize               = renderer.GetProperty<Vector2>(VisualRenderer::Property::EXTRA_SIZE);
+  actualProps.mMixColor                = renderer.GetProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR);
+
+  PrintVisualProperties(actualProps, "Actual event props");
+
+  DALI_TEST_EQUALS(actualProps.mTransformOffset, expectedProps.mTransformOffset, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformSize, expectedProps.mTransformSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOrigin, expectedProps.mTransformOrigin, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformAnchorPoint, expectedProps.mTransformAnchorPoint, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOffsetSizeMode, expectedProps.mTransformOffsetSizeMode, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mExtraSize, expectedProps.mExtraSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mMixColor, expectedProps.mMixColor, TEST_LOCATION);
+}
+
+void CheckSceneGraphVisualProperties(VisualRenderer renderer, VisualProperties expectedProps)
+{
+  tet_infoline("CheckSceneGraphVisualProperties\n");
+
+  VisualProperties actualProps;
+
+  actualProps.mTransformOffset         = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_OFFSET);
+  actualProps.mTransformSize           = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_SIZE);
+  actualProps.mTransformOrigin         = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ORIGIN);
+  actualProps.mTransformAnchorPoint    = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT);
+  actualProps.mTransformOffsetSizeMode = renderer.GetCurrentProperty<Vector4>(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE);
+  actualProps.mExtraSize               = renderer.GetCurrentProperty<Vector2>(VisualRenderer::Property::EXTRA_SIZE);
+  actualProps.mMixColor                = renderer.GetCurrentProperty<Vector3>(VisualRenderer::Property::VISUAL_MIX_COLOR);
+
+  PrintVisualProperties(actualProps, "Actual update props");
+
+  DALI_TEST_EQUALS(actualProps.mTransformOffset, expectedProps.mTransformOffset, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformSize, expectedProps.mTransformSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOrigin, expectedProps.mTransformOrigin, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformAnchorPoint, expectedProps.mTransformAnchorPoint, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mTransformOffsetSizeMode, expectedProps.mTransformOffsetSizeMode, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mExtraSize, expectedProps.mExtraSize, TEST_LOCATION);
+  DALI_TEST_EQUALS(actualProps.mMixColor, expectedProps.mMixColor, TEST_LOCATION);
+}
+
+void CheckUniforms(VisualRenderer renderer, VisualProperties props, std::vector<UniformData>& uniforms, TraceCallStack& callStack, TestGlAbstraction& gl)
+{
+  tet_infoline("CheckUniforms\n");
+
+  TraceCallStack::NamedParams params;
+
+  tet_printf("Callback trace: \n%s\n", callStack.GetTraceString().c_str());
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[0].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[0].name.c_str(), props.mTransformOffset));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[1].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[1].name.c_str(), props.mTransformSize));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[2].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[2].name.c_str(), props.mTransformOrigin));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[3].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[3].name.c_str(), props.mTransformAnchorPoint));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[4].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector4>(uniforms[4].name.c_str(), props.mTransformOffsetSizeMode));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[5].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector2>(uniforms[5].name.c_str(), props.mExtraSize));
+
+  DALI_TEST_CHECK(callStack.FindMethodAndGetParameters(uniforms[6].name, params));
+  DALI_TEST_CHECK(gl.GetUniformValue<Vector3>(uniforms[6].name.c_str(), props.mMixColor));
+}
+
+int UtcDaliVisualRendererAnimatedProperty03(void)
+{
+  TestApplication    application;
+  TestGlAbstraction& gl        = application.GetGlAbstraction();
+  TraceCallStack&    callStack = gl.GetSetUniformTrace();
+  gl.EnableSetUniformCallTrace(true);
+
+  tet_infoline("Test that a visual renderer property can be animated and that the uniforms are set");
+
+  std::vector<UniformData> customUniforms{{"offset", Property::VECTOR2},
+                                          {"size", Property::VECTOR2},
+                                          {"origin", Property::VECTOR2},
+                                          {"anchorPoint", Property::VECTOR2},
+                                          {"offsetSizeMode", Property::VECTOR4},
+                                          {"extraSize", Property::VECTOR2},
+                                          {"mixColor", Property::VECTOR3}};
+
+  application.GetGraphicsController().AddCustomUniforms(customUniforms);
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  VisualProperties props{Vector2(10.f, 10.f), Vector2(200.f, 100.f), Vector2(0.5f, 0.5f), Vector2(0.5f, 0.5f), Vector4::ZERO, Vector2(0.0f, 0.0f), Vector3(Color::SEA_GREEN)};
+  VisualProperties targetProps{Vector2(40.f, 40.f), Vector2(100.f, 200.f), Vector2(0.5f, 0.5f), Vector2(0.5f, 0.5f), Vector4::ZERO, Vector2(25.0f, 25.0f), Vector3(Color::MEDIUM_PURPLE)};
+
+  SetVisualProperties(renderer, props);
+  CheckEventVisualProperties(renderer, props);
+  application.SendNotification();
+  application.Render(0);
+  CheckSceneGraphVisualProperties(renderer, props);
+  CheckUniforms(renderer, props, customUniforms, callStack, gl);
+
+  // Set up a 1 second anim.
+  Animation animation = Animation::New(1.0f);
+
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::TRANSFORM_OFFSET), targetProps.mTransformOffset);
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::TRANSFORM_SIZE), targetProps.mTransformSize);
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::EXTRA_SIZE), targetProps.mExtraSize);
+  animation.AnimateTo(Property(renderer, VisualRenderer::Property::VISUAL_MIX_COLOR), targetProps.mMixColor);
+  animation.Play();
+
+  CheckEventVisualProperties(renderer, targetProps);
+
+  for(int i = 0; i <= 10; ++i)
+  {
+    tet_printf("\n###########  Animation progress: %d%%\n\n", i * 10);
+    VisualProperties propsProgress = VisualProperties::GetPropsAt(0.1f * i, props, targetProps);
+    PrintVisualProperties(propsProgress, "Expected values");
+
+    callStack.Reset();
+    application.SendNotification();
+    application.Render((i == 0 ? 0 : 100));
+
+    CheckEventVisualProperties(renderer, targetProps);
+
+    CheckSceneGraphVisualProperties(renderer, propsProgress);
+    CheckUniforms(renderer, propsProgress, customUniforms, callStack, gl);
+  }
+
+  // Ensure animation finishes
+  application.SendNotification();
+  application.Render(100);
+  CheckSceneGraphVisualProperties(renderer, targetProps);
+  CheckUniforms(renderer, targetProps, customUniforms, callStack, gl);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can't be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = VisualRenderer::Property::TRANSFORM_ANCHOR_POINT;
+  renderer.SetProperty(index, Vector2(AnchorPoint::TOP_RIGHT));
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(AnchorPoint::TOP_RIGHT), 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector2::ZERO);
+  keyFrames.Add(1.0f, Vector2(10.0f, 10.0f));
+  try
+  {
+    animation.AnimateBetween(Property(renderer, index), keyFrames);
+    tet_result(TET_FAIL);
+  }
+  catch(DaliException& e)
+  {
+    DALI_TEST_ASSERT(e, "baseProperty && \"Property is not animatable\"", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a visual renderer property can't be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA;
+  renderer.SetProperty(index, 1.0f);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, 0.5f);
+  keyFrames.Add(1.0f, 1.0f);
+  try
+  {
+    animation.AnimateBetween(Property(renderer, index), keyFrames);
+    tet_result(TET_FAIL);
+  }
+  catch(DaliException& e)
+  {
+    DALI_TEST_ASSERT(e, "baseProperty && \"Property is not animatable\"", TEST_LOCATION);
+  }
+
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 1.0f, 0.0001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVisualRendererAnimatedProperty06(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a parent renderer property can still be animated");
+
+  Shader         shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry       geometry = CreateQuadGeometry();
+  VisualRenderer renderer = VisualRenderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  application.GetScene().Add(actor);
+
+  Property::Index index = DevelRenderer::Property::OPACITY;
+  renderer.SetProperty(index, 1.0f);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(index), 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DevelRenderer::Property::OPACITY), 1.0f, 0.0001f, TEST_LOCATION);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, float(0.5f));
+  keyFrames.Add(1.0f, float(0.0f));
+  animation.AnimateBetween(Property(renderer, index), keyFrames);
+  animation.Play();
+
+  application.SendNotification();
+
+  // Test that the event side properties are set to target value of 0
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 0.25f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DevelRenderer::Property::OPACITY), 0.25f, 0.0001f, TEST_LOCATION);
+
+  // Test that the event side properties are set to target value 0f 0
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+
+  // Complete the animation
+  application.Render(500);
+
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(index), 0.0f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetCurrentProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(renderer.GetProperty<float>(DevelRenderer::Property::OPACITY), 0.0f, 0.0001f, TEST_LOCATION);
+  END_TEST;
+}
old mode 100755 (executable)
new mode 100644 (file)
index ab0fe4d..37fa3fb
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -63,6 +63,11 @@ void SwitchParent(Actor actor, Actor newParent)
   return GetImplementation(actor).SwitchParent(GetImplementation(newParent));
 }
 
+Actor::TouchEventSignalType& HitTestResultSignal(Actor actor)
+{
+  return GetImplementation(actor).HitTestResultSignal();
+}
+
 } // namespace DevelActor
 
 } // namespace Dali
index e1a0896..9d4f0ae 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_ACTOR_DEVEL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -355,6 +355,39 @@ DALI_CORE_API void SetNeedGesturePropagation(Actor actor, bool propagation);
  */
 DALI_CORE_API void SwitchParent(Actor actor, Actor newParent);
 
+/**
+ * @brief This signal is emitted when an actor is hit through hit-test.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void MyCallbackName( Actor actor );
+ * @endcode
+ * actor The actor to intercept
+ *
+ * @note This callback is called when the actor is hit.
+ * If true is returned, TouchEvent is called from the this actor.
+ * If false is returned, the hit test starts again from the next lower actor.
+ *
+ * @note example
+ *   Actor topActor = Actor::New();
+ *   Actor bottomActor = Actor::New();
+ *   topActor.TouchedSignal().Connect(&application, topActorFunctor);
+ *   bottomActor.TouchedSignal().Connect(&application, bottomActorFunctor);
+ * The two actors have no relationship.
+ * So when the topActor is touched, the event cannot be propagated to the bottomActor.
+ *
+ * If you connect HitTestResultSignal to topActor.
+ *   Dali::DevelActor::HitTestResultSignal(topActor).Connect(&application, hitTestResultFunctor);
+ *
+ * If the hitTestResult Functor returns false, it passes the hit-test and starts the hit-test again from the next lower actor.
+ * So the bottomActor can be hit and receive touch events.
+ * If hitTestResult returns true, it means that it has been hit. So it receives a TouchEvent from itself.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_CORE_API Actor::TouchEventSignalType& HitTestResultSignal(Actor actor);
+
 } // namespace DevelActor
 
 } // namespace Dali
index 2df7181..6dc060a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
 #include <dali/devel-api/common/capabilities.h>
 
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/touch-integ.h>
 
 #include <dali/internal/event/actors/actor-coords.h>
 #include <dali/internal/event/actors/actor-parent.h>
@@ -1015,6 +1016,22 @@ void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
   EmitSignal(*this, mLayoutDirectionChangedSignal, type);
 }
 
+bool Actor::EmitHitTestResultSignal(Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp)
+{
+  bool hit = true;
+
+  if(IsHitTestResultRequired())
+  {
+    Dali::Actor        handle(this);
+    Integration::Point newPoint(point);
+    newPoint.SetHitActor(handle);
+    newPoint.SetLocalPosition(hitPointLocal);
+    Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent(timeStamp, newPoint);
+    hit                         = mHitTestResultSignal.Emit(handle, touchEvent);
+  }
+  return hit;
+}
+
 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
 {
   return mParentImpl.ChildAddedSignal();
@@ -1049,6 +1066,7 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mOnRelayoutSignal(),
   mVisibilityChangedSignal(),
   mLayoutDirectionChangedSignal(),
+  mHitTestResultSignal(),
   mTargetOrientation(Quaternion::IDENTITY),
   mTargetColor(Color::WHITE),
   mTargetPosition(Vector3::ZERO),
index b1050a7..3392d0d 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_ACTOR_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,6 +33,8 @@
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 
+#include <dali/integration-api/events/touch-event-integ.h>
+
 #include <dali/internal/common/const-string.h>
 #include <dali/internal/common/internal-constants.h>
 #include <dali/internal/common/memory-pool-object-allocator.h>
@@ -1240,6 +1242,15 @@ public:
   }
 
   /**
+   * Query whether the application or derived actor type requires hit-test result events.
+   * @return True if hit-test result events are required.
+   */
+  bool IsHitTestResultRequired() const
+  {
+    return !mHitTestResultSignal.Empty();
+  }
+
+  /**
    * Query whether the application or derived actor type requires intercept touch events.
    * @return True if intercept touch events are required.
    */
@@ -1375,6 +1386,23 @@ public:
   void EmitLayoutDirectionChangedSignal(LayoutDirection::Type type);
 
   /**
+   * Used by the EventProcessor to emit hit-test result touch event signals.
+   * @param[in] point The point of event touched.
+   * @param[in] hitPointLocal The hit point in the Actor's local reference system.
+   * @param[in] timeStamp The time the event occurred.
+   * @return True if the event was consumed.
+   */
+  bool EmitHitTestResultSignal(Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp);
+
+  /**
+   * @copydoc DevelActor::HitTestResultSignal()
+   */
+  Dali::Actor::TouchEventSignalType& HitTestResultSignal()
+  {
+    return mHitTestResultSignal;
+  }
+
+  /**
    * @copydoc DevelActor::InterceptTouchedSignal()
    */
   Dali::Actor::TouchEventSignalType& InterceptTouchedSignal()
@@ -1865,6 +1893,7 @@ protected:
   Dali::Actor::OnRelayoutSignalType             mOnRelayoutSignal;
   DevelActor::VisibilityChangedSignalType       mVisibilityChangedSignal;
   Dali::Actor::LayoutDirectionChangedSignalType mLayoutDirectionChangedSignal;
+  Dali::Actor::TouchEventSignalType             mHitTestResultSignal;
 
   Quaternion mTargetOrientation; ///< Event-side storage for orientation
   Vector4    mTargetColor;       ///< Event-side storage for color
index 551acc1..1cf4b26 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -61,6 +61,11 @@ struct GestureHitTestCheck : public HitTestAlgorithm::HitTestInterface
     return layer->IsTouchConsumed();
   }
 
+  bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+  {
+    return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+  }
+
   GestureType::Value mType;
 };
 
@@ -71,6 +76,8 @@ GestureProcessor::GestureProcessor(GestureType::Value type)
   mNeedsUpdate(false),
   mType(type),
   mCurrentGesturedActor(nullptr),
+  mPoint(),
+  mEventTime(0u),
   mGesturedActorDisconnected(false)
 {
 }
@@ -84,6 +91,11 @@ void GestureProcessor::ProcessTouch(Scene& scene, const Integration::TouchEvent&
 {
   if(mGestureRecognizer)
   {
+    if(!event.points.empty())
+    {
+      mPoint     = event.points[0];
+      mEventTime = event.time;
+    }
     mGestureRecognizer->SendEvent(scene, event);
   }
 }
@@ -192,6 +204,8 @@ void GestureProcessor::ProcessAndEmit(HitTestAlgorithm::Results& hitTestResults)
 bool GestureProcessor::HitTest(Scene& scene, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults)
 {
   GestureHitTestCheck hitCheck(mType);
+  hitTestResults.point     = mPoint;
+  hitTestResults.eventTime = mEventTime;
   HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), screenCoordinates, hitTestResults, hitCheck);
   return hitTestResults.renderTask && hitTestResults.actor;
 }
index 85261e5..e2015f3 100644 (file)
@@ -186,6 +186,8 @@ protected:                                 //Data
 private:                                             // Data
   GestureType::Value mType;                          ///< Type of GestureProcessor
   Actor*             mCurrentGesturedActor;          ///< The current actor that has been gestured.
+  Integration::Point mPoint;                         ///< The point of event touched.
+  uint32_t           mEventTime;                     ///< The time the event occurred.
   bool               mGesturedActorDisconnected : 1; ///< Indicates whether the gestured actor has been disconnected from the scene
 };
 
index ec5cc7c..81bf36a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -89,6 +89,11 @@ struct HitTestFunctionWrapper : public HitTestInterface
     return false;
   }
 
+  bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+  {
+    return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+  }
+
   Dali::HitTestAlgorithm::HitTestFunction mFunc;
 };
 
@@ -114,6 +119,11 @@ struct ActorTouchableCheck : public HitTestInterface
   {
     return layer->IsTouchConsumed();
   }
+
+  bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+  {
+    return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+  }
 };
 
 /**
@@ -158,7 +168,9 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
                             bool                                       layerIs3d,
                             uint32_t                                   clippingDepth,
                             uint32_t                                   clippingBitPlaneMask,
-                            const RayTest&                             rayTest)
+                            const RayTest&                             rayTest,
+                            const Integration::Point&                  point,
+                            const uint32_t                             eventTime)
 {
   HitActor hit;
 
@@ -245,7 +257,8 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
               }
             }
 
-            if(haveHitActor)
+            // If the hit actor does not want to hit, the hit-test continues.
+            if(haveHitActor && hitCheck.ActorRequiresHitResultCheck(&actor, point, hitPointLocal, eventTime))
             {
               hit.actor       = &actor;
               hit.hitPosition = hitPointLocal;
@@ -302,12 +315,14 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
                                                layerIs3d,
                                                newClippingDepth,
                                                clippingBitPlaneMask,
-                                               rayTest));
+                                               rayTest,
+                                               point,
+                                               eventTime));
 
         // Make sure the set hit actor is actually hittable. This is usually required when we have some
         // clipping as we need to hit-test all actors as we descend the tree regardless of whether they
         // are hittable or not.
-        if(currentHit.actor && !hitCheck.IsActorHittable(currentHit.actor))
+        if(currentHit.actor && (!hitCheck.IsActorHittable(currentHit.actor)))
         {
           continue;
         }
@@ -488,7 +503,9 @@ bool HitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives,
                                        layer->GetBehavior() == Dali::Layer::LAYER_3D,
                                        0u,
                                        0u,
-                                       rayTest);
+                                       rayTest,
+                                       results.point,
+                                       results.eventTime);
             }
             else if(IsWithinSourceActors(*sourceActor, *layer))
             {
@@ -505,7 +522,9 @@ bool HitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives,
                                        layer->GetBehavior() == Dali::Layer::LAYER_3D,
                                        0u,
                                        0u,
-                                       rayTest);
+                                       rayTest,
+                                       results.point,
+                                       results.eventTime);
             }
 
             // If this layer is set to consume the hit, then do not check any layers behind it
@@ -569,7 +588,6 @@ bool HitTestRenderTaskList(const Vector2&    sceneSize,
       // Skip to next task
       continue;
     }
-
     if(HitTestRenderTask(exclusives, sceneSize, layers, renderTask, screenCoordinates, results, hitCheck, rayTest))
     {
       // Return true when an actor is hit (or layer in our render-task consumes the hit)
index e70ddaa..fa22507 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_HIT_TEST_ALGORITHM_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/integration-api/events/touch-event-integ.h>
 #include <dali/internal/event/render-tasks/render-task-impl.h>
 #include <dali/public-api/actors/actor.h>
 
@@ -37,11 +38,13 @@ namespace HitTestAlgorithm
 {
 struct Results
 {
-  RenderTaskPtr renderTask;       ///< The render-task displaying the actor.
-  Dali::Actor   actor;            ///< The hit actor.
-  Vector2       actorCoordinates; ///< The actor coordinates.
-  Vector4       rayOrigin;        ///< The point of origin of the ray.
-  Vector4       rayDirection;     ///< The direction vector of the ray.
+  RenderTaskPtr      renderTask;       ///< The render-task displaying the actor.
+  Dali::Actor        actor;            ///< The hit actor.
+  Vector2            actorCoordinates; ///< The actor coordinates.
+  Vector4            rayOrigin;        ///< The point of origin of the ray.
+  Vector4            rayDirection;     ///< The direction vector of the ray.
+  Integration::Point point;            ///< The point of event touched.
+  uint32_t           eventTime;        ///< The time the event occurred.
 };
 
 /**
@@ -81,6 +84,21 @@ struct HitTestInterface
    */
   virtual bool DoesLayerConsumeHit(Layer* layer) = 0;
 
+  /**
+   * Called by the hit-test algorithm to determine whether the actor will be hit or not.
+   *
+   * @note If true is returned, then this actor will be hit.
+   *       If false is returend, then this actor passes the hit-test and the next actor performs the hit-test.
+   *
+   * @param[in] actor The hit actor.
+   * @param[in] point The point of event touched.
+   * @param[in] hitPointLocal The hit point in the Actor's local reference system.
+   * @param[in] timeStamp The time the event occurred.
+   *
+   * @return true if the actor should be the hit, false otherwise.
+   */
+  virtual bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) = 0;
+
 protected:
   /**
    * Virtual destructor, no deletion through this interface
index 99ddc97..114255e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -153,6 +153,12 @@ struct ActorHoverableCheck : public HitTestAlgorithm::HitTestInterface
   {
     return layer->IsHoverConsumed();
   }
+
+  bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+  {
+    // Hover event is always hit.
+    return true;
+  }
 };
 
 } // unnamed namespace
index 2e173b5..e8673ed 100644 (file)
@@ -308,6 +308,8 @@ bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event
   for(auto&& currentPoint : event.points)
   {
     HitTestAlgorithm::Results hitTestResults;
+    hitTestResults.point = currentPoint;
+    hitTestResults.eventTime = event.time;
     if(!firstPointParsed)
     {
       firstPointParsed = true;
index 4342d90..fc9b85a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -763,6 +763,23 @@ const PropertyInputImpl* Renderer::GetSceneObjectInputProperty(Property::Index i
   return GetSceneObjectAnimatableProperty(index);
 }
 
+void Renderer::AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command)
+{
+  if(!mDrawCommands.capacity())
+  {
+    mDrawCommands.reserve(8);
+  }
+
+  mDrawCommands.emplace_back(command);
+
+  Dali::Internal::SceneGraph::SetDrawCommandsMessage(GetEventThreadServices(),
+                                                     GetRendererSceneObject(),
+                                                     mDrawCommands.data(),
+                                                     uint32_t(mDrawCommands.size())
+
+  );
+}
+
 Renderer::Renderer(const SceneGraph::Renderer* sceneObject)
 : Object(sceneObject),
   mDepthIndex(0),
@@ -781,22 +798,6 @@ Renderer::Renderer(const SceneGraph::Renderer* sceneObject)
 {
 }
 
-void Renderer::SetBlendColor(const Vector4& blendColor)
-{
-  mBlendingOptions.SetBlendColor(blendColor);
-  SetBlendColorMessage(GetEventThreadServices(), GetRendererSceneObject(), GetBlendColor());
-}
-
-const Vector4& Renderer::GetBlendColor() const
-{
-  const Vector4* blendColor = mBlendingOptions.GetBlendColor();
-  if(blendColor)
-  {
-    return *blendColor;
-  }
-  return Color::TRANSPARENT; // GL default
-}
-
 Renderer::~Renderer()
 {
   if(EventThreadServices::IsCoreRunning())
@@ -1163,21 +1164,20 @@ bool Renderer::GetCurrentPropertyValue(Property::Index index, Property::Value& v
   return valueSet;
 }
 
-void Renderer::AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command)
+void Renderer::SetBlendColor(const Vector4& blendColor)
 {
-  if(!mDrawCommands.capacity())
+  mBlendingOptions.SetBlendColor(blendColor);
+  SetBlendColorMessage(GetEventThreadServices(), GetRendererSceneObject(), GetBlendColor());
+}
+
+const Vector4& Renderer::GetBlendColor() const
+{
+  const Vector4* blendColor = mBlendingOptions.GetBlendColor();
+  if(blendColor)
   {
-    mDrawCommands.reserve(8);
+    return *blendColor;
   }
-
-  mDrawCommands.emplace_back(command);
-
-  Dali::Internal::SceneGraph::SetDrawCommandsMessage(GetEventThreadServices(),
-                                                     GetRendererSceneObject(),
-                                                     mDrawCommands.data(),
-                                                     uint32_t(mDrawCommands.size())
-
-  );
+  return Color::TRANSPARENT; // GL default
 }
 
 } // namespace Internal
index ad5ff55..17818ab 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDERER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -211,7 +211,7 @@ public: // Default property extensions from Object
    */
   void AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command);
 
-private: // implementation
+protected: // implementation
   /**
    * @brief Constructor.
    *
@@ -220,16 +220,13 @@ private: // implementation
   Renderer(const SceneGraph::Renderer* sceneObject);
 
   /**
-   * @brief Sets the blend color.
-   * @param[in] blendColor The blend color to set.
+   * A reference counted object may only be deleted by calling Unreference()
    */
-  void SetBlendColor(const Vector4& blendColor);
+  ~Renderer() override;
 
-  /**
-   * @brief Retrieves the blend-color.
-   * @return A const reference to the blend-color
-   */
-  const Vector4& GetBlendColor() const;
+private:
+  Renderer(const Renderer&) = delete;            ///< Deleted copy constructor
+  Renderer& operator=(const Renderer&) = delete; ///< Deleted assignment operator
 
   /**
    * @brief Retrieves the cached event side value of a default property.
@@ -247,17 +244,19 @@ private: // implementation
    */
   bool GetCurrentPropertyValue(Property::Index index, Property::Value& value) const;
 
-protected:
   /**
-   * A reference counted object may only be deleted by calling Unreference()
+   * @brief Sets the blend color.
+   * @param[in] blendColor The blend color to set.
    */
-  ~Renderer() override;
+  void SetBlendColor(const Vector4& blendColor);
 
-private: // unimplemented methods
-  Renderer(const Renderer&);
-  Renderer& operator=(const Renderer&);
+  /**
+   * @brief Retrieves the blend-color.
+   * @return A const reference to the blend-color
+   */
+  const Vector4& GetBlendColor() const;
 
-private:                     // data
+protected:
   GeometryPtr   mGeometry;   ///< Intrusive pointer to the geometry used by this renderer
   TextureSetPtr mTextureSet; ///< Intrusive pointer to the texture set used by this renderer
   ShaderPtr     mShader;     ///< Intrusive pointer to the shader used by this renderer
@@ -279,6 +278,7 @@ private:                     // data
   DevelRenderer::Rendering::Type mRenderingBehavior : 2;        ///< The rendering behavior
   bool                           mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
 
+private:
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands; ///< list of draw commands
 };
 
diff --git a/dali/internal/event/rendering/visual-renderer-impl.cpp b/dali/internal/event/rendering/visual-renderer-impl.cpp
new file mode 100644 (file)
index 0000000..c90448c
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/visual-renderer-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/rendering/scene-graph-renderer.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Properties: |name                              |type     |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY("transformOffset", VECTOR2, true, true, true, Dali::VisualRenderer::Property::TRANSFORM_OFFSET)
+DALI_PROPERTY("transformSize", VECTOR2, true, true, true, Dali::VisualRenderer::Property::TRANSFORM_SIZE)
+DALI_PROPERTY("transformOrigin", VECTOR2, true, false, false, Dali::VisualRenderer::Property::TRANSFORM_ORIGIN)
+DALI_PROPERTY("transformAnchorPoint", VECTOR2, true, false, false, Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT)
+DALI_PROPERTY("transformOffsetSizeMode", VECTOR4, true, false, false, Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE)
+DALI_PROPERTY("extraSize", VECTOR2, true, true, true, Dali::VisualRenderer::Property::EXTRA_SIZE)
+DALI_PROPERTY("visualMixColor", VECTOR3, true, true, true, Dali::VisualRenderer::Property::VISUAL_MIX_COLOR)
+DALI_PROPERTY("preMultipliedAlpha", FLOAT, true, false, false, Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA)
+DALI_PROPERTY_TABLE_END(Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX, VisualRendererDefaultProperties)
+
+// Property string to enumeration tables:
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN(TRANSFORM_POLICY)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::VisualRenderer::TransformPolicy::Type, RELATIVE)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::VisualRenderer::TransformPolicy::Type, ABSOLUTE)
+DALI_ENUM_TO_STRING_TABLE_END(TRANSFORM_POLICY)
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType(typeid(Dali::VisualRenderer), typeid(Dali::Renderer), Create, VisualRendererDefaultProperties);
+
+} // unnamed namespace
+
+VisualRendererPtr VisualRenderer::New()
+{
+  // create scene object first so it's guaranteed to exist for the event side
+  auto sceneObject = SceneGraph::Renderer::New();
+
+  sceneObject->SetVisualProperties(new AnimatableVisualProperties());
+
+  OwnerPointer<SceneGraph::Renderer> transferOwnership(sceneObject);
+  // pass the pointer to base for message passing
+  VisualRendererPtr rendererPtr(new VisualRenderer(sceneObject));
+
+  rendererPtr->AddUniformMappings(); // Ensure properties are mapped to uniforms
+
+  // transfer scene object ownership to update manager
+  EventThreadServices&       eventThreadServices = rendererPtr->GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager       = eventThreadServices.GetUpdateManager();
+  AddRendererMessage(updateManager, transferOwnership);
+
+  eventThreadServices.RegisterObject(rendererPtr.Get());
+  return rendererPtr;
+}
+
+VisualRenderer::VisualRenderer(const SceneGraph::Renderer* sceneObject)
+: Renderer(sceneObject)
+{
+}
+
+VisualRenderer::~VisualRenderer()
+{
+  if(EventThreadServices::IsCoreRunning())
+  {
+    EventThreadServices&       eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager       = eventThreadServices.GetUpdateManager();
+    RemoveRendererMessage(updateManager, GetVisualRendererSceneObject());
+
+    eventThreadServices.UnregisterObject(this);
+  }
+}
+
+const SceneGraph::Renderer& VisualRenderer::GetVisualRendererSceneObject() const
+{
+  return static_cast<const SceneGraph::Renderer&>(GetSceneObject());
+}
+
+void VisualRenderer::SetDefaultProperty(Property::Index        index,
+                                        const Property::Value& propertyValue)
+{
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    Renderer::SetDefaultProperty(index, propertyValue);
+  }
+  else
+  {
+    switch(index)
+    {
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformOffset))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformOffset, mPropertyCache.mTransformOffset);
+          }
+        }
+        break;
+      }
+
+      case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformSize))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformSize, mPropertyCache.mTransformSize);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformOrigin))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformOrigin, mPropertyCache.mTransformOrigin);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformAnchorPoint))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mTransformAnchorPoint, mPropertyCache.mTransformAnchorPoint);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+      {
+        if(propertyValue.Get(mPropertyCache.mTransformOffsetSizeMode))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector4>(GetEventThreadServices(), visualProperties->mTransformOffsetSizeMode, mPropertyCache.mTransformOffsetSizeMode);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::EXTRA_SIZE:
+      {
+        if(propertyValue.Get(mPropertyCache.mExtraSize))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector2>(GetEventThreadServices(), visualProperties->mExtraSize, mPropertyCache.mExtraSize);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+      {
+        if(propertyValue.Get(mPropertyCache.mMixColor))
+        {
+          const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+          auto                        visualProperties = sceneObject.GetVisualProperties();
+          if(visualProperties)
+          {
+            BakeMessage<Vector3>(GetEventThreadServices(), visualProperties->mMixColor, mPropertyCache.mMixColor);
+          }
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+      {
+        float preMultipliedAlpha;
+        if(propertyValue.Get(preMultipliedAlpha))
+        {
+          if(!Equals(mPropertyCache.mPreMultipliedAlpha, preMultipliedAlpha))
+          {
+            const SceneGraph::Renderer& sceneObject      = GetVisualRendererSceneObject();
+            auto                        visualProperties = sceneObject.GetVisualProperties();
+            if(visualProperties)
+            {
+              mPropertyCache.mPreMultipliedAlpha = preMultipliedAlpha;
+              BakeMessage<float>(GetEventThreadServices(), visualProperties->mPreMultipliedAlpha, preMultipliedAlpha);
+            }
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+Property::Value VisualRenderer::GetDefaultProperty(Property::Index index) const
+{
+  Property::Value value;
+
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    value = Renderer::GetDefaultProperty(index);
+  }
+  else
+  {
+    switch(index)
+    {
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+      {
+        value = mPropertyCache.mTransformOffset;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+      {
+        value = mPropertyCache.mTransformSize;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+      {
+        value = mPropertyCache.mTransformOrigin;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+      {
+        value = mPropertyCache.mTransformAnchorPoint;
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+      {
+        value = mPropertyCache.mTransformOffsetSizeMode;
+        break;
+      }
+      case Dali::VisualRenderer::Property::EXTRA_SIZE:
+      {
+        value = mPropertyCache.mExtraSize;
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+      {
+        value = mPropertyCache.mMixColor;
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+      {
+        value = mPropertyCache.mPreMultipliedAlpha;
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
+  }
+
+  return value;
+}
+
+Property::Value VisualRenderer::GetDefaultPropertyCurrentValue(Property::Index index) const
+{
+  Property::Value value;
+
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    value = Renderer::GetDefaultPropertyCurrentValue(index);
+  }
+  else
+  {
+    const SceneGraph::Renderer& sceneObject = GetVisualRendererSceneObject();
+
+    switch(index)
+    {
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformOffset[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformSize[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformOrigin[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformAnchorPoint[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mTransformOffsetSizeMode[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::EXTRA_SIZE:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mExtraSize[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mMixColor[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+      case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+      {
+        auto visualProperties = sceneObject.GetVisualProperties();
+        if(visualProperties)
+        {
+          value = visualProperties->mPreMultipliedAlpha[GetEventThreadServices().GetEventBufferIndex()];
+        }
+        break;
+      }
+    }
+  }
+  return value;
+}
+
+void VisualRenderer::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
+{
+  if(index < Dali::VisualRenderer::Property::DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX)
+  {
+    Renderer::OnNotifyDefaultPropertyAnimation(animation, index, value, animationType);
+  }
+  else
+  {
+    switch(animationType)
+    {
+      case Animation::TO:
+      case Animation::BETWEEN:
+      {
+        switch(index)
+        {
+          case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+          {
+            value.Get(mPropertyCache.mTransformOffset);
+            break;
+          }
+          case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+          {
+            value.Get(mPropertyCache.mTransformSize);
+            break;
+          }
+          case Dali::VisualRenderer::Property::EXTRA_SIZE:
+          {
+            value.Get(mPropertyCache.mExtraSize);
+            break;
+          }
+          case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+          {
+            value.Get(mPropertyCache.mMixColor);
+            break;
+          }
+        }
+        break;
+      }
+
+      case Animation::BY:
+      {
+        switch(index)
+        {
+          case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+          {
+            AdjustValue<Vector2>(mPropertyCache.mTransformOffset, value);
+            break;
+          }
+          case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+          {
+            AdjustValue<Vector2>(mPropertyCache.mTransformSize, value);
+            break;
+          }
+          case Dali::VisualRenderer::Property::EXTRA_SIZE:
+          {
+            AdjustValue<Vector2>(mPropertyCache.mExtraSize, value);
+            break;
+          }
+          case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+          {
+            AdjustValue<Vector3>(mPropertyCache.mMixColor, value);
+            break;
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+const SceneGraph::PropertyBase* VisualRenderer::GetSceneObjectAnimatableProperty(Property::Index index) const
+{
+  const SceneGraph::PropertyBase* property = nullptr;
+
+  switch(index)
+  {
+    case Dali::VisualRenderer::Property::TRANSFORM_OFFSET:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mTransformOffset;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::TRANSFORM_SIZE:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mTransformSize;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::EXTRA_SIZE:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mExtraSize;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::VISUAL_MIX_COLOR:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        property = &visualProperties->mMixColor;
+      }
+      break;
+    }
+  }
+
+  if(!property)
+  {
+    // not our property, ask base
+    property = Renderer::GetSceneObjectAnimatableProperty(index);
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* VisualRenderer::GetSceneObjectInputProperty(Property::Index index) const
+{
+  switch(index)
+  {
+    case Dali::VisualRenderer::Property::TRANSFORM_ORIGIN:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mTransformOrigin;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mTransformAnchorPoint;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mTransformOffsetSizeMode;
+      }
+      break;
+    }
+    case Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA:
+    {
+      auto visualProperties = GetVisualRendererSceneObject().GetVisualProperties();
+      if(visualProperties)
+      {
+        return &visualProperties->mPreMultipliedAlpha;
+      }
+      break;
+    }
+    default:
+    {
+      return GetSceneObjectAnimatableProperty(index);
+    }
+  }
+  return nullptr;
+}
+
+void VisualRenderer::AddUniformMappings()
+{
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_OFFSET, ConstString("offset"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_SIZE, ConstString("size"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, ConstString("offsetSizeMode"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_ORIGIN, ConstString("origin"));
+  AddUniformMapping(Dali::VisualRenderer::Property::TRANSFORM_ANCHOR_POINT, ConstString("anchorPoint"));
+  AddUniformMapping(Dali::VisualRenderer::Property::EXTRA_SIZE, ConstString("extraSize"));
+  AddUniformMapping(Dali::VisualRenderer::Property::VISUAL_MIX_COLOR, ConstString("mixColor"));
+  AddUniformMapping(Dali::VisualRenderer::Property::VISUAL_PRE_MULTIPLIED_ALPHA, ConstString("preMultipliedAlpha"));
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/rendering/visual-renderer-impl.h b/dali/internal/event/rendering/visual-renderer-impl.h
new file mode 100644 (file)
index 0000000..996ce11
--- /dev/null
@@ -0,0 +1,183 @@
+#ifndef DALI_INTERNAL_VISUAL_RENDERER_H
+#define DALI_INTERNAL_VISUAL_RENDERER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/renderer-impl.h> // Dali::Internal::Renderer
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/public-api/rendering/visual-renderer.h> // Dali::VisualRenderer
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Renderer;
+}
+
+class VisualRenderer;
+using VisualRendererPtr = IntrusivePtr<VisualRenderer>;
+
+/**
+ * VisualRenderer is a Renderer that has additional default properties for toolkit
+ */
+class VisualRenderer : public Renderer
+{
+public:
+  /**
+   * Create a new VisualRenderer.
+   * @return A smart-pointer to the newly allocated VisualRenderer.
+   */
+  static VisualRendererPtr New();
+
+  /**
+   * @brief Get the scene graph object
+   *
+   * @return the scene object
+   */
+  const SceneGraph::Renderer& GetVisualRendererSceneObject() const;
+
+public: // Default property extensions from Object
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue) override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  Property::Value GetDefaultProperty(Property::Index index) const override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCurrentValue()
+   */
+  Property::Value GetDefaultPropertyCurrentValue(Property::Index index) const override;
+
+  /**
+    * @copydoc Dali::Internal::Object::OnNotifyDefaultPropertyAnimation()
+    */
+  void OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType) override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty(Property::Index index) const override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  const PropertyInputImpl* GetSceneObjectInputProperty(Property::Index index) const override;
+
+private: // implementation
+  /**
+   * @brief Constructor.
+   *
+   * @param sceneObject the scene graph renderer
+   */
+  VisualRenderer(const SceneGraph::Renderer* sceneObject);
+
+  /**
+   * @brief Retrieves the current value of a default property from the scene-graph.
+   * @param[in]  index  The index of the property
+   * @param[out] value  Is set with the current scene-graph value of the property
+   * @return True if value set, false otherwise.
+   */
+  bool GetCurrentPropertyValue(Property::Index index, Property::Value& value) const;
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  ~VisualRenderer() override;
+
+private:
+  VisualRenderer(const VisualRenderer&) = delete;
+  VisualRenderer& operator=(const VisualRenderer&) = delete;
+
+  /**
+   * @brief Ensure that properties are mapped to uniforms
+   */
+  void AddUniformMappings();
+
+public:
+  struct VisualPropertyCache
+  {
+    Vector2 mTransformOffset{Vector2::ZERO};
+    Vector2 mTransformSize{Vector2::ZERO};
+    Vector2 mTransformOrigin{Vector2::ZERO};
+    Vector2 mTransformAnchorPoint{Vector2::ZERO};
+    Vector4 mTransformOffsetSizeMode{Vector2::ZERO};
+    Vector2 mExtraSize{Vector2::ZERO};
+    Vector3 mMixColor{Vector3::ONE};
+    float   mPreMultipliedAlpha{0.0f};
+  };
+
+  struct AnimatableVisualProperties
+  {
+    AnimatableVisualProperties()
+    : mTransformOffset(Vector2::ZERO),
+      mTransformSize(Vector2::ZERO),
+      mTransformOrigin(Vector2::ZERO),
+      mTransformAnchorPoint(Vector2::ZERO),
+      mTransformOffsetSizeMode(Vector4::ZERO),
+      mExtraSize(Vector2::ZERO),
+      mMixColor(Vector3::ONE),
+      mPreMultipliedAlpha(0.0f)
+    {
+    }
+    SceneGraph::AnimatableProperty<Vector2> mTransformOffset;
+    SceneGraph::AnimatableProperty<Vector2> mTransformSize;
+    SceneGraph::AnimatableProperty<Vector2> mTransformOrigin;
+    SceneGraph::AnimatableProperty<Vector2> mTransformAnchorPoint;
+    SceneGraph::AnimatableProperty<Vector4> mTransformOffsetSizeMode;
+    SceneGraph::AnimatableProperty<Vector2> mExtraSize;
+    SceneGraph::AnimatableProperty<Vector3> mMixColor;
+    SceneGraph::AnimatableProperty<float>   mPreMultipliedAlpha;
+    void*                                   mExtendedProperties{nullptr}; // Enable derived class to extend properties further
+  };
+
+private:
+  VisualPropertyCache mPropertyCache;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::VisualRenderer& GetImplementation(Dali::VisualRenderer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualRenderer handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::VisualRenderer&>(object);
+}
+
+inline const Internal::VisualRenderer& GetImplementation(const Dali::VisualRenderer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualRenderer handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::VisualRenderer&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_RENDERER_H
index bd014f7..73911cc 100644 (file)
@@ -95,6 +95,7 @@ SET( internal_src_files
   ${internal_src_dir}/event/rendering/texture-impl.cpp
   ${internal_src_dir}/event/rendering/texture-set-impl.cpp
   ${internal_src_dir}/event/rendering/renderer-impl.cpp
+  ${internal_src_dir}/event/rendering/visual-renderer-impl.cpp
   ${internal_src_dir}/event/rendering/sampler-impl.cpp
   ${internal_src_dir}/event/rendering/shader-impl.cpp
   ${internal_src_dir}/event/rendering/vertex-buffer-impl.cpp
index 7fc994f..d818dcd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDERER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 #include <dali/internal/common/blending-options.h>
 #include <dali/internal/common/type-abstraction-enums.h>
 #include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/rendering/visual-renderer-impl.h>
 #include <dali/internal/render/data-providers/render-data-provider.h>
 #include <dali/internal/render/renderers/render-renderer.h>
 #include <dali/internal/update/common/animatable-property.h>
@@ -435,6 +436,23 @@ public: // From UniformMapDataProvider
 
   void SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size);
 
+public: // For VisualProperties
+  /**
+   * To be used only for 1st stage initialization in event thread.
+   */
+  void SetVisualProperties(Internal::VisualRenderer::AnimatableVisualProperties* visualProperties)
+  {
+    mVisualProperties = visualProperties;
+  }
+
+  /**
+   * May be accessed from event thread
+   */
+  const Internal::VisualRenderer::AnimatableVisualProperties* GetVisualProperties() const
+  {
+    return mVisualProperties;
+  }
+
 private:
   /**
    * Protected constructor; See also Renderer::New()
@@ -444,12 +462,13 @@ private:
 private:
   CollectedUniformMap mCollectedUniformMap[2]; ///< Uniform maps collected by the renderer
 
-  SceneController*      mSceneController; ///< Used for initializing renderers
-  Render::Renderer*     mRenderer;        ///< Raw pointer to the renderer (that's owned by RenderManager)
-  TextureSet*           mTextureSet;      ///< The texture set this renderer uses. (Not owned)
-  Render::Geometry*     mGeometry;        ///< The geometry this renderer uses. (Not owned)
-  Shader*               mShader;          ///< The shader this renderer uses. (Not owned)
-  OwnerPointer<Vector4> mBlendColor;      ///< The blend color for blending operation
+  SceneController*                            mSceneController;           ///< Used for initializing renderers
+  Render::Renderer*                           mRenderer;                  ///< Raw pointer to the renderer (that's owned by RenderManager)
+  TextureSet*                                 mTextureSet;                ///< The texture set this renderer uses. (Not owned)
+  Render::Geometry*                           mGeometry;                  ///< The geometry this renderer uses. (Not owned)
+  Shader*                                     mShader;                    ///< The shader this renderer uses. (Not owned)
+  VisualRenderer::AnimatableVisualProperties* mVisualProperties{nullptr}; ///< VisualProperties (optional/owned)
+  OwnerPointer<Vector4>                       mBlendColor;                ///< The blend color for blending operation
 
   Dali::Internal::Render::Renderer::StencilParameters mStencilParameters; ///< Struct containing all stencil related options
 
index 9397d14..c962338 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTRUSIVE_PTR_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,9 @@
  *
  */
 
+// EXTERNAL INCLUDES
+#include <cstddef> // for std::nullptr_t
+
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
 
@@ -378,6 +381,62 @@ inline bool operator!=(T* lhs, IntrusivePtr<U> const& rhs)
 }
 
 /**
+ * @brief Comparison overrides of objects with nullptr_t.
+ *
+ * @SINCE_2_1.12
+ * @param[in] lhs Intrusive pointer to compare with
+ * @param[in] rhs nullptr
+ * @return True if the pointers is nullptr
+ */
+template<typename T>
+inline bool operator==(IntrusivePtr<T> const& lhs, std::nullptr_t rhs)
+{
+  return lhs.Get() == nullptr;
+}
+
+/**
+ * @brief Comparison overrides of objects with nullptr_t.
+ *
+ * @SINCE_2_1.12
+ * @param[in] lhs Intrusive pointer to compare with
+ * @param[in] rhs nullptr
+ * @return True if the pointers is not nullptr
+ */
+template<typename T>
+inline bool operator!=(IntrusivePtr<T> const& lhs, std::nullptr_t rhs)
+{
+  return lhs.Get() != nullptr;
+}
+
+/**
+ * @brief Comparison overrides of objects with nullptr_t.
+ *
+ * @SINCE_2_1.12
+ * @param[in] lhs nullptr
+ * @param[in] rhs Intrusive pointer to compare against
+ * @return True if the pointers is nullptr
+ */
+template<typename T>
+inline bool operator==(std::nullptr_t lhs, IntrusivePtr<T> const& rhs)
+{
+  return nullptr == rhs.Get();
+}
+
+/**
+ * @brief Comparison overrides of objects with nullptr_t.
+ *
+ * @SINCE_2_1.12
+ * @param[in] lhs nullptr
+ * @param[in] rhs Intrusive pointer to compare against
+ * @return True if the pointers is not nullptr
+ */
+template<typename T>
+inline bool operator!=(std::nullptr_t lhs, IntrusivePtr<T> const& rhs)
+{
+  return nullptr != rhs.Get();
+}
+
+/**
  * @}
  */
 } // namespace Dali
index 2d1e15a..a1c5a29 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const uint32_t    CORE_MAJOR_VERSION = 2;
 const uint32_t    CORE_MINOR_VERSION = 1;
-const uint32_t    CORE_MICRO_VERSION = 12;
+const uint32_t    CORE_MICRO_VERSION = 13;
 const char* const CORE_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index a70879b..03c1f1f 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_CORE_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/public-api/rendering/texture-set.h>
 #include <dali/public-api/rendering/texture.h>
 #include <dali/public-api/rendering/vertex-buffer.h>
+#include <dali/public-api/rendering/visual-renderer.h>
 
 #include <dali/public-api/signals/base-signal.h>
 #include <dali/public-api/signals/callback.h>
index 43b1478..70d8684 100644 (file)
@@ -70,6 +70,7 @@ SET( public_api_src_files
   ${public_api_src_dir}/rendering/texture.cpp
   ${public_api_src_dir}/rendering/texture-set.cpp
   ${public_api_src_dir}/rendering/renderer.cpp
+  ${public_api_src_dir}/rendering/visual-renderer.cpp
   ${public_api_src_dir}/rendering/sampler.cpp
   ${public_api_src_dir}/rendering/shader.cpp
   ${public_api_src_dir}/signals/callback.cpp
@@ -219,6 +220,7 @@ SET( public_api_core_rendering_header_files
   ${public_api_src_dir}/rendering/texture.h
   ${public_api_src_dir}/rendering/texture-set.h
   ${public_api_src_dir}/rendering/renderer.h
+  ${public_api_src_dir}/rendering/visual-renderer.h
   ${public_api_src_dir}/rendering/sampler.h
   ${public_api_src_dir}/rendering/shader.h
 )
index bb43b42..1cb2544 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_PROPERTY_INDEX_RANGES_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ enum PropertyRanges
   DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX,                            ///< Used by PanGestureDetector. @SINCE_1_0.0
 
   DEFAULT_RENDERER_PROPERTY_START_INDEX         = 9000000,                                                               ///< Start index for Renderer. @SINCE_1_1.44
-  DEFAULT_RENDERER_PROPERTY_MAX_INDEX           = DEFAULT_RENDERER_PROPERTY_START_INDEX + 100000,                        ///< Renderer range: 9000000 to 9100000 @SINCE_1_1.44
+  DEFAULT_RENDERER_PROPERTY_MAX_INDEX           = DEFAULT_RENDERER_PROPERTY_START_INDEX + DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION-1,///< Renderer range: 9,000,000 to 9,009,999 @SINCE_2_1.13
 
   PROPERTY_REGISTRATION_START_INDEX             = 10000000,                                                              ///< The index when registering a property should start from this number. @SINCE_1_0.0
   DEFAULT_PROPERTY_MAX_COUNT                    = PROPERTY_REGISTRATION_START_INDEX,                                     ///< Default Property Range: 0 to 9999999 @SINCE_1_0.0
index d384918..d434f72 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_RENDERER_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -545,6 +545,7 @@ public:
   Shader GetShader() const;
 
 public:
+  /// @cond internal
   /**
    * @brief The constructor.
    * @note  Not intended for application developers.
@@ -552,6 +553,7 @@ public:
    * @param[in] pointer A pointer to a newly allocated Renderer
    */
   explicit DALI_INTERNAL Renderer(Internal::Renderer* pointer);
+  /// @endcond
 };
 
 /**
diff --git a/dali/public-api/rendering/visual-renderer.cpp b/dali/public-api/rendering/visual-renderer.cpp
new file mode 100644 (file)
index 0000000..224efd0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/rendering/visual-renderer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/visual-renderer-impl.h>
+
+namespace Dali
+{
+VisualRenderer VisualRenderer::New(Geometry& geometry, Shader& shader)
+{
+  Internal::VisualRendererPtr renderer = Internal::VisualRenderer::New();
+  renderer->SetGeometry(GetImplementation(geometry));
+  renderer->SetShader(GetImplementation(shader));
+  return VisualRenderer(renderer.Get());
+}
+
+VisualRenderer::VisualRenderer() = default;
+
+VisualRenderer::~VisualRenderer() = default;
+
+VisualRenderer::VisualRenderer(const VisualRenderer& handle) = default;
+
+VisualRenderer VisualRenderer::DownCast(BaseHandle handle)
+{
+  return VisualRenderer(dynamic_cast<Dali::Internal::VisualRenderer*>(handle.GetObjectPtr()));
+}
+
+VisualRenderer& VisualRenderer::operator=(const VisualRenderer& handle) = default;
+
+VisualRenderer::VisualRenderer(VisualRenderer&& rhs) = default;
+
+VisualRenderer& VisualRenderer::operator=(VisualRenderer&& rhs) = default;
+
+VisualRenderer::VisualRenderer(Internal::VisualRenderer* pointer)
+: Dali::Renderer(pointer)
+{
+}
+
+} //namespace Dali
diff --git a/dali/public-api/rendering/visual-renderer.h b/dali/public-api/rendering/visual-renderer.h
new file mode 100644 (file)
index 0000000..844d480
--- /dev/null
@@ -0,0 +1,235 @@
+#ifndef DALI_VISUAL_RENDERER_H
+#define DALI_VISUAL_RENDERER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/rendering/renderer.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_rendering_effects
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class VisualRenderer;
+}
+
+/**
+ * @brief VisualRenderer is a handle to a Renderer with extra properties for Toolkit::Visuals
+ *
+ * @SINCE_2_1.13
+ */
+class DALI_CORE_API VisualRenderer : public Renderer
+{
+public:
+  /**
+   * @brief Policies used by the transform for the offset or size.
+   * @SINCE_2_1.13
+   */
+  struct TransformPolicy
+  {
+    /**
+     * @brief Enumeration for the type of Transform Policy.
+     * @SINCE_2_1.13
+     */
+    enum Type
+    {
+      RELATIVE = 0, ///< Relative to the control (percentage [0.0f to 1.0f] of the control). @SINCE_2_1.13
+      ABSOLUTE = 1  ///< Absolute value in world units. @SINCE_2_1.13
+    };
+  };
+
+  /**
+   * @brief Enumeration for instances of properties belonging to the VisualRenderer class.
+   * @SINCE_2_1.13
+   */
+  struct Property
+  {
+    static constexpr Dali::Property::Index DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX = DEFAULT_RENDERER_PROPERTY_START_INDEX + DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION;
+
+    /**
+     * @brief Enumeration for instances of properties belonging to the VisualRenderer class.
+     * @SINCE_2_1.13
+     */
+    enum
+    {
+      /**
+       * @brief Name "transformOffset", type Property::Vector2, animatable.
+       * @SINCE_2_1.13
+       * @note The default value is (0,0).
+       */
+      TRANSFORM_OFFSET = DEFAULT_VISUAL_RENDERER_PROPERTY_START_INDEX,
+
+      /**
+       * @brief Size of the visual, which can be either relative (percentage [0.0f to 1.0f] of the parent) or absolute (in world units).
+       * @details Name "transformSize", type Property::VECTOR2, animatable.
+       * @SINCE_2_1.13
+       * @see TRANSFORM_SIZE_POLICY
+       */
+      TRANSFORM_SIZE,
+
+      /**
+       * @brief The origin of the visual renderer within its control area.
+       * @details Name "transformOrigin", type Property::VECTOR2
+       * @note This is relative to the size of the actor, where the origin is the center of the actor,
+       * and the range is -0.5 to +0.5 vertically and horizontally
+       * @note Toolkit may impose additional layout directions
+       * @SINCE_2_1.13
+       * @note The default is top left
+       */
+      TRANSFORM_ORIGIN,
+
+      /**
+       * @brief The anchor-point of the visual renderer
+       * @details Name "transformAnchorPoint", type Property::VECTOR2
+       * @note This is relative to the size of the actor; where the origin is the center of the actor,
+       * and the range is -0.5 to +0.5 vertically and horizontally
+       * @note Toolkit may impose additional layout directions
+       * @SINCE_2_1.13
+       * @note The default is top left.
+       */
+      TRANSFORM_ANCHOR_POINT,
+
+      /**
+       * @brief Whether the x or y OFFSET/SIZE values are relative (percentage [0.0f to 1.0f] of the control) or absolute (in world units).
+       * @details Name "transformOffsetSizeMode", type Property::VECTOR4
+       *
+       * @code
+       * visualRenderer.SetProperty( VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE,
+       *                             Vector4( Policy::ABSOLUTE, Policy::RELATIVE, Policy::ABSOLUTE, Policy::RELATIVE ));
+       * @endcode
+       * @see Policy::Type
+       * @SINCE_2_1.13
+       * @note By default, both the x and the y offset/size is RELATIVE.
+       */
+      TRANSFORM_OFFSET_SIZE_MODE,
+
+      /**
+       * @brief Any extra size the shader needs for drawing into.
+       * @details Name "extraSize", type Property::VECTOR2, animatable
+       * @SINCE_2_1.13
+       * @note the default is (0, 0)
+       */
+      EXTRA_SIZE,
+
+      /**
+       * @brief Mix color is a generic color for any visual.
+       * @details Name "visualMixColor", type Property::VECTOR3, animatable
+       * @SINCE_2_1.13
+       */
+      VISUAL_MIX_COLOR,
+
+      /**
+       * @brief PremultipliedAlpha is a float representing a bool, and is either 0.0f, or 1.0f
+       * @details Name "preMultipliedAlpha", type Property::FLOAT
+       * @SINCE_2_1.13
+       */
+      VISUAL_PRE_MULTIPLIED_ALPHA,
+    };
+  };
+
+  /**
+   * @brief Creates a new Renderer object.
+   *
+   * @SINCE_2_1.13
+   * @param[in] geometry Geometry to be used by this renderer
+   * @param[in] shader Shader to be used by this renderer
+   * @return A handle to the Renderer
+   */
+  static VisualRenderer New(Geometry& geometry, Shader& shader);
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   *
+   * @SINCE_2_1.13
+   */
+  VisualRenderer();
+
+  /**
+   * @brief Destructor.
+   *
+   * @SINCE_2_1.13
+   */
+  ~VisualRenderer();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object.
+   *
+   * @SINCE_2_1.13
+   * @param[in] handle Handle to an object
+   */
+  VisualRenderer(const VisualRenderer& handle);
+
+  /**
+   * @brief Downcasts to a visual renderer handle.
+   * If not, a renderer the returned visual renderer handle is left uninitialized.
+   *
+   * @SINCE_2_1.13
+   * @param[in] handle Handle to an object
+   * @return Renderer handle or an uninitialized handle
+   */
+  static VisualRenderer DownCast(BaseHandle handle);
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object.
+   *
+   * @SINCE_2_1.13
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  VisualRenderer& operator=(const VisualRenderer& handle);
+
+  /**
+   * @brief Move constructor.
+   *
+   * @SINCE_2_1.13
+   * @param[in] rhs A reference to the moved handle
+   */
+  VisualRenderer(VisualRenderer&& rhs);
+
+  /**
+   * @brief Move assignment operator.
+   *
+   * @SINCE_2_1.13
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this handle
+   */
+  VisualRenderer& operator=(VisualRenderer&& rhs);
+
+public:
+  /// @cond internal
+  /**
+   * @brief The constructor.
+   * @note  Not intended for application developers.
+   * @SINCE_2_1.13
+   * @param[in] pointer A pointer to a newly allocated VisualRenderer
+   */
+  explicit DALI_INTERNAL VisualRenderer(Internal::VisualRenderer* pointer);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+} //namespace Dali
+
+#endif // DALI_VISUAL_RENDERER_H
index 2c02b0c..c783270 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2
 Summary:    DALi 3D Engine
-Version:    2.1.12
+Version:    2.1.13
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT