2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "cube-transition-effect-impl.h"
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/visual-factory/visual-factory.h>
26 #include <dali/integration-api/debug.h>
29 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
43 // Setup properties, signals and actions using the type-registry.
44 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::CubeTransitionEffect, Dali::BaseHandle, NULL );
46 DALI_SIGNAL_REGISTRATION( Toolkit, CubeTransitionEffect, "transitionCompleted", SIGNAL_TRANSITION_COMPLETED )
48 DALI_TYPE_REGISTRATION_END()
50 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
51 attribute mediump vec2 aPosition;\n
52 varying mediump vec2 vTexCoord;\n
53 uniform mediump mat4 uMvpMatrix;\n
54 uniform mediump vec3 uSize;\n
55 uniform mediump vec4 uTextureRect;\n
59 mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
60 vertexPosition.xyz *= uSize;\n
61 vertexPosition = uMvpMatrix * vertexPosition;\n
63 vTexCoord = aPosition + vec2(0.5);\n
64 vTexCoord = mix(uTextureRect.xy, uTextureRect.zw, vTexCoord);\n
66 gl_Position = vertexPosition;\n
70 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
71 varying mediump vec2 vTexCoord;\n
72 uniform sampler2D sTexture;\n
73 uniform lowp vec4 uColor;\n
74 uniform lowp vec4 uSamplerRect;
78 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
82 Actor CreateTile( const Vector4& samplerRect )
84 Actor tile = Actor::New();
85 tile.SetAnchorPoint( AnchorPoint::CENTER );
86 tile.RegisterProperty( "uTextureRect", samplerRect );
92 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS( 1.0f, 1.0f, 1.0f, 1.0f );
93 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS( 0.5f, 0.5f, 0.5f, 1.0f );
95 CubeTransitionEffect::CubeTransitionEffect( unsigned int rows, unsigned int columns )
96 : Control( ControlBehaviour( DISABLE_STYLE_CHANGE_SIGNALS ) ),
99 mIsAnimating( false ),
101 mAnimationDuration( 1.f ),
102 mCubeDisplacement( 0.f )
106 CubeTransitionEffect::~CubeTransitionEffect()
110 void CubeTransitionEffect::SetTargetRight( unsigned int idx )
112 mBoxType[ idx ] = RIGHT;
114 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
116 mTargetTiles[ idx ].SetParentOrigin( Vector3( 1.f, 0.5f, 0.5f) );
117 mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::YAXIS );
120 void CubeTransitionEffect::SetTargetLeft( unsigned int idx )
122 mBoxType[ idx ] = LEFT;
124 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
126 mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.f, 0.5f, 0.5f) );
127 mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::YAXIS );
130 void CubeTransitionEffect::SetTargetBottom( unsigned int idx )
132 mBoxType[ idx ] = BOTTOM;
134 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
136 mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 0.f, 0.5f) );
137 mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::XAXIS );
140 void CubeTransitionEffect::SetTargetTop( unsigned int idx )
142 mBoxType[ idx ] = TOP;
144 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
146 mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 1.f, 0.5f) );
147 mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::XAXIS );
150 void CubeTransitionEffect::OnRelayout( const Vector2& size, RelayoutContainer& container )
152 mTileSize = Vector2( size.x / mColumns, size.y / mRows );
154 mBoxRoot.SetProperty( Actor::Property::SIZE_WIDTH, size.x );
155 mBoxRoot.SetProperty( Actor::Property::SIZE_HEIGHT, size.y );
156 mBoxRoot.SetProperty( Actor::Property::SIZE_DEPTH, 1.0f );
158 for( size_t i = 0; i < mBoxes.size(); ++i )
160 mBoxes[ i ].SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
161 mBoxes[ i ].SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
163 switch( mBoxType[i] )
168 mBoxes[ i ].SetProperty( Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
169 mBoxes[ i ].SetProperty( Actor::Property::SIZE_DEPTH, mTileSize.x );
175 mBoxes[ i ].SetProperty( Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
176 mBoxes[ i ].SetProperty( Actor::Property::SIZE_DEPTH, mTileSize.y );
182 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
184 it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
185 it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
187 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
189 it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
190 it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
194 void CubeTransitionEffect::Initialize()
196 Self().RegisterProperty( "uTextureRect", Vector4( 0.0f, 0.0f, 1.0f, 1.0f ) );
198 mBoxType.Resize(mColumns * mRows);
200 //create the box parents
201 mBoxRoot = Actor::New();
202 mBoxRoot.SetParentOrigin( ParentOrigin::CENTER );
203 mBoxRoot.SetAnchorPoint( AnchorPoint::CENTER );
205 mCurrentTiles.clear();
206 mTargetTiles.clear();
208 mCurrentTiles.reserve( mColumns * mRows );
209 mTargetTiles.reserve( mColumns * mRows );
211 Vector2 gridSizeInv( 1.0f / mColumns, 1.0f / mRows );
212 Vector3 offset( 0.5f * gridSizeInv.x, 0.5f * gridSizeInv.y, 0.0f );
215 for( unsigned int y = 0; y < mRows; ++y, anchor.y += 1.0f / mRows )
218 for( unsigned int x = 0; x <mColumns; ++x, anchor.x += 1.0f / mColumns )
220 Vector4 textureRect( anchor.x, anchor.y, anchor.x + gridSizeInv.x, anchor.y + gridSizeInv.y );
222 Actor currentTile = CreateTile( textureRect );
223 currentTile.SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
224 currentTile.SetParentOrigin( ParentOrigin::CENTER );
225 mCurrentTiles.push_back( currentTile );
227 Actor targetTile = CreateTile( textureRect );
228 targetTile.SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
229 mTargetTiles.push_back( targetTile );
231 Actor box = Actor::New();
232 box.SetParentOrigin( anchor + offset );
233 box.SetAnchorPoint( AnchorPoint::CENTER );
235 box.Add( currentTile );
236 box.Add( targetTile );
240 mBoxes.push_back( box );
247 void CubeTransitionEffect::OnStageConnection( int depth )
249 Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
250 Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
252 TextureSet textureSet = TextureSet::New();
254 if( mCurrentTexture )
256 textureSet.SetTexture( 0u, mCurrentTexture );
258 mCurrentRenderer = Renderer::New( geometry, shader );
259 mCurrentRenderer.SetTextures( textureSet );
261 mCurrentRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depth );
262 Self().AddRenderer( mCurrentRenderer );
264 Control::OnStageConnection( depth );
267 void CubeTransitionEffect::OnStageDisconnection()
269 if( mCurrentRenderer )
271 Self().RemoveRenderer( mCurrentRenderer );
273 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
275 it->RemoveRenderer( mCurrentRenderer );
277 mCurrentRenderer.Reset();
280 if( mTargetRenderer )
282 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
284 it->RemoveRenderer( mTargetRenderer );
286 mTargetRenderer.Reset();
289 Control::OnStageDisconnection();
292 void CubeTransitionEffect::SetTransitionDuration( float duration )
294 mAnimationDuration = duration;
297 float CubeTransitionEffect::GetTransitionDuration( ) const
299 return mAnimationDuration;
302 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
304 mCubeDisplacement = displacement;
307 float CubeTransitionEffect::GetCubeDisplacement() const
309 return mCubeDisplacement;
312 bool CubeTransitionEffect::IsTransitioning()
317 void CubeTransitionEffect::SetCurrentTexture( Texture texture )
319 mCurrentTexture = texture;
321 if( mCurrentRenderer )
323 TextureSet textureSet = mCurrentRenderer.GetTextures();
324 textureSet.SetTexture( 0u, mCurrentTexture);
328 void CubeTransitionEffect::SetTargetTexture( Texture texture )
330 mTargetTexture = texture;
332 if( mTargetRenderer )
334 TextureSet textureSet = mTargetRenderer.GetTextures();
335 textureSet.SetTexture( 0u, mTargetTexture );
339 void CubeTransitionEffect::StartTransition( bool toNextImage )
341 Vector3 size = Self().GetCurrentSize();
344 StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( -10.f, 0.f ) );
348 StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( 10.f, 0.f ));
352 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
354 if( !mCurrentRenderer )
356 DALI_LOG_ERROR( "Trying to transition a cube transition without an image set\n" );
360 //create the target renderer
361 TextureSet textureSet = TextureSet::New();
364 textureSet.SetTexture( 0u, mTargetTexture );
366 Geometry geometry = mCurrentRenderer.GetGeometry();
367 Shader shader( mCurrentRenderer.GetShader() );
368 mTargetRenderer = Renderer::New( geometry, shader );
369 mTargetRenderer.SetTextures( textureSet );
371 int depthIndex = mCurrentRenderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX);
372 mTargetRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex );
374 for( size_t i = 0; i < mBoxes.size(); ++i )
376 mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
379 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
381 it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
382 it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
383 it->AddRenderer( mCurrentRenderer );
385 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
387 it->AddRenderer( mTargetRenderer );
390 Self().RemoveRenderer( mCurrentRenderer );
391 Self().Add( mBoxRoot );
399 mAnimation = Animation::New( mAnimationDuration );
400 mAnimation.FinishedSignal().Connect( this, &CubeTransitionEffect::OnTransitionFinished );
402 OnStartTransition( panPosition, panDisplacement );
405 void CubeTransitionEffect::PauseTransition()
407 if( mIsAnimating && !mIsPaused )
414 void CubeTransitionEffect::ResumeTransition()
416 if( mIsAnimating && mIsPaused)
423 void CubeTransitionEffect::StopTransition()
425 ResetToInitialState();
428 void CubeTransitionEffect::ResetToInitialState()
432 mIsAnimating = false;
434 Self().Remove( mBoxRoot );
436 for( size_t i = 0; i < mBoxes.size(); ++i )
438 mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
441 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
443 it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
444 it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
445 it->SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
447 if( mCurrentRenderer )
449 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
451 it->RemoveRenderer( mCurrentRenderer );
453 Self().AddRenderer( mCurrentRenderer );
456 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
458 it->SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
460 if( mTargetRenderer )
462 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
464 it->RemoveRenderer( mTargetRenderer );
469 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
472 std::swap( mCurrentTiles, mTargetTiles );
473 std::swap( mCurrentRenderer, mTargetRenderer );
474 std::swap( mCurrentTexture, mTargetTexture );
476 ResetToInitialState();
479 Toolkit::CubeTransitionEffect handle( GetOwner() );
480 mTransitionCompletedSignal.Emit( handle, mCurrentTexture );
483 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
485 return mTransitionCompletedSignal;
488 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
490 Dali::BaseHandle handle( object );
492 bool connected( true );
493 Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
495 if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
497 cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
501 // signalName does not match any signal
508 } // namespace Internal
510 } // namespace Toolkit