Fix builder animation
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / transition-effects / cube-transition-effect-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 // CLASS HEADER
18 #include "cube-transition-effect-impl.h"
19
20 namespace Dali
21 {
22
23 namespace Toolkit
24 {
25
26 namespace Internal
27 {
28
29 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS( 1.0f, 1.0f, 1.0f, 1.0f );
30 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS( 0.5f, 0.5f, 0.5f, 1.0f );
31
32 CubeTransitionEffect::CubeTransitionEffect( unsigned int numRows, unsigned int numColumns, Size viewAreaSize )
33 : mNumRows( numRows ),
34   mNumColumns( numColumns ),
35   mViewAreaSize( viewAreaSize ),
36   mRotateIndex( 0 ),
37   mContainerIndex( 0 ),
38   mChangeTurningDirection( false ),
39   mIsToNextImage( true ),
40   mIsImageLoading( false ),
41   mAnimationDuration( 1.f ),
42   mIsAnimating( false ),
43   mIsPaused( false ),
44   mCubeDisplacement( 0.f ),
45   mFirstTransition( true ),
46   mBufferIndex( 0 )
47 {
48 }
49
50 CubeTransitionEffect::~CubeTransitionEffect()
51 {
52 }
53
54 void CubeTransitionEffect::Initialize()
55 {
56   //create root actor for the cube transition effect, only visible during the transition
57   mRoot = Actor::New();
58   mRoot.SetParentOrigin( ParentOrigin::CENTER );
59   mRoot.SetAnchorPoint( AnchorPoint::CENTER );
60   mRoot.SetVisible(false);
61
62   // create two groups of tiles,
63   // and one group of actors (cubes) serving as parents of every two tiles (one from each image).
64   unsigned int totalNum = mNumColumns* mNumRows;
65   mBoxes.resize( totalNum );
66   mTiles[0].resize( totalNum );
67   mTiles[1].resize( totalNum );
68   mTileSize = Vector2( mViewAreaSize.width / mNumColumns, mViewAreaSize.height / mNumRows );
69   const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
70                               (-mViewAreaSize.height + mTileSize.height) * 0.5f,
71                               -mTileSize.width * 0.5f );
72
73   Image placeHolder = BitmapImage::WHITE();
74   for( unsigned int y = 0; y < mNumRows; y++ )
75   {
76     float positionY = y * mTileSize.height + basePosition.y;
77     for( unsigned int x = 0; x < mNumColumns; x++)
78     {
79       unsigned int idx = y*mNumColumns + x;
80       Actor actor( Actor::New() );
81       mBoxes[idx] = actor;
82       actor.SetParentOrigin( ParentOrigin::CENTER );
83       actor.SetAnchorPoint( AnchorPoint::CENTER );
84       actor.SetPosition( x * mTileSize.width + basePosition.x,
85                          positionY,
86                          basePosition.z );
87       mRoot.Add( actor );
88
89       mTiles[ 0 ][idx] = CreateTile( placeHolder, FULL_BRIGHTNESS );
90       actor.Add( mTiles[ 0 ][idx] );
91
92       mTiles[ 1 ][idx] = CreateTile( placeHolder, HALF_BRIGHTNESS );
93       actor.Add( mTiles[ 1 ][idx] );
94     }
95   }
96
97   // helper actor to create a off-screen image using shader effect
98   mEmptyImage = ImageActor::New( placeHolder );
99   mEmptyImage.SetSize(Stage::GetCurrent().GetSize());
100   mEmptyImage.SetParentOrigin( ParentOrigin::CENTER );
101   mEmptyImage.SetAnchorPoint( AnchorPoint::CENTER );
102   mFullImageCreator = FullAreaImageCreator::New();
103   mEmptyImage.SetShaderEffect( mFullImageCreator );
104   Stage::GetCurrent().Add(mEmptyImage);
105
106   // set up off-screen render task
107   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
108   mOffScreenTask = taskList.CreateTask();
109   mOffScreenTask.SetSourceActor(mEmptyImage);
110   mOffScreenTask.SetExclusive(true);
111   mOffScreenBuffer[0] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
112   mOffScreenBuffer[1] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
113   mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
114   mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
115
116   OnInitialize();
117 }
118
119 ImageActor CubeTransitionEffect::CreateTile( Image image, const Vector4& color )
120 {
121   ImageActor tile = ImageActor::New( image );
122   tile.SetParentOrigin( ParentOrigin::CENTER );
123   tile.SetAnchorPoint( AnchorPoint::CENTER );
124   tile.SetSize( mTileSize );
125   tile.SetColorMode( Dali::USE_OWN_COLOR );
126   tile.SetColor( color );
127
128   return tile;
129 }
130
131 void CubeTransitionEffect::SetTransitionDuration( float duration )
132 {
133   mAnimationDuration = duration;
134 }
135
136 float CubeTransitionEffect::GetTransitionDuration( ) const
137 {
138   return mAnimationDuration;
139 }
140
141 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
142 {
143   mCubeDisplacement = displacement;
144 }
145
146 float CubeTransitionEffect::GetCubeDisplacement() const
147 {
148   return mCubeDisplacement;
149 }
150
151 Actor CubeTransitionEffect::GetRoot()
152 {
153   return mRoot;
154 }
155
156 bool CubeTransitionEffect::IsTransiting()
157 {
158   return mIsImageLoading || mIsAnimating;
159 }
160
161 void CubeTransitionEffect::SetCurrentImage( ImageActor imageActor )
162 {
163   mContainerIndex = std::abs(mRotateIndex) % 2;
164   SetImage( imageActor );
165 }
166
167 void CubeTransitionEffect::SetTargetImage( ImageActor imageActor )
168 {
169   mContainerIndex = std::abs( mRotateIndex+1 ) % 2;
170   SetImage( imageActor );
171 }
172
173 void CubeTransitionEffect::SetImage( ImageActor imageActor )
174 {
175   mCurrentImage = imageActor;
176   mIsImageLoading = true;
177
178   Image image = imageActor.GetImage();
179   mBufferIndex = mBufferIndex^1;
180
181   //must make sure the image is already loaded before using its attributes
182   if( image.GetLoadingState() == ResourceLoadingSucceeded )
183   {
184     OnImageLoaded( image );
185   }
186   else
187   {
188     image.LoadingFinishedSignal().Connect( this, &CubeTransitionEffect::OnImageLoaded );
189   }
190 }
191
192 void CubeTransitionEffect::StartTransition( bool toNextImage )
193 {
194   if( toNextImage )
195   {
196     StartTransition( Vector2( mViewAreaSize.width, mViewAreaSize.height*0.5f ), Vector2( -10.f, 0.f ) );
197   }
198   else
199   {
200     StartTransition( Vector2( 0, mViewAreaSize.height*0.5f ), Vector2( 10.f, 0.f ));
201   }
202 }
203
204 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
205 {
206   mRoot.SetVisible( true );
207   mCurrentImage.SetVisible( false );
208   bool toNextImage = ( panDisplacement.x < 0 ) ? true : false;
209   if( mIsToNextImage != toNextImage )
210   {
211     mChangeTurningDirection = true;
212   }
213   else
214   {
215     mChangeTurningDirection = false;
216   }
217   mIsToNextImage = toNextImage;
218
219   if( mIsToNextImage )
220   {
221     mRotateIndex += 1.f;
222   }
223   else
224   {
225     mRotateIndex -= 1.f;
226   }
227
228   if(mAnimation)
229   {
230     mAnimation.Clear();
231     mAnimation.Reset();
232   }
233   mAnimation = Animation::New( mAnimationDuration );
234   mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
235
236   OnStartTransition( panPosition, panDisplacement );
237 }
238
239 void CubeTransitionEffect::PauseTransition()
240 {
241   if( mIsAnimating && !mIsPaused )
242   {
243     mAnimation.Pause();
244     mIsPaused = true;
245   }
246 }
247
248 void CubeTransitionEffect::ResumeTransition()
249 {
250   if( mIsAnimating && mIsPaused)
251   {
252     mAnimation.Play();
253     mIsPaused = false;
254   }
255 }
256
257 void CubeTransitionEffect::StopTransition()
258 {
259   if( mIsAnimating )
260   {
261     mAnimation.Clear();
262     mAnimation.Reset();
263     mIsPaused = false;
264
265     //reset the position of the cubes
266     //reset the color of the tiles
267     //all these status should be the same as the final state when the transition animation is finished completely
268     const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
269                                 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
270                                  -mTileSize.width * 0.5f );
271     unsigned int anotherIndex = mContainerIndex^1;
272     for( unsigned int y = 0; y < mNumRows; y++ )
273     {
274       float positionY = y * mTileSize.height + basePosition.y;
275       for( unsigned int x = 0; x < mNumColumns; x++)
276       {
277         unsigned int idx = y*mNumColumns + x;
278         mBoxes[idx].SetPosition( x * mTileSize.width + basePosition.x,
279                                  positionY,
280                                  basePosition.z );
281         mTiles[mContainerIndex][idx].SetColor( FULL_BRIGHTNESS );
282         mTiles[anotherIndex][idx].SetColor( HALF_BRIGHTNESS);
283       }
284     }
285
286     // reset the rotation of the cubes, which is different process for different derived classes
287     OnStopTransition();
288
289     mRoot.SetVisible(false);
290     mCurrentImage.SetVisible(true);
291     mIsAnimating = false;
292     mFirstTransition = false;
293   }
294 }
295
296 void CubeTransitionEffect::OnImageLoaded(Image image)
297 {
298   // Fit the image to view area, while keeping the aspect; FitKeepAspectRatio(imageSize, viewAreaSize)
299   ImageAttributes attributes( image.GetAttributes() );
300   float scale = std::min(  mViewAreaSize.width / attributes.GetWidth(), mViewAreaSize.height / attributes.GetHeight() );
301   Vector2 imageSize(attributes.GetWidth()*scale, attributes.GetHeight()*scale);
302
303   mFullImageCreator.SetEffectImage(image);
304   mFullImageCreator.SetRegionSize(mViewAreaSize, imageSize);
305
306   mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
307   mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
308
309   ImageActor::PixelArea pixelArea( 0, 0, mViewAreaSize.x / mNumColumns, mViewAreaSize.y / mNumRows);
310
311   for( unsigned int y = 0; y < mNumRows; y++ )
312   {
313     pixelArea.y = y * pixelArea.height;
314     for( unsigned int x = 0; x < mNumColumns; x++)
315     {
316       pixelArea.x = x * pixelArea.width;
317       unsigned int idx = y*mNumColumns + x;
318       mTiles[mContainerIndex][idx].SetImage( mOffScreenBuffer[mBufferIndex]);
319       mTiles[mContainerIndex][idx].SetPixelArea( pixelArea );
320     }
321   }
322   mIsImageLoading = false;
323 }
324
325 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
326 {
327   mRoot.SetVisible(false);
328   mCurrentImage.SetVisible(true);
329   mIsAnimating = false;
330   mFirstTransition = false;
331
332   //Emit signal
333   Toolkit::CubeTransitionEffect handle( this );
334   mTransitionCompletedSignalV2.Emit( handle, mCurrentImage );
335 }
336
337 Toolkit::CubeTransitionEffect::TransitionCompletedSignalV2& CubeTransitionEffect::TransitionCompletedSignal()
338 {
339   return mTransitionCompletedSignalV2;
340 }
341
342 } // namespace Internal
343
344 } // namespace Toolkit
345
346 } // namespace Dali