Commit 9d495af712dba543fb58953d824eb45ad52fbf9d

Authored by Adeel Kazmi
Committed by Gerrit Code Review
2 parents 0c34fa5a 0dea4641

Merge "Add keyboard support and animation control in SceneLoader demo" into devel/master

examples/scene-loader/scene-loader-example.cpp
1 1 /*
2   - * Copyright (c) 2021 Samsung Electronics Co., Ltd.
  2 + * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -15,6 +15,7 @@
15 15 *
16 16 */
17 17 #include "scene-loader-example.h"
  18 +#include <dali-toolkit/dali-toolkit.h>
18 19 #include <dirent.h>
19 20 #include <cstring>
20 21 #include <string_view>
... ... @@ -32,6 +33,7 @@
32 33 #include "dali/public-api/events/key-event.h"
33 34 #include "dali/public-api/object/property-array.h"
34 35 #include "dali/public-api/render-tasks/render-task-list.h"
  36 +#include "scene-loader-extension.h"
35 37  
36 38 using namespace Dali;
37 39 using namespace Dali::Toolkit;
... ... @@ -80,10 +82,11 @@ StringVector ListFiles(
80 82  
81 83 TextLabel MakeLabel(std::string msg)
82 84 {
83   - TextLabel label = TextLabel::New(msg);
  85 + TextLabel label = TextLabel::New(" " + msg);
84 86 label.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
85 87 label.SetProperty(TextLabel::Property::TEXT_COLOR, Color::WHITE);
86 88 label.SetProperty(TextLabel::Property::PIXEL_SIZE, ITEM_HEIGHT * 4 / 7);
  89 + label.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
87 90 SetActorCentered(label);
88 91 return label;
89 92 }
... ... @@ -108,6 +111,7 @@ struct ItemFactoryImpl : Dali::Toolkit::ItemFactory
108 111 {
109 112 auto label = MakeLabel(mSceneNames[itemId]);
110 113 mTapDetector.Attach(label);
  114 + label.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
111 115 return label;
112 116 }
113 117 };
... ... @@ -172,7 +176,7 @@ void ConfigureBlendShapeShaders(ResourceBundle&amp; resources, const SceneDefinition
172 176 }
173 177 }
174 178  
175   -Actor LoadScene(std::string sceneName, CameraActor camera)
  179 +Actor LoadScene(std::string sceneName, CameraActor camera, std::vector<AnimationDefinition>* animations, Animation& animation)
176 180 {
177 181 ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) {
178 182 return Application::GetResourcePath() + RESOURCE_TYPE_DIRS[type];
... ... @@ -185,12 +189,13 @@ Actor LoadScene(std::string sceneName, CameraActor camera)
185 189 std::vector<AnimationGroupDefinition> animGroups;
186 190 std::vector<CameraParameters> cameraParameters;
187 191 std::vector<LightParameters> lights;
188   - std::vector<AnimationDefinition> animations;
  192 +
  193 + animations->clear();
189 194  
190 195 LoadResult output{
191 196 resources,
192 197 scene,
193   - animations,
  198 + *animations,
194 199 animGroups,
195 200 cameraParameters,
196 201 lights};
... ... @@ -262,13 +267,14 @@ Actor LoadScene(std::string sceneName, CameraActor camera)
262 267 }
263 268 }
264 269  
265   - if(!animations.empty())
  270 + if(!animations->empty())
266 271 {
267 272 auto getActor = [&root](const std::string& name) {
268 273 return root.FindChildByName(name);
269 274 };
270 275  
271   - animations[0].ReAnimate(getActor).Play();
  276 + animation = (*animations)[0].ReAnimate(getActor);
  277 + animation.Play();
272 278 }
273 279  
274 280 return root;
... ... @@ -277,7 +283,8 @@ Actor LoadScene(std::string sceneName, CameraActor camera)
277 283 } // namespace
278 284  
279 285 SceneLoaderExample::SceneLoaderExample(Dali::Application& app)
280   -: mApp(app)
  286 +: mApp(app),
  287 + mSceneLoaderExtension(new SceneLoaderExtension())
