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