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