(Scene3D) Add ControlFlags::DISABLE_VISUALS + Scene3D controls use this flag 89/319389/2
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 10 Feb 2025 09:12:50 +0000 (18:12 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Tue, 11 Feb 2025 04:32:01 +0000 (13:32 +0900)
Scince Visual shaders are not consider in 3D world's behavior, we'd better
remove those features in Scene3D case which application might mis-using

TODO : Model use BackgroundColor when they check bounding box.
We'll  make it to disbale visuals someday.

Change-Id: Id90ab967af461efb005a8be46ea250ba065fd015
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
14 files changed:
automated-tests/src/dali-toolkit/utc-Dali-Control.cpp
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/panel/panel-impl.cpp
dali-scene3d/internal/light/light-impl.cpp
dali-scene3d/internal/model-components/model-node-impl.cpp
dali-toolkit/devel-api/controls/control-wrapper-impl.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/control/control-debug.cpp
dali-toolkit/internal/controls/control/control-visual-data.cpp
dali-toolkit/internal/controls/control/control-visual-data.h
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/controls/control.h

index 5f4293346b3f9c653377063dc502204c6c37687d..099eb52676482ec15e5f7e834b44ba1ff76a320c 100644 (file)
@@ -1527,3 +1527,53 @@ int UtcDaliControlOffScreenRendering(void)
 
   END_TEST;
 }
+
+int UtcDaliControlNewWithDisableVisuals(void)
+{
+  ToolkitTestApplication application;
+
+  Control control = Control::New(Control::ControlBehaviour::DISABLE_VISUALS);
+  control.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  application.GetScene().Add(control);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(0u, control.GetRendererCount(), TEST_LOCATION);
+
+  // Check BackgroundVisual skipped
+  control.SetBackgroundColor(Color::RED);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(0u, control.GetRendererCount(), TEST_LOCATION);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::COLOR);
+  propertyMap.Insert(Visual::Property::MIX_COLOR, Color::BLUE);
+
+  // Check Background or Shadow with property map skipped
+  control.SetProperty(Control::Property::BACKGROUND, propertyMap);
+  control.SetProperty(DevelControl::Property::SHADOW, propertyMap);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(0u, control.GetRendererCount(), TEST_LOCATION);
+
+  Toolkit::Visual::ResourceStatus resourceStatus = control.GetVisualResourceStatus(Control::Property::BACKGROUND);
+  DALI_TEST_EQUALS(control.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(control.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(static_cast<int>(resourceStatus), static_cast<int>(Toolkit::Visual::ResourceStatus::READY), TEST_LOCATION);
+
+  control.ClearBackground();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(0u, control.GetRendererCount(), TEST_LOCATION);
+
+  END_TEST;
+}
index 13e0fe86e857fcabcb33bb0a02f662eb1997bb42..ca500a26f7517e47dc70ef37b633b6fd71c3a2b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
index bdb66c8fdc2cd1bb738320a307f545e25025a366..d37455de174af6d2e3a8f4635fd203e93f11f8a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -106,7 +106,7 @@ Dali::Geometry CreatePlaneGeometry(bool flip = false)
 } // anonymous namespace
 
 Panel::Panel()
-: Control(ControlBehaviour(DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)),
+: Control(ControlBehaviour(DISABLE_VISUALS | DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)),
   mPanelResolution(Vector2::ZERO),
   mResolutionPropertyIndex(Property::INVALID_INDEX),
   mIsTransparent(false),
@@ -363,8 +363,7 @@ void Panel::OnInitialize()
   mDoubleSidedPlaneNode.AddModelPrimitive(doubleSidedPlanePrimitive);
 
   mResolutionPropertyIndex   = mPanelNode.RegisterProperty("resolution", mPanelResolution);
