Add SwitchParent api in actor-devel 49/250549/65
authorSeungho Baek <sbsh.baek@samsung.com>
Tue, 29 Dec 2020 10:16:31 +0000 (19:16 +0900)
committerSeungho Baek <sbsh.baek@samsung.com>
Thu, 3 Jun 2021 08:45:36 +0000 (17:45 +0900)
 - SwitchParent changes parent of an actor without add/remove notification.
 - SwitchParent make an actor keep on Scene during changing parent.
 - To use SwitchParent, both the actor and new parent must be on scene

Change-Id: Ieb2114227b69cfd1fcbbe97930f21bf902e3b2d8
Signed-off-by: Seungho Baek <sbsh.baek@samsung.com>
16 files changed:
automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.cpp
automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.h
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-CustomActor.cpp
dali/devel-api/actors/actor-devel.cpp
dali/devel-api/actors/actor-devel.h
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/actor-parent-impl.cpp
dali/internal/event/actors/actor-parent-impl.h
dali/internal/event/actors/actor-parent.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/public-api/actors/custom-actor-impl.cpp
dali/public-api/actors/custom-actor-impl.h

index e4f1099..db6cfca 100644 (file)
@@ -204,6 +204,16 @@ uint32_t TestCustomActor::GetDepth()
   return GetImpl().mDepth;
 }
 
+void TestCustomActor::SetTransparent(bool transparent)
+{
+  return GetImpl().SetTransparent(transparent);
+}
+
+bool TestCustomActor::IsTransparent()
+{
+  return GetImpl().IsTransparent();
+}
+
 TestCustomActor::TestCustomActor()
 {
 }
@@ -386,6 +396,16 @@ bool TestCustomActor::RelayoutDependentOnChildren(Dimension::Type dimension)
   return false;
 }
 
+void TestCustomActor::SetTransparent(bool transparent)
+{
+  CustomActorImpl::SetTransparent(transparent);
+}
+
+bool TestCustomActor::IsTransparent() const
+{
+  return CustomActorImpl::IsTransparent();
+}
+
 void TestCustomActor::SetDaliProperty(std::string s)
 {
   Self().SetProperty(mDaliProperty, s);
index ed11c58..2a4d483 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_CUSTOM_ACTOR_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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,8 @@ public:
   float                     TestCalculateChildSizeBase(const Dali::Actor& child, Dali::Dimension::Type dimension);
   bool                      TestRelayoutDependentOnChildrenBase(Dali::Dimension::Type dimension);
   uint32_t                  GetDepth();
+  void                      SetTransparent(bool transparent);
+  bool                      IsTransparent();
 
 private:
   TestCustomActor(Impl::TestCustomActor& impl);
@@ -146,6 +148,8 @@ public:
   float                        CalculateChildSize(const Dali::Actor& child, Dali::Dimension::Type dimension) override;
   void                         OnLayoutNegotiated(float size, Dali::Dimension::Type dimension) override;
   bool                         RelayoutDependentOnChildren(Dali::Dimension::Type dimension = Dali::Dimension::ALL_DIMENSIONS) override;
+  void                         SetTransparent(bool transparent);
+  bool                         IsTransparent() const;
   static void                  SetProperty(Dali::BaseObject* object, Dali::Property::Index index, const Dali::Property::Value& value);
   static Dali::Property::Value GetProperty(Dali::BaseObject* object, Dali::Property::Index index);
 
index 12dc2b7..53d13ab 100644 (file)
@@ -637,6 +637,32 @@ int UtcDaliActorRemoveP(void)
   END_TEST;
 }
 
