Text shaper interface
[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/object/type-registry.h>
25 #include <dali/public-api/render-tasks/render-task-list.h>
26
27 namespace Dali
28 {
29
30 namespace Toolkit
31 {
32
33 namespace Internal
34 {
35
36 namespace
37 {
38
39 // Signals
40
41 const char* const SIGNAL_TRANSITION_COMPLETED = "transition-completed";
42
43 TypeRegistration typeRegistration( typeid( Toolkit::CubeTransitionEffect ), typeid( Dali::BaseHandle ), NULL );
44
45 SignalConnectorType signalConnector1( typeRegistration, SIGNAL_TRANSITION_COMPLETED , &CubeTransitionEffect::DoConnectSignal );
46
47 }
48
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 );
51
52 CubeTransitionEffect::CubeTransitionEffect( unsigned int numRows, unsigned int numColumns, Size viewAreaSize )
53 : mNumRows( numRows ),
54   mNumColumns( numColumns ),
55   mViewAreaSize( viewAreaSize ),
56   mRotateIndex( 0 ),
57   mContainerIndex( 0 ),
58   mChangeTurningDirection( false ),
59   mIsToNextImage( true ),
60   mIsImageLoading( false ),
61   mAnimationDuration( 1.f ),
62   mIsAnimating( false ),
63   mIsPaused( false ),
64   mCubeDisplacement( 0.f ),
65   mFirstTransition( true ),
66   mBufferIndex( 0 )
67 {
68 }
69
70 CubeTransitionEffect::~CubeTransitionEffect()
71 {
72 }
73
74 void CubeTransitionEffect::Initialize()
75 {
76   //create root actor for the cube transition effect, only visible during the transition
77   mRoot = Actor::New();
78   mRoot.SetParentOrigin( ParentOrigin::CENTER );
79   mRoot.SetAnchorPoint( AnchorPoint::CENTER );
80   mRoot.SetVisible(false);
81
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 );
92
93   Image placeHolder = BitmapImage::WHITE();
94   for( unsigned int y = 0; y < mNumRows; y++ )
95   {
96     float positionY = y * mTileSize.height + basePosition.y;
97     for( unsigned int x = 0; x < mNumColumns; x++)
98     {
99       unsigned int idx = y*mNumColumns + x;
100       Actor actor( Actor::New() );
101       mBoxes[idx] = actor;
102       actor.SetParentOrigin( ParentOrigin::CENTER );
103       actor.SetAnchorPoint( AnchorPoint::CENTER );
104       actor.SetPosition( x * mTileSize.width + basePosition.x,
105                          positionY,
106                          basePosition.z );
107       mRoot.Add( actor );
108
109       mTiles[ 0 ][idx] = CreateTile( placeHolder, FULL_BRIGHTNESS );
110       actor.Add( mTiles[ 0 ][idx] );
111
112       mTiles[ 1 ][idx] = CreateTile( placeHolder, HALF_BRIGHTNESS );
113       actor.Add( mTiles[ 1 ][idx] );
114     }
115   }
116
117   // helper actor to create a off-screen image using shader effect
118   mEmptyImage = ImageActor::New( placeHolder );
119   mEmptyImage.SetSize(Stage::GetCurrent().GetSize());
120   mEmptyImage.SetParentOrigin( ParentOrigin::CENTER );
121   mEmptyImage.SetAnchorPoint( AnchorPoint::CENTER );
122   mFullImageCreator = FullAreaImageCreator::New();
123   mEmptyImage.SetShaderEffect( mFullImageCreator );
124   Stage::GetCurrent().Add(mEmptyImage);
125
126   // set up off-screen render task
127   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
128   mOffScreenTask = taskList.CreateTask();
129   mOffScreenTask.SetSourceActor(mEmptyImage);
130   mOffScreenTask.SetExclusive(true);
131   mOffScreenBuffer[0] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
132   mOffScreenBuffer[1] = FrameBufferImage::New(mViewAreaSize.x, mViewAreaSize.y);
133   mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
134   mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
135
136   OnInitialize();
137 }
138
139 ImageActor CubeTransitionEffect::CreateTile( Image image, const Vector4& color )
140 {
141   ImageActor tile = ImageActor::New( image );
142   tile.SetParentOrigin( ParentOrigin::CENTER );
143   tile.SetAnchorPoint( AnchorPoint::CENTER );
144   tile.SetSize( mTileSize );
145   tile.SetColorMode( Dali::USE_OWN_COLOR );
146   tile.SetColor( color );
147
148   return tile;
149 }
150
151 void CubeTransitionEffect::SetTransitionDuration( float duration )
152 {
153   mAnimationDuration = duration;
154 }
155
156 float CubeTransitionEffect::GetTransitionDuration( ) const
157 {
158   return mAnimationDuration;
159 }
160
161 void CubeTransitionEffect::SetCubeDisplacement( float displacement )
162 {
163   mCubeDisplacement = displacement;
164 }
165
166 float CubeTransitionEffect::GetCubeDisplacement() const
167 {
168   return mCubeDisplacement;
169 }
170
171 Actor CubeTransitionEffect::GetRoot()
172 {
173   return mRoot;
174 }
175
176 bool CubeTransitionEffect::IsTransiting()
177 {
178   return mIsImageLoading || mIsAnimating;
179 }
180
181 void CubeTransitionEffect::SetCurrentImage( ImageActor imageActor )
182 {
183   mContainerIndex = std::abs(mRotateIndex) % 2;
184   SetImage( imageActor );
185 }
186
187 void CubeTransitionEffect::SetTargetImage( ImageActor imageActor )
188 {
189   mContainerIndex = std::abs( mRotateIndex+1 ) % 2;
190   SetImage( imageActor );
191 }
192
193 void CubeTransitionEffect::SetImage( ImageActor imageActor )
194 {
195   mCurrentImage = imageActor;
196
197   Image image = imageActor.GetImage();
198   ResourceImage resourceImage = ResourceImage::DownCast( image );
199   mBufferIndex = mBufferIndex^1;
200
201   //must make sure the image is already loaded before using its attributes
202   if( resourceImage && resourceImage.GetLoadingState() != ResourceLoadingSucceeded )
203   {
204     mIsImageLoading = true;
205     resourceImage.LoadingFinishedSignal().Connect( this, &CubeTransitionEffect::OnImageLoaded );
206   }
207   else
208   {
209     mIsImageLoading = false;
210     PrepareTiles( image );
211   }
212 }
213
214 void CubeTransitionEffect::StartTransition( bool toNextImage )
215 {
216   if( toNextImage )
217   {
218     StartTransition( Vector2( mViewAreaSize.width, mViewAreaSize.height*0.5f ), Vector2( -10.f, 0.f ) );
219   }
220   else
221   {
222     StartTransition( Vector2( 0, mViewAreaSize.height*0.5f ), Vector2( 10.f, 0.f ));
223   }
224 }
225
226 void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisplacement )
227 {
228   mRoot.SetVisible( true );
229   mCurrentImage.SetVisible( false );
230   bool toNextImage = ( panDisplacement.x < 0 ) ? true : false;
231   if( mIsToNextImage != toNextImage )
232   {
233     mChangeTurningDirection = true;
234   }
235   else
236   {
237     mChangeTurningDirection = false;
238   }
239   mIsToNextImage = toNextImage;
240
241   if( mIsToNextImage )
242   {
243     mRotateIndex += 1.f;
244   }
245   else
246   {
247     mRotateIndex -= 1.f;
248   }
249
250   if(mAnimation)
251   {
252     mAnimation.Clear();
253     mAnimation.Reset();
254   }
255   mAnimation = Animation::New( mAnimationDuration );
256   mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
257
258   OnStartTransition( panPosition, panDisplacement );
259 }
260
261 void CubeTransitionEffect::PauseTransition()
262 {
263   if( mIsAnimating && !mIsPaused )
264   {
265     mAnimation.Pause();
266     mIsPaused = true;
267   }
268 }
269
270 void CubeTransitionEffect::ResumeTransition()
271 {
272   if( mIsAnimating && mIsPaused)
273   {
274     mAnimation.Play();
275     mIsPaused = false;
276   }
277 }
278
279 void CubeTransitionEffect::StopTransition()
280 {
281   if( mIsAnimating )
282   {
283     mAnimation.Clear();
284     mAnimation.Reset();
285     mIsPaused = false;
286
287     //reset the position of the cubes
288     //reset the color of the tiles
289     //all these status should be the same as the final state when the transition animation is finished completely
290     const Vector3 basePosition( (-mViewAreaSize.width + mTileSize.width) * 0.5f,
291                                 (-mViewAreaSize.height + mTileSize.height) * 0.5f,
292                                  -mTileSize.width * 0.5f );
293     unsigned int anotherIndex = mContainerIndex^1;
294     for( unsigned int y = 0; y < mNumRows; y++ )
295     {
296       float positionY = y * mTileSize.height + basePosition.y;
297       for( unsigned int x = 0; x < mNumColumns; x++)
298       {
299         unsigned int idx = y*mNumColumns + x;
300         mBoxes[idx].SetPosition( x * mTileSize.width + basePosition.x,
301                                  positionY,
302                                  basePosition.z );
303         mTiles[mContainerIndex][idx].SetColor( FULL_BRIGHTNESS );
304         mTiles[anotherIndex][idx].SetColor( HALF_BRIGHTNESS);
305       }
306     }
307
308     // reset the rotation of the cubes, which is different process for different derived classes
309     OnStopTransition();
310
311     mRoot.SetVisible(false);
312     mCurrentImage.SetVisible(true);
313     mIsAnimating = false;
314     mFirstTransition = false;
315   }
316 }
317
318 void CubeTransitionEffect::OnImageLoaded(ResourceImage image)
319 {
320   mIsImageLoading = false;
321   PrepareTiles( image );
322 }
323
324 /**
325  * Set sub-image to each tile.
326  * @param[in] image The image content of the imageActor for transition
327  */
328 void CubeTransitionEffect::PrepareTiles( Image image )
329 {
330   // Fit the image to view area, while keeping the aspect; FitKeepAspectRatio(imageSize, viewAreaSize)
331   float scale = std::min(  mViewAreaSize.width / image.GetWidth(), mViewAreaSize.height / image.GetHeight() );
332   Vector2 imageSize(image.GetWidth()*scale, image.GetHeight()*scale);
333
334   mFullImageCreator.SetEffectImage(image);
335   mFullImageCreator.SetRegionSize(mViewAreaSize, imageSize);
336
337   mOffScreenTask.SetTargetFrameBuffer(mOffScreenBuffer[mBufferIndex]);
338   mOffScreenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
339
340   ImageActor::PixelArea pixelArea( 0, 0, mViewAreaSize.x / mNumColumns, mViewAreaSize.y / mNumRows);
341
342   for( unsigned int y = 0; y < mNumRows; y++ )
343   {
344     pixelArea.y = y * pixelArea.height;
345     for( unsigned int x = 0; x < mNumColumns; x++)
346     {
347       pixelArea.x = x * pixelArea.width;
348       unsigned int idx = y*mNumColumns + x;
349       mTiles[mContainerIndex][idx].SetImage( mOffScreenBuffer[mBufferIndex]);
350       mTiles[mContainerIndex][idx].SetPixelArea( pixelArea );
351     }
352   }
353 }
354
355
356 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
357 {
358   mRoot.SetVisible(false);
359   mCurrentImage.SetVisible(true);
360   mIsAnimating = false;
361   mFirstTransition = false;
362
363   //Emit signal
364   Toolkit::CubeTransitionEffect handle( this );
365   mTransitionCompletedSignal.Emit( handle, mCurrentImage );
366 }
367
368 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
369 {
370   return mTransitionCompletedSignal;
371 }
372
373 bool CubeTransitionEffect::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
374 {
375   Dali::BaseHandle handle( object );
376
377   bool connected( true );
378   Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast( handle );
379
380   if( 0 == strcmp( signalName.c_str(), SIGNAL_TRANSITION_COMPLETED ) )
381   {
382     cubeTransitionEffect.TransitionCompletedSignal().Connect( tracker, functor );
383   }
384   else
385   {
386     // signalName does not match any signal
387     connected = false;
388   }
389
390   return connected;
391 }
392
393 } // namespace Internal
394
395 } // namespace Toolkit
396
397 } // namespace Dali