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