+int UtcDaliActorSwitchParentN(void)
+{
+  tet_infoline("Testing Actor::UtcDaliActorSwitchParentN");
+  TestApplication application;
+
+  Actor parent1 = Actor::New();
+  Actor child   = Actor::New();
+
+  DALI_TEST_EQUALS(parent1.GetChildCount(), 0u, TEST_LOCATION);
+
+  parent1.Add(child);
+
+  DALI_TEST_EQUALS(parent1.GetChildCount(), 1u, TEST_LOCATION);
+
+  Actor parent2 = Actor::New();
+
+  DALI_TEST_EQUALS(parent2.GetChildCount(), 0u, TEST_LOCATION);
+
+  // Try switch parent with that both of parent1 and parent2 are off scene.
+  DevelActor::SwitchParent(child, parent2);
+
+  DALI_TEST_EQUALS(parent1.GetChildCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(parent2.GetChildCount(), 0u, TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliActorGetChildCount(void)
 {
   TestApplication application;
@@ -7637,6 +7663,61 @@ int UtcDaliChildMovedSignalP(void)
   END_TEST;
 }
 
+int UtcDaliActorSwitchParentP(void)
+{
+  tet_infoline("Testing Actor::UtcDaliActorSwitchParentP");
+  TestApplication application;
+
+  Actor parent1 = Actor::New();
+  Actor child   = Actor::New();
+
+  application.GetScene().Add(parent1);
+
+  DALI_TEST_EQUALS(parent1.GetChildCount(), 0u, TEST_LOCATION);
+
+  child.OnSceneSignal().Connect(OnSceneCallback);
+  child.OffSceneSignal().Connect(OffSceneCallback);
+
+  // sanity check
+  DALI_TEST_CHECK(gOnSceneCallBackCalled == 0);
+  DALI_TEST_CHECK(gOffSceneCallBackCalled == 0);
+
+  parent1.Add(child);
+
+  DALI_TEST_EQUALS(parent1.GetChildCount(), 1u, TEST_LOCATION);
+
+  DALI_TEST_CHECK(gOnSceneCallBackCalled == 1);
+  DALI_TEST_CHECK(gOffSceneCallBackCalled == 0);
+
+  Actor parent2 = Actor::New();
+  application.GetScene().Add(parent2);
+
+  bool  addSignalReceived = false;
+  ChildAddedSignalCheck addedSignal(addSignalReceived, child);
+  DevelActor::ChildAddedSignal(application.GetScene().GetRootLayer()).Connect(&application, addedSignal);
+  DALI_TEST_EQUALS(addSignalReceived, false, TEST_LOCATION);
+
+  bool  removedSignalReceived = false;
+  ChildRemovedSignalCheck removedSignal(removedSignalReceived, child);
+  DevelActor::ChildRemovedSignal(application.GetScene().GetRootLayer()).Connect(&application, removedSignal);
+  DALI_TEST_EQUALS(removedSignalReceived, false, TEST_LOCATION);
+
+  DevelActor::SwitchParent(child, parent2);
+
+  DALI_TEST_EQUALS(addSignalReceived, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(removedSignalReceived, false, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(parent1.GetChildCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(parent2.GetChildCount(), 1u, TEST_LOCATION);
+
+  DALI_TEST_CHECK(gOnSceneCallBackCalled == 1);
+  DALI_TEST_CHECK(gOffSceneCallBackCalled == 0);
+  DALI_TEST_CHECK(child.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE));
+  DALI_TEST_CHECK(child.GetParent() == parent2);
+
+  END_TEST;
+}
+
 int utcDaliActorCulled(void)
 {
   TestApplication application;
index 208f563..38d718e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -1081,6 +1081,29 @@ int UtcDaliCustomActorCustomActor(void)
   END_TEST;
 }
 
+int UtcDaliCustomActorImplSetTransparent(void)
+{
+  TestApplication application; // Need the type registry
+
+  Test::TestCustomActor actor = Test::TestCustomActor::New();
+  application.GetScene().Add(actor);
+  actor.SetProperty(Actor::Property::OPACITY, 0.1f);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400, 400));
+
+  DALI_TEST_EQUALS(false, actor.IsTransparent(), TEST_LOCATION);
+
+  actor.SetTransparent(true);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(true, actor.IsTransparent(), TEST_LOCATION);
+
+  application.GetScene().Remove(actor);
+  END_TEST;
+}
+
 int UtcDaliCustomActorImplRelayoutRequest(void)
 {
   TestApplication application;
index 9923967..ab0fe4d 100755 (executable)
@@ -58,6 +58,11 @@ void SetNeedGesturePropagation(Actor actor, bool propagation)
   return GetImplementation(actor).SetNeedGesturePropagation(propagation);
 }
 
+void SwitchParent(Actor actor, Actor newParent)
+{
+  return GetImplementation(actor).SwitchParent(GetImplementation(newParent));
+}
+
 } // namespace DevelActor
 
 } // namespace Dali
index f46478e..19b3bd3 100644 (file)
@@ -320,6 +320,16 @@ DALI_CORE_API Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor);
  */
 DALI_CORE_API void SetNeedGesturePropagation(Actor actor, bool propagation);
 
