(Scene3D) Change model's default behavior 73/284173/2
authorEunki, Hong <eunkiki.hong@samsung.com>
Fri, 11 Nov 2022 04:38:51 +0000 (13:38 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 11 Nov 2022 06:56:16 +0000 (15:56 +0900)
1. Make mRootModel's KEYBOARD_FOCUSABLE as false in default.
2. Set ParentOrigin at Intialize timing, not ModelLoad completed

Change-Id: I11ef708f75948584d493f184fa3d929300ef57af
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali-scene3d/utc-Dali-Model.cpp
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/public-api/controls/model/model.cpp
dali-scene3d/public-api/controls/model/model.h

index c18924b..25d2624 100644 (file)
@@ -41,6 +41,7 @@ void model_cleanup(void)
 namespace
 {
 const bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
+const bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
 /**
  * For the AnimatedCube.gltf and its Assets
  * Donated by Norbert Nopper for glTF testing.
@@ -84,6 +85,12 @@ bool TestTouchCallback(Actor, const TouchEvent&)
   return true;
 }
 
+bool gFocusChangedCallBackCalled = false;
+void TestFocusChangedCallback(Actor, Actor)
+{
+  gFocusChangedCallBackCalled = true;
+}
+
 } // namespace
 
 // Negative test case for a method
@@ -587,6 +594,187 @@ int UtcDaliModelChildrenSensitive02(void)
   END_TEST;
 }
 
+int UtcDaliModelChildrenFocusable01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::Model view = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector3(100, 100, 100));
+  view.SetProperty(Dali::Actor::Property::POSITION, Vector3(0, 0, 0));
+  view.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  view.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  // Get vaule. Default is false.
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), DEFAULT_MODEL_CHILDREN_FOCUSABLE, TEST_LOCATION);
+
+  // Allow children actor's focus before on scene.
+  view.SetChildrenFocusable(true);
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), true, TEST_LOCATION);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor meshActor = view.FindChildByName("AnimatedCube");
+  DALI_TEST_CHECK(meshActor);
+
+  // Enable the default algorithm
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK(manager);
+  Dali::Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm(manager, true);
+
+  // connect focusable signal
+  gFocusChangedCallBackCalled = false;
+  meshActor.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+  manager.FocusChangedSignal().Connect(TestFocusChangedCallback);
+
+  // Initialize with some left-positioned actor
+  Control focusStartActor = Control::New();
+  focusStartActor.SetProperty(Dali::Actor::Property::SIZE, Vector3(100, 100, 100));
+  focusStartActor.SetProperty(Dali::Actor::Property::POSITION, Vector3(-200, 0, 0));
+  focusStartActor.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  focusStartActor.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  focusStartActor.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, true);
+  application.GetScene().Add(focusStartActor);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Focusable view find success
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+  DALI_TEST_CHECK(gFocusChangedCallBackCalled);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  // Block children actor's focus
+  view.SetChildrenFocusable(false);
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), false, TEST_LOCATION);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Focusable view find failed
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false);
+  DALI_TEST_CHECK(!gFocusChangedCallBackCalled);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  // Allow again
+  view.SetChildrenFocusable(true);
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), true, TEST_LOCATION);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Focusable view find success
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+  DALI_TEST_CHECK(gFocusChangedCallBackCalled);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  END_TEST;
+}
+
+int UtcDaliModelModelChildrenFocusable02(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::Model view = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector3(100, 100, 100));
+  view.SetProperty(Dali::Actor::Property::POSITION, Vector3(0, 0, 0));
+  view.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  view.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  // Get vaule. Default is true.
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), DEFAULT_MODEL_CHILDREN_FOCUSABLE, TEST_LOCATION);
+
+  // Block children actor's focus before on scene.
+  view.SetChildrenFocusable(false);
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), false, TEST_LOCATION);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor meshActor = view.FindChildByName("AnimatedCube");
+  DALI_TEST_CHECK(meshActor);
+
+  // Enable the default algorithm
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK(manager);
+  Dali::Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm(manager, true);
+
+  // connect focusable signal
+  gFocusChangedCallBackCalled = false;
+  meshActor.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+  manager.FocusChangedSignal().Connect(TestFocusChangedCallback);
+
+  // Initialize with some left-positioned actor
+  Control focusStartActor = Control::New();
+  focusStartActor.SetProperty(Dali::Actor::Property::SIZE, Vector3(100, 100, 100));
+  focusStartActor.SetProperty(Dali::Actor::Property::POSITION, Vector3(-200, 0, 0));
+  focusStartActor.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  focusStartActor.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  focusStartActor.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, true);
+  application.GetScene().Add(focusStartActor);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Focusable view find failed
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false);
+  DALI_TEST_CHECK(!gFocusChangedCallBackCalled);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  // Allow again
+  view.SetChildrenFocusable(true);
+  DALI_TEST_EQUALS(view.GetChildrenFocusable(), true, TEST_LOCATION);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Focusable view find success
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+  DALI_TEST_CHECK(gFocusChangedCallBackCalled);
+
+  // Clear
+  manager.ClearFocus();
+  manager.SetCurrentFocusActor(focusStartActor);
+  gFocusChangedCallBackCalled = false;
+
+  END_TEST;
+}
+
 int UtcDaliModelAnimation01(void)
 {
   ToolkitTestApplication application;
index 5a64d72..86893a7 100644 (file)
@@ -67,6 +67,7 @@ static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
 static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
 
 static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
+static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
 
 static constexpr std::string_view KTX_EXTENSION  = ".ktx";
 static constexpr std::string_view OBJ_EXTENSION  = ".obj";
@@ -184,6 +185,7 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
   mSceneIblScaleFactor(1.0f),
   mIblScaleFactor(1.0f),
   mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
+  mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
   mModelResourceReady(false),
   mIBLResourceReady(true)
 {
@@ -228,6 +230,24 @@ bool Model::GetChildrenSensitive() const
   return mModelChildrenSensitive;
 }
 
+void Model::SetChildrenFocusable(bool enable)
+{
+  if(mModelChildrenFocusable != enable)
+  {
+    mModelChildrenFocusable = enable;
+    if(mModelRoot)
+    {
+      mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
+      mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
+    }
+  }
+}
+
+bool Model::GetChildrenFocusable() const
+{
+  return mModelChildrenFocusable;
+}
+
 void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
 {
   mIBLResourceReady       = false;
@@ -307,6 +327,12 @@ Dali::Animation Model::GetAnimation(const std::string& name) const
 // Private methods
 //
 
+void Model::OnInitialize()
+{
+  // Make ParentOrigin as Center.
+  Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+}
+
 void Model::OnSceneConnection(int depth)
 {
   if(!mModelRoot)
@@ -505,10 +531,11 @@ void Model::LoadModel()
   ScaleModel();
 
   mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
+  mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
+  mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
 
   Self().Add(mModelRoot);
 
-  Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
   Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
 
   mModelResourceReady = true;
index 479653c..7bb4889 100644 (file)
@@ -26,9 +26,9 @@
 #include <dali/public-api/rendering/texture.h>
 
 // INTERNAL INCLUDES
+#include <dali-scene3d/internal/common/image-based-light-observer.h>
 #include <dali-scene3d/public-api/controls/model/model.h>
 #include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
-#include <dali-scene3d/internal/common/image-based-light-observer.h>
 
 namespace Dali
 {
@@ -69,6 +69,16 @@ public:
   bool GetChildrenSensitive() const;
 
   /**
+   * @copydoc Model::SetChildrenFocusable()
+   */
+  void SetChildrenFocusable(bool enable);
+
+  /**
+   * @copydoc Model::GetChildrenFocusable()
+   */
+  bool GetChildrenFocusable() const;
+
+  /**
    * @copydoc Model::SetImageBasedLightSource()
    */
   void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor);
@@ -116,6 +126,11 @@ protected:
 
 private:
   /**
+   * @copydoc Toolkit::Control::OnInitialize
+   */
+  void OnInitialize();
+
+  /**
    * @copydoc CustomActorImpl::OnSceneConnection()
    */
   void OnSceneConnection(int depth) override;
@@ -181,7 +196,6 @@ private:
   void UpdateImageBasedLightScaleFactor();
 
 public: // Overrides ImageBasedLightObserver Methods.
-
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightTexture()
    */
@@ -190,7 +204,7 @@ public: // Overrides ImageBasedLightObserver Methods.
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightScaleFactor()
    */
-  void NotifyImageBasedLightScaleFactor(float scaleFactor)  override;
+  void NotifyImageBasedLightScaleFactor(float scaleFactor) override;
 
 private:
   std::string                    mModelUrl;
@@ -212,6 +226,7 @@ private:
   float         mSceneIblScaleFactor;
   float         mIblScaleFactor;
   bool          mModelChildrenSensitive;
+  bool          mModelChildrenFocusable;
   bool          mModelResourceReady;
   bool          mIBLResourceReady;
 };
