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.
17 #include <dali-toolkit/dali-toolkit.h>
18 #include "shared/view.h"
23 using namespace Dali::Toolkit;
25 class NewWindowController;
29 const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
30 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
31 const char * const LOSE_CONTEXT_IMAGE( DALI_IMAGE_DIR "icon-cluster-wobble.png" );
32 const char * const BASE_IMAGE( DALI_IMAGE_DIR "gallery-large-14.jpg" );
33 const char * const EFFECT_IMAGE( DALI_IMAGE_DIR "gallery-large-18.jpg" );
34 const char * const LOGO_IMAGE(DALI_IMAGE_DIR "dali-logo.png");
36 const float EXPLOSION_DURATION(1.2f);
37 const unsigned int EMIT_INTERVAL_IN_MS(40);
38 const float TRACK_DURATION_IN_MS(970);
40 Application gApplication;
41 NewWindowController* gNewWindowController(NULL);
43 #define MAKE_SHADER(A)#A
45 const char* VERTEX_COLOR_MESH = MAKE_SHADER(
46 attribute mediump vec3 aPosition;\n
47 attribute lowp vec3 aColor;\n
48 uniform mediump mat4 uMvpMatrix;\n
49 uniform mediump vec3 uSize;\n
50 varying lowp vec3 vColor;\n
54 gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
59 const char* FRAGMENT_COLOR_MESH = MAKE_SHADER(
60 uniform lowp vec4 uColor;\n
61 varying lowp vec3 vColor;\n
65 gl_FragColor = vec4(vColor,1.0)*uColor;
69 const char* VERTEX_TEXTURE_MESH = MAKE_SHADER(
70 attribute mediump vec3 aPosition;\n
71 attribute highp vec2 aTexCoord;\n
72 uniform mediump mat4 uMvpMatrix;\n
73 uniform mediump vec3 uSize;\n
74 varying mediump vec2 vTexCoord;\n
78 gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
79 vTexCoord = aTexCoord;\n
83 const char* FRAGMENT_TEXTURE_MESH = MAKE_SHADER(
84 varying mediump vec2 vTexCoord;\n
85 uniform lowp vec4 uColor;\n
86 uniform sampler2D sTexture;\n
90 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;
94 const char* FRAGMENT_BLEND_SHADER = MAKE_SHADER(
95 uniform mediump float alpha;\n
99 mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n
100 mediump vec4 fxColor = texture2D(sEffect, vTexCoord);\n
101 gl_FragColor = mix(fragColor,fxColor, alpha);\n
105 }; // anonymous namespace
108 class NewWindowController : public ConnectionTracker
111 NewWindowController( Application& app );
112 void Create( Application& app );
113 void Destroy( Application& app );
115 void AddBubbles(const Vector2& stageSize);
117 void AddBlendingImageActor();
120 ImageActor CreateBlurredMirrorImage(const char* imageName);
121 FrameBufferImage CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect);
122 void SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction );
123 Geometry CreateMeshGeometry();
124 ShaderEffect CreateColorModifierer( const Vector3& rgbDelta );
126 static void NewWindow(void);
128 bool OnTrackTimerTick();
129 void OnKeyEvent(const KeyEvent& event);
130 bool OnLoseContextButtonClicked( Toolkit::Button button );
131 void OnContextLost();
132 void OnContextRegained();
135 Application mApplication;
136 TextLabel mTextActor;
138 Toolkit::Control mView; ///< The View instance.
139 Toolkit::ToolBar mToolBar; ///< The View's Toolbar.
140 TextLabel mTitleActor; ///< The Toolbar's Title.
141 Layer mContentLayer; ///< Content layer (scrolling cluster content)
142 Toolkit::PushButton mLoseContextButton;
144 Toolkit::BubbleEmitter mEmitter;
145 Timer mEmitTrackTimer;
146 bool mNeedNewAnimation;
147 unsigned int mAnimateComponentCount;
148 Animation mEmitAnimation;
152 NewWindowController::NewWindowController( Application& application )
153 : mApplication(application),
154 mNeedNewAnimation(true)
156 mApplication.InitSignal().Connect(this, &NewWindowController::Create);
157 mApplication.TerminateSignal().Connect(this, &NewWindowController::Destroy);
160 void NewWindowController::Create( Application& app )
162 DemoHelper::RequestThemeChange();
164 Stage stage = Stage::GetCurrent();
165 stage.SetBackgroundColor(Color::YELLOW);
167 stage.KeyEventSignal().Connect(this, &NewWindowController::OnKeyEvent);
169 // The Init signal is received once (only) during the Application lifetime
171 // Hide the indicator bar
172 mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
174 mContentLayer = DemoHelper::CreateView( app,
179 "Context recovery" );
181 Size stageSize = stage.GetSize();
182 Image backgroundImage = ResourceImage::New( BACKGROUND_IMAGE, Dali::ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR );
183 ImageActor backgroundActor = ImageActor::New( backgroundImage );
184 backgroundActor.SetParentOrigin( ParentOrigin::CENTER );
185 backgroundActor.SetZ(-2.f);
186 mContentLayer.Add(backgroundActor);
188 // Point the default render task at the view
189 RenderTaskList taskList = stage.GetRenderTaskList();
190 RenderTask defaultTask = taskList.GetTask( 0u );
193 defaultTask.SetSourceActor( mView );
196 mLoseContextButton = Toolkit::PushButton::New();
197 mLoseContextButton.SetBackgroundImage( ResourceImage::New( LOSE_CONTEXT_IMAGE ) );
198 mLoseContextButton.ClickedSignal().Connect( this, &NewWindowController::OnLoseContextButtonClicked );
199 mToolBar.AddControl( mLoseContextButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
201 Actor logoLayoutActor = Actor::New();
202 logoLayoutActor.SetParentOrigin(ParentOrigin::CENTER);
203 logoLayoutActor.SetPosition(0.0f, -200.0f, 0.0f);
204 logoLayoutActor.SetScale(0.5f);
205 mContentLayer.Add(logoLayoutActor);
207 Image image = ResourceImage::New(LOGO_IMAGE);
208 ImageActor imageActor = ImageActor::New(image);
209 imageActor.SetName("dali-logo");
210 imageActor.SetParentOrigin(ParentOrigin::CENTER);
211 imageActor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
212 logoLayoutActor.Add(imageActor);
214 ImageActor mirrorImageActor = CreateBlurredMirrorImage(LOGO_IMAGE);
215 mirrorImageActor.SetParentOrigin(ParentOrigin::CENTER);
216 mirrorImageActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
217 logoLayoutActor.Add(mirrorImageActor);
219 AddBubbles(stage.GetSize());
221 AddBlendingImageActor();
224 stage.ContextLostSignal().Connect(this, &NewWindowController::OnContextLost);
225 stage.ContextRegainedSignal().Connect(this, &NewWindowController::OnContextRegained);
228 void NewWindowController::Destroy( Application& app )
230 UnparentAndReset(mTextActor);
233 void NewWindowController::AddBubbles(const Vector2& stageSize)
235 mEmitter = Toolkit::BubbleEmitter::New( stageSize,
236 ResourceImage::New( DALI_IMAGE_DIR "bubble-ball.png" ),
237 200, Vector2( 5.0f, 5.0f ) );
239 Image background = ResourceImage::New(BACKGROUND_IMAGE);
240 mEmitter.SetBackground( background, Vector3(0.5f, 0.f,0.5f) );
241 mEmitter.SetBubbleDensity( 9.f );
242 Actor bubbleRoot = mEmitter.GetRootActor();
243 mContentLayer.Add( bubbleRoot );
244 bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
245 bubbleRoot.SetZ(0.1f);
247 mEmitTrackTimer = Timer::New( EMIT_INTERVAL_IN_MS );
248 mEmitTrackTimer.TickSignal().Connect(this, &NewWindowController::OnTrackTimerTick);
249 mEmitTrackTimer.Start();
252 void NewWindowController::AddMeshActor()
254 Geometry meshGeometry = CreateMeshGeometry();
256 // Create a coloured mesh
257 Shader shaderColorMesh = Shader::New( VERTEX_COLOR_MESH, FRAGMENT_COLOR_MESH );
258 Material colorMeshmaterial = Material::New( shaderColorMesh );
259 Renderer colorMeshRenderer = Renderer::New( meshGeometry, colorMeshmaterial );
261 Actor colorMeshActor = Actor::New();
262 colorMeshActor.AddRenderer( colorMeshRenderer );
263 colorMeshActor.SetSize( 175.f,175.f );
264 colorMeshActor.SetParentOrigin( ParentOrigin::CENTER );
265 colorMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
266 colorMeshActor.SetPosition(Vector3(0.0f, 50.0f, 0.0f));
267 colorMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
268 colorMeshActor.SetName("ColorMeshActor");
269 mContentLayer.Add( colorMeshActor );
271 // Create a textured mesh
272 Image effectImage = ResourceImage::New(EFFECT_IMAGE);
273 Sampler sampler = Sampler::New(effectImage, "sTexture");
275 Shader shaderTextureMesh = Shader::New( VERTEX_TEXTURE_MESH, FRAGMENT_TEXTURE_MESH );
276 Material textureMeshMaterial = Material::New( shaderTextureMesh );
277 textureMeshMaterial.AddSampler( sampler );
278 Renderer textureMeshRenderer = Renderer::New( meshGeometry, textureMeshMaterial );
280 Actor textureMeshActor = Actor::New();
281 textureMeshActor.AddRenderer( textureMeshRenderer );
282 textureMeshActor.SetSize( 175.f,175.f );
283 textureMeshActor.SetParentOrigin( ParentOrigin::CENTER );
284 textureMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
285 textureMeshActor.SetPosition(Vector3(0.0f, 200.0f, 0.0f));
286 textureMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
287 textureMeshActor.SetName("TextureMeshActor");
288 mContentLayer.Add( textureMeshActor );
291 void NewWindowController::AddBlendingImageActor()
293 ShaderEffect colorModifier = CreateColorModifierer(Vector3( 0.5f, 0.5f, 0.5f ));
294 Image effectImage = ResourceImage::New(EFFECT_IMAGE);
295 FrameBufferImage fb2 = CreateFrameBufferForImage( EFFECT_IMAGE, effectImage, colorModifier );
297 ImageActor tmpActor = ImageActor::New(fb2);
298 mContentLayer.Add(tmpActor);
299 tmpActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
300 tmpActor.SetAnchorPoint(AnchorPoint::TOP_RIGHT);
301 tmpActor.SetPosition(Vector3(0.0f, 150.0f, 0.0f));
302 tmpActor.SetScale(0.25f);
304 // create blending shader effect
305 ShaderEffect blendShader = ShaderEffect::New( "", FRAGMENT_BLEND_SHADER );
306 blendShader.SetEffectImage( fb2 );
307 blendShader.SetUniform("alpha", 0.5f);
309 Image baseImage = ResourceImage::New(BASE_IMAGE);
310 ImageActor blendActor = ImageActor::New( baseImage );
311 blendActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
312 blendActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
313 blendActor.SetPosition(Vector3(0.0f, 100.0f, 0.0f));
314 blendActor.SetSize(140, 140);
315 blendActor.SetShaderEffect( blendShader );
316 mContentLayer.Add(blendActor);
319 void NewWindowController::AddTextLabel()
321 mTextActor = TextLabel::New("Some text");
322 mTextActor.SetParentOrigin(ParentOrigin::CENTER);
323 mTextActor.SetColor(Color::RED);
324 mTextActor.SetName("PushMe text");
325 mContentLayer.Add( mTextActor );
328 ImageActor NewWindowController::CreateBlurredMirrorImage(const char* imageName)
330 Image image = ResourceImage::New(imageName);
332 Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
333 Vector2 FBOSize = Vector2( intFboSize.GetWidth(), intFboSize.GetHeight() );
334 FrameBufferImage fbo = FrameBufferImage::New( FBOSize.width, FBOSize.height, Pixel::RGBA8888);
336 GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
337 gbv.SetBackgroundColor(Color::TRANSPARENT);
338 gbv.SetUserImageAndOutputRenderTarget( image, fbo );
339 gbv.SetSize(FBOSize);
340 Stage::GetCurrent().Add(gbv);
343 ImageActor blurredActor = ImageActor::New(fbo);
344 blurredActor.SetSize(FBOSize);
345 blurredActor.SetScale(1.0f, -1.0f, 1.0f);
349 FrameBufferImage NewWindowController::CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect)
351 Stage stage = Stage::GetCurrent();
352 Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
353 Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
355 FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
357 RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
359 ImageActor imageActor = ImageActor::New(image);
360 imageActor.SetName("Source image actor");
363 imageActor.SetShaderEffect(shaderEffect);
365 imageActor.SetParentOrigin(ParentOrigin::CENTER);
366 imageActor.SetAnchorPoint(AnchorPoint::CENTER);
367 imageActor.SetScale(1.0f, -1.0f, 1.0f);
368 stage.Add(imageActor); // Not in default image view
370 CameraActor cameraActor = CameraActor::New(FBOSize);
371 cameraActor.SetParentOrigin(ParentOrigin::CENTER);
372 cameraActor.SetFieldOfView(Math::PI*0.25f);
373 cameraActor.SetNearClippingPlane(1.0f);
374 cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
375 cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
376 cameraActor.SetPosition(0.0f, 0.0f, ((FBOSize.height * 0.5f) / tanf(Math::PI * 0.125f)));
377 stage.Add(cameraActor);
379 renderTask.SetSourceActor(imageActor);
380 renderTask.SetInputEnabled(false);
381 renderTask.SetTargetFrameBuffer(framebuffer);
382 renderTask.SetCameraActor( cameraActor );
383 renderTask.SetClearColor( Color::TRANSPARENT );
384 renderTask.SetClearEnabled( true );
385 renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
390 void NewWindowController::SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction)
392 if( mNeedNewAnimation )
394 float duration = Random::Range(1.f, 1.5f);
395 mEmitAnimation = Animation::New( duration );
396 mNeedNewAnimation = false;
397 mAnimateComponentCount = 0;
400 mEmitter.EmitBubble( mEmitAnimation, emitPosition, direction, Vector2(10,10) );
402 mAnimateComponentCount++;
404 if( mAnimateComponentCount % 6 ==0 )
406 mEmitAnimation.Play();
407 mNeedNewAnimation = true;
411 Geometry NewWindowController::CreateMeshGeometry()
413 // Create vertices and specify their color
417 Vector2 textureCoordinates;
421 Vertex vertexData[5] = {
422 { Vector3( 0.0f, 0.0f, 0.5f ), Vector2(0.5f, 0.5f), Vector3(1.0f, 1.0f, 1.0f) },
423 { Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) },
424 { Vector3( 0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) },
425 { Vector3( -0.5f, 0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f, 1.0f, 0.0f) },
426 { Vector3( 0.5f, 0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f, 0.0f, 1.0f) } };
428 Property::Map vertexFormat;
429 vertexFormat["aPosition"] = Property::VECTOR3;
430 vertexFormat["aTexCoord"] = Property::VECTOR2;
431 vertexFormat["aColor"] = Property::VECTOR3;
432 PropertyBuffer vertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, 5 );
433 vertices.SetData( vertexData );
435 // Specify all the faces
436 unsigned int indexData[12] = { 0,1,3,0,2,4,0,3,4,0,2,1 };
437 Property::Map indexFormat;
438 indexFormat["indices"] = Property::UNSIGNED_INTEGER;
439 PropertyBuffer indices = PropertyBuffer::New( PropertyBuffer::STATIC, indexFormat, 12 );
440 indices.SetData( indexData );
442 // Create the geometry object
443 Geometry geometry = Geometry::New();
444 geometry.AddVertexBuffer( vertices );
445 geometry.SetIndexBuffer( indices );
450 ShaderEffect NewWindowController::CreateColorModifierer( const Vector3& rgbDelta )
452 std::string fragmentShader = MAKE_SHADER(
453 precision highp float;\n
454 uniform vec3 uRGBDelta;\n
455 uniform float uIgnoreAlpha;\n
456 float rand(vec2 co) \n
458 return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n}
461 vec4 color = texture2D(sTexture, vTexCoord); \n
462 // modify the hsv Value
463 color.rgb += uRGBDelta * rand(vTexCoord); \n
464 // if the new vale exceeds one, then decrease it
465 color.rgb -= max(color.rgb*2.0 - vec3(2.0), 0.0);\n
466 // if the new vale drops below zero, then increase it
467 color.rgb -= min(color.rgb*2.0, 0.0);\n
468 gl_FragColor = color; \n
472 ShaderEffect shaderEffect = ShaderEffect::New("", fragmentShader);
473 shaderEffect.SetUniform( "uRGBDelta", rgbDelta );
478 void NewWindowController::NewWindow(void)
480 PositionSize posSize(0, 0, 720, 1280);
481 gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
484 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
486 // Add as an idle callback to avoid ProcessEvents being recursively called.
487 mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
491 bool NewWindowController::OnTrackTimerTick()
494 const float radius(250.0f);
496 time += EMIT_INTERVAL_IN_MS;
497 float modTime = time / TRACK_DURATION_IN_MS;
498 float angle = 2.0f*Math::PI*modTime;
500 Vector2 position(radius*cosf(angle), radius*-sinf(angle));
501 Vector2 aimPos(radius*2*sinf(angle), radius*2*-cosf(angle));
502 Vector2 direction = aimPos-position;
503 Vector2 stageSize = Stage::GetCurrent().GetSize();
505 SetUpBubbleEmission( stageSize*0.5f+position, direction );
506 SetUpBubbleEmission( stageSize*0.5f+position*0.75f, direction );
507 SetUpBubbleEmission( stageSize*0.5f+position*0.7f, direction );
512 void NewWindowController::OnKeyEvent(const KeyEvent& event)
514 if(event.state == KeyEvent::Down)
516 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
523 void NewWindowController::OnContextLost()
525 printf("Stage reporting context loss\n");
528 void NewWindowController::OnContextRegained()
530 printf("Stage reporting context regain\n");
533 void RunTest(Application& app)
535 gNewWindowController = new NewWindowController(app);
536 app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
539 // Entry point for Linux & Tizen applications
541 int main(int argc, char **argv)
543 gApplication = Application::New(&argc, &argv);
544 RunTest(gApplication);