Added precision to shader variables.
[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   TextActor                  mTextActor;
87   ImageActor                 mImageActor;
88   ImageActor                 mBlendActor;
89   Image                      mEffectImage;
90   Image                      mBaseImage;
91   LightActor                 mKeyLightActor;
92   MeshActor                  mMeshActor;
93   MeshActor                  mAnimatedMeshActor;
94   Model                      mModel;
95
96   Toolkit::View              mView;                              ///< The View instance.
97   Toolkit::ToolBar           mToolBar;                           ///< The View's Toolbar.
98   TextView                   mTitleActor;                        ///< The Toolbar's Title.
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( Image::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 = Image::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   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(NewWindowController::NewWindow);
192   return true;
193 }
194
195 void NewWindowController::CreateMeshActor()
196 {
197   mEffectImage = Image::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.SetAffectedByLighting( false );
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.SetAffectedByLighting( false );
216   meshActor2.SetName("MeshActor");
217   mContentLayer.Add( meshActor2 );
218 }
219
220 FrameBufferImage NewWindowController::CreateMirrorImage(const char* imageName)
221 {
222   FrameBufferImage fbo;
223   Image image = Image::New(imageName);
224   fbo = CreateFrameBufferForImage(imageName, image, ShaderEffect());
225   return fbo;
226 }
227
228 ImageActor NewWindowController::CreateBlurredMirrorImage(const char* imageName)
229 {
230   FrameBufferImage fbo;
231   Image image = Image::New( imageName );
232   Vector2 FBOSize = Image::GetImageSize(imageName);
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   Vector2 FBOSize = Image::GetImageSize(imageName);
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.SetRotation(Quaternion(M_PI, Vector3::YAXIS));
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                                           Image::New( DALI_IMAGE_DIR "bubble-ball.png" ),
292                                           1000, Vector2( 5.0f, 5.0f ) );
293
294   Image background = Image::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 = Image::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 = TextActor::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::CreateModel()
425 {
426   mModel = Model::New(gModelFile);
427   mModel.LoadingFinishedSignal().Connect(this, &NewWindowController::OnModelLoaded);
428
429   //Create a Key light
430   Light keylight = Light::New("KeyLight");
431   keylight.SetFallOff(Vector2(10000.0f, 10000.0f));
432
433   mCastingLight = Actor::New();
434   mCastingLight.SetParentOrigin(ParentOrigin::CENTER);
435   mCastingLight.SetAnchorPoint(AnchorPoint::CENTER);
436   mCastingLight.SetPosition( Vector3( 0.0f, 0.0f, 800.0f ) );
437   mContentLayer.Add( mCastingLight );
438
439   mKeyLightActor = LightActor::New();
440   mKeyLightActor.SetParentOrigin(ParentOrigin::CENTER);
441   mKeyLightActor.SetName(keylight.GetName());
442
443   //Add all the actors to the stage
444   mCastingLight.Add(mKeyLightActor);
445   mKeyLightActor.SetLight(keylight);
446 }
447
448 void NewWindowController::OnModelLoaded( Model model )
449 {
450   if( model.GetLoadingState() == ResourceLoadingSucceeded )
451   {
452     std::cout << "Succeeded loading model" << std::endl;
453     mModelActor = ModelActorFactory::BuildActorTree(mModel, "");  // Gets root actor
454     mModelActor.SetSize(250.0f, 250.0f);
455     mModelActor.SetPosition(0.0f, 200.0f, 70.0f);
456     mModelActor.SetScale(0.5f);
457     mModelActor.SetRotation(Radian(Math::PI*0.25f), Vector3(1.0, 0.7, 0.0));
458
459     mContentLayer.Add( mModelActor );
460
461     if (mModel.NumberOfAnimations())
462     {
463       mModelAnimation = ModelActorFactory::BuildAnimation(mModel, mModelActor, 0);
464       mModelAnimation.SetDuration(4.0f);
465       mModelAnimation.SetLooping(true);
466       mModelAnimation.Play();
467     }
468   }
469   else
470   {
471     std::cout << "Failed loading model" << std::endl;
472     mApplication.Quit();
473   }
474 }
475
476 void NewWindowController::NewWindow(void)
477 {
478   PositionSize posSize(0, 0, 720, 1280);
479   gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
480 }
481
482 void NewWindowController::OnKeyEvent(const KeyEvent& event)
483 {
484   if(event.state == KeyEvent::Down)
485   {
486     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
487     {
488       mApplication.Quit();
489     }
490   }
491 }
492
493 void NewWindowController::OnContextLost()
494 {
495   printf("Stage reporting context loss\n");
496 }
497
498 void NewWindowController::OnContextRegained()
499 {
500   printf("Stage reporting context regain\n");
501 }
502
503
504
505
506 void RunTest(Application& app)
507 {
508   gNewWindowController = new NewWindowController(app);
509   app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
510 }
511
512 // Entry point for Linux & SLP applications
513 //
514
515 int main(int argc, char **argv)
516 {
517   gApplication = Application::New(&argc, &argv);
518   RunTest(gApplication);
519
520   return 0;
521 }