Add trace log for touch, wheel and gesture
[platform/core/uifw/dali-core.git] / dali / internal / event / events / rotation-gesture / rotation-gesture-processor.cpp
1 /*
2  * Copyright (c) 2023 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/rotation-gesture/rotation-gesture-processor.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/trace.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/rotation-gesture/rotation-gesture-event.h>
30 #include <dali/internal/event/events/rotation-gesture/rotation-gesture-impl.h>
31 #include <dali/internal/event/events/rotation-gesture/rotation-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/events/rotation-gesture.h>
35 #include <dali/public-api/math/vector2.h>
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace
42 {
43 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
44 const uint32_t MINIMUM_TOUCH_EVENTS_REQUIRED             = 4u;
45 const uint32_t MINIMUM_TOUCH_EVENTS_REQUIRED_AFTER_START = 4u;
46
47 /**
48  * Creates a RotationGesture and asks the specified detector to emit its detected signal.
49  * @param[in]  actor             The actor that has been rotationed.
50  * @param[in]  gestureDetectors  The gesture detector container that should emit the signal.
51  * @param[in]  rotationEvent        The rotationEvent received from the adaptor.
52  * @param[in]  localCenter       Relative to the actor attached to the detector.
53  */
54 void EmitRotationSignal(
55   Actor*                          actor,
56   const GestureDetectorContainer& gestureDetectors,
57   const RotationGestureEvent&     rotationEvent,
58   Vector2                         localCenter)
59 {
60   Internal::RotationGesturePtr rotation(new Internal::RotationGesture(rotationEvent.state));
61   rotation->SetTime(rotationEvent.time);
62   rotation->SetRotation(rotationEvent.rotation);
63   rotation->SetScreenCenterPoint(rotationEvent.centerPoint);
64   rotation->SetLocalCenterPoint(localCenter);
65   rotation->SetSourceType(rotationEvent.sourceType);
66   rotation->SetSourceData(rotationEvent.sourceData);
67
68   Dali::Actor                                    actorHandle(actor);
69   const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
70   for(GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter)
71   {
72     static_cast<RotationGestureDetector*>(*iter)->EmitRotationGestureSignal(actorHandle, Dali::RotationGesture(rotation.Get()));
73   }
74 }
75
76 /**
77  * Functor which checks whether the specified actor is attached to the gesture detector.
78  * It returns true if it is no longer attached.  This can be used in remove_if functions.
79  */
80 struct IsNotAttachedFunctor
81 {
82   /**
83    * Constructor
84    * @param[in]  actor  The actor to check whether it is attached.
85    */
86   IsNotAttachedFunctor(Actor* actor)
87   : actorToCheck(actor)
88   {
89   }
90
91   /**
92    * Returns true if not attached, false if it is still attached.
93    * @param[in]  detector  The detector to check.
94    * @return true, if not attached, false otherwise.
95    */
96   bool operator()(const GestureDetector* detector) const
97   {
98     return !detector->IsAttached(*actorToCheck);
99   }
100
101   Actor* actorToCheck; ///< The actor to check whether it is attached or not.
102 };
103
104 } // unnamed namespace
105
106 RotationGestureProcessor::RotationGestureProcessor()
107 : GestureProcessor(GestureType::ROTATION),
108   mRotationGestureDetectors(),
109   mCurrentRotationEmitters(),
110   mCurrentRotationEvent(nullptr),
111   mMinimumTouchEvents(MINIMUM_TOUCH_EVENTS_REQUIRED),
112   mMinimumTouchEventsAfterStart(MINIMUM_TOUCH_EVENTS_REQUIRED_AFTER_START)
113 {
114 }
115
116 void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent& rotationEvent)
117 {
118   DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_ROTATION_GESTURE");
119   switch(rotationEvent.state)
120   {
121     case GestureState::STARTED:
122     {
123       // The rotation gesture should only be sent to the gesture detector which first received it so that
124       // it can be told when the gesture ends as well.
125
126       mCurrentRotationEmitters.clear();
127       ResetActor();
128
129       HitTestAlgorithm::Results hitTestResults;
130       if(HitTest(scene, rotationEvent.centerPoint, hitTestResults))
131       {
132         // Record the current render-task for Screen->Actor coordinate conversions
133         mCurrentRenderTask = hitTestResults.renderTask;
134
135         // Set mCurrentRotationEvent to use inside overridden methods called from ProcessAndEmit()
136         mCurrentRotationEvent = &rotationEvent;
137         ProcessAndEmit(hitTestResults);
138         mCurrentRotationEvent = nullptr;
139       }
140       break;
141     }
142
143     case GestureState::CONTINUING:
144     case GestureState::FINISHED:
145     case GestureState::CANCELLED:
146     {
147       // Only send subsequent rotation gesture signals if we processed the rotation gesture when it started.
148       // Check if actor is still touchable.
149
150       Actor* currentGesturedActor = GetCurrentGesturedActor();
151       if(currentGesturedActor)
152       {
153         if(currentGesturedActor->IsHittable() && !mCurrentRotationEmitters.empty() && mCurrentRenderTask)
154         {
155           // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
156           GestureDetectorContainer::iterator endIter = std::remove_if(mCurrentRotationEmitters.begin(), mCurrentRotationEmitters.end(), IsNotAttachedFunctor(currentGesturedActor));
157           mCurrentRotationEmitters.erase(endIter, mCurrentRotationEmitters.end());
158
159           if(!mCurrentRotationEmitters.empty())
160           {
161             Vector2     actorCoords;
162             RenderTask& renderTaskImpl(*mCurrentRenderTask.Get());
163             currentGesturedActor->ScreenToLocal(renderTaskImpl, actorCoords.x, actorCoords.y, rotationEvent.centerPoint.x, rotationEvent.centerPoint.y);
164
165             EmitRotationSignal(currentGesturedActor, mCurrentRotationEmitters, rotationEvent, actorCoords);
166           }
167           else
168           {
169             // If we have no current emitters then clear rotated actor as well.
170             ResetActor();
171           }
172
173           // Clear current emitters if rotation gesture has ended or been cancelled.
174           if(rotationEvent.state == GestureState::FINISHED || rotationEvent.state == GestureState::CANCELLED)
175           {
176             mCurrentRotationEmitters.clear();
177             ResetActor();
178           }
179         }
180         else
181         {
182           mCurrentRotationEmitters.clear();
183           ResetActor();
184         }
185       }
186       break;
187     }
188
189     case GestureState::CLEAR:
190     case GestureState::POSSIBLE:
191     {
192       // Nothing to do
193       break;
194     }
195   }
196 }
197
198 void RotationGestureProcessor::AddGestureDetector(RotationGestureDetector* gestureDetector, Scene& /* scene */)
199 {
200   bool createRecognizer(mRotationGestureDetectors.empty());
201
202   mRotationGestureDetectors.push_back(gestureDetector);
203
204   if(createRecognizer)
205   {
206     mGestureRecognizer = new RotationGestureRecognizer(*this, mMinimumTouchEvents, mMinimumTouchEventsAfterStart);
207   }
208 }
209
210 void RotationGestureProcessor::RemoveGestureDetector(RotationGestureDetector* gestureDetector)
211 {
212   if(!mCurrentRotationEmitters.empty())
213   {
214     // Check if the removed detector was one that is currently being rotated and remove it from emitters.
215     GestureDetectorContainer::iterator endIter = std::remove(mCurrentRotationEmitters.begin(), mCurrentRotationEmitters.end(), gestureDetector);
216     mCurrentRotationEmitters.erase(endIter, mCurrentRotationEmitters.end());
217
218     // If we no longer have any emitters, then we should clear mCurrentGesturedActor as well
219     if(mCurrentRotationEmitters.empty())
220     {
221       ResetActor();
222     }
223   }
224
225   // Find the detector...
226   RotationGestureDetectorContainer::iterator endIter = std::remove(mRotationGestureDetectors.begin(), mRotationGestureDetectors.end(), gestureDetector);
227   DALI_ASSERT_DEBUG(endIter != mRotationGestureDetectors.end());
228
229   // ...and remove it
230   mRotationGestureDetectors.erase(endIter, mRotationGestureDetectors.end());
231
232   if(mRotationGestureDetectors.empty())
233   {
234     mGestureRecognizer = nullptr;
235   }
236 }
237
238 void RotationGestureProcessor::SetMinimumTouchEvents(uint32_t value)
239 {
240   if(value > 1u && mMinimumTouchEvents != value)
241   {
242     mMinimumTouchEvents = value;
243
244     if(mGestureRecognizer)
245     {
246       RotationGestureRecognizer* rotationRecognizer = dynamic_cast<RotationGestureRecognizer*>(mGestureRecognizer.Get());
247       if(rotationRecognizer)
248       {
249         rotationRecognizer->SetMinimumTouchEvents(value);
250       }
251     }
252   }
253 }
254
255 void RotationGestureProcessor::SetMinimumTouchEventsAfterStart(uint32_t value)
256 {
257   if(value > 1u && mMinimumTouchEventsAfterStart != value)
258   {
259     mMinimumTouchEventsAfterStart = value;
260
261     if(mGestureRecognizer)
262     {
263       RotationGestureRecognizer* rotationRecognizer = dynamic_cast<RotationGestureRecognizer*>(mGestureRecognizer.Get());
264       if(rotationRecognizer)
265       {
266         rotationRecognizer->SetMinimumTouchEventsAfterStart(value);
267       }
268     }
269   }
270 }
271
272 void RotationGestureProcessor::OnGesturedActorStageDisconnection()
273 {
274   mCurrentRotationEmitters.clear();
275 }
276
277 bool RotationGestureProcessor::CheckGestureDetector(GestureDetector* detector, Actor* actor)
278 {
279   // No special case required for rotation.
280   return true;
281 }
282
283 void RotationGestureProcessor::EmitGestureSignal(Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates)
284 {
285   DALI_ASSERT_DEBUG(mCurrentRotationEvent);
286
287   EmitRotationSignal(actor, gestureDetectors, *mCurrentRotationEvent, actorCoordinates);
288
289   if(actor->OnScene())
290   {
291     mCurrentRotationEmitters = gestureDetectors;
292     SetActor(actor);
293   }
294 }
295
296 } // namespace Internal
297
298 } // namespace Dali