281 288 {
282 289 if(!std::getenv("DALI_APPLICATION_PACKAGE"))
283 290 {
... ... @@ -295,6 +302,8 @@ SceneLoaderExample::SceneLoaderExample(Dali::Application&amp; app)
295 302 app.TerminateSignal().Connect(this, &SceneLoaderExample::OnTerminate);
296 303 }
297 304  
  305 +SceneLoaderExample::~SceneLoaderExample() = default;
  306 +
298 307 void SceneLoaderExample::OnInit(Application& app)
299 308 {
300 309 // get scenes
... ... @@ -346,13 +355,20 @@ void SceneLoaderExample::OnInit(Application&amp; app)
346 355  
347 356 Vector3 windowSize(window.GetSize());
348 357 auto itemLayout = DefaultItemLayout::New(DefaultItemLayout::LIST);
349   - itemLayout->SetItemSize(Vector3(windowSize.x, ITEM_HEIGHT, 1.f));
  358 + itemLayout->SetItemSize(Vector3(windowSize.x * 0.9f, ITEM_HEIGHT, 1.f));
350 359 items.AddLayout(*itemLayout);
351 360 navigationView.Push(items);
352 361  
353 362 mItemLayout = itemLayout;
354 363 mItemView = items;
355 364  
  365 + mItemView.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
  366 + KeyboardFocusManager::Get().PreFocusChangeSignal().Connect(this, &SceneLoaderExample::OnKeyboardPreFocusChange);
  367 + KeyboardFocusManager::Get().FocusedActorEnterKeySignal().Connect(this, &SceneLoaderExample::OnKeyboardFocusedActorActivated);
  368 + KeyboardFocusManager::Get().FocusChangedSignal().Connect(this, &SceneLoaderExample::OnKeyboardFocusChanged);
  369 +
  370 + SetActorCentered(KeyboardFocusManager::Get().GetFocusIndicatorActor());
  371 +
356 372 // camera
357 373 auto camera = CameraActor::New();
358 374 camera.SetInvertYAxis(true);
... ... @@ -366,7 +382,36 @@ void SceneLoaderExample::OnInit(Application&amp; app)
366 382 mTapDetector = tapDetector;
367 383  
368 384 // activate layout
369   - mItemView.ActivateLayout(0, windowSize, 1.f);
  385 + mItemView.ActivateLayout(0, windowSize, 0.f);
  386 +
  387 + mSceneLoaderExtension->SetSceneLoader(this);
  388 +}
  389 +
  390 +Actor SceneLoaderExample::OnKeyboardPreFocusChange(Actor current, Actor proposed, Control::KeyboardFocus::Direction direction)
  391 +{
  392 + if(!current && !proposed)
  393 + {
  394 + return mItemView;
  395 + }
  396 +
  397 + return proposed;
  398 +}
  399 +
  400 +void SceneLoaderExample::OnKeyboardFocusedActorActivated(Actor activatedActor)
  401 +{
  402 + if(activatedActor)
  403 + {
  404 + OnTap(activatedActor, Dali::TapGesture());
  405 + }
  406 +}
  407 +
  408 +void SceneLoaderExample::OnKeyboardFocusChanged(Actor originalFocusedActor, Actor currentFocusedActor)
  409 +{
  410 + if(currentFocusedActor)
  411 + {
  412 + auto itemId = mItemView.GetItemId(currentFocusedActor);
  413 + mItemView.ScrollToItem(itemId, 0.1f);
  414 + }
370 415 }
371 416  
372 417 void SceneLoaderExample::OnTerminate(Application& app)
... ... @@ -397,12 +442,21 @@ void SceneLoaderExample::OnKey(const KeyEvent&amp; e)
397 442  
398 443 mNavigationView.Pop();
399 444 mScene.Reset();
  445 +
  446 + if(mActivatedActor)
  447 + {
  448 + KeyboardFocusManager::Get().SetCurrentFocusActor(mActivatedActor);
  449 + }
400 450 }
401 451 else
402 452 {
403 453 mApp.Quit();
404 454 }
405 455 }
  456 + else
  457 + {
  458 + mSceneLoaderExtension->OnKey(e);
  459 + }
