Merge "Removing GL usage from dali core" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / events / tap-gesture / tap-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/tap-gesture/tap-gesture-processor.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/internal/event/common/scene-impl.h>
28 #include <dali/internal/event/events/gesture-requests.h>
29 #include <dali/internal/event/events/tap-gesture/tap-gesture-event.h>
30 #include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
31 #include <dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h>
32 #include <dali/internal/event/render-tasks/render-task-impl.h>
33 #include <dali/public-api/actors/actor.h>
34 #include <dali/public-api/common/dali-common.h>
35 #include <dali/public-api/events/tap-gesture.h>
36 #include <dali/public-api/math/vector2.h>
37
38 namespace Dali
39 {
40 namespace Internal
41 {
42 namespace
43 {
44 /**
45  * Creates a TapGesture and asks the specified detector to emit its detected signal.
46  * @param[in]  actor             The actor on which a tap has occurred.
47  * @param[in]  gestureDetectors  A reference to gesture detectors that should emit the signal.
48  * @param[in]  tapEvent          The tapEvent received from the adaptor.
49  * @param[in]  localPoint        Relative to the actor attached to the detector.
50  */
51 void EmitTapSignal(
52   Actor*                          actor,
53   const GestureDetectorContainer& gestureDetectors,
54   const TapGestureEvent&          tapEvent,
55   Vector2                         localPoint)
56 {
57   Internal::TapGesturePtr tap(new Internal::TapGesture(tapEvent.state));
58   tap->SetTime(tapEvent.time);
59   tap->SetNumberOfTaps(tapEvent.numberOfTaps);
60   tap->SetNumberOfTouches(tapEvent.numberOfTouches);
61   tap->SetScreenPoint(tapEvent.point);
62   tap->SetLocalPoint(localPoint);
63   tap->SetGestureSourceType(tapEvent.gestureSourceType);
64
65   Dali::Actor                                    actorHandle(actor);
66   const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
67   for(GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter)
68   {
69     static_cast<TapGestureDetector*>(*iter)->EmitTapGestureSignal(actorHandle, Dali::TapGesture(tap.Get()));
70   }
71 }
72
73 } // unnamed namespace
74
75 TapGestureProcessor::TapGestureProcessor()
76 : GestureProcessor(GestureType::TAP),
77   mTapGestureDetectors(),
78   mMinTapsRequired(1),
79   mMaxTapsRequired(1),
80   mMinTouchesRequired(1),
81   mMaxTouchesRequired(1),
82   mCurrentTapEvent(nullptr),
83   mPossibleProcessed(false)
84 {
85 }
86
87 TapGestureProcessor::~TapGestureProcessor() = default;
88
89 void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent)
90 {
91   switch(tapEvent.state)
92   {
93     case GestureState::POSSIBLE:
94     {
95       // Do a hit test and if an actor has been hit then save to see if tap event is still valid on a tap( same actor being hit )
96       HitTestAlgorithm::Results hitTestResults;
97       if(HitTest(scene, tapEvent.point, hitTestResults))
98       {
99         SetActor(&GetImplementation(hitTestResults.actor));
100         mCurrentTapActor.SetActor(GetCurrentGesturedActor());
101
102         // Indicate that we've processed a touch down. Bool should be sufficient as a change in actor will result in a cancellation
103         mPossibleProcessed = true;
104       }
105       else
106       {
107         ResetActor();
108       }
109       break;
110     }
111
112     case GestureState::STARTED:
113     {
114       // Ensure that we're processing a hit on the current actor and that we've already processed a touch down
115       HitTestAlgorithm::Results hitTestResults;
116       if(GetCurrentGesturedActor() && HitTest(scene, tapEvent.point, hitTestResults) && mPossibleProcessed)
117       {
118         // Check that this actor is still the one that was used for the last touch down ?
119         if(mCurrentTapActor.GetActor() == &GetImplementation(hitTestResults.actor))
120         {
121           mCurrentTapEvent = &tapEvent;
122           ProcessAndEmit(hitTestResults);
123         }
124         mCurrentTapEvent   = nullptr;
125         mPossibleProcessed = false;
126       }
127       break;
128     }
129
130     case GestureState::CANCELLED:
131     {
132       mPossibleProcessed = false;
133       ResetActor();
134       break;
135     }
136
137     case GestureState::CONTINUING:
138     {
139       DALI_ABORT("Incorrect state received from Integration layer: CONTINUING\n");
140       break;
141     }
142     case GestureState::FINISHED:
143     {
144       DALI_ABORT("Incorrect state received from Integration layer: FINISHED\n");
145       break;
146     }
147     case GestureState::CLEAR:
148     {
149       DALI_ABORT("Incorrect state received from Integration layer: CLEAR\n");
150       break;
151     }
152   }
153 }
154
155 void TapGestureProcessor::AddGestureDetector(TapGestureDetector* gestureDetector, Scene& scene)
156 {
157   bool firstRegistration(mTapGestureDetectors.empty());
158
159   mTapGestureDetectors.push_back(gestureDetector);
160
161   const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
162   const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
163   const unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
164
165   DALI_ASSERT_ALWAYS(minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested");
166
167   if(firstRegistration)
168   {
169     // If this is the first tap gesture detector that has been added, then our minimum and maximum
170     // requirements are the same as each other.
171
172     mMinTapsRequired    = minTapsRequired;
173     mMaxTapsRequired    = maxTapsRequired;
174     mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
175
176     TapGestureRequest request;
177     request.minTaps    = mMinTapsRequired;
178     request.maxTaps    = mMaxTapsRequired;
179     request.minTouches = mMinTouchesRequired;
180     request.maxTouches = mMaxTouchesRequired;
181
182     Size size          = scene.GetSize();
183     mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request));
184   }
185   else
186   {
187     // If we have already registered for tap gesture detection before then we need to check our
188     // minimum and maximums and see if our gesture detection requirements have changed, if they
189     // have, then we should ask the adaptor to update its detection policy.
190
191     // This is quicker than calling UpdateDetection as there is no need to iterate through the container
192
193     unsigned int minTaps    = mMinTapsRequired < minTapsRequired ? mMinTapsRequired : minTapsRequired;
194     unsigned int maxTaps    = mMaxTapsRequired > maxTapsRequired ? mMaxTapsRequired : maxTapsRequired;
195     unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
196     unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
197
198     if((minTaps != mMinTapsRequired) || (maxTaps != mMaxTapsRequired) ||
199        (minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
200     {
201       TapGestureRequest request;
202       request.minTaps = mMinTapsRequired = minTaps;
203       request.maxTaps = mMaxTapsRequired = maxTaps;
204       request.minTouches = mMinTouchesRequired = minTouches;
205       request.maxTouches = mMaxTouchesRequired = maxTouches;
206
207       mGestureRecognizer->Update(request);
208     }
209   }
210 }
211
212 void TapGestureProcessor::RemoveGestureDetector(TapGestureDetector* gestureDetector)
213 {
214   // Find detector ...
215   TapGestureDetectorContainer::iterator endIter = std::remove(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector);
216   DALI_ASSERT_DEBUG(endIter != mTapGestureDetectors.end());
217
218   // ... and remove it
219   mTapGestureDetectors.erase(endIter, mTapGestureDetectors.end());
220
221   if(mTapGestureDetectors.empty())
222   {
223     mGestureRecognizer = nullptr;
224
225     ResetActor();
226   }
227   else
228   {
229     UpdateDetection();
230   }
231 }
232
233 void TapGestureProcessor::GestureDetectorUpdated(TapGestureDetector* gestureDetector)
234 {
235   DALI_ASSERT_DEBUG(find(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector) != mTapGestureDetectors.end());
236
237   const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
238   const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
239
240   DALI_ASSERT_ALWAYS(minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested");
241
242   UpdateDetection();
243 }
244
245 void TapGestureProcessor::UpdateDetection()
246 {
247   DALI_ASSERT_DEBUG(!mTapGestureDetectors.empty());
248
249   unsigned int minTaps    = UINT_MAX;
250   unsigned int maxTaps    = 0;
251   unsigned int minTouches = UINT_MAX;
252   unsigned int maxTouches = 0;
253
254   for(TapGestureDetectorContainer::iterator iter = mTapGestureDetectors.begin(), endIter = mTapGestureDetectors.end(); iter != endIter; ++iter)
255   {
256     TapGestureDetector* detector(*iter);
257
258     if(detector)
259     {
260       const unsigned int minTapsRequired = detector->GetMinimumTapsRequired();
261       const unsigned int maxTapsRequired = detector->GetMaximumTapsRequired();
262       const unsigned int touchesRequired = detector->GetTouchesRequired();
263
264       minTaps    = minTapsRequired < minTaps ? minTapsRequired : minTaps;
265       maxTaps    = maxTapsRequired > maxTaps ? maxTapsRequired : maxTaps;
266       minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
267       maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
268     }
269   }
270
271   if((minTaps != mMinTapsRequired) || (maxTaps != mMaxTapsRequired) ||
272      (minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
273   {
274     TapGestureRequest request;
275     request.minTaps = mMinTapsRequired = minTaps;
276     request.maxTaps = mMaxTapsRequired = maxTaps;
277     request.minTouches = mMinTouchesRequired = minTouches;
278     request.maxTouches = mMaxTouchesRequired = maxTouches;
279
280     mGestureRecognizer->Update(request);
281   }
282 }
283
284 bool TapGestureProcessor::CheckGestureDetector(GestureDetector* detector, Actor* actor)
285 {
286   DALI_ASSERT_DEBUG(mCurrentTapEvent);
287
288   TapGestureDetector* tapDetector(static_cast<TapGestureDetector*>(detector));
289
290   return ((tapDetector->GetMinimumTapsRequired() <= mCurrentTapEvent->numberOfTaps) && (tapDetector->GetMaximumTapsRequired() >= mCurrentTapEvent->numberOfTaps)) &&
291          (tapDetector->GetTouchesRequired() == mCurrentTapEvent->numberOfTouches);
292 }
293
294 void TapGestureProcessor::EmitGestureSignal(Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates)
295 {
296   DALI_ASSERT_DEBUG(mCurrentTapEvent);
297
298   EmitTapSignal(actor, gestureDetectors, *mCurrentTapEvent, actorCoordinates);
299 }
300
301 } // namespace Internal
302
303 } // namespace Dali