-  Constraint scaleConstraint = Constraint::New<Vector3>(mPanelNode, Dali::Actor::Property::SCALE, [](Vector3& output, const PropertyInputContainer& inputs)
-                                                        {
+  Constraint scaleConstraint = Constraint::New<Vector3>(mPanelNode, Dali::Actor::Property::SCALE, [](Vector3& output, const PropertyInputContainer& inputs) {
     Vector3 panelSize = inputs[0]->GetVector3();
     Vector2 panelResolution = inputs[1]->GetVector2();
     output = Y_DIRECTION;
index e43986c8ef840a6bc8983e2581f772fe319ff3b1..c7bc54e513a5577c5783a96ad7389ead04c83fe9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -71,7 +71,7 @@ Dali::Scene3D::Light Light::New()
 }
 
 Light::Light()
-: Control(static_cast<ControlBehaviour>(ControlBehaviour::DISABLE_STYLE_CHANGE_SIGNALS | ActorFlags::DISABLE_SIZE_NEGOTIATION))
+: Control(static_cast<ControlBehaviour>(ControlBehaviour::DISABLE_VISUALS | ControlBehaviour::DISABLE_STYLE_CHANGE_SIGNALS | ActorFlags::DISABLE_SIZE_NEGOTIATION))
 {
 }
 
index 5bc1a1e114a7ce3b63afb79c652039b5bc972229..2d0bfbd8787483ded3f97595e05ce29f6c769324 100644 (file)
@@ -66,7 +66,7 @@ Dali::Scene3D::ModelNode ModelNode::New()
 }
 
 ModelNode::ModelNode()
-: Control(static_cast<ControlBehaviour>(ControlBehaviour::DISABLE_STYLE_CHANGE_SIGNALS | ActorFlags::DISABLE_SIZE_NEGOTIATION))
+: Control(static_cast<ControlBehaviour>(ControlBehaviour::DISABLE_VISUALS | ControlBehaviour::DISABLE_STYLE_CHANGE_SIGNALS | ActorFlags::DISABLE_SIZE_NEGOTIATION))
 {
 }
 
index 6bd10262ec8a83d75ff2a277814f2e7be0d162ba..ef8bbbf575859c524cfb3b82da8b983b7aa4aab0 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_CONTROL_WRAPPER_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -52,6 +52,7 @@ public:
     DISABLE_SIZE_NEGOTIATION             = CustomActorImpl::DISABLE_SIZE_NEGOTIATION,
     REQUIRES_KEYBOARD_NAVIGATION_SUPPORT = Control::REQUIRES_KEYBOARD_NAVIGATION_SUPPORT,
     DISABLE_STYLE_CHANGE_SIGNALS         = Control::DISABLE_STYLE_CHANGE_SIGNALS,
+    DISABLE_VISUALS                      = Control::DISABLE_VISUALS,
 
     LAST_CONTROL_BEHAVIOUR_FLAG
   };
index 89731c07b25ccb367fbf5096a6c5335d5be04bbd..5a299a4c578b2cd8453d716dcc297f690c5b0424 100644 (file)
@@ -417,12 +417,14 @@ Control::Impl::Impl(Control& controlImpl)
   mProcessorRegistered(false)
 {
   mAccessibilityData = std::make_unique<AccessibilityData>(mControlImpl);
-  mVisualData        = std::make_unique<VisualData>(*this);
 }
 
 Control::Impl::~Impl()
 {
-  mVisualData->ClearVisuals();
+  if(mVisualData)
+  {
+    mVisualData->ClearVisuals();
+  }
 
   // All gesture detectors will be destroyed so no need to disconnect.
   delete mStartingPinchScale;
@@ -440,6 +442,11 @@ Control::Impl::~Impl()
   }
 }
 
