2 * Copyright (c) 2014 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/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>
40 // Setup properties, signals and actions using the type-registry.
41 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::CubeTransitionEffect, Dali::BaseHandle, NULL );
43 DALI_SIGNAL_REGISTRATION( Toolkit, CubeTransitionEffect, "transitionCompleted", SIGNAL_TRANSITION_COMPLETED )
45 DALI_TYPE_REGISTRATION_END()
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
56 mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
57 vertexPosition.xyz *= uSize;\n
58 vertexPosition = uMvpMatrix * vertexPosition;\n
60 vTexCoord = aPosition + vec2(0.5);\n
61 vTexCoord = mix(uTextureRect.xy, uTextureRect.zw, vTexCoord);\n
63 gl_Position = vertexPosition;\n
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;
75 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
79 Actor CreateTile( const Vector4& samplerRect )
81 Actor tile = Actor::New();
82 tile.SetAnchorPoint( AnchorPoint::CENTER );
83 tile.RegisterProperty( "uTextureRect", samplerRect );
88 Geometry CreateQuadGeometry()
90 const float halfWidth = 0.5f;
91 const float halfHeight = 0.5f;
92 struct QuadVertex { Vector2 position;};
93 QuadVertex quadVertexData[4] =
95 { Vector2(-halfWidth, -halfHeight) },
96 { Vector2( halfWidth, -halfHeight) },
97 { Vector2(-halfWidth, halfHeight) },
98 { Vector2( halfWidth, halfHeight) }
101 Property::Map quadVertexFormat;
102 quadVertexFormat["aPosition"] = Property::VECTOR2;
103 PropertyBuffer quadVertices = PropertyBuffer::New( quadVertexFormat );
104 quadVertices.SetData( quadVertexData, 4 );
106 // Create the geometry object
107 Geometry geometry = Geometry::New();
108 geometry.AddVertexBuffer( quadVertices );
109 geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
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 );
119 CubeTransitionEffect::CubeTransitionEffect( unsigned int rows, unsigned int columns )
120 : Control( ControlBehaviour( 0 ) ),
123 mIsAnimating( false ),
125 mAnimationDuration( 1.f ),
126 mCubeDisplacement( 0.f )
130 CubeTransitionEffect::~CubeTransitionEffect()
134 void CubeTransitionEffect::SetTargetRight( unsigned int idx )
136 mBoxType[ idx ] = RIGHT;
138 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
140 mTargetTiles[ idx ].SetParentOrigin( Vector3( 1.f, 0.5f, 0.5f) );
141 mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::YAXIS );
144 void CubeTransitionEffect::SetTargetLeft( unsigned int idx )
146 mBoxType[ idx ] = LEFT;
148 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f );
150 mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.f, 0.5f, 0.5f) );
151 mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::YAXIS );
154 void CubeTransitionEffect::SetTargetBottom( unsigned int idx )
156 mBoxType[ idx ] = BOTTOM;
158 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
160 mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 0.f, 0.5f) );
161 mTargetTiles[ idx ].SetOrientation( Degree( 90.f ), Vector3::XAXIS );
164 void CubeTransitionEffect::SetTargetTop( unsigned int idx )
166 mBoxType[ idx ] = TOP;
168 mBoxes[ idx ].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f );
170 mTargetTiles[ idx ].SetParentOrigin( Vector3( 0.5f, 1.f, 0.5f) );
171 mTargetTiles[ idx ].SetOrientation( Degree( -90.f ), Vector3::XAXIS );
174 void CubeTransitionEffect::OnRelayout( const Vector2& size, RelayoutContainer& container )
176 mTileSize = Vector2( size.x / mColumns, size.y / mRows );
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 );
182 for( size_t i = 0; i < mBoxes.size(); ++i )
184 mBoxes[ i ].SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
185 mBoxes[ i ].SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
187 switch( mBoxType[i] )
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 );
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 );
206 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
208 it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
209 it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
211 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
213 it->SetProperty( Actor::Property::SIZE_WIDTH, mTileSize.x );
214 it->SetProperty( Actor::Property::SIZE_HEIGHT, mTileSize.y );
218 void CubeTransitionEffect::Initialize()
220 Self().RegisterProperty( "uTextureRect", Vector4( 0.0f, 0.0f, 1.0f, 1.0f ) );
222 mBoxType.Resize(mColumns * mRows);
224 //create the box parents
225 mBoxRoot = Actor::New();
226 mBoxRoot.SetParentOrigin( ParentOrigin::CENTER );
227 mBoxRoot.SetAnchorPoint( AnchorPoint::CENTER );
229 mCurrentTiles.clear();
230 mTargetTiles.clear();
232 mCurrentTiles.reserve( mColumns * mRows );
233 mTargetTiles.reserve( mColumns * mRows );
235 Vector2 gridSizeInv( 1.0f / mColumns, 1.0f / mRows );
236 Vector3 offset( 0.5f * gridSizeInv.x, 0.5f * gridSizeInv.y, 0.0f );
239 for( unsigned int y = 0; y < mRows; ++y, anchor.y += 1.0f / mRows )
242 for( unsigned int x = 0; x <mColumns; ++x, anchor.x += 1.0f / mColumns )
244 Vector4 textureRect( anchor.x, anchor.y, anchor.x + gridSizeInv.x, anchor.y + gridSizeInv.y );
246 Actor currentTile = CreateTile( textureRect );
247 currentTile.SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
248 currentTile.SetParentOrigin( ParentOrigin::CENTER );
249 mCurrentTiles.push_back( currentTile );
251 Actor targetTile = CreateTile( textureRect );
252 targetTile.SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
253 mTargetTiles.push_back( targetTile );
255 Actor box = Actor::New();
256 box.SetParentOrigin( anchor + offset );
257 box.SetAnchorPoint( AnchorPoint::CENTER );
259 box.Add( currentTile );
260 box.Add( targetTile );
264 mBoxes.push_back( box );
271 void CubeTransitionEffect::OnStageConnection( int depth )
273 Geometry geometry = CreateQuadGeometry();
274 Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
276 Material material = Material::New( shader );
280 material.AddTexture( mCurrentImage, "sTexture" );
282 mCurrentRenderer = Renderer::New( geometry, material );
284 mCurrentRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depth );
285 Self().AddRenderer( mCurrentRenderer );
288 void CubeTransitionEffect::OnStageDisconnection()
290 if( mCurrentRenderer )
292 Self().RemoveRenderer( mCurrentRenderer );
294 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
296 it->RemoveRenderer( mCurrentRenderer );
298 mCurrentRenderer.Reset();
301 if( mTargetRenderer )
303 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
305 it->RemoveRenderer( mTargetRenderer );
307 mTargetRenderer.Reset();
311 void CubeTransitionEffect::SetTransitionDuration( float duration )
313 mAnimationDuration = duration;
316 float CubeTransitionEffect::GetTransitionDuration( ) const
318 return mAnimationDuration;
321 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
323 mCubeDisplacement = displacement;
326 float CubeTransitionEffect::GetCubeDisplacement() const
328 return mCubeDisplacement;
331 bool CubeTransitionEffect::IsTransitioning()
336 void CubeTransitionEffect::SetCurrentImage( Image image )
338 mCurrentImage = image;
340 if( mCurrentRenderer )
342 Material material = mCurrentRenderer.GetMaterial();
344 int index = material.GetTextureIndex("sTexture" );
347 material.SetTextureImage( index, mCurrentImage );
351 material.AddTexture( mCurrentImage, "sTexture" );
356 void CubeTransitionEffect::SetTargetImage( Image image )
358 mTargetImage = image;
360 if( mTargetRenderer )
362 Material material = mTargetRenderer.GetMaterial();
363 material.AddTexture( mTargetImage, "sTexture" );
367 void CubeTransitionEffect::StartTransition( bool toNextImage )
369 Vector3 size = Self().GetCurrentSize();
372 StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( -10.f, 0.f ) );
376 StartTransition( Vector2(size.x* 0.5f, size.y*0.5f), Vector2( 10.f, 0.f ));
380 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
382 if( !mCurrentRenderer )
384 DALI_LOG_ERROR( "Trying to transition a cube transition without an image set" );
388 //create the target renderer
389 Material material = Material::New( mCurrentRenderer.GetMaterial().GetShader() );
392 material.AddTexture( mTargetImage, "sTexture" );
394 Geometry geometry = mCurrentRenderer.GetGeometry();
395 mTargetRenderer = Renderer::New( geometry, material );
397 int depthIndex = mCurrentRenderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX);
398 mTargetRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex );
400 for( size_t i = 0; i < mBoxes.size(); ++i )
402 mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
405 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
407 it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
408 it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
409 it->AddRenderer( mCurrentRenderer );
411 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
413 it->AddRenderer( mTargetRenderer );
416 Self().RemoveRenderer( mCurrentRenderer );
417 Self().Add( mBoxRoot );
425 mAnimation = Animation::New( mAnimationDuration );
426 mAnimation.FinishedSignal().Connect( this, &CubeTransitionEffect::OnTransitionFinished );
428 OnStartTransition( panPosition, panDisplacement );
431 void CubeTransitionEffect::PauseTransition()
433 if( mIsAnimating && !mIsPaused )
440 void CubeTransitionEffect::ResumeTransition()
442 if( mIsAnimating && mIsPaused)
449 void CubeTransitionEffect::StopTransition()
451 ResetToInitialState();
454 void CubeTransitionEffect::ResetToInitialState()
458 mIsAnimating = false;
460 Self().Remove( mBoxRoot );
462 for( size_t i = 0; i < mBoxes.size(); ++i )
464 mBoxes[ i ].SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
467 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
469 it->SetParentOrigin( Vector3( 0.5f, 0.5f, 1.0f) );
470 it->SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( 0.0f ), Vector3::XAXIS ) );
471 it->SetProperty( Actor::Property::COLOR, FULL_BRIGHTNESS );
473 if( mCurrentRenderer )
475 for( ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it )
477 it->RemoveRenderer( mCurrentRenderer );
479 Self().AddRenderer( mCurrentRenderer );
482 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
484 it->SetProperty( Actor::Property::COLOR, HALF_BRIGHTNESS );
486 if( mTargetRenderer )
488 for( ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it )
490 it->RemoveRenderer( mTargetRenderer );
495 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
498 std::swap( mCurrentTiles, mTargetTiles );
499 std::swap( mCurrentRenderer, mTargetRenderer );
500 std::swap( mCurrentImage, mTargetImage );
502 ResetToInitialState();
505 Toolkit::CubeTransitionEffect handle( GetOwner() );
506 mTransitionCompletedSignal.Emit( handle, mCurrentImage );
509 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
511 return mTransitionCompletedSignal;
514 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
516 Dali::BaseHandle handle( object );
518 bool connected( true );
519 Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
521 if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
523 cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
527 // signalName does not match any signal
534 } // namespace Internal
536 } // namespace Toolkit