406 460 }
407 461 }
408 462  
... ... @@ -424,6 +478,8 @@ void SceneLoaderExample::OnPan(Actor actor, const PanGesture&amp; pan)
424 478  
425 479 void SceneLoaderExample::OnTap(Dali::Actor actor, const Dali::TapGesture& tap)
426 480 {
  481 + mActivatedActor = actor;
  482 +
427 483 auto id = mItemView.GetItemId(actor);
428 484  
429 485 try
... ... @@ -432,7 +488,7 @@ void SceneLoaderExample::OnTap(Dali::Actor actor, const Dali::TapGesture&amp; tap)
432 488 auto renderTasks = window.GetRenderTaskList();
433 489 renderTasks.RemoveTask(mSceneRender);
434 490  
435   - auto scene = LoadScene(mSceneNames[id], mSceneCamera);
  491 + auto scene = LoadScene(mSceneNames[id], mSceneCamera, &mSceneAnimations, mCurrentAnimation);
436 492  
437 493 auto sceneRender = renderTasks.CreateTask();
438 494 sceneRender.SetCameraActor(mSceneCamera);
... ... @@ -452,4 +508,6 @@ void SceneLoaderExample::OnTap(Dali::Actor actor, const Dali::TapGesture&amp; tap)
452 508 }
453 509  
454 510 mNavigationView.Push(mScene);
  511 +
  512 + mSceneLoaderExtension->ConnectTouchSignals();
455 513 }
... ...
examples/scene-loader/scene-loader-example.h
1 1 #ifndef SCENE_LAUNCHER_H_
2 2 #define SCENE_LAUNCHER_H_
3 3 /*
4   - * Copyright (c) 2021 Samsung Electronics Co., Ltd.
  4 + * Copyright (c) 2022 Samsung Electronics Co., Ltd.
5 5 *
6 6 * Licensed under the Apache License, Version 2.0 (the "License");
7 7 * you may not use this file except in compliance with the License.
... ... @@ -16,6 +16,8 @@
16 16 * limitations under the License.
17 17 *
18 18 */
  19 +
  20 +#include <memory>
19 21 #include "dali-scene-loader/public-api/animation-definition.h"
20 22 #include "dali-scene-loader/public-api/camera-parameters.h"
21 23 #include "dali-scene-loader/public-api/node-definition.h"
... ... @@ -31,11 +33,13 @@
31 33 #include "dali/public-api/render-tasks/render-task.h"
32 34 #include "dali/public-api/signals/connection-tracker.h"
33 35  
  36 +class SceneLoaderExtension;
  37 +
