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