- 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>
return GetImpl().mDepth;
}
+void TestCustomActor::SetTransparent(bool transparent)
+{
+ return GetImpl().SetTransparent(transparent);
+}
+
+bool TestCustomActor::IsTransparent()
+{
+ return GetImpl().IsTransparent();
+}
+
TestCustomActor::TestCustomActor()
{
}
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);
#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.
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);
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);
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;
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;
/*
- * 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.
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;
return GetImplementation(actor).SetNeedGesturePropagation(propagation);
}
+void SwitchParent(Actor actor, Actor newParent)
+{
+ return GetImplementation(actor).SwitchParent(GetImplementation(newParent));
+}
+
} // namespace DevelActor
} // namespace Dali
*/
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
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
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
}
}
-void Actor::SetParent(ActorParent* parent)
+void Actor::SetParent(ActorParent* parent, bool keepOnScene)
{
if(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());
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());
/**
* @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
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);
*/
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.
/**
* 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()
/*
- * 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.
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");
// 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())
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());
}
}
-void ActorParentImpl::Remove(Actor& child)
+void ActorParentImpl::Remove(Actor& child, bool notify)
{
if((&mOwner == &child) || (!mChildren))
{
mChildren->erase(iter);
DALI_ASSERT_DEBUG(actor->GetParent() == &mOwner);
- actor->SetParent(nullptr);
+ actor->SetParent(nullptr, (notify) ? false : true);
break;
}
}
}
- // 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
* @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.
* @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.
mClippingMode(ClippingMode::DISABLED),
mIsRoot(false),
mIsLayer(false),
- mPositionUsesAnchorPoint(true)
+ mPositionUsesAnchorPoint(true),
+ mTransparent(false)
{
mUniformMapChanged[0] = 0u;
mUniformMapChanged[1] = 0u;
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
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;
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*>;
const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
auto size = rendererUniformMap.Count();
-
if(mShader)
{
size += mShader->GetUniformMap().Count();
{
Renderer::OpacityType opacityType = Renderer::OPAQUE;
+ if(node.IsTransparent())
+ {
+ return Renderer::TRANSPARENT;
+ }
+
switch(mBlendMode)
{
case BlendMode::ON: // If the renderer should always be use blending
/*
- * 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.
return mOwner->RelayoutDependentOnChildrenBase(dimension);
}
+void CustomActorImpl::SetTransparent(bool transparent)
+{
+ mOwner->SetTransparent(transparent);
+}
+
+bool CustomActorImpl::IsTransparent() const
+{
+ return mOwner->IsTransparent();
+}
+
} // namespace Dali
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