Replaced Image with Texture in cube transition effect. All references to the Image...
[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/public-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
89 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS( 1.0f, 1.0f, 1.0f, 1.0f );
90 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS( 0.5f, 0.5f, 0.5f, 1.0f );
91
92 CubeTransitionEffect::CubeTransitionEffect( unsigned int rows, unsigned int columns )
93 : Control( ControlBehaviour( 0 ) ),
94   mRows( rows ),
95   mColumns( columns ),
96   mIsAnimating( false ),
97   mIsPaused( false ),
98   mAnimationDuration( 1.f ),
99   mCubeDisplacement( 0.f )
100 {
101 }
102
103 CubeTransitionEffect::~CubeTransitionEffect()
104 {
105 }
106
107 void CubeTransitionEffect::SetTargetRight( unsigned int idx )
108 {
109   mBoxType[ idx ] = RIGHT;
110
111   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
112
113   mTargetTiles[ idx ].SetParentOrigin( Vector3( 1.f, 0.5f, 0.5f) );
114   mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::YAXIS );
115 }
116
117 void CubeTransitionEffect::SetTargetLeft( unsigned int idx )
118 {
119   mBoxType[ idx ] = LEFT;
120
121   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
122
123   mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.f, 0.5f, 0.5f) );
124   mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::YAXIS );
125 }
126
127 void CubeTransitionEffect::SetTargetBottom( unsigned int idx )
128 {
129   mBoxType[ idx ] = BOTTOM;
130
131   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
132
133   mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 0.f, 0.5f) );
134   mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::XAXIS );
135 }
136
137 void CubeTransitionEffect::SetTargetTop( unsigned int idx )
138 {
139   mBoxType[ idx ] = TOP;
140
141   mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
142
143   mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 1.f, 0.5f) );
144   mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::XAXIS );
145 }
146
147 void CubeTransitionEffect::OnRelayout( const Vector2& size, RelayoutContainer& container )
148 {
149   mTileSize = Vector2( size.x / mColumns, size.y / mRows );
150
151   mBoxRoot.SetProperty( Actor::Property::SIZE_WIDTH, size.x );
152   mBoxRoot.SetProperty( Actor::Property::SIZE_HEIGHT, size.y );
153   mBoxRoot.SetProperty( Actor::Property::SIZE_DEPTH, 1.0f );
154
155   for( size_t i = 0; i < mBoxes.size(); ++i )
156   {
157     mBoxes[ i ].SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
158     mBoxes[ i ].SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
159
160     switch( mBoxType[i] )
161     {
162       case LEFT:
163       case RIGHT:
164       {
165         mBoxes[ i ].SetProperty( Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
166         mBoxes[ i ].SetProperty( Actor::Property::SIZE_DEPTH, mTileSize.x );
167         break;
168       }
169       case BOTTOM:
170       case TOP:
171       {
172         mBoxes[ i ].SetProperty( Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
173         mBoxes[ i ].SetProperty( Actor::Property::SIZE_DEPTH, mTileSize.y );
174         break;
175       }
176     }
177   }
178
179   for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
180   {
181     it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
182     it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
183   }
184   for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
185   {
186     it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
187     it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
188   }
189 }
190
191 void CubeTransitionEffect::Initialize()
192 {
193   Self().RegisterProperty( "uTextureRect", Vector4( 0.0f, 0.0f, 1.0f, 1.0f ) );
194
195   mBoxType.Resize(mColumns * mRows);
196
197   //create the box parents
198   mBoxRoot = Actor::New();
199   mBoxRoot.SetParentOrigin( ParentOrigin::CENTER );
200   mBoxRoot.SetAnchorPoint( AnchorPoint::CENTER );
201
202   mCurrentTiles.clear();
203   mTargetTiles.clear();
204
205   mCurrentTiles.reserve( mColumns * mRows );
206   mTargetTiles.reserve( mColumns * mRows );
207
208   Vector2 gridSizeInv( 1.0f / mColumns, 1.0f / mRows );
209   Vector3 offset( 0.5f * gridSizeInv.x, 0.5f * gridSizeInv.y, 0.0f );
210
211   Vector3 anchor;
212   for( unsigned int y = 0; y < mRows; ++y, anchor.y += 1.0f / mRows )
213   {
214     anchor.x = 0.0f;
215     for( unsigned int x = 0; x <mColumns; ++x, anchor.x += 1.0f / mColumns )
216     {
217       Vector4 textureRect( anchor.x, anchor.y, anchor.x + gridSizeInv.x, anchor.y + gridSizeInv.y );
218
219       Actor currentTile = CreateTile( textureRect );
220       currentTile.SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
221       currentTile.SetParentOrigin( ParentOrigin::CENTER );
222       mCurrentTiles.push_back( currentTile );
223
224       Actor targetTile = CreateTile( textureRect );
225       targetTile.SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
226       mTargetTiles.push_back( targetTile );
227
228       Actor box = Actor::New();
229       box.SetParentOrigin( anchor + offset );
230       box.SetAnchorPoint( AnchorPoint::CENTER );
231
232       box.Add( currentTile );
233       box.Add( targetTile );
234
235       mBoxRoot.Add( box );
236
237       mBoxes.push_back( box );
238     }
239   }
240
241   OnInitialize();
242 }
243
244 void CubeTransitionEffect::OnStageConnection( int depth )
245 {
246   Control::OnStageConnection( depth );
247
248   Geometry geometry = Geometry::QUAD();
249   Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
250
251   TextureSet textureSet = TextureSet::New();
252
253   if( mCurrentTexture )
254   {
255     textureSet.SetTexture( 0u, mCurrentTexture );
256   }
257   mCurrentRenderer = Renderer::New( geometry, shader );
258   mCurrentRenderer.SetTextures( textureSet );
259
260   mCurrentRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depth );
261   Self().AddRenderer( mCurrentRenderer );
262 }
263
264 void CubeTransitionEffect::OnStageDisconnection()
265 {
266   if( mCurrentRenderer )
267   {
268     Self().RemoveRenderer( mCurrentRenderer );
269
270     for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
271     {
272       it->RemoveRenderer( mCurrentRenderer );
273     }
274     mCurrentRenderer.Reset();
275   }
276
277   if( mTargetRenderer )
278   {
279     for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
280     {
281       it->RemoveRenderer( mTargetRenderer );
282     }
283     mTargetRenderer.Reset();
284   }
285
286   Control::OnStageDisconnection();
287 }
288
289 void CubeTransitionEffect::SetTransitionDuration( float duration )
290 {
291   mAnimationDuration = duration;
292 }
293
294 float CubeTransitionEffect::GetTransitionDuration( ) const
295 {
296   return mAnimationDuration;
297 }
298
299 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
300 {
301   mCubeDisplacement = displacement;
302 }
303
304 float CubeTransitionEffect::GetCubeDisplacement() const
305 {
306   return mCubeDisplacement;
307 }
308
309 bool CubeTransitionEffect::IsTransitioning()
310 {
311   return mIsAnimating;
312 }
313
314 void CubeTransitionEffect::SetCurrentTexture( Texture texture )
315 {
316   mCurrentTexture = texture;
317
318   if( mCurrentRenderer )
319   {
320     TextureSet textureSet = mCurrentRenderer.GetTextures();
321     textureSet.SetTexture( 0u, mCurrentTexture);
322   }
323 }
324
325 void CubeTransitionEffect::SetTargetTexture( Texture texture )
326 {
327   mTargetTexture = texture;
328
329   if( mTargetRenderer )
330   {
331     TextureSet textureSet = mTargetRenderer.GetTextures();
332     textureSet.SetTexture( 0u, mTargetTexture );
333   }
334 }
335
336 void CubeTransitionEffect::StartTransition( bool toNextImage )
337 {
338   Vector3 size = Self().GetCurrentSize();
339   if( toNextImage )
340   {
341     StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( -10.f, 0.f ) );
342   }
343   else
344   {
345     StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( 10.f, 0.f ));
346   }
347 }
348
349 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
350 {
351   if( !mCurrentRenderer )
352   {
353     DALI_LOG_ERROR( "Trying to transition a cube transition without an image set" );
354     return;
355   }
356
357   //create the target renderer
358   TextureSet textureSet = TextureSet::New();
359   if( mTargetTexture )
360   {
361     textureSet.SetTexture( 0u, mTargetTexture );
362   }
363   Geometry geometry = mCurrentRenderer.GetGeometry();
364   Shader shader( mCurrentRenderer.GetShader() );
365   mTargetRenderer = Renderer::New( geometry, shader );
366   mTargetRenderer.SetTextures( textureSet );
367
368   int depthIndex = mCurrentRenderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX);
369   mTargetRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex );
370
371   for( size_t i = 0; i < mBoxes.size(); ++i )
372   {
373     mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
374   }
375
376   for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
377   {
378     it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
379     it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
380     it->AddRenderer( mCurrentRenderer );
381   }
382   for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
383   {
384     it->AddRenderer( mTargetRenderer );
385   }
386
387   Self().RemoveRenderer( mCurrentRenderer );
388   Self().Add( mBoxRoot );
389
390   if(mAnimation)
391   {
392     mAnimation.Clear();
393     mAnimation.Reset();
394   }
395
396   mAnimation = Animation::New( mAnimationDuration );
397   mAnimation.FinishedSignal().Connect( this, &CubeTransitionEffect::OnTransitionFinished );
398
399   OnStartTransition( panPosition, panDisplacement );
400 }
401
402 void CubeTransitionEffect::PauseTransition()
403 {
404   if( mIsAnimating && !mIsPaused )
405   {
406     mAnimation.Pause();
407     mIsPaused = true;
408   }
409 }
410
411 void CubeTransitionEffect::ResumeTransition()
412 {
413   if( mIsAnimating && mIsPaused)
414   {
415     mAnimation.Play();
416     mIsPaused = false;
417   }
418 }
419
420 void CubeTransitionEffect::StopTransition()
421 {
422   ResetToInitialState();
423 }
424
425 void CubeTransitionEffect::ResetToInitialState()
426 {
427   mAnimation.Clear();
428   mAnimation.Reset();
429   mIsAnimating = false;
430
431   Self().Remove( mBoxRoot );
432
433   for( size_t i = 0; i < mBoxes.size(); ++i )
434   {
435     mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
436   }
437
438   for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
439   {
440     it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
441     it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
442     it->SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
443   }
444   if( mCurrentRenderer )
445   {
446     for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
447     {
448       it->RemoveRenderer( mCurrentRenderer );
449     }
450     Self().AddRenderer( mCurrentRenderer );
451   }
452
453   for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
454   {
455     it->SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
456   }
457   if( mTargetRenderer )
458   {
459     for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
460     {
461       it->RemoveRenderer( mTargetRenderer );
462     }
463   }
464 }
465
466 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
467 {
468
469   std::swap( mCurrentTiles, mTargetTiles );
470   std::swap( mCurrentRenderer, mTargetRenderer );
471   std::swap( mCurrentTexture, mTargetTexture );
472
473   ResetToInitialState();
474
475   //Emit signal
476   Toolkit::CubeTransitionEffect handle( GetOwner() );
477   mTransitionCompletedSignal.Emit( handle, mCurrentTexture );
478 }
479
480 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
481 {
482   return mTransitionCompletedSignal;
483 }
484
485 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
486 {
487   Dali::BaseHandle handle( object );
488
489   bool connected( true );
490   Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
491
492   if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
493   {
494     cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
495   }
496   else
497   {
498     // signalName does not match any signal
499     connected = false;
500   }
501
502   return connected;
503 }
504
505 } // namespace Internal
506
507 } // namespace Toolkit
508
509 } // namespace Dali