+/**
+ * Switch parent in the same tree.
+ * This method changes the actor's parent with keeping on scene state.
+ * Both of current parent Actor and new parent Actor must already be added on Scene.
+ * This method don't emit notification about add/remove and on/off scene.
+ * @param [in] actor This actor
+ * @param [in] newParent An actor to be a new parent of this actor.
+ */
+DALI_CORE_API void SwitchParent(Actor actor, Actor newParent);
+
 } // namespace DevelActor
 
 } // namespace Dali
index c06b2a4..ed2ea15 100644 (file)
@@ -1118,6 +1118,16 @@ DevelBlendEquation::Type Actor::GetBlendEquation() const
   return mBlendEquation;
 }
 
+void Actor::SetTransparent(bool transparent)
+{
+  SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent);
+}
+
+bool Actor::IsTransparent() const
+{
+  return GetNode().IsTransparent();
+}
+
 void Actor::SetDrawMode(DrawMode::Type drawMode)
 {
   // this flag is not animatable so keep the value
@@ -1388,14 +1398,31 @@ Actor::~Actor()
   delete mRelayoutData;
 }
 
-void Actor::Add(Actor& child)
+void Actor::Add(Actor& child, bool notify)
 {
-  mParentImpl.Add(child);
+  mParentImpl.Add(child, notify);
 }
 
-void Actor::Remove(Actor& child)
+void Actor::Remove(Actor& child, bool notify)
 {
-  mParentImpl.Remove(child);
+  mParentImpl.Remove(child, notify);
+}
+
+void Actor::SwitchParent(Actor& newParent)
+{
+  if(this == &newParent)
+  {
+    DALI_LOG_ERROR("Cannot add actor to itself");
+    return;
+  }
+
+  if(!this->OnScene() || !newParent.OnScene())
+  {
+    DALI_LOG_ERROR("Both of current parent and new parent must be on Scene");
+    return;
+  }
+
+  newParent.Add(*this, false);
 }
 
 uint32_t Actor::GetChildCount() const
@@ -1807,7 +1834,7 @@ void Actor::LowerBelow(Internal::Actor& target)
   }
 }
 