+void Control::Impl::InitializeVisualData()
+{
+  mVisualData = std::make_unique<Control::Impl::VisualData>(*this);
+}
+
 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
 {
   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
@@ -488,53 +495,70 @@ void Control::Impl::ResourceReady()
 
 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
 {
-  mVisualData->RegisterVisual(index, visual);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->RegisterVisual(index, visual);
+  }
 }
 
 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
 {
-  mVisualData->RegisterVisual(index, visual, depthIndex);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->RegisterVisual(index, visual, depthIndex);
+  }
 }
 
 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
 {
-  mVisualData->RegisterVisual(index, visual, enabled);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->RegisterVisual(index, visual, enabled);
+  }
 }
 
 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
 {
-  mVisualData->RegisterVisual(index, visual, enabled, depthIndex);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->RegisterVisual(index, visual, enabled, depthIndex);
+  }
 }
 
 void Control::Impl::UnregisterVisual(Property::Index index)
 {
-  mVisualData->UnregisterVisual(index);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->UnregisterVisual(index);
+  }
 }
 
 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
 {
-  return mVisualData->GetVisual(index);
+  if(DALI_LIKELY(mVisualData))
+  {
+    return mVisualData->GetVisual(index);
+  }
+  return Toolkit::Visual::Base();
 }
 
 bool Control::Impl::IsResourceReady() const
 {
-  return mVisualData->IsResourceReady();
+  if(DALI_LIKELY(mVisualData))
+  {
+    return mVisualData->IsResourceReady();
+  }
+  return true;
 }
 
 void Control::Impl::OnSceneConnection()
 {
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection number of registered visuals(%d)\n", mVisualData->mVisuals.Size());
-
-  Actor self = mControlImpl.Self();
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection number of registered visuals(%d)\n", mVisualData ? mVisualData->mVisuals.Size() : 0u);
 
-  for(RegisteredVisualContainer::Iterator iter = mVisualData->mVisuals.Begin(); iter != mVisualData->mVisuals.End(); iter++)
+  if(DALI_LIKELY(mVisualData))
   {
-    // Check whether the visual is empty and enabled
-    if((*iter)->visual && (*iter)->enabled)
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection Setting visual(%d) on scene\n", (*iter)->index);
-      Toolkit::GetImplementation((*iter)->visual).SetOnScene(self);
-    }
+    Actor self = mControlImpl.Self();
+    mVisualData->ConnectScene(self);
   }
 
   if(mOffScreenRenderingImpl) // mOffScreenRenderingType != NONE
@@ -545,8 +569,13 @@ void Control::Impl::OnSceneConnection()
 
 void Control::Impl::OnSceneDisconnection()
 {
-  Actor self = mControlImpl.Self();
-  mVisualData->ClearScene(self);
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneDisconnection number of registered visuals(%d)\n", mVisualData ? mVisualData->mVisuals.Size() : 0u);
+
+  if(DALI_LIKELY(mVisualData))
+  {
+    Actor self = mControlImpl.Self();
+    mVisualData->ClearScene(self);
+  }
 
   if(mOffScreenRenderingImpl)
   {
@@ -556,28 +585,47 @@ void Control::Impl::OnSceneDisconnection()
 
 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
 {
-  mVisualData->EnableReadyTransitionOverriden(visual, enable);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->EnableReadyTransitionOverriden(visual, enable);
+  }
 }
 
 void Control::Impl::EnableVisual(Property::Index index, bool enable)
 {
-  mVisualData->EnableVisual(index, enable);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->EnableVisual(index, enable);
+  }
 }
 
 bool Control::Impl::IsVisualEnabled(Property::Index index) const
 {
-  return mVisualData->IsVisualEnabled(index);
+  if(DALI_LIKELY(mVisualData))
+  {
+    return mVisualData->IsVisualEnabled(index);
+  }
+  return false;
 }
 
 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
 {
-  return mVisualData->GetVisualResourceStatus(index);
+  if(DALI_LIKELY(mVisualData))
+  {
+    return mVisualData->GetVisualResourceStatus(index);
+  }
+  return Toolkit::Visual::ResourceStatus::READY;
 }
 
 void Control::Impl::AddTransitions(Dali::Animation&               animation,
                                    const Toolkit::TransitionData& handle,
                                    bool                           createAnimation)
 {
+  if(DALI_UNLIKELY(!mVisualData))
+  {
+    return;
+  }
+
   // Setup a Transition from TransitionData.
   const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
   TransitionData::Iterator        end            = transitionData.End();
@@ -646,12 +694,18 @@ void Control::Impl::AddTransitions(Dali::Animation&               animation,
 
 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
 {
-  mVisualData->DoAction(visualIndex, actionId, attributes);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->DoAction(visualIndex, actionId, attributes);
+  }
 }
 
 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
 {
-  mVisualData->DoActionExtension(visualIndex, actionId, attributes);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->DoActionExtension(visualIndex, actionId, attributes);
+  }
 }
 
 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
@@ -784,11 +838,14 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         }
         else if(value.Get(url))
         {
-          // don't know the size to load
-          Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
-          if(visual)
+          if(DALI_LIKELY(controlImpl.mImpl->mVisualData))
           {
-            controlImpl.mImpl->mVisualData->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
+            // don't know the size to load
+            Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
+            if(visual)
+            {
+              controlImpl.mImpl->mVisualData->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
+            }
           }
         }
         else if(value.Get(color))
