/*\r
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
*\r
*/\r
#include "scene-loader-example.h"\r
+#include <dali-toolkit/dali-toolkit.h>\r
#include <dirent.h>\r
#include <cstring>\r
#include <string_view>\r
#include "dali/public-api/events/key-event.h"\r
#include "dali/public-api/object/property-array.h"\r
#include "dali/public-api/render-tasks/render-task-list.h"\r
+#include "scene-loader-extension.h"\r
\r
using namespace Dali;\r
using namespace Dali::Toolkit;\r
\r
TextLabel MakeLabel(std::string msg)\r
{\r
- TextLabel label = TextLabel::New(msg);\r
+ TextLabel label = TextLabel::New(" " + msg);\r
label.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);\r
label.SetProperty(TextLabel::Property::TEXT_COLOR, Color::WHITE);\r
label.SetProperty(TextLabel::Property::PIXEL_SIZE, ITEM_HEIGHT * 4 / 7);\r
+ label.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");\r
SetActorCentered(label);\r
return label;\r
}\r
{\r
auto label = MakeLabel(mSceneNames[itemId]);\r
mTapDetector.Attach(label);\r
+ label.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);\r
return label;\r
}\r
};\r
}\r
}\r
\r
-Actor LoadScene(std::string sceneName, CameraActor camera)\r
+Actor LoadScene(std::string sceneName, CameraActor camera, std::vector<AnimationDefinition>* animations, Animation& animation)\r
{\r
ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) {\r
return Application::GetResourcePath() + RESOURCE_TYPE_DIRS[type];\r
std::vector<AnimationGroupDefinition> animGroups;\r
std::vector<CameraParameters> cameraParameters;\r
std::vector<LightParameters> lights;\r
- std::vector<AnimationDefinition> animations;\r
+\r
+ animations->clear();\r
\r
LoadResult output{\r
resources,\r
scene,\r
- animations,\r
+ *animations,\r
animGroups,\r
cameraParameters,\r
lights};\r
}\r
}\r
\r
- if(!animations.empty())\r
+ if(!animations->empty())\r
{\r
auto getActor = [&root](const std::string& name) {\r
return root.FindChildByName(name);\r
};\r
\r
- animations[0].ReAnimate(getActor).Play();\r
+ animation = (*animations)[0].ReAnimate(getActor);\r
+ animation.Play();\r
}\r
\r
return root;\r
} // namespace\r
\r
SceneLoaderExample::SceneLoaderExample(Dali::Application& app)\r
-: mApp(app)\r
+: mApp(app),\r
+ mSceneLoaderExtension(new SceneLoaderExtension())\r
{\r
if(!std::getenv("DALI_APPLICATION_PACKAGE"))\r
{\r
app.TerminateSignal().Connect(this, &SceneLoaderExample::OnTerminate);\r
}\r
\r
+SceneLoaderExample::~SceneLoaderExample() = default;\r
+\r
void SceneLoaderExample::OnInit(Application& app)\r
{\r
// get scenes\r
\r
Vector3 windowSize(window.GetSize());\r
auto itemLayout = DefaultItemLayout::New(DefaultItemLayout::LIST);\r
- itemLayout->SetItemSize(Vector3(windowSize.x, ITEM_HEIGHT, 1.f));\r
+ itemLayout->SetItemSize(Vector3(windowSize.x * 0.9f, ITEM_HEIGHT, 1.f));\r
items.AddLayout(*itemLayout);\r
navigationView.Push(items);\r
\r
mItemLayout = itemLayout;\r
mItemView = items;\r
\r
+ mItemView.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);\r
+ KeyboardFocusManager::Get().PreFocusChangeSignal().Connect(this, &SceneLoaderExample::OnKeyboardPreFocusChange);\r
+ KeyboardFocusManager::Get().FocusedActorEnterKeySignal().Connect(this, &SceneLoaderExample::OnKeyboardFocusedActorActivated);\r
+ KeyboardFocusManager::Get().FocusChangedSignal().Connect(this, &SceneLoaderExample::OnKeyboardFocusChanged);\r
+\r
+ SetActorCentered(KeyboardFocusManager::Get().GetFocusIndicatorActor());\r
+\r
// camera\r
auto camera = CameraActor::New();\r
camera.SetInvertYAxis(true);\r
mTapDetector = tapDetector;\r
\r
// activate layout\r
- mItemView.ActivateLayout(0, windowSize, 1.f);\r
+ mItemView.ActivateLayout(0, windowSize, 0.f);\r
+\r
+ mSceneLoaderExtension->SetSceneLoader(this);\r
+}\r
+\r
+Actor SceneLoaderExample::OnKeyboardPreFocusChange(Actor current, Actor proposed, Control::KeyboardFocus::Direction direction)\r
+{\r
+ if(!current && !proposed)\r
+ {\r
+ return mItemView;\r
+ }\r
+\r
+ return proposed;\r
+}\r
+\r
+void SceneLoaderExample::OnKeyboardFocusedActorActivated(Actor activatedActor)\r
+{\r
+ if(activatedActor)\r
+ {\r
+ OnTap(activatedActor, Dali::TapGesture());\r
+ }\r
+}\r
+\r
+void SceneLoaderExample::OnKeyboardFocusChanged(Actor originalFocusedActor, Actor currentFocusedActor)\r
+{\r
+ if(currentFocusedActor)\r
+ {\r
+ auto itemId = mItemView.GetItemId(currentFocusedActor);\r
+ mItemView.ScrollToItem(itemId, 0.1f);\r
+ }\r
}\r
\r
void SceneLoaderExample::OnTerminate(Application& app)\r
\r
mNavigationView.Pop();\r
mScene.Reset();\r
+\r
+ if(mActivatedActor)\r
+ {\r
+ KeyboardFocusManager::Get().SetCurrentFocusActor(mActivatedActor);\r
+ }\r
}\r
else\r
{\r
mApp.Quit();\r
}\r
}\r
+ else\r
+ {\r
+ mSceneLoaderExtension->OnKey(e);\r
+ }\r
}\r
}\r
\r
\r
void SceneLoaderExample::OnTap(Dali::Actor actor, const Dali::TapGesture& tap)\r
{\r
+ mActivatedActor = actor;\r
+\r
auto id = mItemView.GetItemId(actor);\r
\r
try\r
auto renderTasks = window.GetRenderTaskList();\r
renderTasks.RemoveTask(mSceneRender);\r
\r
- auto scene = LoadScene(mSceneNames[id], mSceneCamera);\r
+ auto scene = LoadScene(mSceneNames[id], mSceneCamera, &mSceneAnimations, mCurrentAnimation);\r
\r
auto sceneRender = renderTasks.CreateTask();\r
sceneRender.SetCameraActor(mSceneCamera);\r
}\r
\r
mNavigationView.Push(mScene);\r
+\r
+ mSceneLoaderExtension->ConnectTouchSignals();\r
}\r
#ifndef SCENE_LAUNCHER_H_\r
#define SCENE_LAUNCHER_H_\r
/*\r
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
* limitations under the License.\r
*\r
*/\r
+\r
+#include <memory>\r
#include "dali-scene-loader/public-api/animation-definition.h"\r
#include "dali-scene-loader/public-api/camera-parameters.h"\r
#include "dali-scene-loader/public-api/node-definition.h"\r
#include "dali/public-api/render-tasks/render-task.h"\r
#include "dali/public-api/signals/connection-tracker.h"\r
\r
+class SceneLoaderExtension;\r
+\r
class SceneLoaderExample : public Dali::ConnectionTracker\r
{\r
public:\r
SceneLoaderExample(Dali::Application& app);\r
- ~SceneLoaderExample() = default;\r
+ ~SceneLoaderExample();\r
\r
private: // data\r
Dali::Application& mApp;\r
\r
Dali::CameraActor mSceneCamera;\r
Dali::RenderTask mSceneRender;\r
- Dali::Actor mScene;\r
\r
Dali::Quaternion mCameraOrientationInv;\r
\r
Dali::TapGestureDetector mTapDetector;\r
Dali::PanGestureDetector mPanDetector;\r
\r
+ Dali::Actor mActivatedActor;\r
+\r
+public:\r
+ Dali::Actor mScene;\r
+\r
+ std::vector<Dali::SceneLoader::AnimationDefinition> mSceneAnimations;\r
+ Dali::Animation mCurrentAnimation;\r
+\r
+ std::unique_ptr<SceneLoaderExtension> mSceneLoaderExtension;\r
+\r
private: // methods\r
void OnInit(Dali::Application& app);\r
void OnTerminate(Dali::Application& app);\r
void OnKey(const Dali::KeyEvent& e);\r
void OnPan(Dali::Actor actor, const Dali::PanGesture& pan);\r
void OnTap(Dali::Actor actor, const Dali::TapGesture& tap);\r
+\r
+ Dali::Actor OnKeyboardPreFocusChange(Dali::Actor current, Dali::Actor proposed, Dali::Toolkit::Control::KeyboardFocus::Direction direction);\r
+ void OnKeyboardFocusedActorActivated(Dali::Actor activatedActor);\r
+ void OnKeyboardFocusChanged(Dali::Actor originalFocusedActor, Dali::Actor currentFocusedActor);\r
};\r
\r
#endif //SCENE_LAUNCHER_H_\r
--- /dev/null
+/*\r
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+#include <dali-toolkit/dali-toolkit.h>\r
+#include <dali/dali.h>\r
+#include <cstring>\r
+\r
+class SceneLoaderExtension : public Dali::ConnectionTracker\r
+{\r
+public:\r
+ SceneLoaderExtension()\r
+ : mSceneLoader(nullptr),\r
+ mCurrentAnimationIndex(ANIMATION_IDLE)\r
+ {\r
+ }\r
+\r
+ ~SceneLoaderExtension() = default; // Nothing to do in destructor\r
+\r
+ void SetSceneLoader(SceneLoaderExample* sceneLoader)\r
+ {\r
+ mSceneLoader = sceneLoader;\r
+ }\r
+\r
+ void ConnectTouchSignals()\r
+ {\r
+ // This is a temporary hack for now to manually connect these signals.\r
+ // We should connect these signals automatically when loading the scene.\r
+\r
+ if(mSceneLoader)\r
+ {\r
+ ConnectTouchSignal(ICON_IDLE);\r
+ ConnectTouchSignal(ICON_SQUAT);\r
+ ConnectTouchSignal(ICON_JUMPING_JACK);\r
+ ConnectTouchSignal(ICON_LUNGE);\r
+ }\r
+ }\r
+\r
+ void OnKey(const Dali::KeyEvent& e)\r
+ {\r
+ // This is a temporary hack for now to manually handle these key events.\r
+ // We should links them to the animations automatically when loading the scene.\r
+\r
+ switch(e.GetKeyCode())\r
+ {\r
+ case KEY_ONE:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_IDLE);\r
+ break;\r
+ }\r
+ case KEY_TWO:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_IDLE_TO_SQUAT);\r
+ break;\r
+ }\r
+ case KEY_THREE:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_IDLE_TO_JUMPING_JACK);\r
+ break;\r
+ }\r
+ case KEY_FOUR:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_IDLE_TO_LUNGE);\r
+ break;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+private:\r
+ bool PlaySceneAnimation(unsigned int animationIndex)\r
+ {\r
+ if(mSceneLoader && mSceneLoader->mScene)\r
+ {\r
+ if(mSceneLoader->mCurrentAnimation &&\r
+ mCurrentAnimationIndex != ANIMATION_IDLE &&\r
+ mSceneLoader->mCurrentAnimation.GetState() != Dali::Animation::STOPPED)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ auto root = mSceneLoader->mScene;\r
+ auto getActor = [&root](const std::string& name) {\r
+ return root.FindChildByName(name);\r
+ };\r
+\r
+ if(mSceneLoader->mSceneAnimations.size() > animationIndex)\r
+ {\r
+ mCurrentAnimationIndex = animationIndex;\r
+ mSceneLoader->mCurrentAnimation = mSceneLoader->mSceneAnimations[animationIndex].ReAnimate(getActor);\r
+ mSceneLoader->mCurrentAnimation.FinishedSignal().Connect(this, &SceneLoaderExtension::OnAnimationFinished);\r
+ mSceneLoader->mCurrentAnimation.Play();\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ void ConnectTouchSignal(const std::string actorName)\r
+ {\r
+ if(mSceneLoader && mSceneLoader->mScene)\r
+ {\r
+ auto actor = mSceneLoader->mScene.FindChildByName(actorName);\r
+ if(actor)\r
+ {\r
+ actor.TouchedSignal().Connect(this, &SceneLoaderExtension::OnTouch);\r
+ }\r
+ }\r
+ }\r
+\r
+ void OnAnimationFinished(Dali::Animation& source)\r
+ {\r
+ switch(mCurrentAnimationIndex)\r
+ {\r
+ case ANIMATION_IDLE_TO_SQUAT:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_SQUAT_TO_IDLE);\r
+ break;\r
+ }\r
+ case ANIMATION_IDLE_TO_JUMPING_JACK:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_JUMPING_JACK);\r
+ break;\r
+ }\r
+ case ANIMATION_JUMPING_JACK:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_JUMPING_JACK_TO_IDLE);\r
+ break;\r
+ }\r
+ case ANIMATION_IDLE_TO_LUNGE:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_LUNGE);\r
+ break;\r
+ }\r
+ case ANIMATION_LUNGE:\r
+ {\r
+ PlaySceneAnimation(ANIMATION_LUNGE_TO_IDLE);\r
+ break;\r
+ }\r
+ default:\r
+ {\r
+ mCurrentAnimationIndex = ANIMATION_IDLE;\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ bool OnTouch(Dali::Actor actor, const Dali::TouchEvent& touch)\r
+ {\r
+ bool processed = false;\r
+\r
+ if(touch.GetPointCount() > 0)\r
+ {\r
+ if(touch.GetState(0) == Dali::PointState::DOWN)\r
+ {\r
+ auto actorName = actor.GetProperty<std::string>(Dali::Actor::Property::NAME);\r
+\r
+ if(ICON_IDLE == actorName)\r
+ {\r
+ processed = PlaySceneAnimation(ANIMATION_IDLE);\r
+ }\r
+ else if(ICON_SQUAT == actorName)\r
+ {\r
+ processed = PlaySceneAnimation(ANIMATION_IDLE_TO_SQUAT);\r
+ }\r
+ else if(ICON_JUMPING_JACK == actorName)\r
+ {\r
+ processed = PlaySceneAnimation(ANIMATION_IDLE_TO_JUMPING_JACK);\r
+ }\r
+ else if(ICON_LUNGE == actorName)\r
+ {\r
+ processed = PlaySceneAnimation(ANIMATION_IDLE_TO_LUNGE);\r
+ }\r
+ }\r
+ }\r
+ return processed;\r
+ }\r
+\r
+private:\r
+ static constexpr unsigned int KEY_ONE = 10;\r
+ static constexpr unsigned int KEY_TWO = 11;\r
+ static constexpr unsigned int KEY_THREE = 12;\r
+ static constexpr unsigned int KEY_FOUR = 13;\r
+\r
+ // Idle animation\r
+ static constexpr unsigned int ANIMATION_IDLE = 0;\r
+ // Squat animation\r
+ static constexpr unsigned int ANIMATION_IDLE_TO_SQUAT = 3;\r
+ static constexpr unsigned int ANIMATION_SQUAT_TO_IDLE = 15;\r
+ // JumpingJack animation\r
+ static constexpr unsigned int ANIMATION_IDLE_TO_JUMPING_JACK = 1;\r
+ static constexpr unsigned int ANIMATION_JUMPING_JACK = 5;\r
+ static constexpr unsigned int ANIMATION_JUMPING_JACK_TO_IDLE = 6;\r
+ // Lunge animation\r
+ static constexpr unsigned int ANIMATION_IDLE_TO_LUNGE = 2;\r
+ static constexpr unsigned int ANIMATION_LUNGE = 9;\r
+ static constexpr unsigned int ANIMATION_LUNGE_TO_IDLE = 10;\r
+\r
+ inline static const std::string ICON_IDLE = "Idle";\r
+ inline static const std::string ICON_SQUAT = "Squat";\r
+ inline static const std::string ICON_JUMPING_JACK = "JumpingJack";\r
+ inline static const std::string ICON_LUNGE = "Lunge";\r
+\r
+ SceneLoaderExample* mSceneLoader;\r
+ unsigned int mCurrentAnimationIndex;\r
+};\r