2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "color-transition-controller.h"
18 #include "dali-toolkit/dali-toolkit.h"
19 #include "dali/dali.h"
23 using namespace Dali::Toolkit;
27 const float TRANSITION_DURATION = 1.f;
29 const Vector3 INITIAL_COLOR{1.f, 1.f, .25f};
31 const char* const FLOW_MAPS[] = {
43 Texture LoadTexture(const std::string& path)
45 PixelData pixelData = SyncImageLoader::Load(path);
47 Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
48 texture.Upload(pixelData);
52 TextLabel MakeTextLabel(const char* text, const Vector4& color, float pointSize, const Vector2& size)
54 auto tl = TextLabel::New(text);
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);
68 * Demonstrates colour transition using flow maps and uv rotation / scaling.
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.
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.
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;
82 class ColorTransition : public ConnectionTracker
85 ColorTransition(Application& app)
88 app.InitSignal().Connect(this, &ColorTransition::OnInit);
89 app.TerminateSignal().Connect(this, &ColorTransition::OnTerminate);
93 static void OnTransitionFinished(void* data)
95 auto& me = *static_cast<ColorTransition*>(data);
96 me.OnTransitionFinished();
99 void OnInit(Application& app)
101 auto window = mApp.GetWindow();
102 auto windowSize = Vector2{window.GetSize()};
104 // create content root
105 Actor content = Actor::New();
106 CenterActor(content);
107 content.SetProperty(Actor::Property::SIZE, windowSize);
109 mColorTransitionContent = content;
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);
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);
122 ImageView ivIcon = ImageView::New(Application::GetResourcePath() + "images/application-icon-2.png");
124 ivIcon.SetProperty(Actor::Property::POSITION_Y, 120.f);
128 Actor mainRoot = Actor::New();
129 CenterActor(mainRoot);
130 window.Add(mainRoot);
131 mMainRoot = mainRoot;
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());
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);
144 // hook up event handlers
145 window.KeyEventSignal().Connect(this, &ColorTransition::OnKeyEvent);
147 auto tapDetector = TapGestureDetector::New(2);
148 tapDetector.DetectedSignal().Connect(this, &ColorTransition::OnDoubleTap);
149 tapDetector.Attach(window.GetRootLayer());
150 mDoubleTapDetector = tapDetector;
152 mController->SetOnFinished(OnTransitionFinished, this);
155 void OnTerminate(Application& app)
157 auto window = mApp.GetWindow();
158 mDoubleTapDetector.Detach(window.GetRootLayer());
160 UnparentAndReset(mColorTransitionContent);
161 UnparentAndReset(mMainRoot);
166 void OnKeyEvent(const KeyEvent& event)
168 if(event.GetState() == KeyEvent::DOWN)
170 if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
177 void OnDoubleTap(Actor /*actor*/, const TapGesture& tap)
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)
184 LoadFlowMap(FLOW_MAPS[rand() % std::extent<decltype(FLOW_MAPS)>::value]);
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;
191 LoadFlowMap(FLOW_MAPS[i]);
193 RandomizeUvTransform();
195 Vector3 color(rand() % 5, rand() % 5, rand() % 5);
198 mDoubleTapDetector.Detach(mApp.GetWindow().GetRootLayer());
199 mController->RequestTransition(TRANSITION_DURATION, color);
202 void LoadFlowMap(const char* const name)
204 DALI_ASSERT_DEBUG(name && "Flow map name must be given");
205 if(mLastFlowMap != name)
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);
215 void RandomizeUvTransform()
217 mController->SetUvTransform((rand() % 12) * M_PI / 12., 1.f, (rand() % 12) * M_PI / 12., .5f);
220 void OnTransitionFinished()
222 mDoubleTapDetector.Attach(mApp.GetWindow().GetRootLayer());
227 const char* mLastFlowMap = nullptr;
229 Actor mColorTransitionContent;
232 std::unique_ptr<ColorTransitionController> mController;
234 TapGestureDetector mDoubleTapDetector;
237 int DALI_EXPORT_API main(int argc, char** argv)
239 auto app = Application::New(&argc, &argv
242 ".//dali-toolkit-default-theme.json"
245 ColorTransition ct(app);