@@ -1074,11 +1131,15 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::Control::Property::BACKGROUND:
       {
-        Property::Map         map;
-        Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::Control::Property::BACKGROUND);
-        if(visual)
+        Property::Map map;
+
+        if(DALI_LIKELY(controlImpl.mImpl->mVisualData))
         {
-          visual.CreatePropertyMap(map);
+          Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::Control::Property::BACKGROUND);
+          if(visual)
+          {
+            visual.CreatePropertyMap(map);
+          }
         }
 
         value = map;
@@ -1110,11 +1171,15 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::SHADOW:
       {
-        Property::Map         map;
-        Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::SHADOW);
-        if(visual)
+        Property::Map map;
+
+        if(DALI_LIKELY(controlImpl.mImpl->mVisualData))
         {
-          visual.CreatePropertyMap(map);
+          Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::SHADOW);
+          if(visual)
+          {
+            visual.CreatePropertyMap(map);
+          }
         }
 
         value = map;
@@ -1228,24 +1293,27 @@ void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
     // store that fact, e.g. in another property that FocusManager can access.
     mState = newState;
 
-    // Trigger state change and transitions
-    // Apply new style, if stylemanager is available
-    Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
-    if(styleManager)
+    if(DALI_LIKELY(mVisualData))
     {
-      const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
-
-      if(stylePtr)
+      // Trigger state change and transitions
+      // Apply new style, if stylemanager is available
+      Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+      if(styleManager)
       {
-        std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
-        std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
+        const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
 
-        const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
-        const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
-        if(oldStateStyle && newStateStyle)
+        if(stylePtr)
         {
-          // Only change if both state styles exist
-          mVisualData->ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
+          std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
+          std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
+
+          const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
+          const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
+          if(oldStateStyle && newStateStyle)
+          {
+            // Only change if both state styles exist
+            mVisualData->ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
+          }
         }
       }
     }
