d9cb20848a89995e134114a13f8566b329aa45e9
[platform/core/uifw/dali-demo.git] / examples / color-transition / color-transition-controller.cpp
1 /*
2  * Copyright (c) 2020 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 "utils.h"
19 #include "dali/dali.h"
20 #include "dali-toolkit/dali-toolkit.h"
21
22 using namespace Dali;
23 using namespace Dali::Toolkit;
24
25 namespace
26 {
27
28 const Vector4 BG_COLOR = Vector4(0.f, 0.f, 0.f, 0.f);
29
30 const char* const COMPOSITE_VSH = DALI_COMPOSE_SHADER(
31 precision mediump float;
32
33 // <DALI>
34 uniform mat4 uMvpMatrix;
35 uniform vec3 uSize;
36 // </DALI>
37
38 uniform float uFlow;
39 uniform vec4 uUvTransform; // rotation, scale (initial, target))
40
41 attribute vec2 aPosition;
42
43 varying vec2 vUv;
44 varying vec2 vUvFlow;
45
46 void main()
47 {
48   vec4 position = uMvpMatrix * vec4(aPosition * uSize.xy, 0., 1.);
49
50   gl_Position = position;
51
52   vec2 uv = position.xy / (position.ww * 2.);
53   vUv = uv + vec2(.5);
54
55   float alpha = uFlow * .5 + .5;
56   vec2 uvRotationScale = mix(uUvTransform.xy, uUvTransform.zw, alpha);
57   float c = cos(uvRotationScale.x) * uvRotationScale.y;
58   float s = sin(uvRotationScale.x) * uvRotationScale.y;
59   vec4 uvMatrix = vec4(c, -s, s, c);
60   uv = vec2(dot(uvMatrix.xy, uv), dot(uvMatrix.zw, uv));
61
62   // N.B. +y is down which is well aligned with the inverted y of the off-screen render,
63   // however we need to flip the y of the uvs for the flow map.
64   vUvFlow = vec2(uv.x + .5, .5 - uv.y);
65 });
66
67 const char* const COMPOSITE_FSH = DALI_COMPOSE_SHADER(
68 precision mediump float;
69
70 const float kStepsilon = 1e-2;
71
72 uniform sampler2D sColor;
73 uniform sampler2D sFlowMap;
74
75 uniform float uFlow;
76 uniform vec3 uRgb[2];
77
78 varying vec2 vUv;
79 varying vec2 vUvFlow;
80
81 void main()
82 {
83   vec4 colorAlpha = texture2D(sColor, vUv);
84   float flow = smoothstep(.5 - kStepsilon, .5 + kStepsilon, clamp(uFlow + texture2D(sFlowMap, vUvFlow).r, 0., 1.));
85
86   gl_FragColor = vec4(mix(colorAlpha.rgb, mix(uRgb[0], uRgb[1], flow), colorAlpha.a), 1.);
87 });
88
89 } // nonamespace
90
91 ColorTransitionController::ColorTransitionController(WeakHandle<RenderTaskList> window, Actor content, RenderTaskList tasks, Vector3 initialColor)
92 : mWeakRenderTasks(window)
93 {
94   auto contentSize = content.GetProperty(Actor::Property::SIZE).Get<Vector2>();
95
96   auto defaultTask = tasks.GetTask(0);
97
98   // create rendertarget and rendertask
99   auto rtt = Texture::New(TextureType::TEXTURE_2D, Pixel::Format::RGBA8888,
100     static_cast<uint32_t>(contentSize.x), static_cast<uint32_t>(contentSize.y));
101
102   auto fbo = FrameBuffer::New(rtt.GetWidth(), rtt.GetHeight(), FrameBuffer::Attachment::NONE);
103   fbo.AttachColorTexture(rtt);
104
105   RenderTask rtCompositor = tasks.CreateTask();
106   rtCompositor.SetClearEnabled(true);
107   rtCompositor.SetClearColor(BG_COLOR);
108   rtCompositor.SetFrameBuffer(fbo);
109   rtCompositor.SetSourceActor(content);
110   rtCompositor.SetExclusive(true);
111   mRtCompositor = rtCompositor;
112
113   // renderer for the composite
114   ACTOR_DECL(composite);
115   CenterActor(composite);
116   composite.SetProperty(Actor::Property::SIZE, contentSize);
117
118   mPropFlow = composite.RegisterProperty("uFlow", -1.f);
119   mPropUvTransform = composite.RegisterProperty("uUvTransform", Vector4(0.f, 0.f, 1.f, 1.f));
120   mPropRgb[0] = composite.RegisterProperty("uRgb[0]", initialColor);
121   mPropRgb[1] = composite.RegisterProperty("uRgb[1]", Vector3::ONE);
122
123   auto geomComposite = CreateQuadGeometry();
124
125   auto tsComposite = TextureSet::New();
126   tsComposite.SetTexture(0, rtt);
127
128   Sampler flowSampler = Sampler::New();
129   flowSampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT);
130   tsComposite.SetSampler(1, flowSampler);
131
132   auto shdComposite = Shader::New(COMPOSITE_VSH, COMPOSITE_FSH);
133
134   auto compositeRenderer = CreateRenderer(tsComposite, geomComposite, shdComposite);
135   composite.AddRenderer(compositeRenderer);
136
137   mComposite = composite;
138
139   // create transition animation
140   Animation anim = Animation::New(1.f);
141   anim.SetEndAction(Animation::EndAction::DISCARD);
142   anim.AnimateTo(Property(composite, mPropFlow), 1.f);
143   anim.FinishedSignal().Connect(this, &ColorTransitionController::OnTransitionFinished);
144   mAnimation = anim;
145 }
146
147 ColorTransitionController::~ColorTransitionController()
148 {
149   if (auto renderTasks = mWeakRenderTasks.GetHandle())
150   {
151     renderTasks.RemoveTask(mRtCompositor);
152   }
153 }
154
155 Dali::Actor ColorTransitionController::GetComposite()
156 {
157   return mComposite;
158 }
159
160 void ColorTransitionController::SetFlowMap(Texture flowMap)
161 {
162   auto renderer = mComposite.GetRendererAt(0);
163   auto texSet = renderer.GetTextures();
164   texSet.SetTexture(1, flowMap);
165 }
166
167 void ColorTransitionController::SetUvTransform(float initialRotation, float initialScale, float targetRotation, float targetScale)
168 {
169   mComposite.SetProperty(mPropUvTransform, Vector4(initialRotation, initialScale, targetRotation, targetScale));
170 }
171
172 void ColorTransitionController::RequestTransition(float duration, const Dali::Vector3& targetColor)
173 {
174   mComposite.SetProperty(mPropRgb[1], targetColor);
175
176   mAnimation.SetDuration(duration);
177   mAnimation.SetCurrentProgress(0.f);
178   mAnimation.Play();
179 }
180
181 void ColorTransitionController::SetOnFinished(OnFinished onFinished, void* data)
182 {
183   mOnFinished = onFinished;
184   mOnFinishedData = data;
185 }
186
187 void ColorTransitionController::OnTransitionFinished(Animation& anim)
188 {
189   // shift the secondary color down
190   Vector3 color1 = mComposite.GetProperty(mPropRgb[1]).Get<Vector3>();
191   mComposite.SetProperty(mPropRgb[0], color1);
192
193   if (mOnFinished)
194   {
195     mOnFinished(mOnFinishedData);
196   }
197 }