Fixed invalid text selection behaviour
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / transition-effects / cube-transition-effect-impl.cpp
1 /*
2  * Copyright (c) 2021 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/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <cstring> // for strcmp
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
29 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
30 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
31
32 namespace Dali
33 {
34 namespace Toolkit
35 {
36 namespace Internal
37 {
38 namespace
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(Toolkit, CubeTransitionEffect, "transitionCompleted", SIGNAL_TRANSITION_COMPLETED)
44
45 DALI_TYPE_REGISTRATION_END()
46
47 Actor CreateTile(const Vector4& samplerRect)
48 {
49   Actor tile = Actor::New();
50   tile.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
51   tile.RegisterProperty("uTextureRect", samplerRect);
52   return tile;
53 }
54
55 } // namespace
56
57 const Vector4 CubeTransitionEffect::FULL_BRIGHTNESS(1.0f, 1.0f, 1.0f, 1.0f);
58 const Vector4 CubeTransitionEffect::HALF_BRIGHTNESS(0.5f, 0.5f, 0.5f, 1.0f);
59
60 CubeTransitionEffect::CubeTransitionEffect(unsigned int rows, unsigned int columns)
61 : Control(ControlBehaviour(DISABLE_STYLE_CHANGE_SIGNALS)),
62   mRows(rows),
63   mColumns(columns),
64   mIsAnimating(false),
65   mIsPaused(false),
66   mAnimationDuration(1.f),
67   mCubeDisplacement(0.f)
68 {
69 }
70
71 CubeTransitionEffect::~CubeTransitionEffect()
72 {
73 }
74
75 void CubeTransitionEffect::SetTargetRight(unsigned int idx)
76 {
77   mBoxType[idx] = RIGHT;
78
79   mBoxes[idx].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f);
80
81   mTargetTiles[idx].SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(1.f, 0.5f, 0.5f));
82   mTargetTiles[idx].SetProperty(Actor::Property::ORIENTATION, Quaternion(Degree(90.f), Vector3::YAXIS));
83 }
84
85 void CubeTransitionEffect::SetTargetLeft(unsigned int idx)
86 {
87   mBoxType[idx] = LEFT;
88
89   mBoxes[idx].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f);
90
91   mTargetTiles[idx].SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.f, 0.5f, 0.5f));
92   mTargetTiles[idx].SetProperty(Actor::Property::ORIENTATION, Quaternion(Degree(-90.f), Vector3::YAXIS));
93 }
94
95 void CubeTransitionEffect::SetTargetBottom(unsigned int idx)
96 {
97   mBoxType[idx] = BOTTOM;
98
99   mBoxes[idx].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f);
100
101   mTargetTiles[idx].SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.5f, 0.f, 0.5f));
102   mTargetTiles[idx].SetProperty(Actor::Property::ORIENTATION, Quaternion(Degree(90.f), Vector3::XAXIS));
103 }
104
105 void CubeTransitionEffect::SetTargetTop(unsigned int idx)
106 {
107   mBoxType[idx] = TOP;
108
109   mBoxes[idx].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f);
110
111   mTargetTiles[idx].SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.5f, 1.f, 0.5f));
112   mTargetTiles[idx].SetProperty(Actor::Property::ORIENTATION, Quaternion(Degree(-90.f), Vector3::XAXIS));
113 }
114
115 void CubeTransitionEffect::OnRelayout(const Vector2& size, RelayoutContainer& container)
116 {
117   mTileSize = Vector2(size.x / mColumns, size.y / mRows);
118
119   mBoxRoot.SetProperty(Actor::Property::SIZE_WIDTH, size.x);
120   mBoxRoot.SetProperty(Actor::Property::SIZE_HEIGHT, size.y);
121   mBoxRoot.SetProperty(Actor::Property::SIZE_DEPTH, 1.0f);
122
123   for(size_t i = 0; i < mBoxes.size(); ++i)
124   {
125     mBoxes[i].SetProperty(Actor::Property::SIZE_WIDTH, mTileSize.x);
126     mBoxes[i].SetProperty(Actor::Property::SIZE_HEIGHT, mTileSize.y);
127
128     switch(mBoxType[i])
129     {
130       case LEFT:
131       case RIGHT:
132       {
133         mBoxes[i].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.x * 0.5f);
134         mBoxes[i].SetProperty(Actor::Property::SIZE_DEPTH, mTileSize.x);
135         break;
136       }
137       case BOTTOM:
138       case TOP:
139       {
140         mBoxes[i].SetProperty(Actor::Property::PARENT_ORIGIN_Z, 1.0f - mTileSize.y * 0.5f);
141         mBoxes[i].SetProperty(Actor::Property::SIZE_DEPTH, mTileSize.y);
142         break;
143       }
144     }
145   }
146
147   for(ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it)
148   {
149     it->SetProperty(Actor::Property::SIZE_WIDTH, mTileSize.x);
150     it->SetProperty(Actor::Property::SIZE_HEIGHT, mTileSize.y);
151   }
152   for(ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it)
153   {
154     it->SetProperty(Actor::Property::SIZE_WIDTH, mTileSize.x);
155     it->SetProperty(Actor::Property::SIZE_HEIGHT, mTileSize.y);
156   }
157 }
158
159 void CubeTransitionEffect::Initialize()
160 {
161   Self().RegisterProperty("uTextureRect", Vector4(0.0f, 0.0f, 1.0f, 1.0f));
162
163   mBoxType.Resize(mColumns * mRows);
164
165   //create the box parents
166   mBoxRoot = Actor::New();
167   mBoxRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
168   mBoxRoot.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
169
170   mCurrentTiles.clear();
171   mTargetTiles.clear();
172
173   mCurrentTiles.reserve(mColumns * mRows);
174   mTargetTiles.reserve(mColumns * mRows);
175
176   Vector2 gridSizeInv(1.0f / mColumns, 1.0f / mRows);
177   Vector3 offset(0.5f * gridSizeInv.x, 0.5f * gridSizeInv.y, 0.0f);
178
179   Vector3 anchor;
180   for(unsigned int y = 0; y < mRows; ++y, anchor.y += 1.0f / mRows)
181   {
182     anchor.x = 0.0f;
183     for(unsigned int x = 0; x < mColumns; ++x, anchor.x += 1.0f / mColumns)
184     {
185       Vector4 textureRect(anchor.x, anchor.y, anchor.x + gridSizeInv.x, anchor.y + gridSizeInv.y);
186
187       Actor currentTile = CreateTile(textureRect);
188       currentTile.SetProperty(Actor::Property::COLOR, FULL_BRIGHTNESS);
189       currentTile.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
190       mCurrentTiles.push_back(currentTile);
191
192       Actor targetTile = CreateTile(textureRect);
193       targetTile.SetProperty(Actor::Property::COLOR, HALF_BRIGHTNESS);
194       mTargetTiles.push_back(targetTile);
195
196       Actor box = Actor::New();
197       box.SetProperty(Actor::Property::PARENT_ORIGIN, anchor + offset);
198       box.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
199
200       box.Add(currentTile);
201       box.Add(targetTile);
202
203       mBoxRoot.Add(box);
204
205       mBoxes.push_back(box);
206     }
207   }
208
209   OnInitialize();
210 }
211
212 void CubeTransitionEffect::OnSceneConnection(int depth)
213 {
214   Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
215   Shader   shader   = Shader::New(SHADER_CUBE_TRANSITION_EFFECT_VERT, SHADER_CUBE_TRANSITION_EFFECT_FRAG);
216
217   TextureSet textureSet = TextureSet::New();
218
219   if(mCurrentTexture)
220   {
221     textureSet.SetTexture(0u, mCurrentTexture);
222   }
223   mCurrentRenderer = Renderer::New(geometry, shader);
224   mCurrentRenderer.SetTextures(textureSet);
225
226   mCurrentRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, depth);
227   Self().AddRenderer(mCurrentRenderer);
228
229   Control::OnSceneConnection(depth);
230 }
231
232 void CubeTransitionEffect::OnSceneDisconnection()
233 {
234   if(mCurrentRenderer)
235   {
236     Self().RemoveRenderer(mCurrentRenderer);
237
238     for(ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it)
239     {
240       it->RemoveRenderer(mCurrentRenderer);
241     }
242     mCurrentRenderer.Reset();
243   }
244
245   if(mTargetRenderer)
246   {
247     for(ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it)
248     {
249       it->RemoveRenderer(mTargetRenderer);
250     }
251     mTargetRenderer.Reset();
252   }
253
254   Control::OnSceneDisconnection();
255 }
256
257 void CubeTransitionEffect::SetTransitionDuration(float duration)
258 {
259   mAnimationDuration = duration;
260 }
261
262 float CubeTransitionEffect::GetTransitionDuration() const
263 {
264   return mAnimationDuration;
265 }
266
267 void CubeTransitionEffect::SetCubeDisplacement(float displacement)
268 {
269   mCubeDisplacement = displacement;
270 }
271
272 float CubeTransitionEffect::GetCubeDisplacement() const
273 {
274   return mCubeDisplacement;
275 }
276
277 bool CubeTransitionEffect::IsTransitioning()
278 {
279   return mIsAnimating;
280 }
281
282 void CubeTransitionEffect::SetCurrentTexture(Texture texture)
283 {
284   mCurrentTexture = texture;
285
286   if(mCurrentRenderer)
287   {
288     TextureSet textureSet = mCurrentRenderer.GetTextures();
289     textureSet.SetTexture(0u, mCurrentTexture);
290   }
291 }
292
293 void CubeTransitionEffect::SetTargetTexture(Texture texture)
294 {
295   mTargetTexture = texture;
296
297   if(mTargetRenderer)
298   {
299     TextureSet textureSet = mTargetRenderer.GetTextures();
300     textureSet.SetTexture(0u, mTargetTexture);
301   }
302 }
303
304 void CubeTransitionEffect::StartTransition(bool toNextImage)
305 {
306   Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
307   if(toNextImage)
308   {
309     StartTransition(Vector2(size.x * 0.5f, size.y * 0.5f), Vector2(-10.f, 0.f));
310   }
311   else
312   {
313     StartTransition(Vector2(size.x * 0.5f, size.y * 0.5f), Vector2(10.f, 0.f));
314   }
315 }
316
317 void CubeTransitionEffect::StartTransition(Vector2 panPosition, Vector2 panDisplacement)
318 {
319   if(!mCurrentRenderer)
320   {
321     DALI_LOG_ERROR("Trying to transition a cube transition without an image set\n");
322     return;
323   }
324
325   //create the target renderer
326   TextureSet textureSet = TextureSet::New();
327   if(mTargetTexture)
328   {
329     textureSet.SetTexture(0u, mTargetTexture);
330   }
331   Geometry geometry = mCurrentRenderer.GetGeometry();
332   Shader   shader(mCurrentRenderer.GetShader());
333   mTargetRenderer = Renderer::New(geometry, shader);
334   mTargetRenderer.SetTextures(textureSet);
335
336   int depthIndex = mCurrentRenderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX);
337   mTargetRenderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, depthIndex);
338
339   for(size_t i = 0; i < mBoxes.size(); ++i)
340   {
341     mBoxes[i].SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(0.0f), Vector3::XAXIS));
342   }
343
344   for(ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it)
345   {
346     it->SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.5f, 0.5f, 1.0f));
347     it->SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(0.0f), Vector3::XAXIS));
348     it->AddRenderer(mCurrentRenderer);
349   }
350   for(ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it)
351   {
352     it->AddRenderer(mTargetRenderer);
353   }
354
355   Self().RemoveRenderer(mCurrentRenderer);
356   Self().Add(mBoxRoot);
357
358   if(mAnimation)
359   {
360     mAnimation.Clear();
361     mAnimation.Reset();
362   }
363
364   mAnimation = Animation::New(mAnimationDuration);
365   mAnimation.FinishedSignal().Connect(this, &CubeTransitionEffect::OnTransitionFinished);
366
367   OnStartTransition(panPosition, panDisplacement);
368 }
369
370 void CubeTransitionEffect::PauseTransition()
371 {
372   if(mIsAnimating && !mIsPaused)
373   {
374     mAnimation.Pause();
375     mIsPaused = true;
376   }
377 }
378
379 void CubeTransitionEffect::ResumeTransition()
380 {
381   if(mIsAnimating && mIsPaused)
382   {
383     mAnimation.Play();
384     mIsPaused = false;
385   }
386 }
387
388 void CubeTransitionEffect::StopTransition()
389 {
390   ResetToInitialState();
391 }
392
393 void CubeTransitionEffect::ResetToInitialState()
394 {
395   mAnimation.Clear();
396   mAnimation.Reset();
397   mIsAnimating = false;
398
399   Self().Remove(mBoxRoot);
400
401   for(size_t i = 0; i < mBoxes.size(); ++i)
402   {
403     mBoxes[i].SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(0.0f), Vector3::XAXIS));
404   }
405
406   for(ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it)
407   {
408     it->SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.5f, 0.5f, 1.0f));
409     it->SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(0.0f), Vector3::XAXIS));
410     it->SetProperty(Actor::Property::COLOR, FULL_BRIGHTNESS);
411   }
412   if(mCurrentRenderer)
413   {
414     for(ActorArray::iterator it = mCurrentTiles.begin(); it != mCurrentTiles.end(); ++it)
415     {
416       it->RemoveRenderer(mCurrentRenderer);
417     }
418     Self().AddRenderer(mCurrentRenderer);
419   }
420
421   for(ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it)
422   {
423     it->SetProperty(Actor::Property::COLOR, HALF_BRIGHTNESS);
424   }
425   if(mTargetRenderer)
426   {
427     for(ActorArray::iterator it = mTargetTiles.begin(); it != mTargetTiles.end(); ++it)
428     {
429       it->RemoveRenderer(mTargetRenderer);
430     }
431   }
432 }
433
434 void CubeTransitionEffect::OnTransitionFinished(Animation& source)
435 {
436   std::swap(mCurrentTiles, mTargetTiles);
437   std::swap(mCurrentRenderer, mTargetRenderer);
438   std::swap(mCurrentTexture, mTargetTexture);
439
440   ResetToInitialState();
441
442   //Emit signal
443   Toolkit::CubeTransitionEffect handle(GetOwner());
444   mTransitionCompletedSignal.Emit(handle, mCurrentTexture);
445 }
446
447 Toolkit::CubeTransitionEffect::TransitionCompletedSignalType& CubeTransitionEffect::TransitionCompletedSignal()
448 {
449   return mTransitionCompletedSignal;
450 }
451
452 bool CubeTransitionEffect::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
453 {
454   Dali::BaseHandle handle(object);
455
456   bool                          connected(true);
457   Toolkit::CubeTransitionEffect cubeTransitionEffect = Toolkit::CubeTransitionEffect::DownCast(handle);
458
459   if(0 == strcmp(signalName.c_str(), SIGNAL_TRANSITION_COMPLETED))
460   {
461     cubeTransitionEffect.TransitionCompletedSignal().Connect(tracker, functor);
462   }
463   else
464   {
465     // signalName does not match any signal
466     connected = false;
467   }
468
469   return connected;
470 }
471
472 } // namespace Internal
473
474 } // namespace Toolkit
475
476 } // namespace Dali