@@ -1256,29 +1324,32 @@ void Control::Impl::SetSubState(const std::string& subStateName, bool withTransi
 {
   if(mSubStateName != subStateName)
   {
-    // Get existing sub-state visuals, and unregister them
-    Dali::CustomActor handle(mControlImpl.GetOwner());
-
-    Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
-    if(styleManager)
+    if(DALI_LIKELY(mVisualData))
     {
-      const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
-      if(stylePtr)
-      {
-        // Stringify state
-        std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
+      // Get existing sub-state visuals, and unregister them
+      Dali::CustomActor handle(mControlImpl.GetOwner());
 
-        const StylePtr* state = stylePtr->subStates.Find(stateName);
-        if(state)
+      Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+      if(styleManager)
+      {
+        const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
+        if(stylePtr)
         {
-          StylePtr stateStyle(*state);
+          // Stringify state
+          std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
 
-          const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
-          const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
-          if(oldStateStyle && newStateStyle)
+          const StylePtr* state = stylePtr->subStates.Find(stateName);
+          if(state)
           {
-            std::string empty;
-            mVisualData->ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
+            StylePtr stateStyle(*state);
+
+            const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
+            const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
+            if(oldStateStyle && newStateStyle)
+            {
+              std::string empty;
+              mVisualData->ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
+            }
           }
         }
       }
@@ -1316,6 +1387,7 @@ Extents Control::Impl::GetPadding() const
 
 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
 {
+  DALI_ASSERT_ALWAYS(mVisualData && "Visual Disabled control cannot use VisualEventSignal!!");
   return mVisualData->VisualEventSignal();
 }
 
@@ -1407,33 +1479,47 @@ bool Control::Impl::IsCreateAccessibleEnabled() const
 
 void Control::Impl::ApplyFittingMode(const Vector2& size)
 {
-  mVisualData->ApplyFittingMode(size);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->ApplyFittingMode(size);
+  }
 }
 
 void Control::Impl::SetShadow(const Property::Map& map)
 {
-  Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
-  visual.SetName("shadow");
-
-  if(visual)
+  if(DALI_LIKELY(mVisualData))
   {
-    mControlImpl.mImpl->mVisualData->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
+    Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
+    visual.SetName("shadow");
 
-    mControlImpl.RelayoutRequest();
+    if(visual)
+    {
+      mVisualData->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
+
+      mControlImpl.RelayoutRequest();
+    }
   }
 }
 
 void Control::Impl::ClearShadow()
 {
-  mControlImpl.mImpl->mVisualData->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
 
-  // Trigger a size negotiation request that may be needed when unregistering a visual.
-  mControlImpl.RelayoutRequest();
+    // Trigger a size negotiation request that may be needed when unregistering a visual.
+    mControlImpl.RelayoutRequest();
+  }
 }
 
 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
 {
-  return mVisualData->GetVisualProperty(index, visualPropertyKey);
+  if(DALI_LIKELY(mVisualData))
+  {
+    return mVisualData->GetVisualProperty(index, visualPropertyKey);
+  }
+  Dali::Handle handle;
+  return Dali::Property(handle, Property::INVALID_INDEX);
 }
 
 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
@@ -1465,7 +1551,10 @@ void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Inde
 
 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
 {
-  mVisualData->UpdateVisualProperties(properties);
+  if(DALI_LIKELY(mVisualData))
+  {
+    mVisualData->UpdateVisualProperties(properties);
+  }
 }
 
 void Control::Impl::EmitResourceReadySignal()
@@ -1538,10 +1627,13 @@ std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::GetAcce
 
 void Control::Impl::RegisterProcessorOnce()
 {
-  if(!mProcessorRegistered)
+  if(DALI_LIKELY(mVisualData))
   {
-    Adaptor::Get().RegisterProcessorOnce(*this, true);
-    mProcessorRegistered = true;
+    if(!mProcessorRegistered)
+    {
+      Adaptor::Get().RegisterProcessorOnce(*this, true);
+      mProcessorRegistered = true;
+    }
   }
 }
 
@@ -1578,8 +1670,11 @@ void Control::Impl::SetOffScreenRendering(int32_t offScreenRenderingType)
 
 void Control::Impl::Process(bool postProcessor)
 {
-  // Call ApplyFittingMode
-  mVisualData->ApplyFittingMode(mSize);
+  if(DALI_LIKELY(mVisualData))
+  {
+    // Call ApplyFittingMode
+    mVisualData->ApplyFittingMode(mSize);
+  }
   mProcessorRegistered = false;
 }
 
index 4232a827273cc64ad67fc24fee74474cf1a14f58..e097b67350d3ec9032f2742fe29b57850997acc0 100644 (file)
@@ -82,6 +82,11 @@ public:
    */
   ~Impl();
 
+  /**
+   * @brief Initialize private VisualData context for this impl.
+   */
+  void InitializeVisualData();
+
   /**
    * @brief Called when a pinch is detected.
    * @param[in] actor The actor the pinch occurred on
index 7f87f8852c59917bad85880868a5110f9c923029..cd0d84a27d136ad3b8fb833ae787b99a09c0c3f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -292,10 +292,13 @@ std::string DumpControl(const Internal::Control& control)
     oss << "\"name\":\"" << name << "\",\n";
   }
   oss << "\"id\":\"" << control.Self().GetProperty<int>(Actor::Property::ID) << "\",\n";
-  oss << "\"registeredVisuals\":\n"
-      << controlData.mVisualData->mVisuals << ",\n";
-  oss << "\"removeVisuals\":\n"
-      << controlData.mVisualData->mRemoveVisuals << ",\n";
+  if(DALI_LIKELY(controlData.mVisualData))
+  {
+    oss << "\"registeredVisuals\":\n"
+        << controlData.mVisualData->mVisuals << ",\n";
+    oss << "\"removeVisuals\":\n"
+        << controlData.mVisualData->mRemoveVisuals << ",\n";
+  }
   oss << "\"rendererCount\":" << control.Self().GetRendererCount() << ",\n";
   oss << "\"properties\":\n{\n";
   DumpProperties(oss, control.Self()) << "}\n";
index 98c7740e242bd5411c0bbc55625ab000df6157f9..c377c2eb5c91ec18eda5b45c14df7a1bb935d0de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -239,6 +239,19 @@ Control::Impl::VisualData::~VisualData()
 {
 }
 
+void Control::Impl::VisualData::ConnectScene(Actor parent)
+{
+  for(RegisteredVisualContainer::Iterator iter = mVisuals.Begin(); iter != mVisuals.End(); iter++)
+  {
+    // Check whether the visual is empty and enabled
+    if((*iter)->visual && (*iter)->enabled)
+    {
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection Setting visual(%d) on scene\n", (*iter)->index);
+      Toolkit::GetImplementation((*iter)->visual).SetOnScene(parent);
+    }
+  }
+}
+
 void Control::Impl::VisualData::ClearScene(Actor parent)
 {
   SetVisualsOffScene(mVisuals, parent);
index e29c7f1c7f8363a2b6c65c22113d796d3251282f..2481d0dd913a2482975605ce412f8ea2f090f84d 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_DATA_VISUAL_DATA_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -212,6 +212,13 @@ public:
    */
   DevelControl::VisualEventSignalType& VisualEventSignal();
 
+  /**
+   * @brief Notify to all registered visuals to be scene on.
+   *
+   * @param[in] parent Parent actor to scene added visuals to
+   */
+  void ConnectScene(Actor parent);
+
   /**
    * @brief Any visuals set for replacement but not yet ready should still be registered.
    * Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
index e520aa8807f782e81e1bb3bd093493b4371d0baa..e24374931fec1360d19331b65fb14e06b85d68fa 100644 (file)
@@ -78,7 +78,7 @@ void CreateClippingRenderer(Control& controlImpl)
   {
     Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl);
 
-    if(clippingMode == ClippingMode::CLIP_CHILDREN && controlDataImpl.mVisualData->mVisuals.Empty() && self.GetRendererCount() == 0u)
+    if(clippingMode == ClippingMode::CLIP_CHILDREN && (DALI_UNLIKELY(!controlDataImpl.mVisualData) || controlDataImpl.mVisualData->mVisuals.Empty()) && self.GetRendererCount() == 0u)
     {
       controlImpl.SetBackgroundColor(Color::TRANSPARENT);
     }
@@ -466,6 +466,11 @@ Control::~Control()
 
 void Control::Initialize()
 {
+  if(DALI_LIKELY(!(mImpl->mFlags & DISABLE_VISUALS)))
+  {
+    mImpl->InitializeVisualData();
+  }
+
   // Call deriving classes so initialised before styling is applied to them.
   OnInitialize();
 
index 13a3490e6b762106c291d9f12f31372cfedd122c..f27d135efe1a03ad4479e574fb8f5308f8111a8a 100644 (file)
@@ -446,6 +446,7 @@ public: // Helpers for deriving classes
     NOT_IN_USE_1                         = 1 << (CustomActorImpl::ACTOR_FLAG_COUNT + 0),
     REQUIRES_KEYBOARD_NAVIGATION_SUPPORT = 1 << (CustomActorImpl::ACTOR_FLAG_COUNT + 1), ///< True if needs to support keyboard navigation @SINCE_1_0.0
     DISABLE_STYLE_CHANGE_SIGNALS         = 1 << (CustomActorImpl::ACTOR_FLAG_COUNT + 2), ///< True if control should not monitor style change signals @SINCE_1_2_10
+    DISABLE_VISUALS                      = 1 << (CustomActorImpl::ACTOR_FLAG_COUNT + 3), ///< True if control should not use visuals @SINCE_2_3.6
 
     LAST_CONTROL_BEHAVIOUR_FLAG
   };
index 9fa0b7ee7f86db7c11138aee50a1f19bdb2acc52..072fbede2a55c06ab4c50f1aa0eee0980508beab 100644 (file)
@@ -185,6 +185,7 @@ public: // Creation & Destruction
     DISABLE_SIZE_NEGOTIATION             = 1 << (0 + 0), ///< True if control does not need size negotiation, i.e. it can be skipped in the algorithm @SINCE_1_0.0
     REQUIRES_KEYBOARD_NAVIGATION_SUPPORT = 1 << (4 + 1), ///< True if needs to support keyboard navigation @SINCE_1_0.0
     DISABLE_STYLE_CHANGE_SIGNALS         = 1 << (4 + 2), ///< True if control should not monitor style change signals @SINCE_1_2_10
+    DISABLE_VISUALS                      = 1 << (4 + 3), ///< True if control should not use visuals @SINCE_2_3.6
   };
 
   /**