76aed27d94d3f53902f4e1fe49df495693f22dac
[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 <dali/devel-api/actors/mesh-actor.h>
19 #include <dali/devel-api/modeling/material.h>
20 #include <dali/devel-api/geometry/mesh.h>
21
22 #include "shared/view.h"
23 #include <cstdio>
24 #include <iostream>
25
26 using namespace Dali;
27 using namespace Dali::Toolkit;
28
29 class NewWindowController;
30
31 namespace
32 {
33 const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
34 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
35 const char * const LOSE_CONTEXT_IMAGE( DALI_IMAGE_DIR "icon-cluster-wobble.png" );
36 const char * const BASE_IMAGE( DALI_IMAGE_DIR "gallery-large-14.jpg" );
37 const char * const EFFECT_IMAGE( DALI_IMAGE_DIR "gallery-large-18.jpg" );
38
39 const float EXPLOSION_DURATION(1.2f);
40 const unsigned int EMIT_INTERVAL_IN_MS(80);
41 const float TRACK_DURATION_IN_MS(970);
42
43 Application gApplication;
44 NewWindowController* gNewWindowController(NULL);
45
46 const char*const FRAG_SHADER=
47   "uniform mediump float alpha;\n"
48   "\n"
49   "void main()\n"
50   "{\n"
51   "  mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n"
52   "  mediump vec4 fxColor   = texture2D(sEffect, vTexCoord);\n"
53   "  gl_FragColor   = mix(fragColor,fxColor, alpha);\n"
54   "}\n";
55
56 }; // anonymous namespace
57
58
59 class NewWindowController : public ConnectionTracker
60 {
61 public:
62   NewWindowController( Application& app );
63   void Create( Application& app );
64   void Destroy( Application& app );
65   void OnKeyEvent(const KeyEvent& event);
66   bool OnLoseContextButtonClicked( Toolkit::Button button );
67   static void NewWindow(void);
68
69   void OnContextLost();
70   void OnContextRegained();
71   void CreateMeshActor();
72   Mesh CreateMesh(bool, Material);
73   void CreateBubbles(Vector2 stageSize);
74   void CreateBlending();
75   void CreateText();
76   bool OnTrackTimerTick();
77   bool OnExplodeTimerTick();
78   void SetUpAnimation( Vector2 emitPosition, Vector2 direction );
79   FrameBufferImage CreateMirrorImage(const char* imageName);
80   ImageActor CreateBlurredMirrorImage(const char* imageName);
81   FrameBufferImage CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect);
82
83
84 private:
85   Application                mApplication;
86   Actor                      mCastingLight;
87   TextLabel                  mTextActor;
88   ImageActor                 mImageActor;
89   ImageActor                 mBlendActor;
90   Image                      mEffectImage;
91   Image                      mBaseImage;
92   MeshActor                  mMeshActor;
93   MeshActor                  mAnimatedMeshActor;
94
95   Toolkit::Control           mView;                              ///< The View instance.
96   Toolkit::ToolBar           mToolBar;                           ///< The View's Toolbar.
97   TextLabel                   mTitleActor;                        ///< The Toolbar's Title.
98   Layer                      mContentLayer;                      ///< Content layer (scrolling cluster content)
99   Toolkit::PushButton        mLoseContextButton;
100   Vector3                    mHSVDelta;
101   Toolkit::BubbleEmitter     mEmitter;
102
103   Timer                      mEmitTrackTimer;
104   Timer                      mExplodeTimer;
105   bool                       mNeedNewAnimation;
106
107   unsigned int               mAnimateComponentCount;
108   Animation                  mEmitAnimation;
109 };
110
111
112 NewWindowController::NewWindowController( Application& application )
113 : mApplication(application),
114   mHSVDelta(0.5f, 0.0f, 0.5f),
115   mNeedNewAnimation(true)
116 {
117   mApplication.InitSignal().Connect(this, &NewWindowController::Create);
118   mApplication.TerminateSignal().Connect(this, &NewWindowController::Destroy);
119 }
120
121 void NewWindowController::Create( Application& app )
122 {
123   DemoHelper::RequestThemeChange();
124
125   Stage stage = Stage::GetCurrent();
126   stage.SetBackgroundColor(Color::YELLOW);
127
128   stage.KeyEventSignal().Connect(this, &NewWindowController::OnKeyEvent);
129
130   // The Init signal is received once (only) during the Application lifetime
131
132   // Hide the indicator bar
133   mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
134
135   mContentLayer = DemoHelper::CreateView( app,
136                                           mView,
137                                           mToolBar,
138                                           BACKGROUND_IMAGE,
139                                           TOOLBAR_IMAGE,
140                                           "Context recovery" );
141
142   // Point the default render task at the view
143   RenderTaskList taskList = stage.GetRenderTaskList();
144   RenderTask defaultTask = taskList.GetTask( 0u );
145   if ( defaultTask )
146   {
147     defaultTask.SetSourceActor( mView );
148   }
149
150   mLoseContextButton = Toolkit::PushButton::New();
151   mLoseContextButton.SetBackgroundImage( ResourceImage::New( LOSE_CONTEXT_IMAGE ) );
152   mLoseContextButton.ClickedSignal().Connect( this, &NewWindowController::OnLoseContextButtonClicked );
153   mToolBar.AddControl( mLoseContextButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
154
155
156   Actor logoLayoutActor = Actor::New();
157   logoLayoutActor.SetParentOrigin(ParentOrigin::CENTER);
158   logoLayoutActor.SetPosition(0.0f, -200.0f, 0.0f);
159   logoLayoutActor.SetScale(0.5f);
160   mContentLayer.Add(logoLayoutActor);
161
162   Image image = ResourceImage::New(DALI_IMAGE_DIR "dali-logo.png");
163   mImageActor = ImageActor::New(image);
164   mImageActor.SetName("dali-logo");
165   mImageActor.SetParentOrigin(ParentOrigin::CENTER);
166   mImageActor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
167   logoLayoutActor.Add(mImageActor);
168
169   ImageActor mirrorImageActor = CreateBlurredMirrorImage(DALI_IMAGE_DIR "dali-logo.png");
170   mirrorImageActor.SetParentOrigin(ParentOrigin::CENTER);
171   mirrorImageActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
172   logoLayoutActor.Add(mirrorImageActor);
173
174   CreateBubbles(stage.GetSize());
175   CreateMeshActor();
176   CreateBlending();
177   CreateText();
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   UnparentAndReset(mTextActor);
186 }
187
188 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
189 {
190   // Add as an idle callback to avoid ProcessEvents being recursively called.
191   mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
192   return true;
193 }
194
195 void NewWindowController::CreateMeshActor()
196 {
197   mEffectImage = ResourceImage::New(EFFECT_IMAGE);
198
199   Material baseMaterial = Material::New( "Material1" );
200   Dali::MeshActor meshActor = MeshActor::New( CreateMesh(true, baseMaterial) );
201   meshActor.SetScale( 100.0f );
202   meshActor.SetParentOrigin( ParentOrigin::CENTER );
203   meshActor.SetPosition(Vector3( -150.0f, 200.0f, 0.0f ));
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.SetName("MeshActor");
215   mContentLayer.Add( meshActor2 );
216 }
217
218 FrameBufferImage NewWindowController::CreateMirrorImage(const char* imageName)
219 {
220   FrameBufferImage fbo;
221   Image image = ResourceImage::New(imageName);
222   fbo = CreateFrameBufferForImage(imageName, image, ShaderEffect());
223   return fbo;
224 }
225
226 ImageActor NewWindowController::CreateBlurredMirrorImage(const char* imageName)
227 {
228   FrameBufferImage fbo;
229   Image image = ResourceImage::New(imageName);
230   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
231   Vector2 FBOSize = Vector2( intFboSize.GetWidth(), intFboSize.GetHeight() );
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   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
250   Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
251
252   FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
253
254   RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
255
256   ImageActor imageActor = ImageActor::New(image);
257   imageActor.SetName("Source image actor");
258   if(shaderEffect)
259   {
260     imageActor.SetShaderEffect(shaderEffect);
261   }
262   imageActor.SetParentOrigin(ParentOrigin::CENTER);
263   imageActor.SetAnchorPoint(AnchorPoint::CENTER);
264   imageActor.SetScale(1.0f, -1.0f, 1.0f);
265   stage.Add(imageActor); // Not in default image view
266
267   CameraActor cameraActor = CameraActor::New(FBOSize);
268   cameraActor.SetParentOrigin(ParentOrigin::CENTER);
269   cameraActor.SetFieldOfView(Math::PI*0.25f);
270   cameraActor.SetNearClippingPlane(1.0f);
271   cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
272   cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
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   mTextActor = TextLabel::New("Some text");
390   mTextActor.SetParentOrigin(ParentOrigin::CENTER);
391   mTextActor.SetColor(Color::RED);
392   mTextActor.SetName("PushMe text");
393   mContentLayer.Add( mTextActor );
394 }
395
396 Mesh NewWindowController::CreateMesh(bool hasColor, Material material)
397 {
398   // Create vertices and specify their color
399   MeshData::VertexContainer vertices(4);
400   vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) );
401   vertices[ 1 ] = MeshData::Vertex( Vector3(  0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) );
402   vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f,  0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f,1.0f,0.0f) );
403   vertices[ 3 ] = MeshData::Vertex( Vector3(  0.5f,  0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f,0.0f,1.0f) );
404
405   // Specify all the faces
406   MeshData::FaceIndices faces;
407   faces.reserve( 6 ); // 2 triangles in Quad
408   faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
409   faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
410
411   // Create the mesh data from the vertices and faces
412   MeshData meshData;
413   meshData.SetHasColor( hasColor );
414   meshData.SetMaterial( material );
415   meshData.SetVertices( vertices );
416   meshData.SetFaceIndices( faces );
417
418   // Create a mesh from the data
419   Dali::Mesh mesh = Mesh::New( meshData );
420   return mesh;
421 }
422
423 void NewWindowController::NewWindow(void)
424 {
425   PositionSize posSize(0, 0, 720, 1280);
426   gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
427 }
428
429 void NewWindowController::OnKeyEvent(const KeyEvent& event)
430 {
431   if(event.state == KeyEvent::Down)
432   {
433     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
434     {
435       mApplication.Quit();
436     }
437   }
438 }
439
440 void NewWindowController::OnContextLost()
441 {
442   printf("Stage reporting context loss\n");
443 }
444
445 void NewWindowController::OnContextRegained()
446 {
447   printf("Stage reporting context regain\n");
448 }
449
450
451
452
453 void RunTest(Application& app)
454 {
455   gNewWindowController = new NewWindowController(app);
456   app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
457 }
458
459 // Entry point for Linux & Tizen applications
460 //
461
462 int main(int argc, char **argv)
463 {
464   gApplication = Application::New(&argc, &argv);
465   RunTest(gApplication);
466
467   return 0;
468 }