Supply stylesheet using Application constructor
[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 #include <dali-toolkit/devel-api/controls/bubble-effect/bubble-emitter.h>
22 #include <dali-toolkit/devel-api/shader-effects/bubble-effect/color-adjuster.h>
23
24
25 #include "shared/view.h"
26 #include <cstdio>
27 #include <iostream>
28
29 using namespace Dali;
30 using namespace Dali::Toolkit;
31
32 class NewWindowController;
33
34 namespace
35 {
36 const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
37 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
38 const char * const LOSE_CONTEXT_IMAGE( DALI_IMAGE_DIR "icon-cluster-wobble.png" );
39 const char * const BASE_IMAGE( DALI_IMAGE_DIR "gallery-large-14.jpg" );
40 const char * const EFFECT_IMAGE( DALI_IMAGE_DIR "gallery-large-18.jpg" );
41
42 const float EXPLOSION_DURATION(1.2f);
43 const unsigned int EMIT_INTERVAL_IN_MS(80);
44 const float TRACK_DURATION_IN_MS(970);
45
46 Application gApplication;
47 NewWindowController* gNewWindowController(NULL);
48
49 const char*const FRAG_SHADER=
50   "uniform mediump float alpha;\n"
51   "\n"
52   "void main()\n"
53   "{\n"
54   "  mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n"
55   "  mediump vec4 fxColor   = texture2D(sEffect, vTexCoord);\n"
56   "  gl_FragColor   = mix(fragColor,fxColor, alpha);\n"
57   "}\n";
58
59 }; // anonymous namespace
60
61
62 class NewWindowController : public ConnectionTracker
63 {
64 public:
65   NewWindowController( Application& app );
66   void Create( Application& app );
67   void Destroy( Application& app );
68   void OnKeyEvent(const KeyEvent& event);
69   bool OnLoseContextButtonClicked( Toolkit::Button button );
70   static void NewWindow(void);
71
72   void OnContextLost();
73   void OnContextRegained();
74   void CreateMeshActor();
75   Mesh CreateMesh(bool, Material);
76   void CreateBubbles(Vector2 stageSize);
77   void CreateBlending();
78   void CreateText();
79   bool OnTrackTimerTick();
80   bool OnExplodeTimerTick();
81   void SetUpAnimation( Vector2 emitPosition, Vector2 direction );
82   FrameBufferImage CreateMirrorImage(const char* imageName);
83   ImageActor CreateBlurredMirrorImage(const char* imageName);
84   FrameBufferImage CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect);
85
86
87 private:
88   Application                mApplication;
89   Actor                      mCastingLight;
90   TextLabel                  mTextActor;
91   ImageActor                 mImageActor;
92   ImageActor                 mBlendActor;
93   Image                      mEffectImage;
94   Image                      mBaseImage;
95   MeshActor                  mMeshActor;
96   MeshActor                  mAnimatedMeshActor;
97
98   Toolkit::Control           mView;                              ///< The View instance.
99   Toolkit::ToolBar           mToolBar;                           ///< The View's Toolbar.
100   TextLabel                   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
180   stage.ContextLostSignal().Connect(this, &NewWindowController::OnContextLost);
181   stage.ContextRegainedSignal().Connect(this, &NewWindowController::OnContextRegained);
182 }
183
184 void NewWindowController::Destroy( Application& app )
185 {
186   UnparentAndReset(mTextActor);
187 }
188
189 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
190 {
191   // Add as an idle callback to avoid ProcessEvents being recursively called.
192   mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
193   return true;
194 }
195
196 void NewWindowController::CreateMeshActor()
197 {
198   mEffectImage = ResourceImage::New(EFFECT_IMAGE);
199
200   Material baseMaterial = Material::New( "Material1" );
201   Dali::MeshActor meshActor = MeshActor::New( CreateMesh(true, baseMaterial) );
202   meshActor.SetScale( 100.0f );
203   meshActor.SetParentOrigin( ParentOrigin::CENTER );
204   meshActor.SetPosition(Vector3( -150.0f, 200.0f, 0.0f ));
205   meshActor.SetName("MeshActor");
206   mContentLayer.Add( meshActor );
207
208   Material orchidMaterial = Material::New( "Material2" );
209   orchidMaterial.SetDiffuseTexture(mEffectImage);
210
211   Dali::MeshActor meshActor2 = MeshActor::New( CreateMesh(false, orchidMaterial) );
212   meshActor2.SetScale( 100.0f );
213   meshActor2.SetParentOrigin( ParentOrigin::CENTER );
214   meshActor2.SetPosition(Vector3( -150.0f, 310.0f, 0.0f ));
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   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
232   Vector2 FBOSize = Vector2( intFboSize.GetWidth(), intFboSize.GetHeight() );
233   fbo = FrameBufferImage::New( FBOSize.width, FBOSize.height, Pixel::RGBA8888);
234   GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
235   gbv.SetBackgroundColor(Color::TRANSPARENT);
236   gbv.SetUserImageAndOutputRenderTarget( image, fbo );
237   gbv.SetSize(FBOSize);
238   Stage::GetCurrent().Add(gbv);
239   gbv.ActivateOnce();
240
241   ImageActor blurredActor = ImageActor::New(fbo);
242   blurredActor.SetSize(FBOSize);
243   blurredActor.SetScale(1.0f, -1.0f, 1.0f);
244   return blurredActor;
245 }
246
247 FrameBufferImage NewWindowController::CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect)
248 {
249   Stage stage = Stage::GetCurrent();
250   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
251   Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
252
253   FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
254
255   RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
256
257   ImageActor imageActor = ImageActor::New(image);
258   imageActor.SetName("Source image actor");
259   if(shaderEffect)
260   {
261     imageActor.SetShaderEffect(shaderEffect);
262   }
263   imageActor.SetParentOrigin(ParentOrigin::CENTER);
264   imageActor.SetAnchorPoint(AnchorPoint::CENTER);
265   imageActor.SetScale(1.0f, -1.0f, 1.0f);
266   stage.Add(imageActor); // Not in default image view
267
268   CameraActor cameraActor = CameraActor::New(FBOSize);
269   cameraActor.SetParentOrigin(ParentOrigin::CENTER);
270   cameraActor.SetFieldOfView(Math::PI*0.25f);
271   cameraActor.SetNearClippingPlane(1.0f);
272   cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
273   cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
274   cameraActor.SetPosition(0.0f, 0.0f, ((FBOSize.height * 0.5f) / tanf(Math::PI * 0.125f)));
275   stage.Add(cameraActor);
276
277   renderTask.SetSourceActor(imageActor);
278   renderTask.SetInputEnabled(false);
279   renderTask.SetTargetFrameBuffer(framebuffer);
280   renderTask.SetCameraActor( cameraActor );
281   renderTask.SetClearColor( Color::TRANSPARENT );
282   renderTask.SetClearEnabled( true );
283   renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
284
285   return framebuffer;
286 }
287
288 void NewWindowController::CreateBubbles(Vector2 stageSize)
289 {
290   mEmitter = Toolkit::BubbleEmitter::New( stageSize,
291                                           ResourceImage::New( DALI_IMAGE_DIR "bubble-ball.png" ),
292                                           1000, Vector2( 5.0f, 5.0f ) );
293
294   Image background = ResourceImage::New(BACKGROUND_IMAGE);
295   mEmitter.SetBackground( background, mHSVDelta );
296   Actor bubbleRoot = mEmitter.GetRootActor();
297   mContentLayer.Add( bubbleRoot );
298   bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
299   bubbleRoot.SetZ(0.1f);
300
301   mEmitTrackTimer = Timer::New( EMIT_INTERVAL_IN_MS );
302   mEmitTrackTimer.TickSignal().Connect(this, &NewWindowController::OnTrackTimerTick);
303   mEmitTrackTimer.Start();
304
305   //mExplodeTimer = Timer::New( Random::Range(4000.f, 8000.f) );
306   //mExplodeTimer.TickSignal().Connect(this, &NewWindowController::OnExplodeTimerTick);
307   //mExplodeTimer.Start();
308 }
309
310 bool NewWindowController::OnExplodeTimerTick()
311 {
312   mEmitter.StartExplosion( EXPLOSION_DURATION, 5.0f );
313
314   mExplodeTimer = Timer::New( Random::Range(4.f, 8.f) );
315   mExplodeTimer.TickSignal().Connect(this, &NewWindowController::OnExplodeTimerTick);
316   return false;
317 }
318
319 void NewWindowController::SetUpAnimation( Vector2 emitPosition, Vector2 direction )
320 {
321   if( mNeedNewAnimation )
322   {
323     float duration = Random::Range(1.f, 1.5f);
324     mEmitAnimation = Animation::New( duration );
325     mNeedNewAnimation = false;
326     mAnimateComponentCount = 0;
327   }
328
329   mEmitter.EmitBubble( mEmitAnimation, emitPosition, direction, Vector2(1, 1) );
330
331   mAnimateComponentCount++;
332
333   if( mAnimateComponentCount % 20 ==0 )
334   {
335     mEmitAnimation.Play();
336     mNeedNewAnimation = true;
337   }
338 }
339
340 bool NewWindowController::OnTrackTimerTick()
341 {
342   static int time=0;
343   const float radius(250.0f);
344
345   time += EMIT_INTERVAL_IN_MS;
346   float modTime = time / TRACK_DURATION_IN_MS;
347   float angle = 2.0f*Math::PI*modTime;
348
349   Vector2 position(radius*cosf(angle), radius*-sinf(angle));
350   Vector2 aimPos(radius*2*sinf(angle), radius*2*-cosf(angle));
351   Vector2 direction = aimPos-position;
352   Vector2 stageSize = Stage::GetCurrent().GetSize();
353
354   for(int i=0; i<20; i++)
355   {
356     SetUpAnimation( stageSize*0.5f+position, direction );
357   }
358
359   return true;
360 }
361
362
363 void NewWindowController::CreateBlending()
364 {
365   Toolkit::ColorAdjuster colorAdjuster = ColorAdjuster::New(mHSVDelta);
366   FrameBufferImage fb2 = CreateFrameBufferForImage( EFFECT_IMAGE, mEffectImage, colorAdjuster );
367
368   ImageActor tmpActor = ImageActor::New(fb2);
369   mContentLayer.Add(tmpActor);
370   tmpActor.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
371   tmpActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
372   tmpActor.SetScale(0.25f);
373
374   // create blending shader effect
375   ShaderEffect blendShader = ShaderEffect::New( "", FRAG_SHADER );
376   blendShader.SetEffectImage( fb2 );
377   blendShader.SetUniform("alpha", 0.5f);
378
379   mBaseImage = ResourceImage::New(BASE_IMAGE);
380   mBlendActor = ImageActor::New( mBaseImage );
381   mBlendActor.SetParentOrigin(ParentOrigin::CENTER);
382   mBlendActor.SetPosition(Vector3(150.0f, 200.0f, 0.0f));
383   mBlendActor.SetSize(140, 140);
384   mBlendActor.SetShaderEffect( blendShader );
385   mContentLayer.Add(mBlendActor);
386 }
387
388 void NewWindowController::CreateText()
389 {
390   mTextActor = TextLabel::New("Some text");
391   mTextActor.SetParentOrigin(ParentOrigin::CENTER);
392   mTextActor.SetColor(Color::RED);
393   mTextActor.SetName("PushMe text");
394   mContentLayer.Add( mTextActor );
395 }
396
397 Mesh NewWindowController::CreateMesh(bool hasColor, Material material)
398 {
399   // Create vertices and specify their color
400   MeshData::VertexContainer vertices(4);
401   vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) );
402   vertices[ 1 ] = MeshData::Vertex( Vector3(  0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) );
403   vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f,  0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f,1.0f,0.0f) );
404   vertices[ 3 ] = MeshData::Vertex( Vector3(  0.5f,  0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f,0.0f,1.0f) );
405
406   // Specify all the faces
407   MeshData::FaceIndices faces;
408   faces.reserve( 6 ); // 2 triangles in Quad
409   faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
410   faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
411
412   // Create the mesh data from the vertices and faces
413   MeshData meshData;
414   meshData.SetHasColor( hasColor );
415   meshData.SetMaterial( material );
416   meshData.SetVertices( vertices );
417   meshData.SetFaceIndices( faces );
418
419   // Create a mesh from the data
420   Dali::Mesh mesh = Mesh::New( meshData );
421   return mesh;
422 }
423
424 void NewWindowController::NewWindow(void)
425 {
426   PositionSize posSize(0, 0, 720, 1280);
427   gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
428 }
429
430 void NewWindowController::OnKeyEvent(const KeyEvent& event)
431 {
432   if(event.state == KeyEvent::Down)
433   {
434     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
435     {
436       mApplication.Quit();
437     }
438   }
439 }
440
441 void NewWindowController::OnContextLost()
442 {
443   printf("Stage reporting context loss\n");
444 }
445
446 void NewWindowController::OnContextRegained()
447 {
448   printf("Stage reporting context regain\n");
449 }
450
451
452
453
454 void RunTest(Application& app)
455 {
456   gNewWindowController = new NewWindowController(app);
457   app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
458 }
459
460 // Entry point for Linux & Tizen applications
461 //
462
463 int main(int argc, char **argv)
464 {
465   gApplication = Application::New(&argc, &argv, DALI_DEMO_THEME_PATH);
466   RunTest(gApplication);
467
468   return 0;
469 }