From c602b829b1b7a95adc475c206ed51de52c6c49b8 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Fri, 11 Nov 2022 13:38:51 +0900 Subject: [PATCH 1/1] (Scene3D) Change model's default behavior 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 --- .../src/dali-scene3d/utc-Dali-Model.cpp | 188 +++++++++++++++++++++ .../internal/controls/model/model-impl.cpp | 29 +++- dali-scene3d/internal/controls/model/model-impl.h | 21 ++- dali-scene3d/public-api/controls/model/model.cpp | 10 ++ dali-scene3d/public-api/controls/model/model.h | 26 ++- 5 files changed, 269 insertions(+), 5 deletions(-) diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp index c18924b..25d2624 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -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; diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index 5a64d72..86893a7 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -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; diff --git a/dali-scene3d/internal/controls/model/model-impl.h b/dali-scene3d/internal/controls/model/model-impl.h index 479653c..7bb4889 100644 --- a/dali-scene3d/internal/controls/model/model-impl.h +++ b/dali-scene3d/internal/controls/model/model-impl.h @@ -26,9 +26,9 @@ #include // INTERNAL INCLUDES +#include #include #include -#include 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; }; diff --git a/dali-scene3d/public-api/controls/model/model.cpp b/dali-scene3d/public-api/controls/model/model.cpp index 69029d9..c0369ab 100644 --- a/dali-scene3d/public-api/controls/model/model.cpp +++ b/dali-scene3d/public-api/controls/model/model.cpp @@ -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); diff --git a/dali-scene3d/public-api/controls/model/model.h b/dali-scene3d/public-api/controls/model/model.h index 104e054..45ceca1 100644 --- a/dali-scene3d/public-api/controls/model/model.h +++ b/dali-scene3d/public-api/controls/model/model.h @@ -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 -- 2.7.4