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