Update toolkit with ResourceImage/Image split
[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
183   Image image = imageActor.GetImage();
184   ResourceImage resourceImage = ResourceImage::DownCast( image );
185   mBufferIndex = mBufferIndex^1;
186
187   //must make sure the image is already loaded before using its attributes
188   if( resourceImage && resourceImage.GetLoadingState() != ResourceLoadingSucceeded )
189   {
190     mIsImageLoading = true;
191     resourceImage.LoadingFinishedSignal().Connect( this, &CubeTransitionEffect::OnImageLoaded );
192   }
193   else
194   {
195     mIsImageLoading = false;
196     PrepareTiles( image );
197   }
198 }
199
200 void CubeTransitionEffect::StartTransition( bool toNextImage )
201 {
202   if( toNextImage )
203   {
204     StartTransition( Vector2( mViewAreaSize.width, mViewAreaSize.height*0.5f ), Vector2( -10.f, 0.f ) );
205   }
206   else
207   {
208     StartTransition( Vector2( 0, mViewAreaSize.height*0.5f ), Vector2( 10.f, 0.f ));
209   }
210 }
211
212 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
213 {
214   mRoot.SetVisible( true );
215   mCurrentImage.SetVisible( false );
216   bool toNextImage = ( panDisplacement.x < 0 ) ? true : false;
217   if( mIsToNextImage != toNextImage )
218   {
219     mChangeTurningDirection = true;
220   }
221   else
222   {
223     mChangeTurningDirection = false;
224   }
225   mIsToNextImage = toNextImage;
226
227   if( mIsToNextImage )
228   {
229     mRotateIndex += 1.f;
230   }
231   else
232   {
233     mRotateIndex -= 1.f;
234   }
235
236   if(mAnimation)
237   {
238     mAnimation.Clear();
239     mAnimation.Reset();
240   }
241   mAnimation = Animation::New( mAnimationDuration );
242   mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
243
244   OnStartTransition( panPosition, panDisplacement );
245 }
246
247 void CubeTransitionEffect::PauseTransition()
248 {
249   if( mIsAnimating && !mIsPaused )
250   {
251     mAnimation.Pause();
252     mIsPaused = true;
253   }
254 }
255
256 void CubeTransitionEffect::ResumeTransition()
257 {
258   if( mIsAnimating && mIsPaused)
259   {
260     mAnimation.Play();
261     mIsPaused = false;
262   }
263 }
264
265 void CubeTransitionEffect::StopTransition()
266 {
267   if( mIsAnimating )
268   {
269     mAnimation.Clear();
270     mAnimation.Reset();
271     mIsPaused = false;
272
273     //reset the position of the cubes
274     //reset the color of the tiles
275     //all these status should be the same as the final state when the transition animation is finished completely
276     const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
277                                 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
278                                  -mTileSize.width * 0.5f );
279     unsigned int anotherIndex = mContainerIndex^1;
280     for( unsigned int y = 0; y < mNumRows; y++ )
281     {
282       float positionY = y * mTileSize.height + basePosition.y;
283       for( unsigned int x = 0; x < mNumColumns; x++)
284       {
285         unsigned int idx = y*mNumColumns + x;
286         mBoxes[idx].SetPosition( x * mTileSize.width + basePosition.x,
287                                  positionY,
288                                  basePosition.z );
289         mTiles[mContainerIndex][idx].SetColor( FULL_BRIGHTNESS );
290         mTiles[anotherIndex][idx].SetColor( HALF_BRIGHTNESS);
291       }
292     }
293
294     // reset the rotation of the cubes, which is different process for different derived classes
295     OnStopTransition();
296
297     mRoot.SetVisible(false);
298     mCurrentImage.SetVisible(true);
299     mIsAnimating = false;
300     mFirstTransition = false;
301   }
302 }
303
304 void CubeTransitionEffect::OnImageLoaded(ResourceImage image)
305 {
306   mIsImageLoading = false;
307   PrepareTiles( image );
308 }
309
310 /**
311  * Set sub-image to each tile.
312  * @param[in] image The image content of the imageActor for transition
313  */
314 void CubeTransitionEffect::PrepareTiles( Image image )
315 {
316   // Fit the image to view area, while keeping the aspect; FitKeepAspectRatio(imageSize, viewAreaSize)
317   float scale = std::min(  mViewAreaSize.width / image.GetWidth(), mViewAreaSize.height / image.GetHeight() );
318   Vector2 imageSize(image.GetWidth()*scale, image.GetHeight()*scale);
319
320   mFullImageCreator.SetEffectImage(image);
321   mFullImageCreator.SetRegionSize(mViewAreaSize, imageSize);
322
323   mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
324   mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
325
326   ImageActor::PixelArea pixelArea( 0, 0, mViewAreaSize.x / mNumColumns, mViewAreaSize.y / mNumRows);
327
328   for( unsigned int y = 0; y < mNumRows; y++ )
329   {
330     pixelArea.y = y * pixelArea.height;
331     for( unsigned int x = 0; x < mNumColumns; x++)
332     {
333       pixelArea.x = x * pixelArea.width;
334       unsigned int idx = y*mNumColumns + x;
335       mTiles[mContainerIndex][idx].SetImage( mOffScreenBuffer[mBufferIndex]);
336       mTiles[mContainerIndex][idx].SetPixelArea( pixelArea );
337     }
338   }
339 }
340
341
342 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
343 {
344   mRoot.SetVisible(false);
345   mCurrentImage.SetVisible(true);
346   mIsAnimating = false;
347   mFirstTransition = false;
348
349   //Emit signal
350   Toolkit::CubeTransitionEffect handle( this );
351   mTransitionCompletedSignal.Emit( handle, mCurrentImage );
352 }
353
354 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
355 {
356   return mTransitionCompletedSignal;
357 }
358
359 } // namespace Internal
360
361 } // namespace Toolkit
362
363 } // namespace Dali