Updated all files to new format
[platform/core/uifw/dali-demo.git] / examples / color-transition / color-transition.cpp
1 /*
2  * Copyright (c) 2021 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 #include "color-transition-controller.h"
18 #include "dali-toolkit/dali-toolkit.h"
19 #include "dali/dali.h"
20 #include "utils.h"
21
22 using namespace Dali;
23 using namespace Dali::Toolkit;
24
25 namespace
26 {
27 const float TRANSITION_DURATION = 1.f;
28
29 const Vector3 INITIAL_COLOR{1.f, 1.f, .25f};
30
31 const char* const FLOW_MAPS[] = {
32   "circular",
33   "multi-circle",
34   "concentric",
35   "spiral",
36   "conical",
37   "blinds",
38   "radial",
39   "swipe",
40   "bubbles",
41   "image"};
42
43 Texture LoadTexture(const std::string& path)
44 {
45   PixelData pixelData = SyncImageLoader::Load(path);
46
47   Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
48   texture.Upload(pixelData);
49   return texture;
50 }
51
52 TextLabel MakeTextLabel(const char* text, const Vector4& color, float pointSize, const Vector2& size)
53 {
54   auto tl = TextLabel::New(text);
55   CenterActor(tl);
56   tl.SetProperty(Actor::Property::SIZE, size);
57   tl.SetProperty(TextLabel::Property::POINT_SIZE, pointSize);
58   tl.SetProperty(TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
59   tl.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
60   tl.SetProperty(TextLabel::Property::MULTI_LINE, true);
61   tl.SetProperty(TextLabel::Property::TEXT_COLOR, color);
62   return tl;
63 }
64
65 } // namespace
66
67 /**
68  * Demonstrates colour transition using flow maps and uv rotation / scaling.
69  *
70  * Flow maps are greyscale images where the value of the pixels signifies the
71  * progress of the animation, which is added to an animated value which we
72  * use to lerp between old and new colour.
73  *
74  * The colour of the content is used to scale the source / target colour, i.e.
75  * white is affected most, dark is affected less.
76  *
77  * Controls:
78  * - Double-tap middle (33%) of screen: transition using random flow map;
79  * - Double-tap outside the middle of screen: transition using one of the
80  *   effects (flow maps) mapped to the given segment of the screen;
81  */
82 class ColorTransition : public ConnectionTracker
83 {
84 public:
85   ColorTransition(Application& app)
86   : mApp(app)
87   {
88     app.InitSignal().Connect(this, &ColorTransition::OnInit);
89     app.TerminateSignal().Connect(this, &ColorTransition::OnTerminate);
90   }
91
92 private:
93   static void OnTransitionFinished(void* data)
94   {
95     auto& me = *static_cast<ColorTransition*>(data);
96     me.OnTransitionFinished();
97   }
98
99   void OnInit(Application& app)
100   {
101     auto window     = mApp.GetWindow();
102     auto windowSize = Vector2{window.GetSize()};
103
104     // create content root
105     Actor content = Actor::New();
106     CenterActor(content);
107     content.SetProperty(Actor::Property::SIZE, windowSize);
108     window.Add(content);
109     mColorTransitionContent = content;
110
111     // create some example content
112     TextLabel tlHello = MakeTextLabel("<b>HELLO</b>", Vector4::ONE, 60.f, windowSize);
113     tlHello.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
114     tlHello.SetProperty(Actor::Property::POSITION_Y, -60.f);
115     content.Add(tlHello);
116
117     TextLabel tlWorld = MakeTextLabel("<i>WORLD</i>", Vector4(1.f, 1.f, 1.f, .5f), 60.f, windowSize);
118     tlWorld.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
119     tlWorld.SetProperty(Actor::Property::POSITION_Y, 60.f);
120     content.Add(tlWorld);
121
122     ImageView ivIcon = ImageView::New(Application::GetResourcePath() + "images/application-icon-2.png");
123     CenterActor(ivIcon);
124     ivIcon.SetProperty(Actor::Property::POSITION_Y, 120.f);
125     content.Add(ivIcon);
126
127     // create main root
128     Actor mainRoot = Actor::New();
129     CenterActor(mainRoot);
130     window.Add(mainRoot);
131     mMainRoot = mainRoot;
132
133     auto renderTasks     = window.GetRenderTaskList();
134     auto weakRenderTasks = WeakHandle<RenderTaskList>(renderTasks);
135     auto controller      = new ColorTransitionController(weakRenderTasks, content, window.GetRenderTaskList(), INITIAL_COLOR);
136     mController.reset(controller);
137     mainRoot.Add(mController->GetComposite());
138
139     // add content unaffected by effect, to scene.
140     TextLabel tlInstructions = MakeTextLabel("Double tap to change Color", Vector4(.5f, .5f, .5f, 1.f), 10.f, windowSize);
141     tlInstructions.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "TOP");
142     mainRoot.Add(tlInstructions);
143
144     // hook up event handlers
145     window.KeyEventSignal().Connect(this, &ColorTransition::OnKeyEvent);
146
147     auto tapDetector = TapGestureDetector::New(2);
148     tapDetector.DetectedSignal().Connect(this, &ColorTransition::OnDoubleTap);
149     tapDetector.Attach(window.GetRootLayer());
150     mDoubleTapDetector = tapDetector;
151
152     mController->SetOnFinished(OnTransitionFinished, this);
153   }
154
155   void OnTerminate(Application& app)
156   {
157     auto window = mApp.GetWindow();
158     mDoubleTapDetector.Detach(window.GetRootLayer());
159
160     UnparentAndReset(mColorTransitionContent);
161     UnparentAndReset(mMainRoot);
162
163     mController.reset();
164   }
165
166   void OnKeyEvent(const KeyEvent& event)
167   {
168     if(event.GetState() == KeyEvent::DOWN)
169     {
170       if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
171       {
172         mApp.Quit();
173       }
174     }
175   }
176
177   void OnDoubleTap(Actor /*actor*/, const TapGesture& tap)
178   {
179     auto    window     = mApp.GetWindow();
180     auto    windowSize = Vector2{window.GetSize()};
181     Vector2 clip       = tap.GetScreenPoint() / windowSize - Vector2::ONE * .5f; // [-.5, .5]
182     if(clip.Length() < .333f * .5f)
183     {
184       LoadFlowMap(FLOW_MAPS[rand() % std::extent<decltype(FLOW_MAPS)>::value]);
185     }
186     else
187     {
188       float theta = fmodf((atan2(clip.y, clip.x) + M_PI) / (M_PI * 2.) + .75f, 1.f);
189       int   i     = std::extent<decltype(FLOW_MAPS)>::value * theta;
190
191       LoadFlowMap(FLOW_MAPS[i]);
192     }
193     RandomizeUvTransform();
194
195     Vector3 color(rand() % 5, rand() % 5, rand() % 5);
196     color /= 4.f;
197
198     mDoubleTapDetector.Detach(mApp.GetWindow().GetRootLayer());
199     mController->RequestTransition(TRANSITION_DURATION, color);
200   }
201
202   void LoadFlowMap(const char* const name)
203   {
204     DALI_ASSERT_DEBUG(name && "Flow map name must be given");
205     if(mLastFlowMap != name)
206     {
207       std::string flowMapDir  = Application::GetResourcePath() + "images/color-transition/";
208       std::string flowMapPath = flowMapDir + name + ".png";
209       auto        flowMap     = LoadTexture(flowMapPath);
210       DALI_ASSERT_DEBUG(flowMap && "Failed to load flow map.");
211       mController->SetFlowMap(flowMap);
212     }
213   }
214
215   void RandomizeUvTransform()
216   {
217     mController->SetUvTransform((rand() % 12) * M_PI / 12., 1.f, (rand() % 12) * M_PI / 12., .5f);
218   }
219
220   void OnTransitionFinished()
221   {
222     mDoubleTapDetector.Attach(mApp.GetWindow().GetRootLayer());
223   }
224
225   Application& mApp;
226
227   const char* mLastFlowMap = nullptr;
228
229   Actor mColorTransitionContent;
230   Actor mMainRoot;
231
232   std::unique_ptr<ColorTransitionController> mController;
233
234   TapGestureDetector mDoubleTapDetector;
235 };
236
237 int DALI_EXPORT_API main(int argc, char** argv)
238 {
239   auto app = Application::New(&argc, &argv
240 #ifdef WIN32
241                               ,
242                               ".//dali-toolkit-default-theme.json"
243 #endif
244   );
245   ColorTransition ct(app);
246   app.MainLoop();
247   return 0;
248 }