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