END_TEST;
}
+
+int UtcDaliActorIgnored(void)
+{
+ TestApplication application;
+
+ Actor parent = Actor::New();
+ parent.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ application.GetScene().Add(parent);
+
+ Actor child1 = Actor::New();
+ child1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ child1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ parent.Add(child1);
+
+ Actor child2 = Actor::New();
+ child2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ child2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ parent.Add(child2);
+
+ DALI_TEST_EQUALS(child1.IsIgnored(), false, TEST_LOCATION);
+ DALI_TEST_EQUALS(child2.IsIgnored(), false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(0);
+
+ Vector3 childPosition1 = child1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ Vector3 childPosition2 = child2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ DALI_TEST_EQUALS(childPosition1, childPosition2, TEST_LOCATION);
+
+ parent.SetProperty(Actor::Property::POSITION, Vector2(100, 100));
+
+ application.SendNotification();
+ application.Render(0);
+
+ childPosition1 = child1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ childPosition2 = child2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ DALI_TEST_EQUALS(childPosition1, childPosition2, TEST_LOCATION);
+ DALI_TEST_EQUALS(childPosition1, Vector3(100, 100, 0), TEST_LOCATION);
+
+ child2.SetIgnored(true);
+ parent.SetProperty(Actor::Property::POSITION, Vector2(200, 200));
+
+ application.SendNotification();
+ application.Render(0);
+
+ childPosition1 = child1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ childPosition2 = child2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ DALI_TEST_NOT_EQUALS(childPosition1, childPosition2, 0.00001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(childPosition1, Vector3(200, 200, 0), TEST_LOCATION);
+
+ child2.SetIgnored(false);
+
+ application.SendNotification();
+ application.Render(0);
+
+ childPosition1 = child1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ childPosition2 = child2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ DALI_TEST_EQUALS(childPosition1, childPosition2, TEST_LOCATION);
+ DALI_TEST_EQUALS(childPosition1, Vector3(200, 200, 0), TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
* @brief Get the stack of visibility changed actors.
* @return The global visibility changed actors stack.
*/
-ActorContainer& GetVisibilityChagnedActorStack()
+ActorContainer& GetVisibilityChangedActorStack()
{
static ActorContainer gVisibilityChangedActorStack; ///< Stack of visibility changed actors. Latest actor is the latest visibility changed actor.
return gVisibilityChangedActorStack;
ActorPtr Actor::GetVisiblityChangedActor()
{
- if(!GetVisibilityChagnedActorStack().empty())
+ if(!GetVisibilityChangedActorStack().empty())
{
- return GetVisibilityChagnedActorStack().back();
+ return GetVisibilityChangedActorStack().back();
}
return ActorPtr();
}
mIsRoot(ROOT_LAYER == derivedType),
mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
mIsOnScene(false),
+ mIsIgnored(false),
mSensitive(true),
mLeaveRequired(false),
mKeyboardFocusable(false),
// Push the actor at the stack.
// Note that another actor's visibility could be changed during visibility change callback.
// So we need to stack those actors, and then use it.
- GetVisibilityChagnedActorStack().emplace_back(this);
+ GetVisibilityChangedActorStack().emplace_back(this);
EmitInheritedVisibilityChangedSignalRecursively(visiblility);
// Pop the actor from the stack now
- GetVisibilityChagnedActorStack().pop_back();
+ GetVisibilityChangedActorStack().pop_back();
}
}
// Push the actor at the stack.
// Note that another actor's visibility could be changed during visibility change callback.
// So we need to stack those actors, and then use it.
- GetVisibilityChagnedActorStack().emplace_back(this);
+ GetVisibilityChangedActorStack().emplace_back(this);
// Emit the signal on this actor and all its children
mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
}
// Pop the actor from the stack now
- GetVisibilityChagnedActorStack().pop_back();
+ GetVisibilityChangedActorStack().pop_back();
}
}
SetUpdateAreaHintMessage(GetEventThreadServices(), GetNode(), updateAreaHint);
}
+void Actor::SetIgnored(bool ignored)
+{
+ if(ignored != mIsIgnored)
+ {
+ mIsIgnored = ignored;
+ SetIgnoredMessage(GetEventThreadServices(), GetNode(), mIsIgnored);
+ }
+}
+
+bool Actor::IsIgnored() const
+{
+ return mIsIgnored;
+}
+
} // namespace Internal
} // namespace Dali
*/
float GetMaximumSize(Dimension::Type dimension) const;
+ /**
+ * @copydoc Dali::Actor::SetIgnored
+ */
+ void SetIgnored(bool ignored);
+
+ /**
+ * @copydoc Dali::Actor::IsIgnored
+ */
+ bool IsIgnored() const;
+
/**
* @copydoc Dali::Actor::AddRenderer()
*/
*/
bool IsHittable() const
{
- return (IsUserInteractionEnabled()) && IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected();
+ return (IsUserInteractionEnabled()) && (!IsIgnored()) && IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected();
}
/**
const bool mIsRoot : 1; ///< Flag to identify the root actor
const bool mIsLayer : 1; ///< Flag to identify that this is a layer
bool mIsOnScene : 1; ///< Flag to identify whether the actor is on-scene
+ bool mIsIgnored : 1; ///< Flag to identify whether the actor is ignored or not.
bool mSensitive : 1; ///< Whether the actor emits touch event signals
bool mLeaveRequired : 1; ///< Whether a touch event signal is emitted when the a touch leaves the actor's bounds
bool mKeyboardFocusable : 1; ///< Whether the actor should be focusable by keyboard navigation
bool DescendActorHierarchy(Actor* actor) override
{
- return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+ return (!actor->IsIgnored()) &&
+ actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
}
bool DescendActorHierarchy(Actor* actor) override
{
- return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+ return (!actor->IsIgnored()) &&
+ actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
}
bool DescendActorHierarchy(Actor* actor) override
{
- return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+ return (!actor->IsIgnored()) &&
+ actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
}
* @param renderList to add the item to
* @param renderable Node-Renderer pair
* @param viewMatrix used to calculate modelview matrix for the item
- * @param viewMatrixChanged Whether view matrix chagned for this time or not.
+ * @param viewMatrixChanged Whether view matrix changed for this time or not.
* @param camera The camera used to render
* @param isLayer3d Whether we are processing a 3D layer or not
* @param viewportSet Whether the viewport is set or not
* @param renderList to add the items to
* @param renderers to render NodeRendererContainer Node-Renderer pairs
* @param viewMatrix used to calculate modelview matrix for the items
- * @param viewMatrixChanged Whether view matrix chagned for this time or not.
+ * @param viewMatrixChanged Whether view matrix changed for this time or not.
* @param camera The camera used to render
* @param isLayer3d Whether we are processing a 3D layer or not
* @param viewportSet Whether the viewport is set or not
bool& keepRendering)
{
// Short-circuit for invisible nodes
- if(!node.IsVisible(updateBufferIndex))
+ if(!(node.IsVisible(updateBufferIndex) && !node.IsIgnored()))
{
node.GetPartialRenderingData().mVisible = false;
return;
mSizeBase.PushBack(Vector3(0.0f, 0.0f, 0.0f));
mComponentDirty.PushBack(CLEAN_FLAG);
mWorldMatrixDirty.PushBack(false);
+ mIgnored.PushBack(false);
}
else
{
mSizeBase[mComponentCount] = Vector3(0.0f, 0.0f, 0.0f);
mComponentDirty[mComponentCount] = CLEAN_FLAG;
mWorldMatrixDirty[mComponentCount] = false;
+ mIgnored[mComponentCount] = false;
}
mComponentCount++;
mSizeBase[index] = mSizeBase[mComponentCount];
mComponentDirty[index] = mComponentDirty[mComponentCount];
mWorldMatrixDirty[index] = mWorldMatrixDirty[mComponentCount];
+ mIgnored[index] = mIgnored[mComponentCount];
mBoundingSpheres[index] = mBoundingSpheres[mComponentCount];
TransformId lastItemId = mComponentId[mComponentCount];
}
}
+int cnt = 0;
+
bool TransformManager::Update()
{
mUpdated = false;
mReorder = false;
}
+ cnt = 0;
+
// Iterate through all components to compute its world matrix
Vector3 centerPosition;
Vector3 localPosition;
if(DALI_LIKELY(mInheritanceMode[i] != DONT_INHERIT_TRANSFORM && mParent[i] != INVALID_TRANSFORM_ID))
{
const TransformId& parentIndex = mIds[mParent[i]];
+ mIgnored[i] = mIgnored[parentIndex] || mTxComponentStatic[i].mIgnored;
+ if(mIgnored[i])
+ {
+ mComponentDirty[i] >>= 1u; ///< age down.
+ continue;
+ }
+
if(DALI_LIKELY(mInheritanceMode[i] == INHERIT_ALL))
{
if(mComponentDirty[i] || mWorldMatrixDirty[parentIndex])
}
else // Component has no parent or doesn't inherit transform
{
+ mIgnored[i] = mTxComponentStatic[i].mIgnored;
+ if(mIgnored[i])
+ {
+ mComponentDirty[i] >>= 1u; ///< age down.
+ continue;
+ }
+
if(mComponentDirty[i])
{
// TODO : We need to check mComponentDirty since we have to check the size changeness.
std::swap(mComponentDirty[i], mComponentDirty[j]);
std::swap(mBoundingSpheres[i], mBoundingSpheres[j]);
std::swap(mWorld[i], mWorld[j]);
+ std::swap(mIgnored[i], mIgnored[j]);
mIds[mComponentId[i]] = i;
mIds[mComponentId[j]] = j;
mComponentDirty.Resize(mComponentCount);
mWorldMatrixDirty.Resize(mComponentCount);
mOrderedComponents.Resize(mComponentCount);
+ mIgnored.Resize(mComponentCount);
mTxComponentAnimatable.ShrinkToFit();
mTxComponentStatic.ShrinkToFit();
mComponentDirty.ShrinkToFit();
mWorldMatrixDirty.ShrinkToFit();
mOrderedComponents.ShrinkToFit();
+ mIgnored.ShrinkToFit();
}
#endif
}
SetTransfromPropertyIfChanged(mTxComponentStatic[index].mPositionUsesAnchorPoint, mComponentDirty[index], mDirtyFlags, value, STATIC_COMPONENT_FLAG);
}
+void TransformManager::SetIgnored(TransformId id, bool value)
+{
+ TransformId index(mIds[id]);
+
+ SetTransfromPropertyIfChanged(mTxComponentStatic[index].mIgnored, mComponentDirty[index], mDirtyFlags, value, STATIC_COMPONENT_FLAG);
+}
+
} // namespace SceneGraph
} // namespace Internal
} // namespace Dali
TransformComponentStatic()
: mAnchorPoint(AnchorPoint::DEFAULT),
mParentOrigin(ParentOrigin::DEFAULT),
- mPositionUsesAnchorPoint(true)
+ mPositionUsesAnchorPoint(true),
+ mIgnored(false)
{
}
Vector3 mAnchorPoint;
Vector3 mParentOrigin;
bool mPositionUsesAnchorPoint;
+ bool mIgnored;
};
enum InheritanceMode
{
TRANSFORM_PROPERTY_POSITION = 0,
TRANSFORM_PROPERTY_SCALE,
+ TRANSFORM_PROPERTY_IGNORED,
TRANSFORM_PROPERTY_ANCHOR_POINT,
TRANSFORM_PROPERTY_PARENT_ORIGIN,
TRANSFORM_PROPERTY_SIZE,
*/
void SetPositionUsesAnchorPoint(TransformId id, bool value);
+ /**
+ * @brief Sets ignored value.
+ * @param[in] id Id of the transform component.
+ * @param[in] value True if the component is ignored.
+ */
+ void SetIgnored(TransformId id, bool value);
+
private:
//Helper struct to order components
struct SOrderItem
///< Or If we change static component changed, flag become non-zero. Age down at Update time.
///< Note that we don't replace dirty flag as BAKE even if we call Bake operation.
///< (Since single dirty flag controls multiple animatable properties ; Position, Size, Scale, Orientation.)
+ Vector<bool> mIgnored; ///< True if the component is ignored.
Vector<bool> mWorldMatrixDirty; ///< 1u if the world matrix has been updated in this frame, 0 otherwise
Vector<SOrderItem> mOrderedComponents; ///< Used to reorder components when hierarchy changes
PropertyOwnerContainer& postPropertyOwners,
bool updated)
{
+ if(DALI_UNLIKELY(node.IsIgnored())) // almost never ever true
+ {
+ return NodePropertyFlags::NOTHING;
+ }
+
// Apply constraints to the node
ConstrainPropertyOwner(node, updateBufferIndex);
if(!node.GetPostConstraints().Empty())
DALI_ASSERT_DEBUG(rootNode.IsRoot());
// Short-circuit for invisible nodes
- if(DALI_UNLIKELY(!rootNode.IsVisible(updateBufferIndex))) // almost never ever true
+ if(DALI_UNLIKELY(!(rootNode.IsVisible(updateBufferIndex) && !rootNode.IsIgnored()))) // almost never ever true
{
return NodePropertyFlags::NOTHING;
}
// If the root node was not previously visible
BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
- if(DALI_UNLIKELY(!rootNode.IsVisible(previousBuffer))) // almost never ever true
+ if(DALI_UNLIKELY(!(rootNode.IsVisible(previousBuffer) && !rootNode.IsIgnored()))) // almost never ever true
{
// The node was skipped in the previous update; it must recalculate everything
rootNode.SetAllDirtyFlags();
mTransparent(false),
mUpdateAreaChanged(false),
mUpdateAreaUseSize(true),
- mUseTextureUpdateArea(false)
+ mUseTextureUpdateArea(false),
+ mIgnored(false)
{
#ifdef DEBUG_ENABLED
gNodeCount++;
// Set whether the position should use the anchor point
transformManager->SetPositionUsesAnchorPoint(createdTransformId, mPositionUsesAnchorPoint);
+ transformManager->SetIgnored(createdTransformId, mIgnored);
// Set TransformId after initialize done.
mTransformManagerData.mId = createdTransformId;
mAnchorPoint.Set(0, anchor);
}
+ /**
+ * Sets flag to identify whether the node is ignored or not.
+ * @param[in] ignored True to make the node be ignored.
+ */
+ void SetIgnored(const bool ignored)
+ {
+ if(mTransformManagerData.Id() != INVALID_TRANSFORM_ID && mIgnored != ignored)
+ {
+ mIgnored = ignored;
+ mTransformManagerData.Manager()->SetIgnored(mTransformManagerData.Id(), mIgnored);
+ }
+ }
+
+ /**
+ * Retrieve Whether the node is ignored or not.
+ * @return True if the node is ignored.
+ */
+ bool IsIgnored() const
+ {
+ if(mTransformManagerData.Id() != INVALID_TRANSFORM_ID)
+ {
+ return mIgnored;
+ }
+ return false;
+ }
+
/**
* Retrieve the local position of the node, relative to its parent.
* @param[in] bufferIndex The buffer to read from.
bool mUpdateAreaChanged : 1; ///< True if the update area of the node is changed.
bool mUpdateAreaUseSize : 1; ///< True if the update area of the node is same as node size.
bool mUseTextureUpdateArea : 1; ///< Whether the actor uses the update area of the texture instead of its own.
+ bool mIgnored : 1; ///< Whether the node is ignored or not.
// Changes scope, should be at end of class
DALI_LOG_OBJECT_STRING_DECLARATION;
new(slot) LocalType(&node, &Node::SetPositionUsesAnchorPoint, positionUsesAnchorPoint);
}
+inline void SetIgnoredMessage(EventThreadServices& eventThreadServices, const Node& node, bool ignored)
+{
+ 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::SetIgnored, ignored);
+}
+
inline void SetUpdateAreaHintMessage(EventThreadServices& eventThreadServices, const Node& node, const Vector4& updateAreaHint)
{
using LocalType = MessageValue1<Node, Vector4>;
return GetImplementation(*this).GetRelayoutSize(dimension);
}
+void Actor::SetIgnored(bool ignored)
+{
+ GetImplementation(*this).SetIgnored(ignored);
+}
+
+bool Actor::IsIgnored() const
+{
+ return GetImplementation(*this).IsIgnored();
+}
+
+
Actor::TouchEventSignalType& Actor::TouchedSignal()
{
return GetImplementation(*this).TouchedSignal();
*/
float GetRelayoutSize(Dimension::Type dimension) const;
+ /**
+ * @brief Sets a flag to identify whether the Actor is ignored or not.
+ * If the actor is marked as ignored, it will not be rendered and will be excluded from render thread computation.
+ * So, the current properties like WorldPosition and WorldColor become inaccurate.
+ *
+ * @SINCE_2_4.21
+ * @param[in] ignored True to make the actor be ignored.
+ */
+ void SetIgnored(bool ignored);
+
+ /**
+ * @brief Returns whether the Actor is ignored or not.
+ *
+ * @SINCE_2_4.21
+ * @return Return True if the Actor is ignored.
+ */
+ bool IsIgnored() const;
+
public: // Renderer
/**
* @brief Adds a renderer to this actor.