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.
18 #include "color-transition-controller.h"
19 #include "dali/dali.h"
20 #include "dali-toolkit/dali-toolkit.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[] = {
44 Texture LoadTexture(const std::string& path)
46 PixelData pixelData = SyncImageLoader::Load(path);
48 Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(),
49 pixelData.GetWidth(), pixelData.GetHeight());
50 texture.Upload(pixelData);
54 TextLabel MakeTextLabel(const char* text, const Vector4& color, float pointSize, const Vector2& size)
56 auto tl = TextLabel::New(text);
58 tl.SetProperty(Actor::Property::SIZE, size);
59 tl.SetProperty(TextLabel::Property::POINT_SIZE, pointSize);
60 tl.SetProperty(TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
61 tl.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
62 tl.SetProperty(TextLabel::Property::MULTI_LINE, true);
63 tl.SetProperty(TextLabel::Property::TEXT_COLOR, color);
70 * Demonstrates colour transition using flow maps and uv rotation / scaling.
72 * Flow maps are greyscale images where the value of the pixels signifies the
73 * progress of the animation, which is added to an animated value which we
74 * use to lerp between old and new colour.
76 * The colour of the content is used to scale the source / target colour, i.e.
77 * white is affected most, dark is affected less.
80 * - Double-tap middle (33%) of screen: transition using random flow map;
81 * - Double-tap outside the middle of screen: transition using one of the
82 * effects (flow maps) mapped to the given segment of the screen;
84 class ColorTransition: public ConnectionTracker
87 ColorTransition(Application& app)
90 app.InitSignal().Connect(this, &ColorTransition::OnInit);
91 app.TerminateSignal().Connect(this, &ColorTransition::OnTerminate);
95 static void OnTransitionFinished(void* data)
97 auto& me = *static_cast<ColorTransition*>(data);
98 me.OnTransitionFinished();
101 void OnInit(Application& app)
103 auto window = mApp.GetWindow();
104 auto windowSize = Vector2{ window.GetSize() };
106 // create content root
107 Actor content = Actor::New();
108 CenterActor(content);
109 content.SetProperty(Actor::Property::SIZE, windowSize);
111 mColorTransitionContent = content;
113 // create some example content
114 TextLabel tlHello = MakeTextLabel("<b>HELLO</b>", Vector4::ONE, 60.f, windowSize);
115 tlHello.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
116 tlHello.SetProperty(Actor::Property::POSITION_Y, -60.f);
117 content.Add(tlHello);
119 TextLabel tlWorld = MakeTextLabel("<i>WORLD</i>", Vector4(1.f, 1.f, 1.f, .5f), 60.f, windowSize);
120 tlWorld.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
121 tlWorld.SetProperty(Actor::Property::POSITION_Y, 60.f);
122 content.Add(tlWorld);
124 ImageView ivIcon = ImageView::New(Application::GetResourcePath() + "images/application-icon-2.png");
126 ivIcon.SetProperty(Actor::Property::POSITION_Y, 120.f);
130 Actor mainRoot = Actor::New();
131 CenterActor(mainRoot);
132 window.Add(mainRoot);
133 mMainRoot = mainRoot;
135 auto renderTasks = window.GetRenderTaskList();
136 auto weakRenderTasks = WeakHandle<RenderTaskList>(renderTasks);
137 auto controller = new ColorTransitionController(weakRenderTasks, content, window.GetRenderTaskList(), INITIAL_COLOR);
138 mController.reset(controller);
139 mainRoot.Add(mController->GetComposite());
141 // add content unaffected by effect, to scene.
142 TextLabel tlInstructions = MakeTextLabel("Double tap to change Color", Vector4(.5f, .5f, .5f, 1.f), 10.f, windowSize);
143 tlInstructions.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "TOP");
144 mainRoot.Add(tlInstructions);
146 // hook up event handlers
147 window.KeyEventSignal().Connect(this, &ColorTransition::OnKeyEvent);
149 auto tapDetector = TapGestureDetector::New(2);
150 tapDetector.DetectedSignal().Connect(this, &ColorTransition::OnDoubleTap);
151 tapDetector.Attach(window.GetRootLayer());
152 mDoubleTapDetector = tapDetector;
154 mController->SetOnFinished(OnTransitionFinished, this);
157 void OnTerminate(Application& app)
159 auto window = mApp.GetWindow();
160 mDoubleTapDetector.Detach(window.GetRootLayer());
162 UnparentAndReset(mColorTransitionContent);
163 UnparentAndReset(mMainRoot);
168 void OnKeyEvent(const KeyEvent& event)
170 if (event.GetState() == KeyEvent::DOWN)
172 if (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
179 void OnDoubleTap(Actor /*actor*/, const TapGesture& tap)
181 auto window = mApp.GetWindow();
182 auto windowSize = Vector2{ window.GetSize() };
183 Vector2 clip = tap.GetScreenPoint() / windowSize - Vector2::ONE * .5f; // [-.5, .5]
184 if (clip.Length() < .333f * .5f)
186 LoadFlowMap(FLOW_MAPS[rand() % std::extent<decltype(FLOW_MAPS)>::value]);
190 float theta = fmodf((atan2(clip.y, clip.x) + M_PI) / (M_PI * 2.) + .75f, 1.f);
191 int i = std::extent<decltype(FLOW_MAPS)>::value * theta;
193 LoadFlowMap(FLOW_MAPS[i]);
195 RandomizeUvTransform();
197 Vector3 color(rand() % 5, rand() % 5, rand() % 5);
200 mDoubleTapDetector.Detach(mApp.GetWindow().GetRootLayer());
201 mController->RequestTransition(TRANSITION_DURATION, color);
204 void LoadFlowMap(const char* const name)
206 DALI_ASSERT_DEBUG(name && "Flow map name must be given");
207 if (mLastFlowMap != name)
209 std::string flowMapDir = Application::GetResourcePath() + "images/color-transition/";
210 std::string flowMapPath = flowMapDir + name + ".png";
211 auto flowMap = LoadTexture(flowMapPath);
212 DALI_ASSERT_DEBUG(flowMap && "Failed to load flow map.");
213 mController->SetFlowMap(flowMap);
217 void RandomizeUvTransform()
219 mController->SetUvTransform((rand() % 12) * M_PI / 12., 1.f,
220 (rand() % 12) * M_PI / 12., .5f);
223 void OnTransitionFinished()
225 mDoubleTapDetector.Attach(mApp.GetWindow().GetRootLayer());
230 const char* mLastFlowMap = nullptr;
232 Actor mColorTransitionContent;
235 std::unique_ptr<ColorTransitionController> mController;
237 TapGestureDetector mDoubleTapDetector;
240 int DALI_EXPORT_API main(int argc, char** argv)
242 auto app = Application::New(&argc, &argv
244 , ".//dali-toolkit-default-theme.json"
247 ColorTransition ct(app);