-void Actor::SetParent(ActorParent* parent)
+void Actor::SetParent(ActorParent* parent, bool keepOnScene)
 {
   if(parent)
   {
@@ -1818,7 +1845,7 @@ void Actor::SetParent(ActorParent* parent)
     mScene             = parentActor->mScene;
 
     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
-       parentActor->OnScene())
+       parentActor->OnScene() && !keepOnScene)
     {
       // Instruct each actor to create a corresponding node in the scene graph
       ConnectToScene(parentActor->GetHierarchyDepth());
@@ -1834,7 +1861,7 @@ void Actor::SetParent(ActorParent* parent)
     mParent = nullptr;
 
     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
-       OnScene())
+       OnScene() && !keepOnScene)
     {
       // Disconnect the Node & its children from the scene-graph.
       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
index 2857f87..da8a0c1 100644 (file)
@@ -192,12 +192,17 @@ public:
   /**
    * @copydoc Dali::Internal::ActorParent::Add()
    */
-  void Add(Actor& child) override;
+  void Add(Actor& child, bool notify = true) override;
 
   /**
    * @copydoc Dali::Internal::ActorParent::Remove()
    */
-  void Remove(Actor& child) override;
+  void Remove(Actor& child, bool notify = true) override;
+
+  /**
+   * @copydoc Dali::DevelActor::SwitchParent()
+   */
+  void SwitchParent(Actor& newParent);
 
   /**
    * @copydoc Dali::Actor::Unparent
@@ -1225,7 +1230,7 @@ public:
   void RemoveRenderer(uint32_t index);
 
   /**
-   * Set BlendEquation at each renderer that added on this Actor.
+   * @brief Set BlendEquation at each renderer that added on this Actor.
    */
   void SetBlendEquation(DevelBlendEquation::Type blendEquation);
 
@@ -1234,6 +1239,16 @@ public:
    */
   DevelBlendEquation::Type GetBlendEquation() const;
 
+  /**
+   * @brief Set this Actor is transparent or not without any affection on the child Actors.
+   */
+  void SetTransparent(bool transparent);
+
+  /**
+   * @brief Get this Actor is transparent or not.
+   */
+  bool IsTransparent() const;
+
 public:
   /**
    * Converts screen coordinates into the actor's coordinate system.
@@ -1812,8 +1827,9 @@ private:
   /**
    * Set the actor's parent.
    * @param[in] parent The new parent.
+   * @param[in] keepOnScene Keep this actor to be on Scene if this is true.
    */
-  void SetParent(ActorParent* parent);
+  void SetParent(ActorParent* parent, bool keepOnScene = false);
 
   /**
    * For use in derived classes, called after Initialize()
index c0101cc..6d153a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -57,7 +57,7 @@ ActorParentImpl::~ActorParentImpl()
   delete mChildren;
 }
 
-void ActorParentImpl::Add(Actor& child)
+void ActorParentImpl::Add(Actor& child, bool notify)
 {
   DALI_ASSERT_ALWAYS(&mOwner != &child && "Cannot add actor to itself");
   DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
@@ -75,7 +75,7 @@ void ActorParentImpl::Add(Actor& child)
     // if we already have parent, unparent us first
     if(oldParent)
     {
-      oldParent->Remove(child); // This causes OnChildRemove callback & ChildRemoved signal
+      oldParent->Remove(child, notify); // This causes OnChildRemove callback & ChildRemoved signal
 
       // Old parent may need to readjust to missing child
       if(oldParent->RelayoutDependentOnChildren())
@@ -91,11 +91,14 @@ void ActorParentImpl::Add(Actor& child)
       mChildren->push_back(ActorPtr(&child));
 
       // SetParent asserts that child can be added
-      child.SetParent(&mOwner);
+      child.SetParent(&mOwner, !notify);
 
-      // Notification for derived classes
-      mOwner.OnChildAdd(child);
-      EmitChildAddedSignal(child);
+      if(notify)
+      {
+        // Notification for derived classes
+        mOwner.OnChildAdd(child);
+        EmitChildAddedSignal(child);
+      }
 
       child.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
 
@@ -108,7 +111,7 @@ void ActorParentImpl::Add(Actor& child)
   }
 }
 
-void ActorParentImpl::Remove(Actor& child)
+void ActorParentImpl::Remove(Actor& child, bool notify)
 {
   if((&mOwner == &child) || (!mChildren))
   {
@@ -133,7 +136,7 @@ void ActorParentImpl::Remove(Actor& child)
       mChildren->erase(iter);
 
       DALI_ASSERT_DEBUG(actor->GetParent() == &mOwner);
-      actor->SetParent(nullptr);
+      actor->SetParent(nullptr, (notify) ? false : true);
 
       break;
     }
@@ -148,9 +151,12 @@ void ActorParentImpl::Remove(Actor& child)
     }
   }
 
-  // Notification for derived classes
-  mOwner.OnChildRemove(child);
-  EmitChildRemovedSignal(child);
+  if(notify)
+  {
+    // Notification for derived classes
+    mOwner.OnChildRemove(child);
+    EmitChildRemovedSignal(child);
+  }
 }
 
 uint32_t ActorParentImpl::GetChildCount() const
index 0f05f80..98bedb9 100644 (file)
@@ -50,16 +50,19 @@ public:
    * @pre The child actor is not the same as the parent actor.
    * @pre The child actor does not already have a parent.
    * @param [in] child The child.
+   * @param [in] notify Emits notification if set to true. Default is true.
    * @post The child will be referenced by its parent.
    */
-  void Add(Actor& child);
+  void Add(Actor& child, bool notify = true);
 
   /**
    * Removes a child Actor from this ActorParent.
    * @param [in] child The child.
+   * @param [in] notify Emits notification if set to true. Default is true.
    * @post The child will be unreferenced.
+   * @note If notify is false, Add() method must be called after this method.
    */
-  void Remove(Actor& child);
+  void Remove(Actor& child, bool notify = true);
 
   /**
    * Retrieve the number of children held by the actor.
index 9056359..62fdfbd 100644 (file)
@@ -47,16 +47,19 @@ public:
    * @pre The child actor is not the same as the parent actor.
    * @pre The child actor does not already have a parent.
    * @param [in] child The child.
+   * @param [in] notify Emits notification if set to true. Default is true.
    * @post The child will be referenced by its parent.
    */
-  virtual void Add(Actor& child) = 0;
+  virtual void Add(Actor& child, bool notify = true) = 0;
 
   /**
    * Removes a child Actor from this Actor.
    * @param [in] child The child.
+   * @param [in] notify Emits notification if set to true. Default is true.
    * @post The child will be unreferenced.
+   * @note If notify is false, Add() method must be called after this method.
    */
-  virtual void Remove(Actor& child) = 0;
+  virtual void Remove(Actor& child, bool notify = true) = 0;
 
   /**
    * Retrieve the number of children held by the actor.
index 662f3e7..ab3e9a2 100644 (file)
@@ -101,7 +101,8 @@ Node::Node()
   mClippingMode(ClippingMode::DISABLED),
   mIsRoot(false),
   mIsLayer(false),
-  mPositionUsesAnchorPoint(true)
+  mPositionUsesAnchorPoint(true),
+  mTransparent(false)
 {
   mUniformMapChanged[0] = 0u;
   mUniformMapChanged[1] = 0u;
index 6f6e681..b0a5818 100644 (file)
@@ -725,6 +725,16 @@ public:
     return mDrawMode;
   }
 
+  void SetTransparent(bool transparent)
+  {
+    mTransparent = transparent;
+  }
+
+  bool IsTransparent() const
+  {
+    return mTransparent;
+  }
+
   /*
    * Returns the transform id of the node
    * @return The transform component id of the node
@@ -954,6 +964,7 @@ protected:
   bool               mIsRoot : 1;                  ///< True if the node cannot have a parent
   bool               mIsLayer : 1;                 ///< True if the node is a layer
   bool               mPositionUsesAnchorPoint : 1; ///< True if the node should use the anchor-point when calculating the position
+  bool               mTransparent : 1;             ///< True if this node is transparent. This value do not affect children.
 
   // Changes scope, should be at end of class
   DALI_LOG_OBJECT_STRING_DECLARATION;
@@ -1038,6 +1049,17 @@ inline void SetDrawModeMessage(EventThreadServices& eventThreadServices, const N
   new(slot) LocalType(&node, &Node::SetDrawMode, drawMode);
 }
 
+inline void SetTransparentMessage(EventThreadServices& eventThreadServices, const Node& node, bool transparent)
+{
+  using LocalType = MessageValue1<Node, bool>;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new(slot) LocalType(&node, &Node::SetTransparent, transparent);
+}
+
 inline void DetachRendererMessage(EventThreadServices& eventThreadServices, const Node& node, const Renderer& renderer)
 {
   using LocalType = MessageValue1<Node, const Renderer*>;
index d09f835..dd765b8 100644 (file)
@@ -191,7 +191,6 @@ bool Renderer::PrepareRender(BufferIndex updateBufferIndex)
       const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
 
       auto size = rendererUniformMap.Count();
-
       if(mShader)
       {
         size += mShader->GetUniformMap().Count();
@@ -696,6 +695,11 @@ Renderer::OpacityType Renderer::GetOpacityType(BufferIndex updateBufferIndex, co
 {
   Renderer::OpacityType opacityType = Renderer::OPAQUE;
 
+  if(node.IsTransparent())
+  {
+    return Renderer::TRANSPARENT;
+  }
+
   switch(mBlendMode)
   {
     case BlendMode::ON: // If the renderer should always be use blending
index 1ff533b..ad000b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -83,4 +83,14 @@ bool CustomActorImpl::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
   return mOwner->RelayoutDependentOnChildrenBase(dimension);
 }
 
+void CustomActorImpl::SetTransparent(bool transparent)
+{
+  mOwner->SetTransparent(transparent);
+}
+
+bool CustomActorImpl::IsTransparent() const
+{
+  return mOwner->IsTransparent();
+}
+
 } // namespace Dali
index 1400f45..cc1a53e 100644 (file)
@@ -268,6 +268,16 @@ public:
   virtual void OnLayoutNegotiated(float size, Dimension::Type dimension) = 0;
 
   /**
+   * @brief Set this CustomActor is transparent or not without any affection on the child Actors.
+   */
+  void SetTransparent(bool transparent);
+
+  /**
+   * @brief Get this CustomActor is transparent or not.
+   */
+  bool IsTransparent() const;
+
+  /**
    * @brief Retrieves the extension for this control.
    *
    * @SINCE_1_0.0