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/common/stage.h>
24 #include <dali/public-api/images/buffer-image.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/public-api/render-tasks/render-task-list.h>
41 // Setup properties, signals and actions using the type-registry.
42 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::CubeTransitionEffect, Dali::BaseHandle, NULL );
44 DALI_SIGNAL_REGISTRATION( CubeTransitionEffect, "transition-completed", SIGNAL_TRANSITION_COMPLETED )
46 DALI_TYPE_REGISTRATION_END()
50 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS( 1.0f, 1.0f, 1.0f, 1.0f );
51 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS( 0.5f, 0.5f, 0.5f, 1.0f );
53 CubeTransitionEffect::CubeTransitionEffect( unsigned int numRows, unsigned int numColumns, Size viewAreaSize )
54 : mNumRows( numRows ),
55 mNumColumns( numColumns ),
56 mViewAreaSize( viewAreaSize ),
59 mChangeTurningDirection( false ),
60 mIsToNextImage( true ),
61 mIsImageLoading( false ),
62 mAnimationDuration( 1.f ),
63 mIsAnimating( false ),
65 mCubeDisplacement( 0.f ),
66 mFirstTransition( true ),
71 CubeTransitionEffect::~CubeTransitionEffect()
75 void CubeTransitionEffect::Initialize()
77 //create root actor for the cube transition effect, only visible during the transition
79 mRoot.SetParentOrigin( ParentOrigin::CENTER );
80 mRoot.SetAnchorPoint( AnchorPoint::CENTER );
81 mRoot.SetVisible(false);
83 // create two groups of tiles,
84 // and one group of actors (cubes) serving as parents of every two tiles (one from each image).
85 unsigned int totalNum = mNumColumns* mNumRows;
86 mBoxes.resize( totalNum );
87 mTiles[0].resize( totalNum );
88 mTiles[1].resize( totalNum );
89 mTileSize = Vector2( mViewAreaSize.width / mNumColumns, mViewAreaSize.height / mNumRows );
90 const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
91 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
92 -mTileSize.width * 0.5f );
94 Image placeHolder = BufferImage::WHITE();
95 for( unsigned int y = 0; y < mNumRows; y++ )
97 float positionY = y * mTileSize.height + basePosition.y;
98 for( unsigned int x = 0; x < mNumColumns; x++)
100 unsigned int idx = y*mNumColumns + x;
101 Actor actor( Actor::New() );
103 actor.SetParentOrigin( ParentOrigin::CENTER );
104 actor.SetAnchorPoint( AnchorPoint::CENTER );
105 actor.SetPosition( x * mTileSize.width + basePosition.x,
110 mTiles[ 0 ][idx] = CreateTile( placeHolder, FULL_BRIGHTNESS );
111 actor.Add( mTiles[ 0 ][idx] );
113 mTiles[ 1 ][idx] = CreateTile( placeHolder, HALF_BRIGHTNESS );
114 actor.Add( mTiles[ 1 ][idx] );
118 // helper actor to create a off-screen image using shader effect
119 mEmptyImage = ImageActor::New( placeHolder );
120 mEmptyImage.SetRelayoutEnabled( false );
121 mEmptyImage.SetSize(Stage::GetCurrent().GetSize());
122 mEmptyImage.SetParentOrigin( ParentOrigin::CENTER );
123 mEmptyImage.SetAnchorPoint( AnchorPoint::CENTER );
124 mFullImageCreator = FullAreaImageCreator::New();
125 mEmptyImage.SetShaderEffect( mFullImageCreator );
126 Stage::GetCurrent().Add(mEmptyImage);
128 // set up off-screen render task
129 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
130 mOffScreenTask = taskList.CreateTask();
131 mOffScreenTask.SetSourceActor(mEmptyImage);
132 mOffScreenTask.SetExclusive(true);
133 mOffScreenBuffer[0] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
134 mOffScreenBuffer[1] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
135 mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
136 mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
141 ImageActor CubeTransitionEffect::CreateTile( Image image, const Vector4& color )
143 ImageActor tile = ImageActor::New( image );
144 tile.SetRelayoutEnabled( false );
145 tile.SetParentOrigin( ParentOrigin::CENTER );
146 tile.SetAnchorPoint( AnchorPoint::CENTER );
147 tile.SetSize( mTileSize );
148 tile.SetColorMode( Dali::USE_OWN_COLOR );
149 tile.SetColor( color );
154 void CubeTransitionEffect::SetTransitionDuration( float duration )
156 mAnimationDuration = duration;
159 float CubeTransitionEffect::GetTransitionDuration( ) const
161 return mAnimationDuration;
164 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
166 mCubeDisplacement = displacement;
169 float CubeTransitionEffect::GetCubeDisplacement() const
171 return mCubeDisplacement;
174 Actor CubeTransitionEffect::GetRoot()
179 bool CubeTransitionEffect::IsTransiting()
181 return mIsImageLoading || mIsAnimating;
184 void CubeTransitionEffect::SetCurrentImage( ImageActor imageActor )
186 mContainerIndex = std::abs(mRotateIndex) % 2;
187 SetImage( imageActor );
190 void CubeTransitionEffect::SetTargetImage( ImageActor imageActor )
192 mContainerIndex = std::abs( mRotateIndex+1 ) % 2;
193 SetImage( imageActor );
196 void CubeTransitionEffect::SetImage( ImageActor imageActor )
198 mCurrentImage = imageActor;
200 Image image = imageActor.GetImage();
201 ResourceImage resourceImage = ResourceImage::DownCast( image );
202 mBufferIndex = mBufferIndex^1;
204 //must make sure the image is already loaded before using its attributes
205 if( resourceImage && resourceImage.GetLoadingState() != ResourceLoadingSucceeded )
207 mIsImageLoading = true;
208 resourceImage.LoadingFinishedSignal().Connect( this, &CubeTransitionEffect::OnImageLoaded );
212 mIsImageLoading = false;
213 PrepareTiles( image );
217 void CubeTransitionEffect::StartTransition( bool toNextImage )
221 StartTransition( Vector2( mViewAreaSize.width, mViewAreaSize.height*0.5f ), Vector2( -10.f, 0.f ) );
225 StartTransition( Vector2( 0, mViewAreaSize.height*0.5f ), Vector2( 10.f, 0.f ));
229 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
231 mRoot.SetVisible( true );
232 mCurrentImage.SetVisible( false );
233 bool toNextImage = ( panDisplacement.x < 0 ) ? true : false;
234 if( mIsToNextImage != toNextImage )
236 mChangeTurningDirection = true;
240 mChangeTurningDirection = false;
242 mIsToNextImage = toNextImage;
258 mAnimation = Animation::New( mAnimationDuration );
259 mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
261 OnStartTransition( panPosition, panDisplacement );
264 void CubeTransitionEffect::PauseTransition()
266 if( mIsAnimating && !mIsPaused )
273 void CubeTransitionEffect::ResumeTransition()
275 if( mIsAnimating && mIsPaused)
282 void CubeTransitionEffect::StopTransition()
290 //reset the position of the cubes
291 //reset the color of the tiles
292 //all these status should be the same as the final state when the transition animation is finished completely
293 const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
294 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
295 -mTileSize.width * 0.5f );
296 unsigned int anotherIndex = mContainerIndex^1;
297 for( unsigned int y = 0; y < mNumRows; y++ )
299 float positionY = y * mTileSize.height + basePosition.y;
300 for( unsigned int x = 0; x < mNumColumns; x++)
302 unsigned int idx = y*mNumColumns + x;
303 mBoxes[idx].SetPosition( x * mTileSize.width + basePosition.x,
306 mTiles[mContainerIndex][idx].SetColor( FULL_BRIGHTNESS );
307 mTiles[anotherIndex][idx].SetColor( HALF_BRIGHTNESS);
311 // reset the rotation of the cubes, which is different process for different derived classes
314 mRoot.SetVisible(false);
315 mCurrentImage.SetVisible(true);
316 mIsAnimating = false;
317 mFirstTransition = false;
321 void CubeTransitionEffect::OnImageLoaded(ResourceImage image)
323 mIsImageLoading = false;
324 PrepareTiles( image );
328 * Set sub-image to each tile.
329 * @param[in] image The image content of the imageActor for transition
331 void CubeTransitionEffect::PrepareTiles( Image image )
333 // Fit the image to view area, while keeping the aspect; FitKeepAspectRatio(imageSize, viewAreaSize)
334 float scale = std::min( mViewAreaSize.width / image.GetWidth(), mViewAreaSize.height / image.GetHeight() );
335 Vector2 imageSize(image.GetWidth()*scale, image.GetHeight()*scale);
337 mFullImageCreator.SetEffectImage(image);
338 mFullImageCreator.SetRegionSize(mViewAreaSize, imageSize);
340 mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
341 mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
343 ImageActor::PixelArea pixelArea( 0, 0, mViewAreaSize.x / mNumColumns, mViewAreaSize.y / mNumRows);
345 for( unsigned int y = 0; y < mNumRows; y++ )
347 pixelArea.y = y * pixelArea.height;
348 for( unsigned int x = 0; x < mNumColumns; x++)
350 pixelArea.x = x * pixelArea.width;
351 unsigned int idx = y*mNumColumns + x;
352 mTiles[mContainerIndex][idx].SetImage( mOffScreenBuffer[mBufferIndex]);
353 mTiles[mContainerIndex][idx].SetPixelArea( pixelArea );
359 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
361 mRoot.SetVisible(false);
362 mCurrentImage.SetVisible(true);
363 mIsAnimating = false;
364 mFirstTransition = false;
367 Toolkit::CubeTransitionEffect handle( this );
368 mTransitionCompletedSignal.Emit( handle, mCurrentImage );
371 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
373 return mTransitionCompletedSignal;
376 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
378 Dali::BaseHandle handle( object );
380 bool connected( true );
381 Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
383 if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
385 cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
389 // signalName does not match any signal
396 } // namespace Internal
398 } // namespace Toolkit