[Tizen] Not execute the remove callback
[platform/core/uifw/dali-core.git] / dali / internal / event / events / gesture-processor.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 <dali/internal/event/events/gesture-processor.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/internal/event/actors/actor-impl.h>
24 #include <dali/internal/event/actors/layer-impl.h>
25 #include <dali/internal/event/common/scene-impl.h>
26 #include <dali/internal/event/events/actor-gesture-data.h>
27 #include <dali/internal/event/events/hit-test-algorithm-impl.h>
28 #include <dali/internal/event/events/ray-test.h>
29 #include <dali/internal/event/render-tasks/render-task-impl.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 namespace
36 {
37 /**
38  * Functor to check whether an actor requires a particular gesture or not
39  */
40 struct GestureHitTestCheck : public HitTestAlgorithm::HitTestInterface
41 {
42   GestureHitTestCheck(GestureType::Value type)
43   : mType(type)
44   {
45   }
46
47   bool IsActorHittable(Actor* actor) override
48   {
49     return actor->IsGestureRequired(mType) && // Does the Application or derived actor type require the gesture?
50            actor->IsHittable();               // Is actor sensitive, visible and on the scene?
51   }
52
53   bool DescendActorHierarchy(Actor* actor) override
54   {
55     return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
56            actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
57   }
58
59   bool DoesLayerConsumeHit(Layer* layer) override
60   {
61     return layer->IsTouchConsumed();
62   }
63
64   GestureType::Value mType;
65 };
66
67 } // unnamed namespace
68
69 GestureProcessor::GestureProcessor(GestureType::Value type)
70 : mGestureRecognizer(),
71   mNeedsUpdate(false),
72   mType(type),
73   mCurrentGesturedActor(nullptr),
74   mGesturedActorDisconnected(false)
75 {
76 }
77
78 GestureProcessor::~GestureProcessor()
79 {
80   ResetActor();
81 }
82
83 void GestureProcessor::ProcessTouch(Scene& scene, const Integration::TouchEvent& event)
84 {
85   if(mGestureRecognizer)
86   {
87     mGestureRecognizer->SendEvent(scene, event);
88   }
89 }
90
91 void GestureProcessor::GetGesturedActor(Actor*& actor, GestureDetectorContainer& gestureDetectors)
92 {
93   while(actor)
94   {
95     // We may be checking a parent so ensure the parent requires this gesture (and do not unintentionally create the gesture data for the parent)
96     if(actor->IsGestureRequired(mType))
97     {
98       // Retrieve the actor's detectors and check if they satisfy current gesture
99       const GestureDetectorContainer&                connectedDetectors(actor->GetGestureData().GetGestureDetectorContainer(mType));
100       const GestureDetectorContainer::const_iterator endIter(connectedDetectors.end());
101       for(GestureDetectorContainer::const_iterator iter = connectedDetectors.begin(); iter != endIter; ++iter)
102       {
103         GestureDetector* current(*iter);
104
105         // Check deriving class for whether the current gesture satisfies the gesture detector's parameters.
106         if(CheckGestureDetector(current, actor))
107         {
108           gestureDetectors.push_back(current);
109         }
110       }
111
112       // The hit actor or one of the parents is a gestured actor, break out.
113       if(!gestureDetectors.empty())
114       {
115         break;
116       }
117     }
118
119     // No match, we should now check the hit actor's parent.
120     actor = actor->GetParent();
121   }
122 }
123
124 void GestureProcessor::ProcessAndEmit(HitTestAlgorithm::Results& hitTestResults)
125 {
126   if(hitTestResults.actor)
127   {
128     Actor*  hitTestActor(&GetImplementation(hitTestResults.actor));
129     Actor*  actor(hitTestActor);
130     RayTest rayTest;
131
132     while(actor)
133     {
134       GestureDetectorContainer gestureDetectors;
135       GetGesturedActor(actor, gestureDetectors);
136
137       if(actor && !gestureDetectors.empty())
138       {
139         // We have a match but check if the hit point is within the gestured actor's bounds.
140         // If it is not then continue up the actor hierarchy.
141
142         if(actor == hitTestActor)
143         {
144           // Our gesture detector's attached actor WAS the hit actor so we can can emit the signal.
145           EmitGestureSignal(actor, gestureDetectors, hitTestResults.actorCoordinates);
146           // If NeedGesturePropagation is true, it passes the gesture to the parent.
147           if(!actor->NeedGesturePropagation())
148           {
149             break; // We have found AND emitted a signal on the gestured actor, break out.
150           }
151           actor->SetNeedGesturePropagation(false);
152         }
153         else
154         {
155           if(actor->IsHittable())
156           {
157             const Vector3 size(actor->GetCurrentSize());
158
159             if((size.x > 0.0f) && (size.y > 0.0f))
160             {
161               // Ensure tap is within the actor's area
162               if(rayTest.SphereTest(*actor, hitTestResults.rayOrigin, hitTestResults.rayDirection)) // Quick check
163               {
164                 Vector2 hitPointLocal;
165                 float   distance(0.0f);
166                 if(rayTest.ActorTest(*actor, hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance))
167                 {
168                   // One of the parents was the gestured actor so we can emit the signal for that actor.
169                   EmitGestureSignal(actor, gestureDetectors, hitPointLocal);
170                   // If NeedGesturePropagation is true, it passes the gesture to the parent.
171                   if(!actor->NeedGesturePropagation())
172                   {
173                     break; // We have found AND emitted a signal on the gestured actor, break out.
174                   }
175                   actor->SetNeedGesturePropagation(false);
176                 }
177               }
178             }
179           }
180         }
181       }
182
183       // Continue up hierarchy to see if any of the parents require this gesture.
184       if(actor)
185       {
186         actor = actor->GetParent();
187       }
188     }
189   }
190 }
191
192 bool GestureProcessor::HitTest(Scene& scene, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults)
193 {
194   GestureHitTestCheck hitCheck(mType);
195   HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), screenCoordinates, hitTestResults, hitCheck);
196   return hitTestResults.renderTask && hitTestResults.actor;
197 }
198
199 void GestureProcessor::SetActor(Actor* actor)
200 {
201   if(actor && actor != mCurrentGesturedActor)
202   {
203     ResetActor();
204
205     mCurrentGesturedActor = actor;
206     mCurrentGesturedActor->AddObserver(*this);
207   }
208   mGesturedActorDisconnected = false;
209 }
210
211 void GestureProcessor::ResetActor()
212 {
213   if(mCurrentGesturedActor)
214   {
215     mCurrentGesturedActor->RemoveObserver(*this);
216     mCurrentGesturedActor      = nullptr;
217     mGesturedActorDisconnected = false;
218   }
219 }
220
221 Actor* GestureProcessor::GetCurrentGesturedActor()
222 {
223   return mGesturedActorDisconnected ? nullptr : mCurrentGesturedActor;
224 }
225
226 void GestureProcessor::SceneObjectRemoved(Object& object)
227 {
228   if(mCurrentGesturedActor == &object &&
229      !mGesturedActorDisconnected)
230   {
231     // Inform deriving classes.
232     OnGesturedActorStageDisconnection();
233
234     // do not call object.RemoveObserver here, object is currently iterating through observers... you wouldnt want to upset object now would you?
235     mGesturedActorDisconnected = true;
236   }
237 }
238
239 void GestureProcessor::ObjectDestroyed(Object& object)
240 {
241   if(mCurrentGesturedActor == &object)
242   {
243     // Inform deriving classes.
244     OnGesturedActorStageDisconnection();
245
246     mCurrentGesturedActor = nullptr;
247   }
248 }
249
250 } // namespace Internal
251
252 } // namespace Dali