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