Merge "Size negotiation patch 4: Remove SetRelayoutEnabled" into tizen
[platform/core/uifw/dali-demo.git] / examples / new-window / new-window-example.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <dali-toolkit/dali-toolkit.h>
18 #include "shared/view.h"
19 #include <cstdio>
20 #include <iostream>
21
22 using namespace Dali;
23 using namespace Dali::Toolkit;
24
25 class NewWindowController;
26
27 namespace
28 {
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
35 const float EXPLOSION_DURATION(1.2f);
36 const unsigned int EMIT_INTERVAL_IN_MS(80);
37 const float TRACK_DURATION_IN_MS(970);
38
39 Application gApplication;
40 NewWindowController* gNewWindowController(NULL);
41
42 const char*const FRAG_SHADER=
43   "uniform mediump float alpha;\n"
44   "\n"
45   "void main()\n"
46   "{\n"
47   "  mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n"
48   "  mediump vec4 fxColor   = texture2D(sEffect, vTexCoord);\n"
49   "  gl_FragColor   = mix(fragColor,fxColor, alpha);\n"
50   "}\n";
51
52 }; // anonymous namespace
53
54
55 class NewWindowController : public ConnectionTracker
56 {
57 public:
58   NewWindowController( Application& app );
59   void Create( Application& app );
60   void Destroy( Application& app );
61   void OnKeyEvent(const KeyEvent& event);
62   bool OnLoseContextButtonClicked( Toolkit::Button button );
63   static void NewWindow(void);
64
65   void OnContextLost();
66   void OnContextRegained();
67   void CreateMeshActor();
68   Mesh CreateMesh(bool, Material);
69   void CreateBubbles(Vector2 stageSize);
70   void CreateBlending();
71   void CreateText();
72   bool OnTrackTimerTick();
73   bool OnExplodeTimerTick();
74   void SetUpAnimation( Vector2 emitPosition, Vector2 direction );
75   FrameBufferImage CreateMirrorImage(const char* imageName);
76   ImageActor CreateBlurredMirrorImage(const char* imageName);
77   FrameBufferImage CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect);
78
79
80 private:
81   Application                mApplication;
82   Actor                      mCastingLight;
83   TextLabel                  mTextActor;
84   ImageActor                 mImageActor;
85   ImageActor                 mBlendActor;
86   Image                      mEffectImage;
87   Image                      mBaseImage;
88   MeshActor                  mMeshActor;
89   MeshActor                  mAnimatedMeshActor;
90
91   Toolkit::View              mView;                              ///< The View instance.
92   Toolkit::ToolBar           mToolBar;                           ///< The View's Toolbar.
93   TextLabel                   mTitleActor;                        ///< The Toolbar's Title.
94   Layer                      mContentLayer;                      ///< Content layer (scrolling cluster content)
95   Toolkit::PushButton        mLoseContextButton;
96   Vector3                    mHSVDelta;
97   Toolkit::BubbleEmitter     mEmitter;
98
99   Timer                      mEmitTrackTimer;
100   Timer                      mExplodeTimer;
101   bool                       mNeedNewAnimation;
102
103   unsigned int               mAnimateComponentCount;
104   Animation                  mEmitAnimation;
105 };
106
107
108 NewWindowController::NewWindowController( Application& application )
109 : mApplication(application),
110   mHSVDelta(0.5f, 0.0f, 0.5f),
111   mNeedNewAnimation(true)
112 {
113   mApplication.InitSignal().Connect(this, &NewWindowController::Create);
114   mApplication.TerminateSignal().Connect(this, &NewWindowController::Destroy);
115 }
116
117 void NewWindowController::Create( Application& app )
118 {
119   DemoHelper::RequestThemeChange();
120
121   Stage stage = Stage::GetCurrent();
122   stage.SetBackgroundColor(Color::YELLOW);
123
124   stage.KeyEventSignal().Connect(this, &NewWindowController::OnKeyEvent);
125
126   // The Init signal is received once (only) during the Application lifetime
127
128   // Hide the indicator bar
129   mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
130
131   mContentLayer = DemoHelper::CreateView( app,
132                                           mView,
133                                           mToolBar,
134                                           BACKGROUND_IMAGE,
135                                           TOOLBAR_IMAGE,
136                                           "Context recovery" );
137
138   // Point the default render task at the view
139   RenderTaskList taskList = stage.GetRenderTaskList();
140   RenderTask defaultTask = taskList.GetTask( 0u );
141   if ( defaultTask )
142   {
143     defaultTask.SetSourceActor( mView );
144   }
145
146   mLoseContextButton = Toolkit::PushButton::New();
147   mLoseContextButton.SetBackgroundImage( ResourceImage::New( LOSE_CONTEXT_IMAGE ) );
148   mLoseContextButton.ClickedSignal().Connect( this, &NewWindowController::OnLoseContextButtonClicked );
149   mToolBar.AddControl( mLoseContextButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
150
151
152   Actor logoLayoutActor = Actor::New();
153   logoLayoutActor.SetParentOrigin(ParentOrigin::CENTER);
154   logoLayoutActor.SetPosition(0.0f, -200.0f, 0.0f);
155   logoLayoutActor.SetScale(0.5f);
156   mContentLayer.Add(logoLayoutActor);
157
158   Image image = ResourceImage::New(DALI_IMAGE_DIR "dali-logo.png");
159   mImageActor = ImageActor::New(image);
160   mImageActor.SetName("dali-logo");
161   mImageActor.SetParentOrigin(ParentOrigin::CENTER);
162   mImageActor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
163   logoLayoutActor.Add(mImageActor);
164
165   ImageActor mirrorImageActor = CreateBlurredMirrorImage(DALI_IMAGE_DIR "dali-logo.png");
166   mirrorImageActor.SetParentOrigin(ParentOrigin::CENTER);
167   mirrorImageActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
168   logoLayoutActor.Add(mirrorImageActor);
169
170   CreateBubbles(stage.GetSize());
171   CreateMeshActor();
172   CreateBlending();
173   CreateText();
174
175   stage.ContextLostSignal().Connect(this, &NewWindowController::OnContextLost);
176   stage.ContextRegainedSignal().Connect(this, &NewWindowController::OnContextRegained);
177 }
178
179 void NewWindowController::Destroy( Application& app )
180 {
181   UnparentAndReset(mTextActor);
182 }
183
184 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
185 {
186   // Add as an idle callback to avoid ProcessEvents being recursively called.
187   mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
188   return true;
189 }
190
191 void NewWindowController::CreateMeshActor()
192 {
193   mEffectImage = ResourceImage::New(EFFECT_IMAGE);
194
195   Material baseMaterial = Material::New( "Material1" );
196   Dali::MeshActor meshActor = MeshActor::New( CreateMesh(true, baseMaterial) );
197   meshActor.SetScale( 100.0f );
198   meshActor.SetParentOrigin( ParentOrigin::CENTER );
199   meshActor.SetPosition(Vector3( -150.0f, 200.0f, 0.0f ));
200   meshActor.SetName("MeshActor");
201   mContentLayer.Add( meshActor );
202
203   Material orchidMaterial = Material::New( "Material2" );
204   orchidMaterial.SetDiffuseTexture(mEffectImage);
205
206   Dali::MeshActor meshActor2 = MeshActor::New( CreateMesh(false, orchidMaterial) );
207   meshActor2.SetScale( 100.0f );
208   meshActor2.SetParentOrigin( ParentOrigin::CENTER );
209   meshActor2.SetPosition(Vector3( -150.0f, 310.0f, 0.0f ));
210   meshActor2.SetName("MeshActor");
211   mContentLayer.Add( meshActor2 );
212 }
213
214 FrameBufferImage NewWindowController::CreateMirrorImage(const char* imageName)
215 {
216   FrameBufferImage fbo;
217   Image image = ResourceImage::New(imageName);
218   fbo = CreateFrameBufferForImage(imageName, image, ShaderEffect());
219   return fbo;
220 }
221
222 ImageActor NewWindowController::CreateBlurredMirrorImage(const char* imageName)
223 {
224   FrameBufferImage fbo;
225   Image image = ResourceImage::New(imageName);
226   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
227   Vector2 FBOSize = Vector2( intFboSize.GetWidth(), intFboSize.GetHeight() );
228   fbo = FrameBufferImage::New( FBOSize.width, FBOSize.height, Pixel::RGBA8888);
229   GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
230   gbv.SetBackgroundColor(Color::TRANSPARENT);
231   gbv.SetUserImageAndOutputRenderTarget( image, fbo );
232   gbv.SetSize(FBOSize);
233   Stage::GetCurrent().Add(gbv);
234   gbv.ActivateOnce();
235
236   ImageActor blurredActor = ImageActor::New(fbo);
237   blurredActor.SetSize(FBOSize);
238   blurredActor.SetScale(1.0f, -1.0f, 1.0f);
239   return blurredActor;
240 }
241
242 FrameBufferImage NewWindowController::CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect)
243 {
244   Stage stage = Stage::GetCurrent();
245   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
246   Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
247
248   FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
249
250   RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
251
252   ImageActor imageActor = ImageActor::New(image);
253   imageActor.SetName("Source image actor");
254   if(shaderEffect)
255   {
256     imageActor.SetShaderEffect(shaderEffect);
257   }
258   imageActor.SetParentOrigin(ParentOrigin::CENTER);
259   imageActor.SetAnchorPoint(AnchorPoint::CENTER);
260   imageActor.SetScale(1.0f, -1.0f, 1.0f);
261   stage.Add(imageActor); // Not in default image view
262
263   CameraActor cameraActor = CameraActor::New(FBOSize);
264   cameraActor.SetParentOrigin(ParentOrigin::CENTER);
265   cameraActor.SetFieldOfView(Math::PI*0.25f);
266   cameraActor.SetNearClippingPlane(1.0f);
267   cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
268   cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
269   cameraActor.SetPosition(0.0f, 0.0f, ((FBOSize.height * 0.5f) / tanf(Math::PI * 0.125f)));
270   stage.Add(cameraActor);
271
272   renderTask.SetSourceActor(imageActor);
273   renderTask.SetInputEnabled(false);
274   renderTask.SetTargetFrameBuffer(framebuffer);
275   renderTask.SetCameraActor( cameraActor );
276   renderTask.SetClearColor( Color::TRANSPARENT );
277   renderTask.SetClearEnabled( true );
278   renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
279
280   return framebuffer;
281 }
282
283 void NewWindowController::CreateBubbles(Vector2 stageSize)
284 {
285   mEmitter = Toolkit::BubbleEmitter::New( stageSize,
286                                           ResourceImage::New( DALI_IMAGE_DIR "bubble-ball.png" ),
287                                           1000, Vector2( 5.0f, 5.0f ) );
288
289   Image background = ResourceImage::New(BACKGROUND_IMAGE);
290   mEmitter.SetBackground( background, mHSVDelta );
291   Actor bubbleRoot = mEmitter.GetRootActor();
292   mContentLayer.Add( bubbleRoot );
293   bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
294   bubbleRoot.SetZ(0.1f);
295
296   mEmitTrackTimer = Timer::New( EMIT_INTERVAL_IN_MS );
297   mEmitTrackTimer.TickSignal().Connect(this, &NewWindowController::OnTrackTimerTick);
298   mEmitTrackTimer.Start();
299
300   //mExplodeTimer = Timer::New( Random::Range(4000.f, 8000.f) );
301   //mExplodeTimer.TickSignal().Connect(this, &NewWindowController::OnExplodeTimerTick);
302   //mExplodeTimer.Start();
303 }
304
305 bool NewWindowController::OnExplodeTimerTick()
306 {
307   mEmitter.StartExplosion( EXPLOSION_DURATION, 5.0f );
308
309   mExplodeTimer = Timer::New( Random::Range(4.f, 8.f) );
310   mExplodeTimer.TickSignal().Connect(this, &NewWindowController::OnExplodeTimerTick);
311   return false;
312 }
313
314 void NewWindowController::SetUpAnimation( Vector2 emitPosition, Vector2 direction )
315 {
316   if( mNeedNewAnimation )
317   {
318     float duration = Random::Range(1.f, 1.5f);
319     mEmitAnimation = Animation::New( duration );
320     mNeedNewAnimation = false;
321     mAnimateComponentCount = 0;
322   }
323
324   mEmitter.EmitBubble( mEmitAnimation, emitPosition, direction, Vector2(1, 1) );
325
326   mAnimateComponentCount++;
327
328   if( mAnimateComponentCount % 20 ==0 )
329   {
330     mEmitAnimation.Play();
331     mNeedNewAnimation = true;
332   }
333 }
334
335 bool NewWindowController::OnTrackTimerTick()
336 {
337   static int time=0;
338   const float radius(250.0f);
339
340   time += EMIT_INTERVAL_IN_MS;
341   float modTime = time / TRACK_DURATION_IN_MS;
342   float angle = 2.0f*Math::PI*modTime;
343
344   Vector2 position(radius*cosf(angle), radius*-sinf(angle));
345   Vector2 aimPos(radius*2*sinf(angle), radius*2*-cosf(angle));
346   Vector2 direction = aimPos-position;
347   Vector2 stageSize = Stage::GetCurrent().GetSize();
348
349   for(int i=0; i<20; i++)
350   {
351     SetUpAnimation( stageSize*0.5f+position, direction );
352   }
353
354   return true;
355 }
356
357
358 void NewWindowController::CreateBlending()
359 {
360   Toolkit::ColorAdjuster colorAdjuster = ColorAdjuster::New(mHSVDelta);
361   FrameBufferImage fb2 = CreateFrameBufferForImage( EFFECT_IMAGE, mEffectImage, colorAdjuster );
362
363   ImageActor tmpActor = ImageActor::New(fb2);
364   mContentLayer.Add(tmpActor);
365   tmpActor.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
366   tmpActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
367   tmpActor.SetScale(0.25f);
368
369   // create blending shader effect
370   ShaderEffect blendShader = ShaderEffect::New( "", FRAG_SHADER );
371   blendShader.SetEffectImage( fb2 );
372   blendShader.SetUniform("alpha", 0.5f);
373
374   mBaseImage = ResourceImage::New(BASE_IMAGE);
375   mBlendActor = ImageActor::New( mBaseImage );
376   mBlendActor.SetParentOrigin(ParentOrigin::CENTER);
377   mBlendActor.SetPosition(Vector3(150.0f, 200.0f, 0.0f));
378   mBlendActor.SetSize(140, 140);
379   mBlendActor.SetShaderEffect( blendShader );
380   mContentLayer.Add(mBlendActor);
381 }
382
383 void NewWindowController::CreateText()
384 {
385   mTextActor = TextLabel::New("Some text");
386   mTextActor.SetParentOrigin(ParentOrigin::CENTER);
387   mTextActor.SetColor(Color::RED);
388   mTextActor.SetName("PushMe text");
389   mContentLayer.Add( mTextActor );
390 }
391
392 Mesh NewWindowController::CreateMesh(bool hasColor, Material material)
393 {
394   // Create vertices and specify their color
395   MeshData::VertexContainer vertices(4);
396   vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) );
397   vertices[ 1 ] = MeshData::Vertex( Vector3(  0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) );
398   vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f,  0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f,1.0f,0.0f) );
399   vertices[ 3 ] = MeshData::Vertex( Vector3(  0.5f,  0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f,0.0f,1.0f) );
400
401   // Specify all the faces
402   MeshData::FaceIndices faces;
403   faces.reserve( 6 ); // 2 triangles in Quad
404   faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
405   faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
406
407   // Create the mesh data from the vertices and faces
408   MeshData meshData;
409   meshData.SetHasColor( hasColor );
410   meshData.SetMaterial( material );
411   meshData.SetVertices( vertices );
412   meshData.SetFaceIndices( faces );
413
414   // Create a mesh from the data
415   Dali::Mesh mesh = Mesh::New( meshData );
416   return mesh;
417 }
418
419 void NewWindowController::NewWindow(void)
420 {
421   PositionSize posSize(0, 0, 720, 1280);
422   gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
423 }
424
425 void NewWindowController::OnKeyEvent(const KeyEvent& event)
426 {
427   if(event.state == KeyEvent::Down)
428   {
429     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
430     {
431       mApplication.Quit();
432     }
433   }
434 }
435
436 void NewWindowController::OnContextLost()
437 {
438   printf("Stage reporting context loss\n");
439 }
440
441 void NewWindowController::OnContextRegained()
442 {
443   printf("Stage reporting context regain\n");
444 }
445
446
447
448
449 void RunTest(Application& app)
450 {
451   gNewWindowController = new NewWindowController(app);
452   app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
453 }
454
455 // Entry point for Linux & Tizen applications
456 //
457
458 int main(int argc, char **argv)
459 {
460   gApplication = Application::New(&argc, &argv);
461   RunTest(gApplication);
462
463   return 0;
464 }