/* * Copyright (c) 2017 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 #include using namespace Dali; namespace // unnamed namespace { const char* TEXTURE_URL = DEMO_IMAGE_DIR "RadialEffect-280x280.png"; const unsigned int TEXTURE_WIDTH = 280; const unsigned int TEXTURE_HEIGHT = 280; const int NUMBER_OF_SIDES( 64 ); // number of sides of the polygon used as a stencil const float INITIAL_DELAY( 2.0f ); // initial delay before showing the circle const float PROGRESS_DURATION( 0.5f ); // number of seconds to fully show the circle /* * Vertex shader for textured quad */ const char* VERTEX_SHADER_TEXTURED = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n uniform mediump mat4 uMvpMatrix;\n // DALi shader builtin uniform mediump vec3 uSize;\n // DALi shader builtin \n varying mediump vec2 vTexCoord;\n void main()\n {\n mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n vertexPosition.xyz *= uSize;\n vTexCoord = vec2(1.0, 1.0)*(aPosition + vec2(0.5) );\n gl_Position = uMvpMatrix * vertexPosition;\n }\n ); /* * Fragment shaderfor textured quad */ const char* FRAGMENT_SHADER_TEXTURED = DALI_COMPOSE_SHADER( uniform sampler2D uTexture;\n \n varying mediump vec2 vTexCoord;\n void main()\n {\n mediump vec4 texColor = texture2D( uTexture, vTexCoord );\n gl_FragColor = texColor;\n }\n ); /* * Vertex shader for polygon */ const char* VERTEX_SHADER_BASIC = DALI_COMPOSE_SHADER( attribute mediump vec3 aPosition;\n uniform mediump mat4 uMvpMatrix;\n // DALi shader builtin uniform mediump vec3 uSize;\n // DALi shader builtin uniform mediump float uProgress;\n \n varying mediump vec2 vTexCoord;\n void main()\n {\n mediump vec4 vertexPosition = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n \n float index = aPosition.z;\n if( uProgress < index )\n {\n vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n }\n \n vertexPosition.xyz *= uSize;\n gl_Position = uMvpMatrix * vertexPosition;\n }\n ); /* * Fragment shader for polygon */ const char* FRAGMENT_SHADER_BASIC = DALI_COMPOSE_SHADER( void main()\n {\n gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );\n }\n ); } // unnamed namespace // This example shows how to render a radial progress indicator // class RadialProgressController : public ConnectionTracker { public: RadialProgressController( Application& application ) : mApplication( application ) { // Connect to the Application's Init signal mApplication.InitSignal().Connect( this, &RadialProgressController::Create ); } ~RadialProgressController() { // Nothing to do here } // The Init signal is received once (only) during the Application lifetime void Create( Application& application ) { Stage stage = Stage::GetCurrent(); stage.SetBackgroundColor( Color::BLACK ); // 1. Create actor to show the effect mActor = Actor::New(); mActor.SetAnchorPoint( AnchorPoint::CENTER ); mActor.SetParentOrigin( ParentOrigin::CENTER ); mActor.SetSize( Vector2( TEXTURE_WIDTH, TEXTURE_HEIGHT ) ); mActor.RegisterProperty("uProgress", float(1.0f) ); stage.Add( mActor ); // 1. Create stencil renderer i.e. a triangle fan in the shape of a circle Renderer stencilRenderer = CreatePolygon( NUMBER_OF_SIDES ); mActor.AddRenderer( stencilRenderer ); // 2. Create textured quad renderer Renderer texturedQuad = CreateTexturedQuad( TEXTURE_URL ); mActor.AddRenderer( texturedQuad ); // 5. Animate the progress uniform Animation animation = Animation::New( PROGRESS_DURATION + INITIAL_DELAY ); animation.AnimateTo( Property(mActor,"uProgress"), float(NUMBER_OF_SIDES+1), TimePeriod(INITIAL_DELAY, PROGRESS_DURATION) ); animation.Play(); // 6. Exit the application when touched stage.GetRootLayer().TouchSignal().Connect( this, &RadialProgressController::OnTouch ); } bool OnTouch( Actor actor, const TouchData& touch ) { // quit the application mApplication.Quit(); return true; } /** * Generates stencil mask geometry. Geometry is rendered as * a triangle fan and occupies square 2.0x2.0. * @param[in] numberOfSides The more subdivisions the more smooth mask animation. */ Renderer CreatePolygon( unsigned int numberOfSides ) { float count( numberOfSides ); // compute radial step in radians const float STEP( (2.0f * M_PI) / count ); float angle( 0.0f ); std::vector< Vector3 > vertices; vertices.push_back( Vector3::ZERO ); for( size_t i = 0; i <= numberOfSides; ++i ) { vertices.push_back( Vector3( -0.5f * cos( angle ), -0.5f * sin( angle ), i+1 ) ); angle += STEP; } Property::Map vertexFormat; vertexFormat[ "aPosition" ] = Property::VECTOR3; // describe vertex format ( only 2-dimensional positions ) PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat ); vertexBuffer.SetData( vertices.data(), vertices.size() ); // create geometry Geometry geometry = Geometry::New(); geometry.AddVertexBuffer( vertexBuffer ); geometry.SetType( Geometry::TRIANGLE_FAN ); Shader shader = Shader::New( VERTEX_SHADER_BASIC, FRAGMENT_SHADER_BASIC ); Renderer renderer = Renderer::New( geometry, shader ); // Setting stencil data. We don't want to render to the color buffer so // with use of RenderMode property we specify that only stencil buffer will // be affected. renderer.SetProperty( Renderer::Property::RENDER_MODE, RenderMode::STENCIL ); // Set stencil function renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION, StencilFunction::ALWAYS ); // Stencil function reference renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_REFERENCE, 1 ); // Stencil function mask renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_MASK, 0xFF ); // Set stencil operations renderer.SetProperty( Renderer::Property::STENCIL_OPERATION_ON_FAIL, StencilOperation::KEEP ); renderer.SetProperty( Renderer::Property::STENCIL_OPERATION_ON_Z_FAIL, StencilOperation::KEEP ); renderer.SetProperty( Renderer::Property::STENCIL_OPERATION_ON_Z_PASS, StencilOperation::REPLACE ); // Stencil mask to write renderer.SetProperty( Renderer::Property::STENCIL_MASK, 0xFF ); // Set depth index lower than textured quad renderer, so stencil will render first renderer.SetProperty( Renderer::Property::DEPTH_INDEX, 1 ); return renderer; } /** * Creates textured quad renderer */ Renderer CreateTexturedQuad( const char* url ) { // Create shader & geometry needed by Renderer Shader shader = Shader::New( VERTEX_SHADER_TEXTURED, FRAGMENT_SHADER_TEXTURED ); Property::Map vertexFormat; vertexFormat["aPosition"] = Property::VECTOR2; PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat ); const float P( 0.5f ); const Vector2 vertices[] = { Vector2( -P, -P ), Vector2( +P, -P ), Vector2( -P, +P ), Vector2( +P, +P ) }; vertexBuffer.SetData( vertices, 4 ); // Instantiate quad geometry Geometry geometry = Geometry::New(); geometry.AddVertexBuffer( vertexBuffer ); geometry.SetType( Geometry::TRIANGLE_STRIP ); // Load texture PixelData pixelData = Toolkit::SyncImageLoader::Load( url ); Texture texture = Texture::New( TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight() ); texture.Upload( pixelData ); texture.GenerateMipmaps(); // Create texture set TextureSet textureSet = TextureSet::New(); textureSet.SetTexture( 0, texture ); // Create renderer Renderer renderer = Renderer::New( geometry, shader ); renderer.SetTextures( textureSet ); // Set mode indicating we will use both stencil and color buffers renderer.SetProperty( Renderer::Property::RENDER_MODE, RenderMode::COLOR_STENCIL ); // Stencil function - expecing drawing only when function mask matches exactly renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION, StencilFunction::EQUAL ); renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_REFERENCE, 1 ); renderer.SetProperty( Renderer::Property::STENCIL_FUNCTION_MASK, 0xFF ); // We don't want to draw to the stencil, so setting stencil draw mask to 0 renderer.SetProperty( Renderer::Property::STENCIL_MASK, 0x00 ); // Make sure the quad will render after drawing to stencil buffer renderer.SetProperty( Renderer::Property::DEPTH_INDEX, 2 ); return renderer; } private: Application& mApplication; Actor mActor; }; void RunTest( Application& application ) { RadialProgressController test( application ); application.MainLoop(); } // Entry point for Linux & Tizen applications // int DALI_EXPORT_API main( int argc, char **argv ) { Application application = Application::New( &argc, &argv ); RunTest( application ); return 0; }