diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml
index 0671f04..8cf0fc8 100644
--- a/com.samsung.dali-demo.xml
+++ b/com.samsung.dali-demo.xml
@@ -61,6 +61,9 @@
+
+
+
diff --git a/examples-reel/dali-examples-reel.cpp b/examples-reel/dali-examples-reel.cpp
index 8284065..f0e152a 100644
--- a/examples-reel/dali-examples-reel.cpp
+++ b/examples-reel/dali-examples-reel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ int DALI_EXPORT_API main(int argc, char** argv)
demo.AddExample(Example("buttons.example", DALI_DEMO_STR_TITLE_BUTTONS));
demo.AddExample(Example("clipping.example", DALI_DEMO_STR_TITLE_CLIPPING));
demo.AddExample(Example("clipping-draw-order.example", DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER));
+ demo.AddExample(Example("color-transition.example", DALI_DEMO_STR_TITLE_COLOR_TRANSITION));
demo.AddExample(Example("color-visual.example", DALI_DEMO_STR_TITLE_COLOR_VISUAL));
demo.AddExample(Example("deferred-shading.example", DALI_DEMO_STR_TITLE_DEFERRED_SHADING));
demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION));
diff --git a/examples/color-transition/color-transition-controller.cpp b/examples/color-transition/color-transition-controller.cpp
new file mode 100644
index 0000000..d9cb208
--- /dev/null
+++ b/examples/color-transition/color-transition-controller.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "color-transition-controller.h"
+#include "utils.h"
+#include "dali/dali.h"
+#include "dali-toolkit/dali-toolkit.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+
+const Vector4 BG_COLOR = Vector4(0.f, 0.f, 0.f, 0.f);
+
+const char* const COMPOSITE_VSH = DALI_COMPOSE_SHADER(
+precision mediump float;
+
+//
+uniform mat4 uMvpMatrix;
+uniform vec3 uSize;
+//
+
+uniform float uFlow;
+uniform vec4 uUvTransform; // rotation, scale (initial, target))
+
+attribute vec2 aPosition;
+
+varying vec2 vUv;
+varying vec2 vUvFlow;
+
+void main()
+{
+ vec4 position = uMvpMatrix * vec4(aPosition * uSize.xy, 0., 1.);
+
+ gl_Position = position;
+
+ vec2 uv = position.xy / (position.ww * 2.);
+ vUv = uv + vec2(.5);
+
+ float alpha = uFlow * .5 + .5;
+ vec2 uvRotationScale = mix(uUvTransform.xy, uUvTransform.zw, alpha);
+ float c = cos(uvRotationScale.x) * uvRotationScale.y;
+ float s = sin(uvRotationScale.x) * uvRotationScale.y;
+ vec4 uvMatrix = vec4(c, -s, s, c);
+ uv = vec2(dot(uvMatrix.xy, uv), dot(uvMatrix.zw, uv));
+
+ // N.B. +y is down which is well aligned with the inverted y of the off-screen render,
+ // however we need to flip the y of the uvs for the flow map.
+ vUvFlow = vec2(uv.x + .5, .5 - uv.y);
+});
+
+const char* const COMPOSITE_FSH = DALI_COMPOSE_SHADER(
+precision mediump float;
+
+const float kStepsilon = 1e-2;
+
+uniform sampler2D sColor;
+uniform sampler2D sFlowMap;
+
+uniform float uFlow;
+uniform vec3 uRgb[2];
+
+varying vec2 vUv;
+varying vec2 vUvFlow;
+
+void main()
+{
+ vec4 colorAlpha = texture2D(sColor, vUv);
+ float flow = smoothstep(.5 - kStepsilon, .5 + kStepsilon, clamp(uFlow + texture2D(sFlowMap, vUvFlow).r, 0., 1.));
+
+ gl_FragColor = vec4(mix(colorAlpha.rgb, mix(uRgb[0], uRgb[1], flow), colorAlpha.a), 1.);
+});
+
+} // nonamespace
+
+ColorTransitionController::ColorTransitionController(WeakHandle window, Actor content, RenderTaskList tasks, Vector3 initialColor)
+: mWeakRenderTasks(window)
+{
+ auto contentSize = content.GetProperty(Actor::Property::SIZE).Get();
+
+ auto defaultTask = tasks.GetTask(0);
+
+ // create rendertarget and rendertask
+ auto rtt = Texture::New(TextureType::TEXTURE_2D, Pixel::Format::RGBA8888,
+ static_cast(contentSize.x), static_cast(contentSize.y));
+
+ auto fbo = FrameBuffer::New(rtt.GetWidth(), rtt.GetHeight(), FrameBuffer::Attachment::NONE);
+ fbo.AttachColorTexture(rtt);
+
+ RenderTask rtCompositor = tasks.CreateTask();
+ rtCompositor.SetClearEnabled(true);
+ rtCompositor.SetClearColor(BG_COLOR);
+ rtCompositor.SetFrameBuffer(fbo);
+ rtCompositor.SetSourceActor(content);
+ rtCompositor.SetExclusive(true);
+ mRtCompositor = rtCompositor;
+
+ // renderer for the composite
+ ACTOR_DECL(composite);
+ CenterActor(composite);
+ composite.SetProperty(Actor::Property::SIZE, contentSize);
+
+ mPropFlow = composite.RegisterProperty("uFlow", -1.f);
+ mPropUvTransform = composite.RegisterProperty("uUvTransform", Vector4(0.f, 0.f, 1.f, 1.f));
+ mPropRgb[0] = composite.RegisterProperty("uRgb[0]", initialColor);
+ mPropRgb[1] = composite.RegisterProperty("uRgb[1]", Vector3::ONE);
+
+ auto geomComposite = CreateQuadGeometry();
+
+ auto tsComposite = TextureSet::New();
+ tsComposite.SetTexture(0, rtt);
+
+ Sampler flowSampler = Sampler::New();
+ flowSampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT);
+ tsComposite.SetSampler(1, flowSampler);
+
+ auto shdComposite = Shader::New(COMPOSITE_VSH, COMPOSITE_FSH);
+
+ auto compositeRenderer = CreateRenderer(tsComposite, geomComposite, shdComposite);
+ composite.AddRenderer(compositeRenderer);
+
+ mComposite = composite;
+
+ // create transition animation
+ Animation anim = Animation::New(1.f);
+ anim.SetEndAction(Animation::EndAction::DISCARD);
+ anim.AnimateTo(Property(composite, mPropFlow), 1.f);
+ anim.FinishedSignal().Connect(this, &ColorTransitionController::OnTransitionFinished);
+ mAnimation = anim;
+}
+
+ColorTransitionController::~ColorTransitionController()
+{
+ if (auto renderTasks = mWeakRenderTasks.GetHandle())
+ {
+ renderTasks.RemoveTask(mRtCompositor);
+ }
+}
+
+Dali::Actor ColorTransitionController::GetComposite()
+{
+ return mComposite;
+}
+
+void ColorTransitionController::SetFlowMap(Texture flowMap)
+{
+ auto renderer = mComposite.GetRendererAt(0);
+ auto texSet = renderer.GetTextures();
+ texSet.SetTexture(1, flowMap);
+}
+
+void ColorTransitionController::SetUvTransform(float initialRotation, float initialScale, float targetRotation, float targetScale)
+{
+ mComposite.SetProperty(mPropUvTransform, Vector4(initialRotation, initialScale, targetRotation, targetScale));
+}
+
+void ColorTransitionController::RequestTransition(float duration, const Dali::Vector3& targetColor)
+{
+ mComposite.SetProperty(mPropRgb[1], targetColor);
+
+ mAnimation.SetDuration(duration);
+ mAnimation.SetCurrentProgress(0.f);
+ mAnimation.Play();
+}
+
+void ColorTransitionController::SetOnFinished(OnFinished onFinished, void* data)
+{
+ mOnFinished = onFinished;
+ mOnFinishedData = data;
+}
+
+void ColorTransitionController::OnTransitionFinished(Animation& anim)
+{
+ // shift the secondary color down
+ Vector3 color1 = mComposite.GetProperty(mPropRgb[1]).Get();
+ mComposite.SetProperty(mPropRgb[0], color1);
+
+ if (mOnFinished)
+ {
+ mOnFinished(mOnFinishedData);
+ }
+}
diff --git a/examples/color-transition/color-transition-controller.h b/examples/color-transition/color-transition-controller.h
new file mode 100644
index 0000000..962ec27
--- /dev/null
+++ b/examples/color-transition/color-transition-controller.h
@@ -0,0 +1,63 @@
+#ifndef DALI_DEMO_COLOR_TRANSITION_CONTROLLER_H
+#define DALI_DEMO_COLOR_TRANSITION_CONTROLLER_H
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "dali/public-api/adaptor-framework/window.h"
+#include "dali/public-api/object/weak-handle.h"
+#include "dali/public-api/actors/actor.h"
+#include "dali/public-api/animation/animation.h"
+#include "dali/public-api/rendering/texture.h"
+#include "dali/public-api/render-tasks/render-task.h"
+#include "dali/public-api/render-tasks/render-task-list.h"
+
+class ColorTransitionController: public Dali::ConnectionTracker
+{
+public:
+ using OnFinished = void(*)(void*);
+
+ ColorTransitionController(Dali::WeakHandle renderTasks, Dali::Actor content, Dali::RenderTaskList tasks, Dali::Vector3 initialColor);
+ ~ColorTransitionController();
+
+ Dali::Actor GetComposite();
+
+ void SetFlowMap(Dali::Texture flowMap);
+
+ void SetUvTransform(float initialRotation, float initialScale, float targetRotation, float targetScale);
+
+ void SetOnFinished(OnFinished onFinished, void* onFinishedData);
+
+ void RequestTransition(float duration, const Dali::Vector3& targetColor);
+
+private:
+ void OnTransitionFinished(Dali::Animation& anim);
+
+ Dali::Actor mComposite;
+ Dali::Property::Index mPropFlow;
+ Dali::Property::Index mPropUvTransform;
+ Dali::Property::Index mPropRgb[2];
+
+ Dali::RenderTask mRtCompositor;
+
+ Dali::Animation mAnimation;
+
+ OnFinished mOnFinished = nullptr;
+ void* mOnFinishedData = nullptr;
+
+ Dali::WeakHandle mWeakRenderTasks;
+};
+
+#endif //DALI_DEMO_COLOR_TRANSITION_CONTROLLER_H
diff --git a/examples/color-transition/color-transition.cpp b/examples/color-transition/color-transition.cpp
new file mode 100644
index 0000000..095f3e7
--- /dev/null
+++ b/examples/color-transition/color-transition.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "utils.h"
+#include "color-transition-controller.h"
+#include "dali/dali.h"
+#include "dali-toolkit/dali-toolkit.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+const float TRANSITION_DURATION = 1.f;
+
+const Vector3 INITIAL_COLOR{ 1.f, 1.f, .25f };
+
+const char* const FLOW_MAPS[] = {
+ "circular",
+ "multi-circle",
+ "concentric",
+ "spiral",
+ "conical",
+ "blinds",
+ "radial",
+ "swipe",
+ "bubbles",
+ "image"
+};
+
+Texture LoadTexture(const std::string& path)
+{
+ PixelData pixelData = SyncImageLoader::Load(path);
+
+ Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(),
+ pixelData.GetWidth(), pixelData.GetHeight());
+ texture.Upload(pixelData);
+ return texture;
+}
+
+TextLabel MakeTextLabel(const char* text, const Vector4& color, float pointSize, const Vector2& size)
+{
+ auto tl = TextLabel::New(text);
+ CenterActor(tl);
+ tl.SetProperty(Actor::Property::SIZE, size);
+ tl.SetProperty(TextLabel::Property::POINT_SIZE, pointSize);
+ tl.SetProperty(TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
+ tl.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
+ tl.SetProperty(TextLabel::Property::MULTI_LINE, true);
+ tl.SetProperty(TextLabel::Property::TEXT_COLOR, color);
+ return tl;
+}
+
+}
+
+/**
+ * Demonstrates colour transition using flow maps and uv rotation / scaling.
+ *
+ * Flow maps are greyscale images where the value of the pixels signifies the
+ * progress of the animation, which is added to an animated value which we
+ * use to lerp between old and new colour.
+ *
+ * The colour of the content is used to scale the source / target colour, i.e.
+ * white is affected most, dark is affected less.
+ *
+ * Controls:
+ * - Double-tap middle (33%) of screen: transition using random flow map;
+ * - Double-tap outside the middle of screen: transition using one of the
+ * effects (flow maps) mapped to the given segment of the screen;
+ */
+class ColorTransition: public ConnectionTracker
+{
+public:
+ ColorTransition(Application& app)
+ : mApp(app)
+ {
+ app.InitSignal().Connect(this, &ColorTransition::OnInit);
+ app.TerminateSignal().Connect(this, &ColorTransition::OnTerminate);
+ }
+
+private:
+ static void OnTransitionFinished(void* data)
+ {
+ auto& me = *static_cast(data);
+ me.OnTransitionFinished();
+ }
+
+ void OnInit(Application& app)
+ {
+ auto window = mApp.GetWindow();
+ auto windowSize = Vector2{ window.GetSize() };
+
+ // create content root
+ Actor content = Actor::New();
+ CenterActor(content);
+ content.SetProperty(Actor::Property::SIZE, windowSize);
+ window.Add(content);
+ mColorTransitionContent = content;
+
+ // create some example content
+ TextLabel tlHello = MakeTextLabel("HELLO", Vector4::ONE, 60.f, windowSize);
+ tlHello.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+ tlHello.SetProperty(Actor::Property::POSITION_Y, -60.f);
+ content.Add(tlHello);
+
+ TextLabel tlWorld = MakeTextLabel("WORLD", Vector4(1.f, 1.f, 1.f, .5f), 60.f, windowSize);
+ tlWorld.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+ tlWorld.SetProperty(Actor::Property::POSITION_Y, 60.f);
+ content.Add(tlWorld);
+
+ ImageView ivIcon = ImageView::New(Application::GetResourcePath() + "images/application-icon-2.png");
+ CenterActor(ivIcon);
+ ivIcon.SetProperty(Actor::Property::POSITION_Y, 120.f);
+ content.Add(ivIcon);
+
+ // create main root
+ Actor mainRoot = Actor::New();
+ CenterActor(mainRoot);
+ window.Add(mainRoot);
+ mMainRoot = mainRoot;
+
+ auto renderTasks = window.GetRenderTaskList();
+ auto weakRenderTasks = WeakHandle(renderTasks);
+ auto controller = new ColorTransitionController(weakRenderTasks, content, window.GetRenderTaskList(), INITIAL_COLOR);
+ mController.reset(controller);
+ mainRoot.Add(mController->GetComposite());
+
+ // add content unaffected by effect, to scene.
+ TextLabel tlInstructions = MakeTextLabel("Double tap to change Color", Vector4(.5f, .5f, .5f, 1.f), 10.f, windowSize);
+ tlInstructions.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "TOP");
+ mainRoot.Add(tlInstructions);
+
+ // hook up event handlers
+ window.KeyEventSignal().Connect(this, &ColorTransition::OnKeyEvent);
+
+ auto tapDetector = TapGestureDetector::New(2);
+ tapDetector.DetectedSignal().Connect(this, &ColorTransition::OnDoubleTap);
+ tapDetector.Attach(window.GetRootLayer());
+ mDoubleTapDetector = tapDetector;
+
+ mController->SetOnFinished(OnTransitionFinished, this);
+ }
+
+ void OnTerminate(Application& app)
+ {
+ auto window = mApp.GetWindow();
+ mDoubleTapDetector.Detach(window.GetRootLayer());
+
+ UnparentAndReset(mColorTransitionContent);
+ UnparentAndReset(mMainRoot);
+
+ mController.reset();
+ }
+
+ void OnKeyEvent(const KeyEvent& event)
+ {
+ if (event.GetState() == KeyEvent::DOWN)
+ {
+ if (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
+ {
+ mApp.Quit();
+ }
+ }
+ }
+
+ void OnDoubleTap(Actor /*actor*/, const TapGesture& tap)
+ {
+ auto window = mApp.GetWindow();
+ auto windowSize = Vector2{ window.GetSize() };
+ Vector2 clip = tap.GetScreenPoint() / windowSize - Vector2::ONE * .5f; // [-.5, .5]
+ if (clip.Length() < .333f * .5f)
+ {
+ LoadFlowMap(FLOW_MAPS[rand() % std::extent::value]);
+ }
+ else
+ {
+ float theta = fmodf((atan2(clip.y, clip.x) + M_PI) / (M_PI * 2.) + .75f, 1.f);
+ int i = std::extent::value * theta;
+
+ LoadFlowMap(FLOW_MAPS[i]);
+ }
+ RandomizeUvTransform();
+
+ Vector3 color(rand() % 5, rand() % 5, rand() % 5);
+ color /= 4.f;
+
+ mDoubleTapDetector.Detach(mApp.GetWindow().GetRootLayer());
+ mController->RequestTransition(TRANSITION_DURATION, color);
+ }
+
+ void LoadFlowMap(const char* const name)
+ {
+ DALI_ASSERT_DEBUG(name && "Flow map name must be given");
+ if (mLastFlowMap != name)
+ {
+ std::string flowMapDir = Application::GetResourcePath() + "images/color-transition/";
+ std::string flowMapPath = flowMapDir + name + ".png";
+ auto flowMap = LoadTexture(flowMapPath);
+ DALI_ASSERT_DEBUG(flowMap && "Failed to load flow map.");
+ mController->SetFlowMap(flowMap);
+ }
+ }
+
+ void RandomizeUvTransform()
+ {
+ mController->SetUvTransform((rand() % 12) * M_PI / 12., 1.f,
+ (rand() % 12) * M_PI / 12., .5f);
+ }
+
+ void OnTransitionFinished()
+ {
+ mDoubleTapDetector.Attach(mApp.GetWindow().GetRootLayer());
+ }
+
+ Application& mApp;
+
+ const char* mLastFlowMap = nullptr;
+
+ Actor mColorTransitionContent;
+ Actor mMainRoot;
+
+ std::unique_ptr mController;
+
+ TapGestureDetector mDoubleTapDetector;
+};
+
+int DALI_EXPORT_API main(int argc, char** argv)
+{
+ auto app = Application::New(&argc, &argv
+#ifdef WIN32
+ , ".//dali-toolkit-default-theme.json"
+#endif
+ );
+ ColorTransition ct(app);
+ app.MainLoop();
+ return 0;
+}
diff --git a/examples/color-transition/utils.cpp b/examples/color-transition/utils.cpp
new file mode 100644
index 0000000..c226bfe
--- /dev/null
+++ b/examples/color-transition/utils.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "utils.h"
+
+#include
+#include
+
+#include
+
+using namespace Dali;
+
+Geometry CreateQuadGeometry()
+{
+ // Create geometry -- unit square with whole of the texture mapped to it.
+ struct Vertex
+ {
+ Vector3 aPosition;
+ };
+
+ Vertex vertexData[] = {
+ { Vector3(-.5f, .5f, .0f) },
+ { Vector3(.5f, .5f, .0f) },
+ { Vector3(-.5f, -.5f, .0f) },
+ { Vector3(.5f, -.5f, .0f) },
+ };
+
+ VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map()
+ .Add("aPosition", Property::VECTOR3));
+ vertexBuffer.SetData(vertexData, std::extent::value);
+
+ Geometry geometry = Geometry::New();
+ geometry.AddVertexBuffer(vertexBuffer);
+ geometry.SetType(Geometry::TRIANGLE_STRIP);
+ return geometry;
+}
+
+Renderer CreateRenderer(TextureSet textures, Geometry geometry, Shader shader, uint32_t options)
+{
+ Renderer renderer = Renderer::New(geometry, shader);
+ renderer.SetProperty(Renderer::Property::BLEND_MODE,
+ (options & RendererOptions::BLEND) ? BlendMode::ON : BlendMode::OFF);
+ renderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE,
+ (options & RendererOptions::DEPTH_TEST) ? DepthTestMode::ON : DepthTestMode::OFF);
+ renderer.SetProperty(Renderer::Property::DEPTH_WRITE_MODE,
+ (options & RendererOptions::DEPTH_WRITE) ? DepthWriteMode::ON : DepthWriteMode::OFF);
+
+ int faceCulling = (((options & RendererOptions::CULL_BACK) != 0) << 1) |
+ ((options & RendererOptions::CULL_FRONT) != 0);
+ renderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, faceCulling);
+
+ if (!textures)
+ {
+ textures = TextureSet::New();
+ }
+
+ renderer.SetTextures(textures);
+ return renderer;
+}
+
+void CenterActor(Actor actor)
+{
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+}
+
diff --git a/examples/color-transition/utils.h b/examples/color-transition/utils.h
new file mode 100644
index 0000000..9a4b1bc
--- /dev/null
+++ b/examples/color-transition/utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef DALI_DEMO_COLOR_TRANSITION_UTILS_H_
+#define DALI_DEMO_COLOR_TRANSITION_UTILS_H_
+
+#include "dali/public-api/actors/actor.h"
+#include "dali/public-api/rendering/geometry.h"
+#include "dali/public-api/rendering/renderer.h"
+#include "dali/public-api/rendering/texture.h"
+
+#define ACTOR_DECL(x) auto x = Dali::Actor::New(); x.SetProperty(Actor::Property::NAME, #x);
+
+/**
+ * @brief Creates a unit quad centered on the origin (i.e. vertex positions
+ * between -.5 and .5).
+ */
+Dali::Geometry CreateQuadGeometry();
+
+struct RendererOptions
+{
+ enum
+ {
+ NONE = 0x0,
+ BLEND = 0x01,
+ DEPTH_TEST = 0x02,
+ DEPTH_WRITE = 0x04,
+ CULL_BACK = 0x08,
+ CULL_FRONT = 0x10,
+ };
+};
+
+///@brief Creates a renderer with the given @a textures set, @a geometry, @a shader
+/// and @a options from above.
+///@note Back face culling is on.
+///@note If textures is not a valid handle, an empty texture set will be created.
+Dali::Renderer CreateRenderer(
+ Dali::TextureSet textures,
+ Dali::Geometry geometry,
+ Dali::Shader shader,
+ uint32_t options = RendererOptions::NONE);
+
+///@brief Sets @a actor's anchor point and parent origin to center.
+void CenterActor(Dali::Actor actor);
+
+#endif //DALI_DEMO_COLOR_TRANSITION_UTILS_H_
diff --git a/resources/images/color-transition/blinds.png b/resources/images/color-transition/blinds.png
new file mode 100644
index 0000000..3f255b0
--- /dev/null
+++ b/resources/images/color-transition/blinds.png
diff --git a/resources/images/color-transition/bubbles.png b/resources/images/color-transition/bubbles.png
new file mode 100644
index 0000000..d570227
--- /dev/null
+++ b/resources/images/color-transition/bubbles.png
diff --git a/resources/images/color-transition/circular.png b/resources/images/color-transition/circular.png
new file mode 100644
index 0000000..35cf6d7
--- /dev/null
+++ b/resources/images/color-transition/circular.png
diff --git a/resources/images/color-transition/concentric.png b/resources/images/color-transition/concentric.png
new file mode 100644
index 0000000..654cd0a
--- /dev/null
+++ b/resources/images/color-transition/concentric.png
diff --git a/resources/images/color-transition/conical.png b/resources/images/color-transition/conical.png
new file mode 100644
index 0000000..28e6b77
--- /dev/null
+++ b/resources/images/color-transition/conical.png
diff --git a/resources/images/color-transition/image.png b/resources/images/color-transition/image.png
new file mode 100644
index 0000000..1038b7e
--- /dev/null
+++ b/resources/images/color-transition/image.png
diff --git a/resources/images/color-transition/multi-circle.png b/resources/images/color-transition/multi-circle.png
new file mode 100644
index 0000000..5230edd
--- /dev/null
+++ b/resources/images/color-transition/multi-circle.png
diff --git a/resources/images/color-transition/radial.png b/resources/images/color-transition/radial.png
new file mode 100644
index 0000000..f36a2f5
--- /dev/null
+++ b/resources/images/color-transition/radial.png
diff --git a/resources/images/color-transition/spiral.png b/resources/images/color-transition/spiral.png
new file mode 100644
index 0000000..d7490aa
--- /dev/null
+++ b/resources/images/color-transition/spiral.png
diff --git a/resources/images/color-transition/swipe.png b/resources/images/color-transition/swipe.png
new file mode 100644
index 0000000..86651b7
--- /dev/null
+++ b/resources/images/color-transition/swipe.png
diff --git a/resources/po/en_GB.po b/resources/po/en_GB.po
index 2445e70..8b9bb90 100755
--- a/resources/po/en_GB.po
+++ b/resources/po/en_GB.po
@@ -46,6 +46,9 @@ msgstr "Clipping"
msgid "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER"
msgstr "Clipping Draw Order"
+msgid "DALI_DEMO_STR_TITLE_COLOR_TRANSITION"
+msgstr "Colour Transition"
+
msgid "DALI_DEMO_STR_TITLE_COLOR_VISUAL"
msgstr "Colour Visual"
diff --git a/resources/po/en_US.po b/resources/po/en_US.po
index d31b85e..e3be533 100755
--- a/resources/po/en_US.po
+++ b/resources/po/en_US.po
@@ -46,6 +46,9 @@ msgstr "Clipping"
msgid "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER"
msgstr "Clipping Draw Order"
+msgid "DALI_DEMO_STR_TITLE_COLOR_TRANSITION"
+msgstr "Color Transition"
+
msgid "DALI_DEMO_STR_TITLE_COLOR_VISUAL"
msgstr "Color Visual"
diff --git a/shared/dali-demo-strings.h b/shared/dali-demo-strings.h
index 6d9f754..08a7a17 100644
--- a/shared/dali-demo-strings.h
+++ b/shared/dali-demo-strings.h
@@ -50,6 +50,7 @@ extern "C"
#define DALI_DEMO_STR_TITLE_CARD_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CARD_ACTIVE")
#define DALI_DEMO_STR_TITLE_CLIPPING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING")
#define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER")
+#define DALI_DEMO_STR_TITLE_COLOR_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_TRANSITION")
#define DALI_DEMO_STR_TITLE_COLOR_VISUAL dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_VISUAL")
#define DALI_DEMO_STR_TITLE_DEFERRED_SHADING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_DEFERRED_SHADING")
#define DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW")
@@ -155,6 +156,7 @@ extern "C"
#define DALI_DEMO_STR_TITLE_CARD_ACTIVE "Card Active"
#define DALI_DEMO_STR_TITLE_CLIPPING "Clipping"
#define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER "Clipping Draw Order"
+#define DALI_DEMO_STR_TITLE_COLOR_TRANSITION "Color Transition"
#define DALI_DEMO_STR_TITLE_COLOR_VISUAL "Color Visual"
#define DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW "Gaussian Blur"
#define DALI_DEMO_STR_TITLE_GESTURES "Gestures"