2 * Copyright (c) 2017 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/dali.h>
19 #include <dali-toolkit/dali-toolkit.h>
23 namespace // unnamed namespace
26 const char* TEXTURE_URL = DEMO_IMAGE_DIR "RadialEffect-280x280.png";
27 const unsigned int TEXTURE_WIDTH = 280;
28 const unsigned int TEXTURE_HEIGHT = 280;
30 const int NUMBER_OF_SIDES( 64 ); // number of sides of the polygon used as a stencil
31 const float INITIAL_DELAY( 2.0f ); // initial delay before showing the circle
32 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
103 } // unnamed namespace
106 // This example shows how to render a radial progress indicator
108 class RadialProgressController : public ConnectionTracker
112 RadialProgressController( Application& application )
113 : mApplication( application )
115 // Connect to the Application's Init signal
116 mApplication.InitSignal().Connect( this, &RadialProgressController::Create );
119 ~RadialProgressController()
121 // Nothing to do here
124 // The Init signal is received once (only) during the Application lifetime
125 void Create( Application& application )
127 Stage stage = Stage::GetCurrent();
128 stage.SetBackgroundColor( Color::BLACK );
130 // Connect to the stage's key signal to allow Back and Escape to exit.
131 stage.KeyEventSignal().Connect( this, &RadialProgressController::OnKeyEvent );
133 // 1. Create actor to show the effect
134 mActor = Actor::New();
135 mActor.SetAnchorPoint( AnchorPoint::CENTER );
136 mActor.SetParentOrigin( ParentOrigin::CENTER );
137 mActor.SetSize( Vector2( TEXTURE_WIDTH, TEXTURE_HEIGHT ) );
138 mActor.RegisterProperty("uProgress", float(1.0f) );
141 // 1. Create stencil renderer i.e. a triangle fan in the shape of a circle
142 Renderer stencilRenderer = CreatePolygon( NUMBER_OF_SIDES );
143 mActor.AddRenderer( stencilRenderer );
145 // 2. Create textured quad renderer
146 Renderer texturedQuad = CreateTexturedQuad( TEXTURE_URL );
147 mActor.AddRenderer( texturedQuad );
149 // 5. Animate the progress uniform
150 Animation animation = Animation::New( PROGRESS_DURATION + INITIAL_DELAY );
151 animation.AnimateTo( Property(mActor,"uProgress"), float(NUMBER_OF_SIDES+1), TimePeriod(INITIAL_DELAY, PROGRESS_DURATION) );
154 // 6. Exit the application when touched
155 stage.GetRootLayer().TouchSignal().Connect( this, &RadialProgressController::OnTouch );
158 bool OnTouch( Actor actor, const TouchData& touch )
160 // quit the application
166 * Generates stencil mask geometry. Geometry is rendered as
167 * a triangle fan and occupies square 2.0x2.0.
168 * @param[in] numberOfSides The more subdivisions the more smooth mask animation.
170 Renderer CreatePolygon( unsigned int numberOfSides )
172 float count( numberOfSides );
174 // compute radial step in radians
175 const float STEP( (2.0f * M_PI) / count );
178 std::vector< Vector3 > vertices;
179 vertices.push_back( Vector3::ZERO );
181 for( size_t i = 0; i <= numberOfSides; ++i )
183 vertices.push_back( Vector3( -0.5f * cos( angle ), -0.5f * sin( angle ), i+1 ) );
187 Property::Map vertexFormat;
188 vertexFormat[ "aPosition" ] = Property::VECTOR3;
190 // describe vertex format ( only 2-dimensional positions )
191 PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
192 vertexBuffer.SetData( vertices.data(), vertices.size() );
195 Geometry geometry = Geometry::New();
196 geometry.AddVertexBuffer( vertexBuffer );
197 geometry.SetType( Geometry::TRIANGLE_FAN );
199 Shader shader = Shader::New( VERTEX_SHADER_BASIC, FRAGMENT_SHADER_BASIC );
200 Renderer renderer = Renderer::New( geometry, shader );
202 // Setting stencil data. We don't want to render to the color buffer so
203 // with use of RenderMode property we specify that only stencil buffer will
205 renderer.SetProperty( Renderer::Property::RENDER_MODE, RenderMode::STENCIL );
207 // Set stencil function
208 renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION, StencilFunction::ALWAYS );
210 // Stencil function reference
211 renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_REFERENCE, 1 );
213 // Stencil function mask
214 renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_MASK, 0xFF );
216 // Set stencil operations
217 renderer.SetProperty( Renderer::Property::STENCIL_OPERATION_ON_FAIL, StencilOperation::KEEP );
218 renderer.SetProperty( Renderer::Property::STENCIL_OPERATION_ON_Z_FAIL, StencilOperation::KEEP );
219 renderer.SetProperty( Renderer::Property::STENCIL_OPERATION_ON_Z_PASS, StencilOperation::REPLACE );
221 // Stencil mask to write
222 renderer.SetProperty( Renderer::Property::STENCIL_MASK, 0xFF );
224 // Set depth index lower than textured quad renderer, so stencil will render first
225 renderer.SetProperty( Renderer::Property::DEPTH_INDEX, 1 );
231 * Creates textured quad renderer
233 Renderer CreateTexturedQuad( const char* url )
235 // Create shader & geometry needed by Renderer
237 Shader shader = Shader::New( VERTEX_SHADER_TEXTURED, FRAGMENT_SHADER_TEXTURED );
239 Property::Map vertexFormat;
240 vertexFormat["aPosition"] = Property::VECTOR2;
241 PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
243 const float P( 0.5f );
244 const Vector2 vertices[] = {
251 vertexBuffer.SetData( vertices, 4 );
253 // Instantiate quad geometry
254 Geometry geometry = Geometry::New();
255 geometry.AddVertexBuffer( vertexBuffer );
256 geometry.SetType( Geometry::TRIANGLE_STRIP );
259 PixelData pixelData = Toolkit::SyncImageLoader::Load( url );
260 Texture texture = Texture::New( TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight() );
261 texture.Upload( pixelData );
262 texture.GenerateMipmaps();
264 // Create texture set
265 TextureSet textureSet = TextureSet::New();
266 textureSet.SetTexture( 0, texture );
269 Renderer renderer = Renderer::New( geometry, shader );
270 renderer.SetTextures( textureSet );
272 // Set mode indicating we will use both stencil and color buffers
273 renderer.SetProperty( Renderer::Property::RENDER_MODE, RenderMode::COLOR_STENCIL );
275 // Stencil function - expecing drawing only when function mask matches exactly
276 renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION, StencilFunction::EQUAL );
277 renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_REFERENCE, 1 );
278 renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_MASK, 0xFF );
280 // We don't want to draw to the stencil, so setting stencil draw mask to 0
281 renderer.SetProperty( Renderer::Property::STENCIL_MASK, 0x00 );
283 // Make sure the quad will render after drawing to stencil buffer
284 renderer.SetProperty( Renderer::Property::DEPTH_INDEX, 2 );
290 * @brief Called when any key event is received
292 * Will use this to quit the application if Back or the Escape key is received
293 * @param[in] event The key event information
295 void OnKeyEvent( const KeyEvent& event )
297 if( event.state == KeyEvent::Down )
299 if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
308 Application& mApplication;
313 // Entry point for Linux & Tizen applications
314 int DALI_EXPORT_API main( int argc, char **argv )
316 Application application = Application::New( &argc, &argv );
317 RadialProgressController test( application );
318 application.MainLoop();