2 * Copyright (c) 2014 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/rendering/renderer.h>
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali-toolkit/devel-api/controls/bubble-effect/bubble-emitter.h>
26 #include "shared/view.h"
29 using namespace Dali::Toolkit;
31 class NewWindowController;
35 const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
36 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
37 const char * const LOSE_CONTEXT_IMAGE( DALI_IMAGE_DIR "icon-cluster-wobble.png" );
38 const char * const BASE_IMAGE( DALI_IMAGE_DIR "gallery-large-14.jpg" );
39 const char * const EFFECT_IMAGE( DALI_IMAGE_DIR "gallery-large-18.jpg" );
40 const char * const LOGO_IMAGE(DALI_IMAGE_DIR "dali-logo.png");
42 const float EXPLOSION_DURATION(1.2f);
43 const unsigned int EMIT_INTERVAL_IN_MS(40);
44 const float TRACK_DURATION_IN_MS(970);
46 Application gApplication;
47 NewWindowController* gNewWindowController(NULL);
49 #define MAKE_SHADER(A)#A
51 const char* VERTEX_COLOR_MESH = MAKE_SHADER(
52 attribute mediump vec3 aPosition;\n
53 attribute lowp vec3 aColor;\n
54 uniform mediump mat4 uMvpMatrix;\n
55 uniform mediump vec3 uSize;\n
56 varying lowp vec3 vColor;\n
60 gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
65 const char* FRAGMENT_COLOR_MESH = MAKE_SHADER(
66 uniform lowp vec4 uColor;\n
67 varying lowp vec3 vColor;\n
71 gl_FragColor = vec4(vColor,1.0)*uColor;
75 const char* VERTEX_TEXTURE_MESH = MAKE_SHADER(
76 attribute mediump vec3 aPosition;\n
77 attribute highp vec2 aTexCoord;\n
78 uniform mediump mat4 uMvpMatrix;\n
79 uniform mediump vec3 uSize;\n
80 varying mediump vec2 vTexCoord;\n
84 gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
85 vTexCoord = aTexCoord;\n
89 const char* FRAGMENT_TEXTURE_MESH = MAKE_SHADER(
90 varying mediump vec2 vTexCoord;\n
91 uniform lowp vec4 uColor;\n
92 uniform sampler2D sTexture;\n
96 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;
100 const char* FRAGMENT_BLEND_SHADER = MAKE_SHADER(
101 uniform mediump float alpha;\n
105 mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n
106 mediump vec4 fxColor = texture2D(sEffect, vTexCoord);\n
107 gl_FragColor = mix(fragColor,fxColor, alpha);\n
111 }; // anonymous namespace
114 class NewWindowController : public ConnectionTracker
117 NewWindowController( Application& app );
118 void Create( Application& app );
119 void Destroy( Application& app );
121 void AddBubbles(const Vector2& stageSize);
123 void AddBlendingImageActor();
126 ImageActor CreateBlurredMirrorImage(const char* imageName);
127 FrameBufferImage CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect);
128 void SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction );
129 Geometry CreateMeshGeometry();
130 ShaderEffect CreateColorModifierer( const Vector3& rgbDelta );
132 static void NewWindow(void);
134 bool OnTrackTimerTick();
135 void OnKeyEvent(const KeyEvent& event);
136 bool OnLoseContextButtonClicked( Toolkit::Button button );
137 void OnContextLost();
138 void OnContextRegained();
141 Application mApplication;
142 TextLabel mTextActor;
144 Toolkit::Control mView; ///< The View instance.
145 Toolkit::ToolBar mToolBar; ///< The View's Toolbar.
146 TextLabel mTitleActor; ///< The Toolbar's Title.
147 Layer mContentLayer; ///< Content layer (scrolling cluster content)
148 Toolkit::PushButton mLoseContextButton;
150 Toolkit::BubbleEmitter mEmitter;
151 Timer mEmitTrackTimer;
152 bool mNeedNewAnimation;
153 unsigned int mAnimateComponentCount;
154 Animation mEmitAnimation;
158 NewWindowController::NewWindowController( Application& application )
159 : mApplication(application),
160 mNeedNewAnimation(true)
162 mApplication.InitSignal().Connect(this, &NewWindowController::Create);
163 mApplication.TerminateSignal().Connect(this, &NewWindowController::Destroy);
166 void NewWindowController::Create( Application& app )
168 Stage stage = Stage::GetCurrent();
169 stage.SetBackgroundColor(Color::YELLOW);
171 stage.KeyEventSignal().Connect(this, &NewWindowController::OnKeyEvent);
173 // The Init signal is received once (only) during the Application lifetime
175 // Hide the indicator bar
176 mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
178 mContentLayer = DemoHelper::CreateView( app,
183 "Context recovery" );
185 Size stageSize = stage.GetSize();
186 Image backgroundImage = ResourceImage::New( BACKGROUND_IMAGE, Dali::ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR );
187 ImageActor backgroundActor = ImageActor::New( backgroundImage );
188 backgroundActor.SetParentOrigin( ParentOrigin::CENTER );
189 backgroundActor.SetZ(-2.f);
190 mContentLayer.Add(backgroundActor);
192 // Point the default render task at the view
193 RenderTaskList taskList = stage.GetRenderTaskList();
194 RenderTask defaultTask = taskList.GetTask( 0u );
197 defaultTask.SetSourceActor( mView );
200 mLoseContextButton = Toolkit::PushButton::New();
201 mLoseContextButton.SetBackgroundImage( ResourceImage::New( LOSE_CONTEXT_IMAGE ) );
202 mLoseContextButton.ClickedSignal().Connect( this, &NewWindowController::OnLoseContextButtonClicked );
203 mToolBar.AddControl( mLoseContextButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
205 Actor logoLayoutActor = Actor::New();
206 logoLayoutActor.SetParentOrigin(ParentOrigin::CENTER);
207 logoLayoutActor.SetPosition(0.0f, -200.0f, 0.0f);
208 logoLayoutActor.SetScale(0.5f);
209 mContentLayer.Add(logoLayoutActor);
211 Image image = ResourceImage::New(LOGO_IMAGE);
212 ImageActor imageActor = ImageActor::New(image);
213 imageActor.SetName("dali-logo");
214 imageActor.SetParentOrigin(ParentOrigin::CENTER);
215 imageActor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
216 logoLayoutActor.Add(imageActor);
218 ImageActor mirrorImageActor = CreateBlurredMirrorImage(LOGO_IMAGE);
219 mirrorImageActor.SetParentOrigin(ParentOrigin::CENTER);
220 mirrorImageActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
221 logoLayoutActor.Add(mirrorImageActor);
223 AddBubbles(stage.GetSize());
225 AddBlendingImageActor();
228 stage.ContextLostSignal().Connect(this, &NewWindowController::OnContextLost);
229 stage.ContextRegainedSignal().Connect(this, &NewWindowController::OnContextRegained);
232 void NewWindowController::Destroy( Application& app )
234 UnparentAndReset(mTextActor);
237 void NewWindowController::AddBubbles(const Vector2& stageSize)
239 mEmitter = Toolkit::BubbleEmitter::New( stageSize,
240 ResourceImage::New( DALI_IMAGE_DIR "bubble-ball.png" ),
241 200, Vector2( 5.0f, 5.0f ) );
243 Image background = ResourceImage::New(BACKGROUND_IMAGE);
244 mEmitter.SetBackground( background, Vector3(0.5f, 0.f,0.5f) );
245 mEmitter.SetBubbleDensity( 9.f );
246 Actor bubbleRoot = mEmitter.GetRootActor();
247 mContentLayer.Add( bubbleRoot );
248 bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
249 bubbleRoot.SetZ(0.1f);
251 mEmitTrackTimer = Timer::New( EMIT_INTERVAL_IN_MS );
252 mEmitTrackTimer.TickSignal().Connect(this, &NewWindowController::OnTrackTimerTick);
253 mEmitTrackTimer.Start();
256 void NewWindowController::AddMeshActor()
258 Geometry meshGeometry = CreateMeshGeometry();
260 // Create a coloured mesh
261 Shader shaderColorMesh = Shader::New( VERTEX_COLOR_MESH, FRAGMENT_COLOR_MESH );
262 Material colorMeshmaterial = Material::New( shaderColorMesh );
263 Renderer colorMeshRenderer = Renderer::New( meshGeometry, colorMeshmaterial );
265 Actor colorMeshActor = Actor::New();
266 colorMeshActor.AddRenderer( colorMeshRenderer );
267 colorMeshActor.SetSize( 175.f,175.f );
268 colorMeshActor.SetParentOrigin( ParentOrigin::CENTER );
269 colorMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
270 colorMeshActor.SetPosition(Vector3(0.0f, 50.0f, 0.0f));
271 colorMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
272 colorMeshActor.SetName("ColorMeshActor");
273 mContentLayer.Add( colorMeshActor );
275 // Create a textured mesh
276 Image effectImage = ResourceImage::New(EFFECT_IMAGE);
277 Sampler sampler = Sampler::New(effectImage, "sTexture");
279 Shader shaderTextureMesh = Shader::New( VERTEX_TEXTURE_MESH, FRAGMENT_TEXTURE_MESH );
280 Material textureMeshMaterial = Material::New( shaderTextureMesh );
281 textureMeshMaterial.AddSampler( sampler );
282 Renderer textureMeshRenderer = Renderer::New( meshGeometry, textureMeshMaterial );
284 Actor textureMeshActor = Actor::New();
285 textureMeshActor.AddRenderer( textureMeshRenderer );
286 textureMeshActor.SetSize( 175.f,175.f );
287 textureMeshActor.SetParentOrigin( ParentOrigin::CENTER );
288 textureMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
289 textureMeshActor.SetPosition(Vector3(0.0f, 200.0f, 0.0f));
290 textureMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
291 textureMeshActor.SetName("TextureMeshActor");
292 mContentLayer.Add( textureMeshActor );
295 void NewWindowController::AddBlendingImageActor()
297 ShaderEffect colorModifier = CreateColorModifierer(Vector3( 0.5f, 0.5f, 0.5f ));
298 Image effectImage = ResourceImage::New(EFFECT_IMAGE);
299 FrameBufferImage fb2 = CreateFrameBufferForImage( EFFECT_IMAGE, effectImage, colorModifier );
301 ImageActor tmpActor = ImageActor::New(fb2);
302 mContentLayer.Add(tmpActor);
303 tmpActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
304 tmpActor.SetAnchorPoint(AnchorPoint::TOP_RIGHT);
305 tmpActor.SetPosition(Vector3(0.0f, 150.0f, 0.0f));
306 tmpActor.SetScale(0.25f);
308 // create blending shader effect
309 ShaderEffect blendShader = ShaderEffect::New( "", FRAGMENT_BLEND_SHADER );
310 blendShader.SetEffectImage( fb2 );
311 blendShader.SetUniform("alpha", 0.5f);
313 Image baseImage = ResourceImage::New(BASE_IMAGE);
314 ImageActor blendActor = ImageActor::New( baseImage );
315 blendActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
316 blendActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
317 blendActor.SetPosition(Vector3(0.0f, 100.0f, 0.0f));
318 blendActor.SetSize(140, 140);
319 blendActor.SetShaderEffect( blendShader );
320 mContentLayer.Add(blendActor);
323 void NewWindowController::AddTextLabel()
325 mTextActor = TextLabel::New("Some text");
326 mTextActor.SetParentOrigin(ParentOrigin::CENTER);
327 mTextActor.SetColor(Color::RED);
328 mTextActor.SetName("PushMe text");
329 mContentLayer.Add( mTextActor );
332 ImageActor NewWindowController::CreateBlurredMirrorImage(const char* imageName)
334 Image image = ResourceImage::New(imageName);
336 Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
337 Vector2 FBOSize = Vector2( intFboSize.GetWidth(), intFboSize.GetHeight() );
338 FrameBufferImage fbo = FrameBufferImage::New( FBOSize.width, FBOSize.height, Pixel::RGBA8888);
340 GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
341 gbv.SetBackgroundColor(Color::TRANSPARENT);
342 gbv.SetUserImageAndOutputRenderTarget( image, fbo );
343 gbv.SetSize(FBOSize);
344 Stage::GetCurrent().Add(gbv);
347 ImageActor blurredActor = ImageActor::New(fbo);
348 blurredActor.SetSize(FBOSize);
349 blurredActor.SetScale(1.0f, -1.0f, 1.0f);
353 FrameBufferImage NewWindowController::CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect)
355 Stage stage = Stage::GetCurrent();
356 Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
357 Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
359 FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
361 RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
363 ImageActor imageActor = ImageActor::New(image);
364 imageActor.SetName("Source image actor");
367 imageActor.SetShaderEffect(shaderEffect);
369 imageActor.SetParentOrigin(ParentOrigin::CENTER);
370 imageActor.SetAnchorPoint(AnchorPoint::CENTER);
371 imageActor.SetScale(1.0f, -1.0f, 1.0f);
372 stage.Add(imageActor); // Not in default image view
374 CameraActor cameraActor = CameraActor::New(FBOSize);
375 cameraActor.SetParentOrigin(ParentOrigin::CENTER);
376 cameraActor.SetFieldOfView(Math::PI*0.25f);
377 cameraActor.SetNearClippingPlane(1.0f);
378 cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
379 cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
380 cameraActor.SetPosition(0.0f, 0.0f, ((FBOSize.height * 0.5f) / tanf(Math::PI * 0.125f)));
381 stage.Add(cameraActor);
383 renderTask.SetSourceActor(imageActor);
384 renderTask.SetInputEnabled(false);
385 renderTask.SetTargetFrameBuffer(framebuffer);
386 renderTask.SetCameraActor( cameraActor );
387 renderTask.SetClearColor( Color::TRANSPARENT );
388 renderTask.SetClearEnabled( true );
389 renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
394 void NewWindowController::SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction)
396 if( mNeedNewAnimation )
398 float duration = Random::Range(1.f, 1.5f);
399 mEmitAnimation = Animation::New( duration );
400 mNeedNewAnimation = false;
401 mAnimateComponentCount = 0;
404 mEmitter.EmitBubble( mEmitAnimation, emitPosition, direction, Vector2(10,10) );
406 mAnimateComponentCount++;
408 if( mAnimateComponentCount % 6 ==0 )
410 mEmitAnimation.Play();
411 mNeedNewAnimation = true;
415 Geometry NewWindowController::CreateMeshGeometry()
417 // Create vertices and specify their color
421 Vector2 textureCoordinates;
425 Vertex vertexData[5] = {
426 { Vector3( 0.0f, 0.0f, 0.5f ), Vector2(0.5f, 0.5f), Vector3(1.0f, 1.0f, 1.0f) },
427 { Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) },
428 { Vector3( 0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) },
429 { Vector3( -0.5f, 0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f, 1.0f, 0.0f) },
430 { Vector3( 0.5f, 0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f, 0.0f, 1.0f) } };
432 Property::Map vertexFormat;
433 vertexFormat["aPosition"] = Property::VECTOR3;
434 vertexFormat["aTexCoord"] = Property::VECTOR2;
435 vertexFormat["aColor"] = Property::VECTOR3;
436 PropertyBuffer vertices = PropertyBuffer::New( vertexFormat, 5 );
437 vertices.SetData( vertexData );
439 // Specify all the faces
440 unsigned int indexData[12] = { 0,1,3,0,2,4,0,3,4,0,2,1 };
441 Property::Map indexFormat;
442 indexFormat["indices"] = Property::UNSIGNED_INTEGER;
443 PropertyBuffer indices = PropertyBuffer::New( indexFormat, 12 );
444 indices.SetData( indexData );
446 // Create the geometry object
447 Geometry geometry = Geometry::New();
448 geometry.AddVertexBuffer( vertices );
449 geometry.SetIndexBuffer( indices );
454 ShaderEffect NewWindowController::CreateColorModifierer( const Vector3& rgbDelta )
456 std::string fragmentShader = MAKE_SHADER(
457 precision highp float;\n
458 uniform vec3 uRGBDelta;\n
459 uniform float uIgnoreAlpha;\n
460 float rand(vec2 co) \n
462 return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n}
465 vec4 color = texture2D(sTexture, vTexCoord); \n
466 // modify the hsv Value
467 color.rgb += uRGBDelta * rand(vTexCoord); \n
468 // if the new vale exceeds one, then decrease it
469 color.rgb -= max(color.rgb*2.0 - vec3(2.0), 0.0);\n
470 // if the new vale drops below zero, then increase it
471 color.rgb -= min(color.rgb*2.0, 0.0);\n
472 gl_FragColor = color; \n
476 ShaderEffect shaderEffect = ShaderEffect::New("", fragmentShader);
477 shaderEffect.SetUniform( "uRGBDelta", rgbDelta );
482 void NewWindowController::NewWindow(void)
484 PositionSize posSize(0, 0, 720, 1280);
485 gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
488 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
490 // Add as an idle callback to avoid ProcessEvents being recursively called.
491 mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
495 bool NewWindowController::OnTrackTimerTick()
498 const float radius(250.0f);
500 time += EMIT_INTERVAL_IN_MS;
501 float modTime = time / TRACK_DURATION_IN_MS;
502 float angle = 2.0f*Math::PI*modTime;
504 Vector2 position(radius*cosf(angle), radius*-sinf(angle));
505 Vector2 aimPos(radius*2*sinf(angle), radius*2*-cosf(angle));
506 Vector2 direction = aimPos-position;
507 Vector2 stageSize = Stage::GetCurrent().GetSize();
509 SetUpBubbleEmission( stageSize*0.5f+position, direction );
510 SetUpBubbleEmission( stageSize*0.5f+position*0.75f, direction );
511 SetUpBubbleEmission( stageSize*0.5f+position*0.7f, direction );
516 void NewWindowController::OnKeyEvent(const KeyEvent& event)
518 if(event.state == KeyEvent::Down)
520 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
527 void NewWindowController::OnContextLost()
529 printf("Stage reporting context loss\n");
532 void NewWindowController::OnContextRegained()
534 printf("Stage reporting context regain\n");
537 void RunTest(Application& app)
539 gNewWindowController = new NewWindowController(app);
540 app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
543 // Entry point for Linux & Tizen applications
545 int main(int argc, char **argv)
547 gApplication = Application::New(&argc, &argv, DALI_DEMO_THEME_PATH);
548 RunTest(gApplication);