[dali_2.3.26] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / events / gesture-processor.cpp
1 /*
2  * Copyright (c) 2022 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   bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp, bool isGeometry) override
65   {
66     return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
67   }
68
69   GestureType::Value mType;
70 };
71
72 } // unnamed namespace
73
74 GestureProcessor::GestureProcessor(GestureType::Value type)
75 : mGestureRecognizer(),
76   mNeedsUpdate(false),
77   mType(type),
78   mCurrentGesturedActor(nullptr),
79   mPoint(),
80   mEventTime(0u),
81   mGesturedActorDisconnected(false),
82   mFeededActor(nullptr),
83   mRenderTask(),
84   mGestureDetector(nullptr)
85 {
86 }
87
88 GestureProcessor::~GestureProcessor()
89 {
90   ResetActor();
91 }
92
93 void GestureProcessor::ProcessTouch(Scene& scene, const Integration::TouchEvent& event)
94 {
95   if(mGestureRecognizer)
96   {
97     if(!event.points.empty())
98     {
99       mPoint     = event.points[0];
100       mEventTime = event.time;
101     }
102     mFeededActor = nullptr;
103     mGestureDetector = nullptr;
104     mGestureRecognizer->SendEvent(scene, event);
105   }
106 }
107
108 void GestureProcessor::ProcessTouch(GestureDetector* gestureDetector, Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
109 {
110   if(mGestureRecognizer)
111   {
112     if(!event.points.empty())
113     {
114       mPoint     = event.points[0];
115       mEventTime = event.time;
116     }
117     mGestureDetector = gestureDetector;
118     mFeededActor.SetActor(&actor);
119     mRenderTask = &renderTask;
120     mGestureRecognizer->SendEvent(scene, event);
121   }
122 }
123
124 Actor* GestureProcessor::GetFeededActor()
125 {
126   return mFeededActor.GetActor();
127 }
128
129 GestureDetector* GestureProcessor::GetFeededGestureDetector()
130 {
131   return mGestureDetector;
132 }
133
134 RenderTaskPtr GestureProcessor::GetFeededRenderTask()
135 {
136   return mRenderTask;
137 }
138
139 void GestureProcessor::GetGesturedActor(Actor*& actor, GestureDetectorContainer& gestureDetectors)
140 {
141   while(actor)
142   {
143     // We may be checking a parent so ensure the parent requires this gesture (and do not unintentionally create the gesture data for the parent)
144     if(actor->IsGestureRequired(mType))
145     {
146       // Retrieve the actor's detectors and check if they satisfy current gesture
147       const GestureDetectorContainer&                connectedDetectors(actor->GetGestureData().GetGestureDetectorContainer(mType));
148       const GestureDetectorContainer::const_iterator endIter(connectedDetectors.end());
149       for(GestureDetectorContainer::const_iterator iter = connectedDetectors.begin(); iter != endIter; ++iter)
150       {
151         GestureDetector* current(*iter);
152
153         // Check deriving class for whether the current gesture satisfies the gesture detector's parameters.
154         if(CheckGestureDetector(current, actor))
155         {
156           gestureDetectors.push_back(current);
157         }
158       }
159
160       // The hit actor or one of the parents is a gestured actor, break out.
161       if(!gestureDetectors.empty())
162       {
163         break;
164       }
165     }
166
167     // No match, we should now check the hit actor's parent.
168     actor = actor->GetParent();
169   }
170 }
171
172 void GestureProcessor::ProcessAndEmit(HitTestAlgorithm::Results& hitTestResults)
173 {
174   if(hitTestResults.actor)
175   {
176     Actor*  hitTestActor(&GetImplementation(hitTestResults.actor));
177     Actor*  actor(hitTestActor);
178     RayTest rayTest;
179
180     while(actor)
181     {
182       GestureDetectorContainer gestureDetectors;
183       GetGesturedActor(actor, gestureDetectors);
184
185       if(actor && !gestureDetectors.empty())
186       {
187         // We have a match but check if the hit point is within the gestured actor's bounds.
188         // If it is not then continue up the actor hierarchy.
189
190         if(actor == hitTestActor)
191         {
192           // Our gesture detector's attached actor WAS the hit actor so we can can emit the signal.
193           EmitGestureSignal(actor, gestureDetectors, hitTestResults.actorCoordinates);
194           // If NeedGesturePropagation is true, it passes the gesture to the parent.
195           if(!actor->NeedGesturePropagation())
196           {
197             break; // We have found AND emitted a signal on the gestured actor, break out.
198           }
199           actor->SetNeedGesturePropagation(false);
200         }
201         else
202         {
203           if(actor->IsHittable())
204           {
205             const Vector3 size(actor->GetCurrentSize());
206
207             if((size.x > 0.0f) && (size.y > 0.0f))
208             {
209               // Ensure tap is within the actor's area
210               if(rayTest.SphereTest(*actor, hitTestResults.rayOrigin, hitTestResults.rayDirection)) // Quick check
211               {
212                 Vector2 hitPointLocal;
213                 float   distance(0.0f);
214                 if(rayTest.ActorTest(*actor, hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance))
215                 {
216                   // One of the parents was the gestured actor so we can emit the signal for that actor.
217                   EmitGestureSignal(actor, gestureDetectors, hitPointLocal);
218                   // If NeedGesturePropagation is true, it passes the gesture to the parent.
219                   if(!actor->NeedGesturePropagation())
220                   {
221                     break; // We have found AND emitted a signal on the gestured actor, break out.
222                   }
223                   actor->SetNeedGesturePropagation(false);
224                 }
225               }
226             }
227           }
228         }
229       }
230
231       // Continue up hierarchy to see if any of the parents require this gesture.
232       if(actor)
233       {
234         actor = actor->GetParent();
235       }
236     }
237   }
238 }
239
240 void GestureProcessor::ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults, GestureDetector* gestureDetector)
241 {
242   if(hitTestResults.actor && gestureDetector)
243   {
244     Actor*  actor(&GetImplementation(hitTestResults.actor));
245     GestureDetectorContainer gestureDetectors;
246     // Check deriving class for whether the current gesture satisfies the gesture detector's parameters.
247     if(actor && actor->IsVisible() && gestureDetector && CheckGestureDetector(gestureDetector, actor))
248     {
249       gestureDetectors.push_back(gestureDetector);
250       gestureDetector->SetDetected(true);
251       EmitGestureSignal(actor, gestureDetectors, hitTestResults.actorCoordinates);
252     }
253   }
254 }
255
256 bool GestureProcessor::HitTest(Scene& scene, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults)
257 {
258   GestureHitTestCheck hitCheck(mType);
259   hitTestResults.point     = mPoint;
260   hitTestResults.eventTime = mEventTime;
261   HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), screenCoordinates, hitTestResults, hitCheck);
262   return hitTestResults.renderTask && hitTestResults.actor;
263 }
264
265 void GestureProcessor::SetActor(Actor* actor)
266 {
267   if(actor && actor != mCurrentGesturedActor)
268   {
269     ResetActor();
270
271     mCurrentGesturedActor = actor;
272     mCurrentGesturedActor->AddObserver(*this);
273   }
274   mGesturedActorDisconnected = false;
275 }
276
277 void GestureProcessor::ResetActor()
278 {
279   if(mCurrentGesturedActor)
280   {
281     mCurrentGesturedActor->RemoveObserver(*this);
282     mCurrentGesturedActor      = nullptr;
283     mGesturedActorDisconnected = false;
284   }
285 }
286
287 Actor* GestureProcessor::GetCurrentGesturedActor()
288 {
289   return mGesturedActorDisconnected ? nullptr : mCurrentGesturedActor;
290 }
291
292 void GestureProcessor::SceneObjectRemoved(Object& object)
293 {
294   if(mCurrentGesturedActor == &object &&
295      !mGesturedActorDisconnected)
296   {
297     // Inform deriving classes.
298     OnGesturedActorStageDisconnection();
299
300     // do not call object.RemoveObserver here, object is currently iterating through observers... you wouldnt want to upset object now would you?
301     mGesturedActorDisconnected = true;
302   }
303 }
304
305 void GestureProcessor::ObjectDestroyed(Object& object)
306 {
307   if(mCurrentGesturedActor == &object)
308   {
309     // Inform deriving classes.
310     OnGesturedActorStageDisconnection();
311
312     mCurrentGesturedActor = nullptr;
313   }
314 }
315
316 } // namespace Internal
317
318 } // namespace Dali