Rendering API clean-up
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / transition-effects / cube-transition-effect-impl.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
18 // CLASS HEADER
19 #include "cube-transition-effect-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/devel-api/object/type-registry-helper.h>
25 #include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
26 #include <dali/integration-api/debug.h>
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 // Setup properties, signals and actions using the type-registry.
41 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::CubeTransitionEffect, Dali::BaseHandle, NULL );
42
43 DALI_SIGNAL_REGISTRATION( Toolkit, CubeTransitionEffect, "transitionCompleted",  SIGNAL_TRANSITION_COMPLETED )
44
45 DALI_TYPE_REGISTRATION_END()
46
47 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
48   attribute mediump vec2 aPosition;\n
49   varying mediump vec2 vTexCoord;\n
50   uniform mediump mat4 uMvpMatrix;\n
51   uniform mediump vec3 uSize;\n
52   uniform mediump vec4 uTextureRect;\n
53   \n
54   void main()\n
55   {\n
56     mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
57     vertexPosition.xyz *= uSize;\n
58     vertexPosition = uMvpMatrix * vertexPosition;\n
59     \n
60     vTexCoord = aPosition + vec2(0.5);\n
61     vTexCoord = mix(uTextureRect.xy, uTextureRect.zw, vTexCoord);\n
62
63     gl_Position = vertexPosition;\n
64   }\n
65 );
66
67 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
68   varying mediump vec2 vTexCoord;\n
69   uniform sampler2D sTexture;\n
70   uniform lowp vec4 uColor;\n
71   uniform lowp vec4 uSamplerRect;
72   \n
73   void main()\n
74   {\n
75     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
76   }\n
77 );
78
79 Actor CreateTile( const Vector4& samplerRect )
80 {
81  Actor tile = Actor::New();
82   tile.SetAnchorPoint( AnchorPoint::CENTER );
83   tile.RegisterProperty( "uTextureRect", samplerRect );
84   return tile;
85 }
86
87
88 Geometry CreateQuadGeometry()
89 {
90   const float halfWidth = 0.5f;
91   const float halfHeight = 0.5f;
92   struct QuadVertex { Vector2 position;};
93   QuadVertex quadVertexData[4] =
94   {
95       { Vector2(-halfWidth, -halfHeight) },
96       { Vector2( halfWidth, -halfHeight) },
97       { Vector2(-halfWidth, halfHeight)  },
98       { Vector2( halfWidth, halfHeight)  }
99   };
100
101   Property::Map quadVertexFormat;
102   quadVertexFormat["aPosition"] = Property::VECTOR2;
103   PropertyBuffer quadVertices = PropertyBuffer::New( quadVertexFormat );
104   quadVertices.SetData( quadVertexData, 4 );
105
106   // Create the geometry object
107   Geometry geometry = Geometry::New();
108   geometry.AddVertexBuffer( quadVertices );
109   geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
110
111   return geometry;
112 }
113
114 }
115
116 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS( 1.0f, 1.0f, 1.0f, 1.0f );
117 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS( 0.5f, 0.5f, 0.5f, 1.0f );
118
119 CubeTransitionEffect::CubeTransitionEffect( unsigned int rows, unsigned int columns )
120 : Control( ControlBehaviour( 0 ) ),
121   mRows( rows ),
122   mColumns( columns ),
123   mIsAnimating( false ),
124   mIsPaused( false ),
125   mAnimationDuration( 1.f ),
126   mCubeDisplacement( 0.f )
127 {
128 }
129
130 CubeTransitionEffect::~CubeTransitionEffect()
131 {
132 }
133
134 void CubeTransitionEffect::SetTargetRight( unsigned int idx )
135 {
136   mBoxType[ idx ] = RIGHT;
137
138   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
139
140   mTargetTiles[ idx ].SetParentOrigin( Vector3( 1.f, 0.5f, 0.5f) );
141   mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::YAXIS );
142 }
143
144 void CubeTransitionEffect::SetTargetLeft( unsigned int idx )
145 {
146   mBoxType[ idx ] = LEFT;
147
148   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
149
150   mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.f, 0.5f, 0.5f) );
151   mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::YAXIS );
152 }
153
154 void CubeTransitionEffect::SetTargetBottom( unsigned int idx )
155 {
156   mBoxType[ idx ] = BOTTOM;
157
158   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
159
160   mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 0.f, 0.5f) );
161   mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::XAXIS );
162 }
163
164 void CubeTransitionEffect::SetTargetTop( unsigned int idx )
165 {
166   mBoxType[ idx ] = TOP;
167
168   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
169
170   mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 1.f, 0.5f) );
171   mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::XAXIS );
172 }
173
174 void CubeTransitionEffect::OnRelayout( const Vector2& size, RelayoutContainer& container )
175 {
176   mTileSize = Vector2( size.x / mColumns, size.y / mRows );
177
178   mBoxRoot.SetProperty( Actor::Property::SIZE_WIDTH, size.x );
179   mBoxRoot.SetProperty( Actor::Property::SIZE_HEIGHT, size.y );
180   mBoxRoot.SetProperty( Actor::Property::SIZE_DEPTH, 1.0f );
181
182   for( size_t i = 0; i < mBoxes.size(); ++i )
183   {
184     mBoxes[ i ].SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
185     mBoxes[ i ].SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
186
187     switch( mBoxType[i] )
188     {
189       case LEFT:
190       case RIGHT:
191       {
192         mBoxes[ i ].SetProperty( Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
193         mBoxes[ i ].SetProperty( Actor::Property::SIZE_DEPTH, mTileSize.x );
194         break;
195       }
196       case BOTTOM:
197       case TOP:
198       {
199         mBoxes[ i ].SetProperty( Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
200         mBoxes[ i ].SetProperty( Actor::Property::SIZE_DEPTH, mTileSize.y );
201         break;
202       }
203     }
204   }
205
206   for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
207   {
208     it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
209     it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
210   }
211   for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
212   {
213     it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
214     it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
215   }
216 }
217
218 void CubeTransitionEffect::Initialize()
219 {
220   Self().RegisterProperty( "uTextureRect", Vector4( 0.0f, 0.0f, 1.0f, 1.0f ) );
221
222   mBoxType.Resize(mColumns * mRows);
223
224   //create the box parents
225   mBoxRoot = Actor::New();
226   mBoxRoot.SetParentOrigin( ParentOrigin::CENTER );
227   mBoxRoot.SetAnchorPoint( AnchorPoint::CENTER );
228
229   mCurrentTiles.clear();
230   mTargetTiles.clear();
231
232   mCurrentTiles.reserve( mColumns * mRows );
233   mTargetTiles.reserve( mColumns * mRows );
234
235   Vector2 gridSizeInv( 1.0f / mColumns, 1.0f / mRows );
236   Vector3 offset( 0.5f * gridSizeInv.x, 0.5f * gridSizeInv.y, 0.0f );
237
238   Vector3 anchor;
239   for( unsigned int y = 0; y < mRows; ++y, anchor.y += 1.0f / mRows )
240   {
241     anchor.x = 0.0f;
242     for( unsigned int x = 0; x <mColumns; ++x, anchor.x += 1.0f / mColumns )
243     {
244       Vector4 textureRect( anchor.x, anchor.y, anchor.x + gridSizeInv.x, anchor.y + gridSizeInv.y );
245
246       Actor currentTile = CreateTile( textureRect );
247       currentTile.SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
248       currentTile.SetParentOrigin( ParentOrigin::CENTER );
249       mCurrentTiles.push_back( currentTile );
250
251       Actor targetTile = CreateTile( textureRect );
252       targetTile.SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
253       mTargetTiles.push_back( targetTile );
254
255       Actor box = Actor::New();
256       box.SetParentOrigin( anchor + offset );
257       box.SetAnchorPoint( AnchorPoint::CENTER );
258
259       box.Add( currentTile );
260       box.Add( targetTile );
261
262       mBoxRoot.Add( box );
263
264       mBoxes.push_back( box );
265     }
266   }
267
268   OnInitialize();
269 }
270
271 void CubeTransitionEffect::OnStageConnection( int depth )
272 {
273   Control::OnStageConnection( depth );
274
275   Geometry geometry = CreateQuadGeometry();
276   Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
277
278   TextureSet textureSet = TextureSet::New();
279
280   if( mCurrentImage )
281   {
282     textureSet.SetImage( 0u, mCurrentImage );
283   }
284   mCurrentRenderer = Renderer::New( geometry, shader );
285   mCurrentRenderer.SetTextures( textureSet );
286
287   mCurrentRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depth );
288   Self().AddRenderer( mCurrentRenderer );
289 }
290
291 void CubeTransitionEffect::OnStageDisconnection()
292 {
293   if( mCurrentRenderer )
294   {
295     Self().RemoveRenderer( mCurrentRenderer );
296
297     for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
298     {
299       it->RemoveRenderer( mCurrentRenderer );
300     }
301     mCurrentRenderer.Reset();
302   }
303
304   if( mTargetRenderer )
305   {
306     for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
307     {
308       it->RemoveRenderer( mTargetRenderer );
309     }
310     mTargetRenderer.Reset();
311   }
312
313   Control::OnStageDisconnection();
314 }
315
316 void CubeTransitionEffect::SetTransitionDuration( float duration )
317 {
318   mAnimationDuration = duration;
319 }
320
321 float CubeTransitionEffect::GetTransitionDuration( ) const
322 {
323   return mAnimationDuration;
324 }
325
326 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
327 {
328   mCubeDisplacement = displacement;
329 }
330
331 float CubeTransitionEffect::GetCubeDisplacement() const
332 {
333   return mCubeDisplacement;
334 }
335
336 bool CubeTransitionEffect::IsTransitioning()
337 {
338   return mIsAnimating;
339 }
340
341 void CubeTransitionEffect::SetCurrentImage( Image image )
342 {
343   mCurrentImage = image;
344   if( mCurrentRenderer )
345   {
346     TextureSet textureSet = mCurrentRenderer.GetTextures();
347     textureSet.SetImage( 0u, mCurrentImage );
348   }
349 }
350
351 void CubeTransitionEffect::SetTargetImage( Image image )
352 {
353   mTargetImage = image;
354
355   if( mTargetRenderer )
356   {
357     TextureSet textureSet = mTargetRenderer.GetTextures();
358     textureSet.SetImage( 0u, mTargetImage );
359   }
360 }
361
362 void CubeTransitionEffect::StartTransition( bool toNextImage )
363 {
364   Vector3 size = Self().GetCurrentSize();
365   if( toNextImage )
366   {
367     StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( -10.f, 0.f ) );
368   }
369   else
370   {
371     StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( 10.f, 0.f ));
372   }
373 }
374
375 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
376 {
377   if( !mCurrentRenderer )
378   {
379     DALI_LOG_ERROR( "Trying to transition a cube transition without an image set" );
380     return;
381   }
382
383   //create the target renderer
384   TextureSet textureSet = TextureSet::New();
385   if( mTargetImage )
386   {
387     textureSet.SetImage( 0u, mTargetImage );
388   }
389   Geometry geometry = mCurrentRenderer.GetGeometry();
390   Shader shader( mCurrentRenderer.GetShader() );
391   mTargetRenderer = Renderer::New( geometry, shader );
392   mTargetRenderer.SetTextures( textureSet );
393
394   int depthIndex = mCurrentRenderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX);
395   mTargetRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex );
396
397   for( size_t i = 0; i < mBoxes.size(); ++i )
398   {
399     mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
400   }
401
402   for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
403   {
404     it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
405     it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
406     it->AddRenderer( mCurrentRenderer );
407   }
408   for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
409   {
410     it->AddRenderer( mTargetRenderer );
411   }
412
413   Self().RemoveRenderer( mCurrentRenderer );
414   Self().Add( mBoxRoot );
415
416   if(mAnimation)
417   {
418     mAnimation.Clear();
419     mAnimation.Reset();
420   }
421
422   mAnimation = Animation::New( mAnimationDuration );
423   mAnimation.FinishedSignal().Connect( this, &CubeTransitionEffect::OnTransitionFinished );
424
425   OnStartTransition( panPosition, panDisplacement );
426 }
427
428 void CubeTransitionEffect::PauseTransition()
429 {
430   if( mIsAnimating && !mIsPaused )
431   {
432     mAnimation.Pause();
433     mIsPaused = true;
434   }
435 }
436
437 void CubeTransitionEffect::ResumeTransition()
438 {
439   if( mIsAnimating && mIsPaused)
440   {
441     mAnimation.Play();
442     mIsPaused = false;
443   }
444 }
445
446 void CubeTransitionEffect::StopTransition()
447 {
448   ResetToInitialState();
449 }
450
451 void CubeTransitionEffect::ResetToInitialState()
452 {
453   mAnimation.Clear();
454   mAnimation.Reset();
455   mIsAnimating = false;
456
457   Self().Remove( mBoxRoot );
458
459   for( size_t i = 0; i < mBoxes.size(); ++i )
460   {
461     mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
462   }
463
464   for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
465   {
466     it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
467     it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
468     it->SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
469   }
470   if( mCurrentRenderer )
471   {
472     for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
473     {
474       it->RemoveRenderer( mCurrentRenderer );
475     }
476     Self().AddRenderer( mCurrentRenderer );
477   }
478
479   for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
480   {
481     it->SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
482   }
483   if( mTargetRenderer )
484   {
485     for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
486     {
487       it->RemoveRenderer( mTargetRenderer );
488     }
489   }
490 }
491
492 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
493 {
494
495   std::swap( mCurrentTiles, mTargetTiles );
496   std::swap( mCurrentRenderer, mTargetRenderer );
497   std::swap( mCurrentImage, mTargetImage );
498
499   ResetToInitialState();
500
501   //Emit signal
502   Toolkit::CubeTransitionEffect handle( GetOwner() );
503   mTransitionCompletedSignal.Emit( handle, mCurrentImage );
504 }
505
506 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
507 {
508   return mTransitionCompletedSignal;
509 }
510
511 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
512 {
513   Dali::BaseHandle handle( object );
514
515   bool connected( true );
516   Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
517
518   if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
519   {
520     cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
521   }
522   else
523   {
524     // signalName does not match any signal
525     connected = false;
526   }
527
528   return connected;
529 }
530
531 } // namespace Internal
532
533 } // namespace Toolkit
534
535 } // namespace Dali