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/devel-api/images/texture-set-image.h>
19 #include <dali/public-api/rendering/renderer.h>
20 #include <dali-toolkit/dali-toolkit.h>
21 #include <dali-toolkit/devel-api/controls/bubble-effect/bubble-emitter.h>
22 #include <dali-toolkit/devel-api/controls/buttons/button-devel.h>
23 #include <dali-toolkit/devel-api/controls/gaussian-blur-view/gaussian-blur-view.h>
29 #include "shared/view.h"
30 #include "shared/utility.h"
33 using namespace Dali::Toolkit;
35 class NewWindowController;
39 const char * const BACKGROUND_IMAGE( DEMO_IMAGE_DIR "background-2.jpg" );
40 const char * const TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
41 const char * const LOSE_CONTEXT_IMAGE( DEMO_IMAGE_DIR "icon-cluster-wobble.png" );
42 const char * const LOSE_CONTEXT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-cluster-wobble-selected.png" );
43 const char * const BASE_IMAGE( DEMO_IMAGE_DIR "gallery-large-14.jpg" );
44 const char * const EFFECT_IMAGE( DEMO_IMAGE_DIR "gallery-large-18.jpg" );
45 const char * const LOGO_IMAGE(DEMO_IMAGE_DIR "dali-logo.png");
47 const float EXPLOSION_DURATION(1.2f);
48 const unsigned int EMIT_INTERVAL_IN_MS(40);
49 const float TRACK_DURATION_IN_MS(970);
51 Application gApplication;
52 NewWindowController* gNewWindowController(NULL);
54 #define MAKE_SHADER(A)#A
56 const char* VERTEX_COLOR_MESH = MAKE_SHADER(
57 attribute mediump vec3 aPosition;\n
58 attribute lowp vec3 aColor;\n
59 uniform mediump mat4 uMvpMatrix;\n
60 uniform mediump vec3 uSize;\n
61 varying lowp vec3 vColor;\n
65 gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
70 const char* FRAGMENT_COLOR_MESH = MAKE_SHADER(
71 uniform lowp vec4 uColor;\n
72 varying lowp vec3 vColor;\n
76 gl_FragColor = vec4(vColor,1.0)*uColor;
80 const char* VERTEX_TEXTURE_MESH = MAKE_SHADER(
81 attribute mediump vec3 aPosition;\n
82 attribute highp vec2 aTexCoord;\n
83 uniform mediump mat4 uMvpMatrix;\n
84 uniform mediump vec3 uSize;\n
85 varying mediump vec2 vTexCoord;\n
89 gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
90 vTexCoord = aTexCoord;\n
94 const char* FRAGMENT_TEXTURE_MESH = MAKE_SHADER(
95 varying mediump vec2 vTexCoord;\n
96 uniform lowp vec4 uColor;\n
97 uniform sampler2D sTexture;\n
101 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;
105 const char* FRAGMENT_BLEND_SHADER = MAKE_SHADER(
106 varying mediump vec2 vTexCoord;\n
107 uniform sampler2D sTexture;\n
108 uniform sampler2D sEffect;\n
109 uniform mediump float alpha;\n
113 mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n
114 mediump vec4 fxColor = texture2D(sEffect, vTexCoord);\n
115 gl_FragColor = mix(fragColor,fxColor, alpha);\n
119 }; // anonymous namespace
122 class NewWindowController : public ConnectionTracker
125 NewWindowController( Application& app );
126 void Create( Application& app );
127 void Destroy( Application& app );
129 void AddBubbles( Actor& parentActor, const Vector2& stageSize);
130 void AddMeshActor( Actor& parentActor );
131 void AddBlendingImageActor( Actor& parentActor );
132 void AddTextLabel( Actor& parentActor );
134 ImageView CreateBlurredMirrorImage(const char* imageName);
135 FrameBufferImage CreateFrameBufferForImage( const char* imageName, Property::Map& shaderEffect, const Vector3& rgbDelta );
136 void SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction );
137 Geometry CreateMeshGeometry();
138 Dali::Property::Map CreateColorModifierer();
140 static void NewWindow(void);
142 bool OnTrackTimerTick();
143 void OnKeyEvent(const KeyEvent& event);
144 bool OnLoseContextButtonClicked( Toolkit::Button button );
145 void OnContextLost();
146 void OnContextRegained();
149 Application mApplication;
150 TextLabel mTextActor;
152 Toolkit::Control mView; ///< The View instance.
153 Toolkit::ToolBar mToolBar; ///< The View's Toolbar.
154 TextLabel mTitleActor; ///< The Toolbar's Title.
155 Layer mContentLayer; ///< Content layer (scrolling cluster content)
156 Toolkit::PushButton mLoseContextButton;
158 Toolkit::BubbleEmitter mEmitter;
159 Timer mEmitTrackTimer;
160 bool mNeedNewAnimation;
161 unsigned int mAnimateComponentCount;
162 Animation mEmitAnimation;
166 NewWindowController::NewWindowController( Application& application )
167 : mApplication(application),
168 mNeedNewAnimation(true),
169 mAnimateComponentCount( 0 )
171 mApplication.InitSignal().Connect(this, &NewWindowController::Create);
172 mApplication.TerminateSignal().Connect(this, &NewWindowController::Destroy);
175 void NewWindowController::Create( Application& app )
177 Stage stage = Stage::GetCurrent();
178 stage.SetBackgroundColor(Color::YELLOW);
180 stage.KeyEventSignal().Connect(this, &NewWindowController::OnKeyEvent);
182 // The Init signal is received once (only) during the Application lifetime
184 // Hide the indicator bar
185 mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
187 mContentLayer = DemoHelper::CreateView( app,
192 "Context recovery" );
194 Size stageSize = stage.GetSize();
195 ImageView backgroundActor = ImageView::New( BACKGROUND_IMAGE, Dali::ImageDimensions( stageSize.x, stageSize.y ) );
196 backgroundActor.SetParentOrigin( ParentOrigin::CENTER );
197 mContentLayer.Add(backgroundActor);
199 // Point the default render task at the view
200 RenderTaskList taskList = stage.GetRenderTaskList();
201 RenderTask defaultTask = taskList.GetTask( 0u );
204 defaultTask.SetSourceActor( mView );
207 mLoseContextButton = Toolkit::PushButton::New();
208 mLoseContextButton.SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, LOSE_CONTEXT_IMAGE );
209 mLoseContextButton.SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, LOSE_CONTEXT_IMAGE_SELECTED );
210 mLoseContextButton.ClickedSignal().Connect( this, &NewWindowController::OnLoseContextButtonClicked );
211 mToolBar.AddControl( mLoseContextButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
213 Actor logoLayoutActor = Actor::New();
214 logoLayoutActor.SetParentOrigin(ParentOrigin::CENTER);
215 logoLayoutActor.SetPosition(0.0f, -200.0f, 0.0f);
216 logoLayoutActor.SetScale(0.5f);
217 backgroundActor.Add(logoLayoutActor);
219 ImageView imageView = ImageView::New( LOGO_IMAGE );
220 imageView.SetName("daliLogo");
221 imageView.SetParentOrigin(ParentOrigin::CENTER);
222 imageView.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
223 logoLayoutActor.Add(imageView);
225 ImageView mirrorImageView = CreateBlurredMirrorImage(LOGO_IMAGE);
226 mirrorImageView.SetParentOrigin(ParentOrigin::TOP_CENTER);
227 mirrorImageView.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
228 logoLayoutActor.Add(mirrorImageView);
230 AddBubbles( backgroundActor, stage.GetSize());
231 AddMeshActor( backgroundActor );
232 AddBlendingImageActor( backgroundActor );
233 AddTextLabel( backgroundActor );
235 stage.ContextLostSignal().Connect(this, &NewWindowController::OnContextLost);
236 stage.ContextRegainedSignal().Connect(this, &NewWindowController::OnContextRegained);
239 void NewWindowController::Destroy( Application& app )
241 UnparentAndReset(mTextActor);
244 void NewWindowController::AddBubbles( Actor& parentActor, const Vector2& stageSize)
246 mEmitter = Toolkit::BubbleEmitter::New( stageSize,
247 DemoHelper::LoadTexture( DEMO_IMAGE_DIR "bubble-ball.png" ),
248 200, Vector2( 5.0f, 5.0f ) );
250 Texture background = DemoHelper::LoadTexture(BACKGROUND_IMAGE);
251 mEmitter.SetBackground( background, Vector3(0.5f, 0.f,0.5f) );
252 mEmitter.SetBubbleDensity( 9.f );
253 Actor bubbleRoot = mEmitter.GetRootActor();
254 parentActor.Add( bubbleRoot );
255 bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
256 bubbleRoot.SetZ(0.1f);
258 mEmitTrackTimer = Timer::New( EMIT_INTERVAL_IN_MS );
259 mEmitTrackTimer.TickSignal().Connect(this, &NewWindowController::OnTrackTimerTick);
260 mEmitTrackTimer.Start();
263 void NewWindowController::AddMeshActor( Actor& parentActor )
265 Geometry meshGeometry = CreateMeshGeometry();
267 // Create a coloured mesh
268 Shader shaderColorMesh = Shader::New( VERTEX_COLOR_MESH, FRAGMENT_COLOR_MESH );
269 Renderer colorMeshRenderer = Renderer::New( meshGeometry, shaderColorMesh );
271 Actor colorMeshActor = Actor::New();
272 colorMeshActor.AddRenderer( colorMeshRenderer );
273 colorMeshActor.SetSize( 175.f,175.f, 175.f );
274 colorMeshActor.SetParentOrigin( ParentOrigin::CENTER );
275 colorMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
276 colorMeshActor.SetPosition(Vector3(0.0f, 50.0f, 0.0f));
277 colorMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
278 colorMeshActor.SetName("ColorMeshActor");
280 // Create a textured mesh
281 Texture effectTexture = DemoHelper::LoadTexture(EFFECT_IMAGE);
282 Shader shaderTextureMesh = Shader::New( VERTEX_TEXTURE_MESH, FRAGMENT_TEXTURE_MESH );
283 TextureSet textureSet = TextureSet::New();
284 textureSet.SetTexture( 0u, effectTexture );
285 Renderer textureMeshRenderer = Renderer::New( meshGeometry, shaderTextureMesh );
286 textureMeshRenderer.SetTextures( textureSet );
288 Actor textureMeshActor = Actor::New();
289 textureMeshActor.AddRenderer( textureMeshRenderer );
290 textureMeshActor.SetSize( 175.f,175.f, 175.f );
291 textureMeshActor.SetParentOrigin( ParentOrigin::CENTER );
292 textureMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
293 textureMeshActor.SetPosition(Vector3(0.0f, 200.0f, 0.0f));
294 textureMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
295 textureMeshActor.SetName("TextureMeshActor");
297 Layer layer3d = Layer::New();
298 layer3d.SetParentOrigin( ParentOrigin::CENTER );
299 layer3d.SetAnchorPoint( AnchorPoint::CENTER );
300 layer3d.SetBehavior(Layer::LAYER_3D);
302 layer3d.Add( colorMeshActor );
303 layer3d.Add( textureMeshActor );
304 parentActor.Add(layer3d);
307 void NewWindowController::AddBlendingImageActor( Actor& parentActor )
309 Property::Map colorModifier = CreateColorModifierer();
311 FrameBufferImage fb2 = CreateFrameBufferForImage( EFFECT_IMAGE, colorModifier, Vector3( 0.5f, 0.5f, 0.5f ) );
313 ImageView tmpActor = ImageView::New(fb2);
314 parentActor.Add(tmpActor);
315 tmpActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
316 tmpActor.SetAnchorPoint(AnchorPoint::TOP_RIGHT);
317 tmpActor.SetPosition(Vector3(0.0f, 150.0f, 0.0f));
318 tmpActor.SetScale(0.25f);
320 // create blending shader effect
321 Property::Map customShader;
322 customShader[ "fragmentShader" ] = FRAGMENT_BLEND_SHADER;
324 map[ "shader" ] = customShader;
326 ImageView blendActor = ImageView::New( BASE_IMAGE );
327 blendActor.SetProperty( ImageView::Property::IMAGE, map );
328 blendActor.RegisterProperty( "alpha", 0.5f );
330 blendActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
331 blendActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
332 blendActor.SetPosition(Vector3(0.0f, 100.0f, 0.0f));
333 blendActor.SetSize(140, 140);
334 parentActor.Add(blendActor);
336 TextureSet textureSet = blendActor.GetRendererAt(0u).GetTextures();
337 TextureSetImage( textureSet, 1u, fb2 );
340 void NewWindowController::AddTextLabel( Actor& parentActor )
342 mTextActor = TextLabel::New("Some text");
343 mTextActor.SetParentOrigin(ParentOrigin::CENTER);
344 mTextActor.SetColor(Color::RED);
345 mTextActor.SetName("PushMe text");
346 parentActor.Add( mTextActor );
349 ImageView NewWindowController::CreateBlurredMirrorImage(const char* imageName)
351 Image image = DemoHelper::LoadImage(imageName);
353 Vector2 FBOSize = Vector2( image.GetWidth(), image.GetHeight() );
354 FrameBufferImage fbo = FrameBufferImage::New( FBOSize.width, FBOSize.height, Pixel::RGBA8888);
356 GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
357 gbv.SetBackgroundColor(Color::TRANSPARENT);
358 gbv.SetUserImageAndOutputRenderTarget( image, fbo );
359 gbv.SetSize(FBOSize);
360 Stage::GetCurrent().Add(gbv);
363 ImageView blurredActor = ImageView::New(fbo);
364 blurredActor.SetSize(FBOSize);
365 blurredActor.SetScale(1.0f, -1.0f, 1.0f);
369 FrameBufferImage NewWindowController::CreateFrameBufferForImage(const char* imageName, Property::Map& shaderEffect, const Vector3& rgbDelta )
371 Stage stage = Stage::GetCurrent();
372 Uint16Pair intFboSize = ResourceImage::GetImageSize( imageName );
373 Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
375 FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
377 RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
379 ImageView imageView = ImageView::New( imageName );
380 imageView.SetName("Source image actor");
381 imageView.SetProperty( ImageView::Property::IMAGE, shaderEffect );
382 imageView.RegisterProperty( "uRGBDelta", rgbDelta );
384 imageView.SetParentOrigin(ParentOrigin::CENTER);
385 imageView.SetAnchorPoint(AnchorPoint::CENTER);
386 imageView.SetScale(1.0f, -1.0f, 1.0f);
387 stage.Add(imageView); // Not in default image view
389 CameraActor cameraActor = CameraActor::New(FBOSize);
390 cameraActor.SetParentOrigin(ParentOrigin::CENTER);
391 cameraActor.SetFieldOfView(Math::PI*0.25f);
392 cameraActor.SetNearClippingPlane(1.0f);
393 cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
394 cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
395 cameraActor.SetPosition(0.0f, 0.0f, ((FBOSize.height * 0.5f) / tanf(Math::PI * 0.125f)));
396 stage.Add(cameraActor);
398 renderTask.SetSourceActor(imageView);
399 renderTask.SetInputEnabled(false);
400 renderTask.SetTargetFrameBuffer(framebuffer);
401 renderTask.SetCameraActor( cameraActor );
402 renderTask.SetClearColor( Color::TRANSPARENT );
403 renderTask.SetClearEnabled( true );
404 renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
409 void NewWindowController::SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction)
411 if( mNeedNewAnimation )
413 float duration = Random::Range(1.f, 1.5f);
414 mEmitAnimation = Animation::New( duration );
415 mNeedNewAnimation = false;
416 mAnimateComponentCount = 0;
419 mEmitter.EmitBubble( mEmitAnimation, emitPosition, direction, Vector2(10,10) );
421 mAnimateComponentCount++;
423 if( mAnimateComponentCount % 6 ==0 )
425 mEmitAnimation.Play();
426 mNeedNewAnimation = true;
430 Geometry NewWindowController::CreateMeshGeometry()
432 // Create vertices and specify their color
436 Vector2 textureCoordinates;
440 Vertex vertexData[5] = {
441 { Vector3( 0.0f, 0.0f, 0.5f ), Vector2(0.5f, 0.5f), Vector3(1.0f, 1.0f, 1.0f) },
442 { Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) },
443 { Vector3( 0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) },
444 { Vector3( -0.5f, 0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f, 1.0f, 0.0f) },
445 { Vector3( 0.5f, 0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f, 0.0f, 1.0f) } };
447 Property::Map vertexFormat;
448 vertexFormat["aPosition"] = Property::VECTOR3;
449 vertexFormat["aTexCoord"] = Property::VECTOR2;
450 vertexFormat["aColor"] = Property::VECTOR3;
451 PropertyBuffer vertices = PropertyBuffer::New( vertexFormat );
452 vertices.SetData( vertexData, 5 );
454 // Specify all the faces
455 unsigned short indexData[12] = { 0,1,3,0,2,4,0,3,4,0,2,1 };
457 // Create the geometry object
458 Geometry geometry = Geometry::New();
459 geometry.AddVertexBuffer( vertices );
460 geometry.SetIndexBuffer( &indexData[0], 12 );
465 Dali::Property::Map NewWindowController::CreateColorModifierer()
467 const char* fragmentShader ( DALI_COMPOSE_SHADER (
468 precision highp float;\n
469 uniform vec3 uRGBDelta;\n
470 uniform float uIgnoreAlpha;\n
472 varying mediump vec2 vTexCoord;\n
473 uniform sampler2D sTexture;\n
475 float rand(vec2 co) \n
477 return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n}
480 vec4 color = texture2D(sTexture, vTexCoord); \n
481 // modify the hsv Value
482 color.rgb += uRGBDelta * rand(vTexCoord); \n
483 // if the new vale exceeds one, then decrease it
484 color.rgb -= max(color.rgb*2.0 - vec3(2.0), 0.0);\n
485 // if the new vale drops below zero, then increase it
486 color.rgb -= min(color.rgb*2.0, 0.0);\n
487 gl_FragColor = color; \n
492 Property::Map customShader;
493 customShader[ "fragmentShader" ] = fragmentShader;
494 map[ "shader" ] = customShader;
499 void NewWindowController::NewWindow(void)
501 PositionSize posSize(0, 0, 720, 1280);
502 gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
505 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
507 // Add as an idle callback to avoid ProcessEvents being recursively called.
508 mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
512 bool NewWindowController::OnTrackTimerTick()
515 const float radius(250.0f);
517 time += EMIT_INTERVAL_IN_MS;
518 float modTime = time / TRACK_DURATION_IN_MS;
519 float angle = 2.0f*Math::PI*modTime;
521 Vector2 position(radius*cosf(angle), radius*-sinf(angle));
522 Vector2 aimPos(radius*2*sinf(angle), radius*2*-cosf(angle));
523 Vector2 direction = aimPos-position;
524 Vector2 stageSize = Stage::GetCurrent().GetSize();
526 SetUpBubbleEmission( stageSize*0.5f+position, direction );
527 SetUpBubbleEmission( stageSize*0.5f+position*0.75f, direction );
528 SetUpBubbleEmission( stageSize*0.5f+position*0.7f, direction );
533 void NewWindowController::OnKeyEvent(const KeyEvent& event)
535 if(event.state == KeyEvent::Down)
537 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
544 void NewWindowController::OnContextLost()
546 printf("Stage reporting context loss\n");
549 void NewWindowController::OnContextRegained()
551 printf("Stage reporting context regain\n");
554 void RunTest(Application& app)
556 gNewWindowController = new NewWindowController(app);
557 app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
560 // Entry point for Linux & Tizen applications
562 int DALI_EXPORT_API main(int argc, char **argv)
564 gApplication = Application::New(&argc, &argv, DEMO_THEME_PATH);
565 RunTest(gApplication);