index 69029d9..c0369ab 100644 (file)
@@ -77,6 +77,16 @@ bool Model::GetChildrenSensitive() const
   return GetImpl(*this).GetChildrenSensitive();
 }
 
+void Model::SetChildrenFocusable(bool enable)
+{
+  GetImpl(*this).SetChildrenFocusable(enable);
+}
+
+bool Model::GetChildrenFocusable() const
+{
+  return GetImpl(*this).GetChildrenFocusable();
+}
+
 void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
 {
   GetImpl(*this).SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor);
index 104e054..45ceca1 100644 (file)
@@ -162,7 +162,7 @@ public:
    * @SINCE_2_1.43
    * @note Even if we set children sensitive as false, model itself's sensitive
    * is depend on it's property.
-   * @note If we don't call this API, default is false. (Allow to traversal model's children during hit-test)
+   * @note If we don't call this API, default is false. (Don't allow to traversal model's children during hit-test)
    *
    * @param[in] enable True to enable model's children can use events.
    */
@@ -177,6 +177,30 @@ public:
   bool GetChildrenSensitive() const;
 
   /**
+   * @brief Whether allow this model's children actor to be keyboard focusable.
+   *
+   * Usually, 3D Model might have a lot of actors. And most of them don't need to check focusable.
+   * To optimize traversal, we need to setup some flag that this model don't allow (or allow) to traversal
+   * children so that child can be keyboard focusable.
+   *
+   * @SINCE_2_2.2
+   * @note Even if we set children focusable as false, model itself's focusable
+   * is depend on it's property.
+   * @note If we don't call this API, default is false. (Don't allow to traversal model's children during focusable test)
+   *
+   * @param[in] enable True to enable model's children can be focusable.
+   */
+  void SetChildrenFocusable(bool enable);
+
+  /**
+   * @brief Gets whether this Model allow model's children actor to be keyboard focusable or not.
+   *
+   * @SINCE_2_2.2
+   * @return bool True if this Model allow model children are focusable.
+   */
+  bool GetChildrenFocusable() const;
+
+  /**
    * @brief Changes Image Based Light as the input textures.
    *
    * @SINCE_2_1.41