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 <dali/public-api/common/stage.h>
23 #include <dali/public-api/images/buffer-image.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/object/type-registry-helper.h>
26 #include <dali/public-api/render-tasks/render-task-list.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( CubeTransitionEffect, "transition-completed", SIGNAL_TRANSITION_COMPLETED )
45 DALI_TYPE_REGISTRATION_END()
49 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS( 1.0f, 1.0f, 1.0f, 1.0f );
50 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS( 0.5f, 0.5f, 0.5f, 1.0f );
52 CubeTransitionEffect::CubeTransitionEffect( unsigned int numRows, unsigned int numColumns, Size viewAreaSize )
53 : mNumRows( numRows ),
54 mNumColumns( numColumns ),
55 mViewAreaSize( viewAreaSize ),
58 mChangeTurningDirection( false ),
59 mIsToNextImage( true ),
60 mIsImageLoading( false ),
61 mAnimationDuration( 1.f ),
62 mIsAnimating( false ),
64 mCubeDisplacement( 0.f ),
65 mFirstTransition( true ),
70 CubeTransitionEffect::~CubeTransitionEffect()
74 void CubeTransitionEffect::Initialize()
76 //create root actor for the cube transition effect, only visible during the transition
78 mRoot.SetParentOrigin( ParentOrigin::CENTER );
79 mRoot.SetAnchorPoint( AnchorPoint::CENTER );
80 mRoot.SetVisible(false);
82 // create two groups of tiles,
83 // and one group of actors (cubes) serving as parents of every two tiles (one from each image).
84 unsigned int totalNum = mNumColumns* mNumRows;
85 mBoxes.resize( totalNum );
86 mTiles[0].resize( totalNum );
87 mTiles[1].resize( totalNum );
88 mTileSize = Vector2( mViewAreaSize.width / mNumColumns, mViewAreaSize.height / mNumRows );
89 const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
90 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
91 -mTileSize.width * 0.5f );
93 Image placeHolder = BufferImage::WHITE();
94 for( unsigned int y = 0; y < mNumRows; y++ )
96 float positionY = y * mTileSize.height + basePosition.y;
97 for( unsigned int x = 0; x < mNumColumns; x++)
99 unsigned int idx = y*mNumColumns + x;
100 Actor actor( Actor::New() );
102 actor.SetParentOrigin( ParentOrigin::CENTER );
103 actor.SetAnchorPoint( AnchorPoint::CENTER );
104 actor.SetPosition( x * mTileSize.width + basePosition.x,
109 mTiles[ 0 ][idx] = CreateTile( placeHolder, FULL_BRIGHTNESS );
110 actor.Add( mTiles[ 0 ][idx] );
112 mTiles[ 1 ][idx] = CreateTile( placeHolder, HALF_BRIGHTNESS );
113 actor.Add( mTiles[ 1 ][idx] );
117 // helper actor to create a off-screen image using shader effect
118 mEmptyImage = ImageActor::New( placeHolder );
119 mEmptyImage.SetRelayoutEnabled( false );
120 mEmptyImage.SetSize(Stage::GetCurrent().GetSize());
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.SetRelayoutEnabled( false );
144 tile.SetParentOrigin( ParentOrigin::CENTER );
145 tile.SetAnchorPoint( AnchorPoint::CENTER );
146 tile.SetSize( mTileSize );
147 tile.SetColorMode( Dali::USE_OWN_COLOR );
148 tile.SetColor( color );
153 void CubeTransitionEffect::SetTransitionDuration( float duration )
155 mAnimationDuration = duration;
158 float CubeTransitionEffect::GetTransitionDuration( ) const
160 return mAnimationDuration;
163 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
165 mCubeDisplacement = displacement;
168 float CubeTransitionEffect::GetCubeDisplacement() const
170 return mCubeDisplacement;
173 Actor CubeTransitionEffect::GetRoot()
178 bool CubeTransitionEffect::IsTransiting()
180 return mIsImageLoading || mIsAnimating;
183 void CubeTransitionEffect::SetCurrentImage( ImageActor imageActor )
185 mContainerIndex = std::abs(mRotateIndex) % 2;
186 SetImage( imageActor );
189 void CubeTransitionEffect::SetTargetImage( ImageActor imageActor )
191 mContainerIndex = std::abs( mRotateIndex+1 ) % 2;
192 SetImage( imageActor );
195 void CubeTransitionEffect::SetImage( ImageActor imageActor )
197 mCurrentImage = imageActor;
199 Image image = imageActor.GetImage();
200 ResourceImage resourceImage = ResourceImage::DownCast( image );
201 mBufferIndex = mBufferIndex^1;
203 //must make sure the image is already loaded before using its attributes
204 if( resourceImage && resourceImage.GetLoadingState() != ResourceLoadingSucceeded )
206 mIsImageLoading = true;
207 resourceImage.LoadingFinishedSignal().Connect( this, &CubeTransitionEffect::OnImageLoaded );
211 mIsImageLoading = false;
212 PrepareTiles( image );
216 void CubeTransitionEffect::StartTransition( bool toNextImage )
220 StartTransition( Vector2( mViewAreaSize.width, mViewAreaSize.height*0.5f ), Vector2( -10.f, 0.f ) );
224 StartTransition( Vector2( 0, mViewAreaSize.height*0.5f ), Vector2( 10.f, 0.f ));
228 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
230 mRoot.SetVisible( true );
231 mCurrentImage.SetVisible( false );
232 bool toNextImage = ( panDisplacement.x < 0 ) ? true : false;
233 if( mIsToNextImage != toNextImage )
235 mChangeTurningDirection = true;
239 mChangeTurningDirection = false;
241 mIsToNextImage = toNextImage;
257 mAnimation = Animation::New( mAnimationDuration );
258 mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
260 OnStartTransition( panPosition, panDisplacement );
263 void CubeTransitionEffect::PauseTransition()
265 if( mIsAnimating && !mIsPaused )
272 void CubeTransitionEffect::ResumeTransition()
274 if( mIsAnimating && mIsPaused)
281 void CubeTransitionEffect::StopTransition()
289 //reset the position of the cubes
290 //reset the color of the tiles
291 //all these status should be the same as the final state when the transition animation is finished completely
292 const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
293 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
294 -mTileSize.width * 0.5f );
295 unsigned int anotherIndex = mContainerIndex^1;
296 for( unsigned int y = 0; y < mNumRows; y++ )
298 float positionY = y * mTileSize.height + basePosition.y;
299 for( unsigned int x = 0; x < mNumColumns; x++)
301 unsigned int idx = y*mNumColumns + x;
302 mBoxes[idx].SetPosition( x * mTileSize.width + basePosition.x,
305 mTiles[mContainerIndex][idx].SetColor( FULL_BRIGHTNESS );
306 mTiles[anotherIndex][idx].SetColor( HALF_BRIGHTNESS);
310 // reset the rotation of the cubes, which is different process for different derived classes
313 mRoot.SetVisible(false);
314 mCurrentImage.SetVisible(true);
315 mIsAnimating = false;
316 mFirstTransition = false;
320 void CubeTransitionEffect::OnImageLoaded(ResourceImage image)
322 mIsImageLoading = false;
323 PrepareTiles( image );
327 * Set sub-image to each tile.
328 * @param[in] image The image content of the imageActor for transition
330 void CubeTransitionEffect::PrepareTiles( Image image )
332 // Fit the image to view area, while keeping the aspect; FitKeepAspectRatio(imageSize, viewAreaSize)
333 float scale = std::min( mViewAreaSize.width / image.GetWidth(), mViewAreaSize.height / image.GetHeight() );
334 Vector2 imageSize(image.GetWidth()*scale, image.GetHeight()*scale);
336 mFullImageCreator.SetEffectImage(image);
337 mFullImageCreator.SetRegionSize(mViewAreaSize, imageSize);
339 mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
340 mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
342 ImageActor::PixelArea pixelArea( 0, 0, mViewAreaSize.x / mNumColumns, mViewAreaSize.y / mNumRows);
344 for( unsigned int y = 0; y < mNumRows; y++ )
346 pixelArea.y = y * pixelArea.height;
347 for( unsigned int x = 0; x < mNumColumns; x++)
349 pixelArea.x = x * pixelArea.width;
350 unsigned int idx = y*mNumColumns + x;
351 mTiles[mContainerIndex][idx].SetImage( mOffScreenBuffer[mBufferIndex]);
352 mTiles[mContainerIndex][idx].SetPixelArea( pixelArea );
358 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
360 mRoot.SetVisible(false);
361 mCurrentImage.SetVisible(true);
362 mIsAnimating = false;
363 mFirstTransition = false;
366 Toolkit::CubeTransitionEffect handle( this );
367 mTransitionCompletedSignal.Emit( handle, mCurrentImage );
370 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
372 return mTransitionCompletedSignal;
375 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
377 Dali::BaseHandle handle( object );
379 bool connected( true );
380 Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
382 if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
384 cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
388 // signalName does not match any signal
395 } // namespace Internal
397 } // namespace Toolkit