2 * Copyright (c) 2020 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"
19 #include "dali/dali.h"
20 #include "dali-toolkit/dali-toolkit.h"
23 using namespace Dali::Toolkit;
28 const Vector4 BG_COLOR = Vector4(0.f, 0.f, 0.f, 0.f);
30 const char* const COMPOSITE_VSH = DALI_COMPOSE_SHADER(
31 precision mediump float;
34 uniform mat4 uMvpMatrix;
39 uniform vec4 uUvTransform; // rotation, scale (initial, target))
41 attribute vec2 aPosition;
48 vec4 position = uMvpMatrix * vec4(aPosition * uSize.xy, 0., 1.);
50 gl_Position = position;
52 vec2 uv = position.xy / (position.ww * 2.);
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));
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);
67 const char* const COMPOSITE_FSH = DALI_COMPOSE_SHADER(
68 precision mediump float;
70 const float kStepsilon = 1e-2;
72 uniform sampler2D sColor;
73 uniform sampler2D sFlowMap;
83 vec4 colorAlpha = texture2D(sColor, vUv);
84 float flow = smoothstep(.5 - kStepsilon, .5 + kStepsilon, clamp(uFlow + texture2D(sFlowMap, vUvFlow).r, 0., 1.));
86 gl_FragColor = vec4(mix(colorAlpha.rgb, mix(uRgb[0], uRgb[1], flow), colorAlpha.a), 1.);
91 ColorTransitionController::ColorTransitionController(WeakHandle<RenderTaskList> window, Actor content, RenderTaskList tasks, Vector3 initialColor)
92 : mWeakRenderTasks(window)
94 auto contentSize = content.GetProperty(Actor::Property::SIZE).Get<Vector2>();
96 auto defaultTask = tasks.GetTask(0);
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));
102 auto fbo = FrameBuffer::New(rtt.GetWidth(), rtt.GetHeight(), FrameBuffer::Attachment::NONE);
103 fbo.AttachColorTexture(rtt);
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;
113 // renderer for the composite
114 ACTOR_DECL(composite);
115 CenterActor(composite);
116 composite.SetProperty(Actor::Property::SIZE, contentSize);
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);
123 auto geomComposite = CreateQuadGeometry();
125 auto tsComposite = TextureSet::New();
126 tsComposite.SetTexture(0, rtt);
128 Sampler flowSampler = Sampler::New();
129 flowSampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT);
130 tsComposite.SetSampler(1, flowSampler);
132 auto shdComposite = Shader::New(COMPOSITE_VSH, COMPOSITE_FSH);
134 auto compositeRenderer = CreateRenderer(tsComposite, geomComposite, shdComposite);
135 composite.AddRenderer(compositeRenderer);
137 mComposite = composite;
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);
147 ColorTransitionController::~ColorTransitionController()
149 if (auto renderTasks = mWeakRenderTasks.GetHandle())
151 renderTasks.RemoveTask(mRtCompositor);
155 Dali::Actor ColorTransitionController::GetComposite()
160 void ColorTransitionController::SetFlowMap(Texture flowMap)
162 auto renderer = mComposite.GetRendererAt(0);
163 auto texSet = renderer.GetTextures();
164 texSet.SetTexture(1, flowMap);
167 void ColorTransitionController::SetUvTransform(float initialRotation, float initialScale, float targetRotation, float targetScale)
169 mComposite.SetProperty(mPropUvTransform, Vector4(initialRotation, initialScale, targetRotation, targetScale));
172 void ColorTransitionController::RequestTransition(float duration, const Dali::Vector3& targetColor)
174 mComposite.SetProperty(mPropRgb[1], targetColor);
176 mAnimation.SetDuration(duration);
177 mAnimation.SetCurrentProgress(0.f);
181 void ColorTransitionController::SetOnFinished(OnFinished onFinished, void* data)
183 mOnFinished = onFinished;
184 mOnFinishedData = data;
187 void ColorTransitionController::OnTransitionFinished(Animation& anim)
189 // shift the secondary color down
190 Vector3 color1 = mComposite.GetProperty(mPropRgb[1]).Get<Vector3>();
191 mComposite.SetProperty(mPropRgb[0], color1);
195 mOnFinished(mOnFinishedData);