Updated all files to new format
[platform/core/uifw/dali-demo.git] / shared / bubble-animator.cpp
1 /*\r
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  * http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  *\r
16  */\r
17 \r
18 // CLASS HEADER\r
19 #include "bubble-animator.h"\r
20 \r
21 #include <dali-toolkit/devel-api/shader-effects/distance-field-effect.h>\r
22 #include <dali-toolkit/public-api/controls/image-view/image-view.h>\r
23 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>\r
24 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>\r
25 #include <dali/public-api/animation/constraint.h>\r
26 #include <dali/public-api/math/random.h>\r
27 #include <dali/public-api/rendering/shader.h>\r
28 \r
29 using namespace Dali;\r
30 using namespace Dali::Toolkit;\r
31 \r
32 namespace\r
33 {\r
34 const char* const BUBBLE_COLOR_STYLE_NAME[] =\r
35   {\r
36     "BubbleColor1",\r
37     "BubbleColor2",\r
38     "BubbleColor3",\r
39     "BubbleColor4"};\r
40 constexpr int NUMBER_OF_BUBBLE_COLORS(sizeof(BUBBLE_COLOR_STYLE_NAME) / sizeof(BUBBLE_COLOR_STYLE_NAME[0]));\r
41 \r
42 const char* const SHAPE_IMAGE_TABLE[] =\r
43   {\r
44     DEMO_IMAGE_DIR "shape-circle.png",\r
45     DEMO_IMAGE_DIR "shape-bubble.png"};\r
46 constexpr int NUMBER_OF_SHAPE_IMAGES(sizeof(SHAPE_IMAGE_TABLE) / sizeof(SHAPE_IMAGE_TABLE[0]));\r
47 \r
48 constexpr int   NUM_BACKGROUND_IMAGES   = 18;\r
49 constexpr float BACKGROUND_SPREAD_SCALE = 1.5f;\r
50 \r
51 constexpr unsigned int BACKGROUND_ANIMATION_DURATION = 15000; // 15 secs\r
52 \r
53 constexpr float BUBBLE_MIN_Z = -1.0;\r
54 constexpr float BUBBLE_MAX_Z = 0.0f;\r
55 \r
56 /**\r
57  * Constraint to return a position for a bubble based on the scroll value and vertical wrapping\r
58  */\r
59 struct AnimateBubbleConstraint\r
60 {\r
61 public:\r
62   AnimateBubbleConstraint(const Vector3& initialPos, float scale)\r
63   : mInitialX(initialPos.x),\r
64     mScale(scale)\r
65   {\r
66   }\r
67 \r
68   void operator()(Vector3& position, const PropertyInputContainer& inputs)\r
69   {\r
70     const Vector3& parentSize = inputs[1]->GetVector3();\r
71     const Vector3& childSize  = inputs[2]->GetVector3();\r
72 \r
73     // Wrap bubbles vertically.\r
74     float range = parentSize.y + childSize.y;\r
75     // This performs a float mod (we don't use fmod as we want the arithmetic modulus as opposed to the remainder).\r
76     position.y -= range * (floor(position.y / range) + 0.5f);\r
77 \r
78     // Bubbles X position moves parallax to horizontal\r
79     // panning by a scale factor unique to each bubble.\r
80     position.x = mInitialX + (inputs[0]->GetVector2().x * mScale);\r
81   }\r
82 \r
83 private:\r
84   float mInitialX;\r
85   float mScale;\r
86 };\r
87 \r
88 } // unnamed namespace\r
89 \r
90 void BubbleAnimator::Initialize(Dali::Actor parent, Dali::Actor scrollView)\r
91 {\r
92   mScrollView = scrollView;\r
93 \r
94   // Populate background and bubbles - needs to be scrollViewLayer so scroll ends show\r
95   Actor bubbleContainer = Actor::New();\r
96   bubbleContainer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);\r
97   bubbleContainer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);\r
98   bubbleContainer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);\r
99   AddBackgroundActors(bubbleContainer, NUM_BACKGROUND_IMAGES);\r
100   parent.Add(bubbleContainer);\r
101 \r
102   // Background animation\r
103   mAnimationTimer = Timer::New(BACKGROUND_ANIMATION_DURATION);\r
104   mAnimationTimer.TickSignal().Connect(this, &BubbleAnimator::PauseAnimation);\r
105   mAnimationTimer.Start();\r
106   mBackgroundAnimsPlaying = true;\r
107 }\r
108 \r
109 bool BubbleAnimator::PauseAnimation()\r
110 {\r
111   if(mBackgroundAnimsPlaying)\r
112   {\r
113     for(auto&& anim : mBackgroundAnimations)\r
114     {\r
115       anim.Stop();\r
116     }\r
117 \r
118     mBackgroundAnimsPlaying = false;\r
119   }\r
120   return false;\r
121 }\r
122 \r
123 void BubbleAnimator::PlayAnimation()\r
124 {\r
125   if(!mBackgroundAnimsPlaying)\r
126   {\r
127     for(auto&& anim : mBackgroundAnimations)\r
128     {\r
129       anim.Play();\r
130     }\r
131 \r
132     mBackgroundAnimsPlaying = true;\r
133   }\r
134 \r
135   mAnimationTimer.SetInterval(BACKGROUND_ANIMATION_DURATION);\r
136 }\r
137 void BubbleAnimator::InitializeBackgroundActors(Dali::Actor actor)\r
138 {\r
139   // Delete current animations\r
140   mBackgroundAnimations.clear();\r
141 \r
142   // Create new animations\r
143   const Vector3 size = actor.GetTargetSize();\r
144 \r
145   for(unsigned int i = 0, childCount = actor.GetChildCount(); i < childCount; ++i)\r
146   {\r
147     Actor child = actor.GetChildAt(i);\r
148 \r
149     // Calculate a random position\r
150     Vector3 childPos(Random::Range(-size.x * 0.5f * BACKGROUND_SPREAD_SCALE, size.x * 0.85f * BACKGROUND_SPREAD_SCALE),\r
151                      Random::Range(-size.y, size.y),\r
152                      Random::Range(BUBBLE_MIN_Z, BUBBLE_MAX_Z));\r
153 \r
154     child.SetProperty(Actor::Property::POSITION, childPos);\r
155 \r
156     // Define bubble horizontal parallax and vertical wrapping\r
157     Actor scrollView = mScrollView.GetHandle();\r
158     if(scrollView)\r
159     {\r
160       Constraint animConstraint = Constraint::New<Vector3>(child, Actor::Property::POSITION, AnimateBubbleConstraint(childPos, Random::Range(-0.85f, 0.25f)));\r
161       animConstraint.AddSource(Source(scrollView, ScrollView::Property::SCROLL_POSITION));\r
162       animConstraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE));\r
163       animConstraint.AddSource(Dali::LocalSource(Dali::Actor::Property::SIZE));\r
164       animConstraint.SetRemoveAction(Constraint::DISCARD);\r
165       animConstraint.Apply();\r
166     }\r
167 \r
168     // Kickoff animation\r
169     Animation animation = Animation::New(Random::Range(30.0f, 160.0f));\r
170     animation.AnimateBy(Property(child, Actor::Property::POSITION), Vector3(0.0f, -2000.0f, 0.0f), AlphaFunction::LINEAR);\r
171     animation.SetLooping(true);\r
172     animation.Play();\r
173     mBackgroundAnimations.push_back(animation);\r
174   }\r
175 }\r
176 \r
177 void BubbleAnimator::AddBackgroundActors(Actor layer, int count)\r
178 {\r
179   for(int i = 0; i < count; ++i)\r
180   {\r
181     float randSize  = Random::Range(10.0f, 400.0f);\r
182     int   shapeType = static_cast<int>(Random::Range(0.0f, NUMBER_OF_SHAPE_IMAGES - 1) + 0.5f);\r
183 \r
184     ImageView dfActor = ImageView::New();\r
185     dfActor.SetProperty(Actor::Property::SIZE, Vector2(randSize, randSize));\r
186     dfActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);\r
187 \r
188     // Set the Image URL and the custom shader at the same time\r
189     Dali::Property::Map effect = Toolkit::CreateDistanceFieldEffect();\r
190     Property::Map       imageMap;\r
191     imageMap.Add(ImageVisual::Property::URL, SHAPE_IMAGE_TABLE[shapeType]);\r
192     imageMap.Add(Toolkit::Visual::Property::SHADER, effect);\r
193     dfActor.SetProperty(Toolkit::ImageView::Property::IMAGE, imageMap);\r
194 \r
195     dfActor.SetStyleName(BUBBLE_COLOR_STYLE_NAME[i % NUMBER_OF_BUBBLE_COLORS]);\r
196 \r
197     layer.Add(dfActor);\r
198   }\r
199 \r
200   // Positioning will occur when the layer is relaid out\r
201   layer.OnRelayoutSignal().Connect(this, &BubbleAnimator::InitializeBackgroundActors);\r
202 }\r