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.
18 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali/dali.h>
23 namespace // unnamed namespace
25 const char* TEXTURE_URL = DEMO_IMAGE_DIR "RadialEffect-280x280.png";
26 const unsigned int TEXTURE_WIDTH = 280;
27 const unsigned int TEXTURE_HEIGHT = 280;
29 const int NUMBER_OF_SIDES(64); // number of sides of the polygon used as a stencil
30 const float INITIAL_DELAY(2.0f); // initial delay before showing the circle
31 const float PROGRESS_DURATION(0.5f); // number of seconds to fully show the circle
36 * Vertex shader for textured quad
38 const char* VERTEX_SHADER_TEXTURED = DALI_COMPOSE_SHADER(
39 attribute mediump vec2 aPosition;\n
40 uniform mediump mat4 uMvpMatrix;\n // DALi shader builtin
41 uniform mediump vec3 uSize;\n // DALi shader builtin
43 varying mediump vec2 vTexCoord;\n
46 mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
47 vertexPosition.xyz *= uSize;\n
48 vTexCoord = vec2(1.0, 1.0)*(aPosition + vec2(0.5) );\n
49 gl_Position = uMvpMatrix * vertexPosition;\n
54 * Fragment shaderfor textured quad
56 const char* FRAGMENT_SHADER_TEXTURED = DALI_COMPOSE_SHADER(
57 uniform sampler2D uTexture;\n
59 varying mediump vec2 vTexCoord;\n
62 mediump vec4 texColor = texture2D( uTexture, vTexCoord );\n
63 gl_FragColor = texColor;\n
68 * Vertex shader for polygon
70 const char* VERTEX_SHADER_BASIC = DALI_COMPOSE_SHADER(
71 attribute mediump vec3 aPosition;\n
72 uniform mediump mat4 uMvpMatrix;\n // DALi shader builtin
73 uniform mediump vec3 uSize;\n // DALi shader builtin
74 uniform mediump float uProgress;\n
76 varying mediump vec2 vTexCoord;\n
79 mediump vec4 vertexPosition = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n
81 float index = aPosition.z;\n
82 if( uProgress < index )\n
84 vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n
87 vertexPosition.xyz *= uSize;\n
88 gl_Position = uMvpMatrix * vertexPosition;\n
93 * Fragment shader for polygon
95 const char* FRAGMENT_SHADER_BASIC = DALI_COMPOSE_SHADER(
99 gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );\n
104 } // unnamed namespace
106 // This example shows how to render a radial progress indicator
108 class RadialProgressController : public ConnectionTracker
111 RadialProgressController(Application& application)
112 : mApplication(application)
114 // Connect to the Application's Init signal
115 mApplication.InitSignal().Connect(this, &RadialProgressController::Create);
118 ~RadialProgressController()
120 // Nothing to do here
123 // The Init signal is received once (only) during the Application lifetime
124 void Create(Application& application)
126 Window window = application.GetWindow();
127 window.SetBackgroundColor(Color::BLACK);
129 // Connect to the window's key signal to allow Back and Escape to exit.
130 window.KeyEventSignal().Connect(this, &RadialProgressController::OnKeyEvent);
132 // 1. Create actor to show the effect
133 mActor = Actor::New();
134 mActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
135 mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
136 mActor.SetProperty(Actor::Property::SIZE, Vector2(TEXTURE_WIDTH, TEXTURE_HEIGHT));
137 mActor.RegisterProperty("uProgress", float(1.0f));
140 // 1. Create stencil renderer i.e. a triangle fan in the shape of a circle
141 Renderer stencilRenderer = CreatePolygon(NUMBER_OF_SIDES);
142 mActor.AddRenderer(stencilRenderer);
144 // 2. Create textured quad renderer
145 Renderer texturedQuad = CreateTexturedQuad(TEXTURE_URL);
146 mActor.AddRenderer(texturedQuad);
148 // 5. Animate the progress uniform
149 Animation animation = Animation::New(PROGRESS_DURATION + INITIAL_DELAY);
150 animation.AnimateTo(Property(mActor, "uProgress"), float(NUMBER_OF_SIDES + 1), TimePeriod(INITIAL_DELAY, PROGRESS_DURATION));
153 // 6. Exit the application when touched
154 window.GetRootLayer().TouchedSignal().Connect(this, &RadialProgressController::OnTouch);
157 bool OnTouch(Actor actor, const TouchEvent& touch)
159 // quit the application
165 * Generates stencil mask geometry. Geometry is rendered as
166 * a triangle fan and occupies square 2.0x2.0.
167 * @param[in] numberOfSides The more subdivisions the more smooth mask animation.
169 Renderer CreatePolygon(unsigned int numberOfSides)
171 float count(numberOfSides);
173 // compute radial step in radians
174 const float STEP((2.0f * M_PI) / count);
177 std::vector<Vector3> vertices;
178 vertices.push_back(Vector3::ZERO);
180 for(size_t i = 0; i <= numberOfSides; ++i)
182 vertices.push_back(Vector3(-0.5f * cos(angle), -0.5f * sin(angle), i + 1));
186 Property::Map vertexFormat;
187 vertexFormat["aPosition"] = Property::VECTOR3;
189 // describe vertex format ( only 2-dimensional positions )
190 VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
191 vertexBuffer.SetData(vertices.data(), vertices.size());
194 Geometry geometry = Geometry::New();
195 geometry.AddVertexBuffer(vertexBuffer);
196 geometry.SetType(Geometry::TRIANGLE_FAN);
198 Shader shader = Shader::New(VERTEX_SHADER_BASIC, FRAGMENT_SHADER_BASIC);
199 Renderer renderer = Renderer::New(geometry, shader);
201 // Setting stencil data. We don't want to render to the color buffer so
202 // with use of RenderMode property we specify that only stencil buffer will
204 renderer.SetProperty(Renderer::Property::RENDER_MODE, RenderMode::STENCIL);
206 // Set stencil function
207 renderer.SetProperty(Renderer::Property::STENCIL_FUNCTION, StencilFunction::ALWAYS);
209 // Stencil function reference
210 renderer.SetProperty(Renderer::Property::STENCIL_FUNCTION_REFERENCE, 1);
212 // Stencil function mask
213 renderer.SetProperty(Renderer::Property::STENCIL_FUNCTION_MASK, 0xFF);
215 // Set stencil operations
216 renderer.SetProperty(Renderer::Property::STENCIL_OPERATION_ON_FAIL, StencilOperation::KEEP);
217 renderer.SetProperty(Renderer::Property::STENCIL_OPERATION_ON_Z_FAIL, StencilOperation::KEEP);
218 renderer.SetProperty(Renderer::Property::STENCIL_OPERATION_ON_Z_PASS, StencilOperation::REPLACE);
220 // Stencil mask to write
221 renderer.SetProperty(Renderer::Property::STENCIL_MASK, 0xFF);
223 // Set depth index lower than textured quad renderer, so stencil will render first
224 renderer.SetProperty(Renderer::Property::DEPTH_INDEX, 1);
230 * Creates textured quad renderer
232 Renderer CreateTexturedQuad(const char* url)
234 // Create shader & geometry needed by Renderer
236 Shader shader = Shader::New(VERTEX_SHADER_TEXTURED, FRAGMENT_SHADER_TEXTURED);
238 Property::Map vertexFormat;
239 vertexFormat["aPosition"] = Property::VECTOR2;
240 VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
243 const Vector2 vertices[] = {
249 vertexBuffer.SetData(vertices, 4);
251 // Instantiate quad geometry
252 Geometry geometry = Geometry::New();
253 geometry.AddVertexBuffer(vertexBuffer);
254 geometry.SetType(Geometry::TRIANGLE_STRIP);
257 PixelData pixelData = Toolkit::SyncImageLoader::Load(url);
258 Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
259 texture.Upload(pixelData);
260 texture.GenerateMipmaps();
262 // Create texture set
263 TextureSet textureSet = TextureSet::New();
264 textureSet.SetTexture(0, texture);
267 Renderer renderer = Renderer::New(geometry, shader);
268 renderer.SetTextures(textureSet);
270 // Set mode indicating we will use both stencil and color buffers
271 renderer.SetProperty(Renderer::Property::RENDER_MODE, RenderMode::COLOR_STENCIL);
273 // Stencil function - expecing drawing only when function mask matches exactly
274 renderer.SetProperty(Renderer::Property::STENCIL_FUNCTION, StencilFunction::EQUAL);
275 renderer.SetProperty(Renderer::Property::STENCIL_FUNCTION_REFERENCE, 1);
276 renderer.SetProperty(Renderer::Property::STENCIL_FUNCTION_MASK, 0xFF);
278 // We don't want to draw to the stencil, so setting stencil draw mask to 0
279 renderer.SetProperty(Renderer::Property::STENCIL_MASK, 0x00);
281 // Make sure the quad will render after drawing to stencil buffer
282 renderer.SetProperty(Renderer::Property::DEPTH_INDEX, 2);
288 * @brief Called when any key event is received
290 * Will use this to quit the application if Back or the Escape key is received
291 * @param[in] event The key event information
293 void OnKeyEvent(const KeyEvent& event)
295 if(event.GetState() == KeyEvent::DOWN)
297 if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
305 Application& mApplication;
310 int DALI_EXPORT_API main(int argc, char** argv)
312 Application application = Application::New(&argc, &argv);
313 RadialProgressController test(application);
314 application.MainLoop();