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/devel-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( Toolkit, 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.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
121 mEmptyImage.SetParentOrigin( ParentOrigin::CENTER );
122 mEmptyImage.SetAnchorPoint( AnchorPoint::CENTER );
123 mFullImageCreator = FullAreaImageCreator::New();
124 mEmptyImage.SetShaderEffect( mFullImageCreator );
125 Stage::GetCurrent().Add(mEmptyImage);
127 // set up off-screen render task
128 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
129 mOffScreenTask = taskList.CreateTask();
130 mOffScreenTask.SetSourceActor(mEmptyImage);
131 mOffScreenTask.SetExclusive(true);
132 mOffScreenBuffer[0] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
133 mOffScreenBuffer[1] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
134 mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
135 mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
140 ImageActor CubeTransitionEffect::CreateTile( Image image, const Vector4& color )
142 ImageActor tile = ImageActor::New( image );
143 tile.SetParentOrigin( ParentOrigin::CENTER );
144 tile.SetAnchorPoint( AnchorPoint::CENTER );
145 tile.SetSize( mTileSize );
146 tile.SetColorMode( Dali::USE_OWN_COLOR );
147 tile.SetColor( color );
152 void CubeTransitionEffect::SetTransitionDuration( float duration )
154 mAnimationDuration = duration;
157 float CubeTransitionEffect::GetTransitionDuration( ) const
159 return mAnimationDuration;
162 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
164 mCubeDisplacement = displacement;
167 float CubeTransitionEffect::GetCubeDisplacement() const
169 return mCubeDisplacement;
172 Actor CubeTransitionEffect::GetRoot()
177 bool CubeTransitionEffect::IsTransiting()
179 return mIsImageLoading || mIsAnimating;
182 void CubeTransitionEffect::SetCurrentImage( ImageActor imageActor )
184 mContainerIndex = std::abs(mRotateIndex) % 2;
185 SetImage( imageActor );
188 void CubeTransitionEffect::SetTargetImage( ImageActor imageActor )
190 mContainerIndex = std::abs( mRotateIndex+1 ) % 2;
191 SetImage( imageActor );
194 void CubeTransitionEffect::SetImage( ImageActor imageActor )
196 mCurrentImage = imageActor;
198 Image image = imageActor.GetImage();
199 ResourceImage resourceImage = ResourceImage::DownCast( image );
200 mBufferIndex = mBufferIndex^1;
202 //must make sure the image is already loaded before using its attributes
203 if( resourceImage && resourceImage.GetLoadingState() != ResourceLoadingSucceeded )
205 mIsImageLoading = true;
206 resourceImage.LoadingFinishedSignal().Connect( this, &CubeTransitionEffect::OnImageLoaded );
210 mIsImageLoading = false;
211 PrepareTiles( image );
215 void CubeTransitionEffect::StartTransition( bool toNextImage )
219 StartTransition( Vector2( mViewAreaSize.width, mViewAreaSize.height*0.5f ), Vector2( -10.f, 0.f ) );
223 StartTransition( Vector2( 0, mViewAreaSize.height*0.5f ), Vector2( 10.f, 0.f ));
227 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
229 mRoot.SetVisible( true );
230 mCurrentImage.SetVisible( false );
231 bool toNextImage = ( panDisplacement.x < 0 ) ? true : false;
232 if( mIsToNextImage != toNextImage )
234 mChangeTurningDirection = true;
238 mChangeTurningDirection = false;
240 mIsToNextImage = toNextImage;
256 mAnimation = Animation::New( mAnimationDuration );
257 mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
259 OnStartTransition( panPosition, panDisplacement );
262 void CubeTransitionEffect::PauseTransition()
264 if( mIsAnimating && !mIsPaused )
271 void CubeTransitionEffect::ResumeTransition()
273 if( mIsAnimating && mIsPaused)
280 void CubeTransitionEffect::StopTransition()
288 //reset the position of the cubes
289 //reset the color of the tiles
290 //all these status should be the same as the final state when the transition animation is finished completely
291 const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
292 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
293 -mTileSize.width * 0.5f );
294 unsigned int anotherIndex = mContainerIndex^1;
295 for( unsigned int y = 0; y < mNumRows; y++ )
297 float positionY = y * mTileSize.height + basePosition.y;
298 for( unsigned int x = 0; x < mNumColumns; x++)
300 unsigned int idx = y*mNumColumns + x;
301 mBoxes[idx].SetPosition( x * mTileSize.width + basePosition.x,
304 mTiles[mContainerIndex][idx].SetColor( FULL_BRIGHTNESS );
305 mTiles[anotherIndex][idx].SetColor( HALF_BRIGHTNESS);
309 // reset the rotation of the cubes, which is different process for different derived classes
312 mRoot.SetVisible(false);
313 mCurrentImage.SetVisible(true);
314 mIsAnimating = false;
315 mFirstTransition = false;
319 void CubeTransitionEffect::OnImageLoaded(ResourceImage image)
321 mIsImageLoading = false;
322 PrepareTiles( image );
326 * Set sub-image to each tile.
327 * @param[in] image The image content of the imageActor for transition
329 void CubeTransitionEffect::PrepareTiles( Image image )
331 // Fit the image to view area, while keeping the aspect; FitKeepAspectRatio(imageSize, viewAreaSize)
332 float scale = std::min( mViewAreaSize.width / image.GetWidth(), mViewAreaSize.height / image.GetHeight() );
333 Vector2 imageSize(image.GetWidth()*scale, image.GetHeight()*scale);
335 mFullImageCreator.SetEffectImage(image);
336 mFullImageCreator.SetRegionSize(mViewAreaSize, imageSize);
338 mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
339 mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
341 ImageActor::PixelArea pixelArea( 0, 0, mViewAreaSize.x / mNumColumns, mViewAreaSize.y / mNumRows);
343 for( unsigned int y = 0; y < mNumRows; y++ )
345 pixelArea.y = y * pixelArea.height;
346 for( unsigned int x = 0; x < mNumColumns; x++)
348 pixelArea.x = x * pixelArea.width;
349 unsigned int idx = y*mNumColumns + x;
350 mTiles[mContainerIndex][idx].SetImage( mOffScreenBuffer[mBufferIndex]);
351 mTiles[mContainerIndex][idx].SetPixelArea( pixelArea );
357 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
359 mRoot.SetVisible(false);
360 mCurrentImage.SetVisible(true);
361 mIsAnimating = false;
362 mFirstTransition = false;
365 Toolkit::CubeTransitionEffect handle( this );
366 mTransitionCompletedSignal.Emit( handle, mCurrentImage );
369 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
371 return mTransitionCompletedSignal;
374 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
376 Dali::BaseHandle handle( object );
378 bool connected( true );
379 Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
381 if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
383 cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
387 // signalName does not match any signal
394 } // namespace Internal
396 } // namespace Toolkit