34 38 class SceneLoaderExample : public Dali::ConnectionTracker
35 39 {
36 40 public:
37 41 SceneLoaderExample(Dali::Application& app);
38   - ~SceneLoaderExample() = default;
  42 + ~SceneLoaderExample();
39 43  
40 44 private: // data
41 45 Dali::Application& mApp;
... ... @@ -50,13 +54,22 @@ private: // data
50 54  
51 55 Dali::CameraActor mSceneCamera;
52 56 Dali::RenderTask mSceneRender;
53   - Dali::Actor mScene;
54 57  
55 58 Dali::Quaternion mCameraOrientationInv;
56 59  
57 60 Dali::TapGestureDetector mTapDetector;
58 61 Dali::PanGestureDetector mPanDetector;
59 62  
  63 + Dali::Actor mActivatedActor;
  64 +
  65 +public:
  66 + Dali::Actor mScene;
  67 +
  68 + std::vector<Dali::SceneLoader::AnimationDefinition> mSceneAnimations;
  69 + Dali::Animation mCurrentAnimation;
  70 +
  71 + std::unique_ptr<SceneLoaderExtension> mSceneLoaderExtension;
  72 +
60 73 private: // methods
61 74 void OnInit(Dali::Application& app);
62 75 void OnTerminate(Dali::Application& app);
... ... @@ -64,6 +77,10 @@ private: // methods
64 77 void OnKey(const Dali::KeyEvent& e);
65 78 void OnPan(Dali::Actor actor, const Dali::PanGesture& pan);
66 79 void OnTap(Dali::Actor actor, const Dali::TapGesture& tap);
  80 +
  81 + Dali::Actor OnKeyboardPreFocusChange(Dali::Actor current, Dali::Actor proposed, Dali::Toolkit::Control::KeyboardFocus::Direction direction);
  82 + void OnKeyboardFocusedActorActivated(Dali::Actor activatedActor);
  83 + void OnKeyboardFocusChanged(Dali::Actor originalFocusedActor, Dali::Actor currentFocusedActor);
67 84 };
68 85  
69 86 #endif //SCENE_LAUNCHER_H_
... ...
examples/scene-loader/scene-loader-extension.h 0 โ†’ 100644
  1 +/*
  2 + * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + *
  16 + */
  17 +
  18 +#include <dali-toolkit/dali-toolkit.h>
  19 +#include <dali/dali.h>
  20 +#include <cstring>
  21 +
  22 +class SceneLoaderExtension : public Dali::ConnectionTracker
  23 +{
  24 +public:
  25 + SceneLoaderExtension()
  26 + : mSceneLoader(nullptr),
  27 + mCurrentAnimationIndex(ANIMATION_IDLE)
  28 + {
  29 + }
  30 +
  31 + ~SceneLoaderExtension() = default; // Nothing to do in destructor
  32 +
  33 + void SetSceneLoader(SceneLoaderExample* sceneLoader)
  34 + {
  35 + mSceneLoader = sceneLoader;
  36 + }
  37 +
  38 + void ConnectTouchSignals()
  39 + {
  40 + // This is a temporary hack for now to manually connect these signals.
  41 + // We should connect these signals automatically when loading the scene.
  42 +
  43 + if(mSceneLoader)
  44 + {
  45 + ConnectTouchSignal(ICON_IDLE);
  46 + ConnectTouchSignal(ICON_SQUAT);
  47 + ConnectTouchSignal(ICON_JUMPING_JACK);
  48 + ConnectTouchSignal(ICON_LUNGE);
  49 + }
  50 + }
  51 +
  52 + void OnKey(const Dali::KeyEvent& e)
  53 + {
  54 + // This is a temporary hack for now to manually handle these key events.
  55 + // We should links them to the animations automatically when loading the scene.
  56 +
  57 + switch(e.GetKeyCode())
  58 + {
  59 + case KEY_ONE:
  60 + {
  61 + PlaySceneAnimation(ANIMATION_IDLE);
  62 + break;
  63 + }
  64 + case KEY_TWO:
  65 + {
  66 + PlaySceneAnimation(ANIMATION_IDLE_TO_SQUAT);
  67 + break;
  68 + }
  69 + case KEY_THREE:
  70 + {
  71 + PlaySceneAnimation(ANIMATION_IDLE_TO_JUMPING_JACK);
  72 + break;
  73 + }
  74 + case KEY_FOUR:
  75 + {
  76 + PlaySceneAnimation(ANIMATION_IDLE_TO_LUNGE);
  77 + break;
  78 + }
  79 + default:
  80 + break;
  81 + }
  82 + }
  83 +
  84 +private:
  85 + bool PlaySceneAnimation(unsigned int animationIndex)
  86 + {
  87 + if(mSceneLoader && mSceneLoader->mScene)
  88 + {
  89 + if(mSceneLoader->mCurrentAnimation &&
  90 + mCurrentAnimationIndex != ANIMATION_IDLE &&
  91 + mSceneLoader->mCurrentAnimation.GetState() != Dali::Animation::STOPPED)
  92 + {
  93 + return false;
  94 + }
  95 +
  96 + auto root = mSceneLoader->mScene;
  97 + auto getActor = [&root](const std::string& name) {
  98 + return root.FindChildByName(name);
  99 + };
  100 +
  101 + if(mSceneLoader->mSceneAnimations.size() > animationIndex)
  102 + {
  103 + mCurrentAnimationIndex = animationIndex;
  104 + mSceneLoader->mCurrentAnimation = mSceneLoader->mSceneAnimations[animationIndex].ReAnimate(getActor);
  105 + mSceneLoader->mCurrentAnimation.FinishedSignal().Connect(this, &SceneLoaderExtension::OnAnimationFinished);
  106 + mSceneLoader->mCurrentAnimation.Play();
  107 + }
  108 + }
  109 +
  110 + return true;
  111 + }
  112 +
  113 + void ConnectTouchSignal(const std::string actorName)
  114 + {
  115 + if(mSceneLoader && mSceneLoader->mScene)
  116 + {
  117 + auto actor = mSceneLoader->mScene.FindChildByName(actorName);
  118 + if(actor)
  119 + {
  120 + actor.TouchedSignal().Connect(this, &SceneLoaderExtension::OnTouch);
  121 + }
  122 + }
  123 + }
  124 +
  125 + void OnAnimationFinished(Dali::Animation& source)
  126 + {
  127 + switch(mCurrentAnimationIndex)
  128 + {
  129 + case ANIMATION_IDLE_TO_SQUAT:
  130 + {
  131 + PlaySceneAnimation(ANIMATION_SQUAT_TO_IDLE);
  132 + break;
  133 + }
  134 + case ANIMATION_IDLE_TO_JUMPING_JACK:
  135 + {
  136 + PlaySceneAnimation(ANIMATION_JUMPING_JACK);
  137 + break;
  138 + }
  139 + case ANIMATION_JUMPING_JACK:
  140 + {
  141 + PlaySceneAnimation(ANIMATION_JUMPING_JACK_TO_IDLE);
  142 + break;
  143 + }
  144 + case ANIMATION_IDLE_TO_LUNGE:
  145 + {
  146 + PlaySceneAnimation(ANIMATION_LUNGE);
  147 + break;
  148 + }
  149 + case ANIMATION_LUNGE:
  150 + {
  151 + PlaySceneAnimation(ANIMATION_LUNGE_TO_IDLE);
  152 + break;
  153 + }
  154 + default:
  155 + {
  156 + mCurrentAnimationIndex = ANIMATION_IDLE;
  157 + break;
  158 + }
  159 + break;
  160 + }
  161 + }
  162 +
  163 + bool OnTouch(Dali::Actor actor, const Dali::TouchEvent& touch)
  164 + {
  165 + bool processed = false;
  166 +
  167 + if(touch.GetPointCount() > 0)
  168 + {
  169 + if(touch.GetState(0) == Dali::PointState::DOWN)
  170 + {
  171 + auto actorName = actor.GetProperty<std::string>(Dali::Actor::Property::NAME);
  172 +
  173 + if(ICON_IDLE == actorName)
  174 + {
  175 + processed = PlaySceneAnimation(ANIMATION_IDLE);
  176 + }
  177 + else if(ICON_SQUAT == actorName)
  178 + {
  179 + processed = PlaySceneAnimation(ANIMATION_IDLE_TO_SQUAT);
  180 + }
  181 + else if(ICON_JUMPING_JACK == actorName)
  182 + {
  183 + processed = PlaySceneAnimation(ANIMATION_IDLE_TO_JUMPING_JACK);
  184 + }
  185 + else if(ICON_LUNGE == actorName)
  186 + {
  187 + processed = PlaySceneAnimation(ANIMATION_IDLE_TO_LUNGE);
  188 + }
  189 + }
  190 + }
  191 + return processed;
  192 + }
  193 +
  194 +private:
  195 + static constexpr unsigned int KEY_ONE = 10;
  196 + static constexpr unsigned int KEY_TWO = 11;
  197 + static constexpr unsigned int KEY_THREE = 12;
  198 + static constexpr unsigned int KEY_FOUR = 13;
  199 +
  200 + // Idle animation
  201 + static constexpr unsigned int ANIMATION_IDLE = 0;
  202 + // Squat animation
  203 + static constexpr unsigned int ANIMATION_IDLE_TO_SQUAT = 3;
  204 + static constexpr unsigned int ANIMATION_SQUAT_TO_IDLE = 15;
  205 + // JumpingJack animation
  206 + static constexpr unsigned int ANIMATION_IDLE_TO_JUMPING_JACK = 1;
  207 + static constexpr unsigned int ANIMATION_JUMPING_JACK = 5;
  208 + static constexpr unsigned int ANIMATION_JUMPING_JACK_TO_IDLE = 6;
  209 + // Lunge animation
  210 + static constexpr unsigned int ANIMATION_IDLE_TO_LUNGE = 2;
  211 + static constexpr unsigned int ANIMATION_LUNGE = 9;
  212 + static constexpr unsigned int ANIMATION_LUNGE_TO_IDLE = 10;
  213 +
  214 + inline static const std::string ICON_IDLE = "Idle";
  215 + inline static const std::string ICON_SQUAT = "Squat";
  216 + inline static const std::string ICON_JUMPING_JACK = "JumpingJack";
  217 + inline static const std::string ICON_LUNGE = "Lunge";
  218 +
  219 + SceneLoaderExample* mSceneLoader;
  220 + unsigned int mCurrentAnimationIndex;
  221 +};
... ...