[dali_2.3.26] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / update / gestures / scene-graph-pan-gesture.h
1 #ifndef DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H
2 #define DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/devel-api/threading/mutex.h>
23 #include <dali/internal/event/events/pan-gesture/pan-gesture-impl.h>
24 #include <dali/internal/update/common/property-owner.h>
25 #include <dali/internal/update/gestures/gesture-properties.h>
26 #include <dali/public-api/common/vector-wrapper.h>
27
28 namespace Dali
29 {
30 class PanGesture;
31
32 namespace Internal
33 {
34 struct PanGestureProfiling;
35
36 namespace SceneGraph
37 {
38 /**
39  * The latest pan gesture information is stored in this scene object.
40  */
41 class PanGesture : public PropertyOwner
42 {
43 public:
44   enum PredictionMode
45   {
46     PREDICTION_NONE = 0,
47     PREDICTION_1,
48     PREDICTION_2,
49   };
50
51   enum SmoothingMode
52   {
53     SMOOTHING_NONE,       // No smoothing.
54     SMOOTHING_LAST_VALUE, // Smooth between last value and latest value.
55     SMOOTHING_MULTI_TAP,  // Uses multitap smoothing, only available with Prediction mode 2.
56   };
57
58   static const PredictionMode DEFAULT_PREDICTION_MODE;
59   static const int            NUM_PREDICTION_MODES;
60
61   static const SmoothingMode DEFAULT_SMOOTHING_MODE;
62   static const int           NUM_SMOOTHING_MODES;
63
64   // Latest Pan Information
65
66   /**
67    * Only stores the information we actually require from Dali::PanGesture
68    */
69   struct PanInfo
70   {
71     /**
72      * Stores the velocity, displacement and position.
73      */
74     struct Info
75     {
76       Info() = default;
77
78       /**
79        * Copy constructor
80        */
81       Info(const Info& rhs) = default;
82
83       /**
84        * Assignment operator
85        */
86       Info& operator=(const Info& rhs)
87       {
88         if(this != &rhs)
89         {
90           velocity     = rhs.velocity;
91           displacement = rhs.displacement;
92           position     = rhs.position;
93         }
94
95         return *this;
96       }
97
98       // Data
99
100       Vector2 velocity;
101       Vector2 displacement;
102       Vector2 position;
103     };
104
105     /**
106      * Constructor
107      */
108     PanInfo()
109     : time(0u),
110       state(GestureState::CLEAR),
111       read(true)
112     {
113     }
114
115     /**
116      * Copy constructor
117      */
118     PanInfo(const PanInfo& rhs)
119     : time(rhs.time),
120       state(rhs.state),
121       local(rhs.local),
122       screen(rhs.screen),
123       read(true)
124     {
125     }
126
127     /**
128      * Assignment operator
129      */
130     PanInfo& operator=(const PanInfo& rhs)
131     {
132       if(this != &rhs)
133       {
134         time   = rhs.time;
135         state  = rhs.state;
136         local  = rhs.local;
137         screen = rhs.screen;
138         read   = rhs.read;
139       }
140
141       return *this;
142     }
143
144     /**
145      * Assignment operator
146      * @param[in] gesture A Dali::Gesture
147      */
148     PanInfo& operator=(const Internal::PanGesture& rhs)
149     {
150       time  = rhs.GetTime();
151       state = rhs.GetState();
152
153       local.velocity     = rhs.GetVelocity();
154       local.displacement = rhs.GetDisplacement();
155       local.position     = rhs.GetPosition();
156
157       screen.velocity     = rhs.GetScreenVelocity();
158       screen.displacement = rhs.GetScreenDisplacement();
159       screen.position     = rhs.GetScreenPosition();
160
161       return *this;
162     }
163
164     // Data
165     unsigned int  time;
166     GestureState  state;
167     Info          local;
168     Info          screen;
169     volatile bool read;
170   };
171
172   using PanInfoHistory          = std::vector<PanInfo>;
173   using PanInfoHistoryIter      = PanInfoHistory::iterator;
174   using PanInfoHistoryConstIter = PanInfoHistory::const_iterator;
175
176 private:
177   static const unsigned int PAN_GESTURE_HISTORY = 30u;
178
179 public:
180   /**
181    * Create a new PanGesture
182    */
183   static PanGesture* New();
184
185   /**
186    * Virtual destructor
187    */
188   ~PanGesture() override;
189
190   /**
191    * Adds a PanGesture to the internal circular-buffer waiting to be handled by UpdateProperties.
192    * @param[in]  gesture  The latest pan gesture.
193    */
194   void AddGesture(const Internal::PanGesture& gesture);
195
196   /**
197    * @brief Removes pan events from the history that are older than maxAge, leaving at least minEvents
198    *
199    * @param[in] panHistory The pan event history container
200    * @param[in] currentTime The current frame time
201    * @param[in] maxAge Maximum age of an event before removing (in millis)
202    * @param[in] minEvents The minimum number of events to leave in history, oldest events are removed before newest
203    */
204   void RemoveOldHistory(PanInfoHistory& panHistory, unsigned int currentTime, unsigned int maxAge, unsigned int minEvents);
205
206   /**
207    * Uses elapsed time and time stamps
208    */
209   void PredictionMode1(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistory& panHistory, unsigned int lastVSyncTime, unsigned int nextVSyncTime);
210
211   /**
212    * Blends two points together.
213    * The blend value ranges are:
214    * 0.0f = use 100% of current value.
215    * 1.0f = use half-way average of current and last value.
216    *
217    * @param[in,out] gesture     Pass in current gesture, outputs result of blend.
218    * @param[in]     lastGesture Pass in gesture to blend between.
219    */
220   void BlendPoints(PanInfo& gesture, PanInfo& lastGesture, float blendValue);
221
222   /**
223    * Called by the update manager so that we can update the value of our properties.
224    * @param[in]  nextRenderTime  The estimated time of the next render (in milliseconds).
225    * @return true, if properties were updated.
226    */
227   bool UpdateProperties(unsigned int lastRenderTime, unsigned int nextRenderTime);
228
229   /**
230    * Retrieves a reference to the panning flag property.
231    * @return The panning flag property.
232    */
233   const GesturePropertyBool& GetPanningProperty() const;
234
235   /**
236    * Retrieves a reference to the screen position property.
237    * @return The screen position property.
238    */
239   const GesturePropertyVector2& GetScreenPositionProperty() const;
240
241   /**
242    * Retrieves a reference to the screen velocity property.
243    * @return The screen velocity property.
244    */
245   const GesturePropertyVector2& GetScreenVelocityProperty() const;
246
247   /**
248    * Retrieves a reference to the screen displacement property.
249    * @return The screen displacement property.
250    */
251   const GesturePropertyVector2& GetScreenDisplacementProperty() const;
252
253   /**
254    * Retrieves a reference to the local position property.
255    * @return The local position property.
256    */
257   const GesturePropertyVector2& GetLocalPositionProperty() const;
258
259   /**
260    * Retrieves a reference to the local displacement property.
261    * @return The local displacement property.
262    */
263   const GesturePropertyVector2& GetLocalDisplacementProperty() const;
264
265   /**
266    * Retrieves a reference to the local velocity property.
267    * @return The local velocity property.
268    */
269   const GesturePropertyVector2& GetLocalVelocityProperty() const;
270
271   /**
272    * @brief Sets the prediction mode of the pan gesture
273    *
274    * @param[in] mode The prediction mode
275    */
276   void SetPredictionMode(PredictionMode mode);
277
278   /**
279    * @brief Sets the prediction amount of the pan gesture
280    *
281    * @param[in] amount The prediction amount in milliseconds
282    */
283   void SetPredictionAmount(unsigned int amount);
284
285   /**
286    * @brief Sets the upper bound of the prediction amount for clamping
287    *
288    * @param[in] amount The prediction amount in milliseconds
289    */
290   void SetMaximumPredictionAmount(unsigned int amount);
291
292   /**
293    * @brief Sets the lower bound of the prediction amount for clamping
294    *
295    * @param[in] amount The prediction amount in milliseconds
296    */
297   void SetMinimumPredictionAmount(unsigned int amount);
298
299   /**
300    * @brief Sets the amount of prediction interpolation to adjust when the pan velocity is changed
301    *
302    * @param[in] amount The prediction amount in milliseconds
303    */
304   void SetPredictionAmountAdjustment(unsigned int amount);
305
306   /**
307    * @brief Sets the prediction mode of the pan gesture
308    *
309    * @param[in] mode The prediction mode
310    */
311   void SetSmoothingMode(SmoothingMode mode);
312
313   /**
314    * @brief Sets the amount of smoothing to apply for the current smoothing mode
315    *
316    * @param[in] amount The amount of smoothing [0.0f,1.0f]
317    */
318   void SetSmoothingAmount(float amount);
319
320   /*
321    * @brief Sets whether to use actual times of the real gesture and frames or not.
322    *
323    * @param[in] value True = use actual times, False = use perfect values
324    */
325   void SetUseActualTimes(bool value);
326
327   /**
328    * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating.
329    *
330    * @param[in] value Time range in ms
331    */
332   void SetInterpolationTimeRange(int value);
333
334   /**
335    * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration.
336    *
337    * @param[in] value True = use scalar prediction only
338    */
339   void SetScalarOnlyPredictionEnabled(bool value);
340
341   /**
342    * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values.
343    *
344    * @param[in] value True = use two point prediction
345    */
346   void SetTwoPointPredictionEnabled(bool value);
347
348   /**
349    * @brief Sets the time in the past to interpolate the second point when using two point interpolation.
350    *
351    * @param[in] value Time in past in ms
352    */
353   void SetTwoPointInterpolatePastTime(int value);
354
355   /**
356    * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity.
357    *
358    * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
359    */
360   void SetTwoPointVelocityBias(float value);
361
362   /**
363    * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration.
364    *
365    * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
366    */
367   void SetTwoPointAccelerationBias(float value);
368
369   /**
370    * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled).
371    *
372    * @param[in] value Time in past in ms
373    */
374   void SetMultitapSmoothingRange(int value);
375
376   /**
377    * Called to provide pan-gesture profiling information.
378    */
379   void EnableProfiling();
380
381   /**
382    * Reset default properties, custom ones not supported due to this being the only object in scene side
383    * @param updateBufferIndex index to use
384    */
385   void ResetDefaultProperties(BufferIndex updateBufferIndex);
386
387 private:
388   /**
389    * Protected constructor.
390    */
391   PanGesture();
392
393   // Undefined
394   PanGesture(const PanGesture&);
395
396 private:
397   // Struct to keep pairs of local and screen data together.
398   // TODO: This can encapsulate some functionality also.
399   using RelativeVectors = struct
400
401   {
402     Vector2 local;
403
404     Vector2 screen;
405   };
406
407   /**
408    * Houses new code to process input events and generate an output point.
409    *
410    * @param[in]  lastVSyncTime The time of the last render (in milliseconds)
411    * @param[in]  nextVSyncTime The estimated time of the next render (in milliseconds)
412    */
413   bool NewAlgorithm(unsigned int lastVSyncTime, unsigned int nextVSyncTime);
414
415   /**
416    * Gets the (absolute) time difference between two times.
417    * This is limited by minimumDelta, so it can be safe to use as a divisor.
418    * This function is wrapped so that the behviour can be overridden to return a "perfect" time difference (overrideDifference).
419    *
420    * @param[in]  timeA The first time to calculate from
421    * @param[in]  timeB The second time to calculate from
422    * @param[in]  minimumDelta The smallest amount the difference can become
423    * @param[in]  overrideDifference The time difference to return if using perfect times
424    */
425   inline float GetDivisibleTimeDifference(int timeA, int timeB, float minimumDelta, float overrideDifference);
426
427   /**
428    * This limits the change currentAcceleration can have over lastAcceleration by the specified changeLimit value.
429    *
430    * @param[in]  currentAcceleration The acceleration to modify
431    * @param[in]  lastAcceleration The acceleration to limit against
432    * @param[in]  changeLimit The maximum change (in either direction)
433    */
434   void LimitAccelerationChange(RelativeVectors& currentAcceleration, RelativeVectors& lastAcceleration, float changeLimit);
435
436   /**
437    * Reads all events received this frame into a linear buffer.
438    * A lock is held while this is done.
439    */
440   unsigned int ReadFrameEvents();
441
442   /**
443    * Converts between input rate and internal rate (typically 60Hz internally).
444    * Also writes to the pan history container.
445    * TODO: Does not need to return the gesture if it is in the history also, but currently it's used.
446    * (if rate conversion does not generate a point there are points still in history, but this can been done with a bool property).
447    *
448    * @param[out] rateConvertedGesture Result gesture for this frame is writen here.
449    * @param[in]  eventsThisFrame Number of events to convert
450    * @param[in]  currentFrameTime Time of the frame we will render to
451    * @param[in]  lastFrameTime Time of the last rendered frame
452    * @param[out] justStarted Set to true if we are now starting a new gesture
453    * @param[out] justFinished Set to true if we are now finishing a gesture
454    */
455   bool InputRateConversion(PanInfo& rateConvertedGesture, unsigned int eventsThisFrame, unsigned int currentFrameTime, unsigned int lastFrameTime, bool& justStarted, bool& justFinished);
456
457   /**
458    * Generates an interpolated point at the specified point in time.
459    *
460    * @param[in]  history of points to use
461    * @param[in]  currentTime Time of the frame we will render to
462    * @param[in]  targetTime Time of the point to generate
463    * @param[in]  range Range of time (each side of target time) to use points from
464    * @param[out] outPoint Generated point
465    * @param[out] acceleration Generated acceleration
466    * @param[in]  outputTimeGranularity Time difference between output point (typically 60Hz)
467    * @param[in]  eraseUnused Set to true to clean up any history not used by the function
468    */
469   bool InterpolatePoint(PanInfoHistory& history, unsigned int currentTime, unsigned int targetTime, unsigned int range, PanInfo& outPoint, RelativeVectors& acceleration, int outputTimeGranularity, bool eraseUnused);
470
471   /**
472    * Predicts a point in the future, based on the supplied point and acceleration.
473    * Other user configuration settings are considered.
474    *
475    * @param[in] startPoint Starting point to use. Position and velocity are taken from here.
476    * @param[in] accelerationToUse The acceleration to use.
477    * @param[out] predictedPoint Generated predicted point
478    * @param[in]  currentFrameTime Time of the frame we will render to
479    * @param[in]  previousFrameTime Time of the last rendered frame
480    * @param[in]  noPreviousData Set to true if we are just starting a gesture
481    */
482   void PredictionMode2(PanInfo& startPoint, RelativeVectors& accelerationToUse, PanInfo& predictedPoint, unsigned int currentFrameTime, unsigned int previousFrameTime, bool noPreviousData);
483
484 private:
485   // Undefined
486   PanGesture& operator=(const PanGesture&);
487
488   // Defines information to be gathered by the gesture reading code.
489   struct FrameGestureInfo
490   {
491     PanGesture::PanInfo frameGesture;
492     float               acceleration;
493     unsigned int        eventsThisFrame;
494     bool                justStarted;
495     bool                justFinished;
496
497     FrameGestureInfo()
498     : acceleration(0.0f),
499       eventsThisFrame(0),
500       justStarted(false),
501       justFinished(false)
502     {
503     }
504   };
505
506   /**
507    * Reads gestures from input, builds history.
508    * @param[out] info Written to with information about gestures read this frame.
509    * @param[in] currentTimestamp The time of this frame.
510    */
511   bool ReadGestures(FrameGestureInfo& info, unsigned int currentTimestamp);
512
513   /**
514    * Reads gestures from input and resamples data, builds history.
515    * @param[out] info Written to with information about gestures read this frame.
516    * @param[in] currentTimestamp The time of this frame.
517    */
518   bool ReadAndResampleGestures(FrameGestureInfo& info, unsigned int currentTimestamp);
519
520 private:
521   // Properties
522   GesturePropertyBool    mPanning;            ///< panning flag
523   GesturePropertyVector2 mScreenPosition;     ///< screenPosition
524   GesturePropertyVector2 mScreenDisplacement; ///< screenDisplacement
525   GesturePropertyVector2 mScreenVelocity;     ///< screenVelocity
526   GesturePropertyVector2 mLocalPosition;      ///< localPosition
527   GesturePropertyVector2 mLocalDisplacement;  ///< localDisplacement
528   GesturePropertyVector2 mLocalVelocity;      ///< localVelocity
529
530   PanInfoHistory  mPanHistory;
531   PanInfoHistory  mPredictionHistory;
532   PanInfo         mGestures[PAN_GESTURE_HISTORY];     ///< Circular buffer storing the 4 most recent gestures.
533   PanInfo         mReadGestures[PAN_GESTURE_HISTORY]; ///< Linear buffer storing the most recent gestures (to reduce read lock time).
534   PanInfo         mLastGesture;                       ///< The last gesture. (last update frame).
535   PanInfo         mTargetGesture;                     ///< The most recent input gesture, if the current used gesture does not match.
536   PanInfo         mLastUnmodifiedGesture;             ///< The last gesture before any processing was done on it.
537   PanInfo         mLastSecondInterpolatedPoint;       ///< Stores the last second interpolated point we generated.
538   PanInfo         mLastFrameReadGesture;              ///< Stores the last gesture read.
539   PanInfo         mLastPredictedPoint;                ///< Stores the last predicted point we generated.
540   RelativeVectors mLastAcceleration;                  ///< Stores the acceleration value from the acceleration limiting last frame.
541   RelativeVectors mLastInterpolatedAcceleration;      ///< Stores the second interpolated point acceleration value from the last frame.
542   RelativeVectors mLastInitialAcceleration;           ///< Stores the initial acceleration value from the last frame.
543
544   volatile unsigned int mWritePosition; ///< The next PanInfo buffer to write to. (starts at 0).
545   unsigned int          mReadPosition;  ///< The next PanInfo buffer to read. (starts at 0).
546   bool                  mNotAtTarget;   ///< Keeps track of if the last gesture used was the most recent received.
547   bool                  mInGesture;     ///< True if the gesture is currently being handled i.e. between STARTED <-> FINISHED/CANCELLED.
548   bool                  mPredictionAmountOverridden;
549   bool                  mSmoothingAmountOverridden;
550
551   PanGestureProfiling* mProfiling; ///< NULL unless pan-gesture profiling information is required.
552   Dali::Mutex          mMutex;     ///< Mutex to lock access.
553
554   // Environment variables:
555
556   PredictionMode mPredictionMode;              ///< The pan gesture prediction mode
557   unsigned int   mPredictionAmount;            ///< how far into future to predict in milliseconds
558   unsigned int   mCurrentPredictionAmount;     ///< the current prediction amount used by the prediction algorithm
559   unsigned int   mMaxPredictionAmount;         ///< the maximum prediction amount used by the prediction algorithm
560   unsigned int   mMinPredictionAmount;         ///< the minimum prediction amount used by the prediction algorithm
561   unsigned int   mPredictionAmountAdjustment;  ///< the prediction amount to adjust in milliseconds when pan velocity changes
562   SmoothingMode  mSmoothingMode;               ///< The pan gesture prediction mode
563   float          mSmoothingAmount;             ///< How much smoothing to apply [0.0f,1.0f]
564   bool           mUseActualTimes;              ///< Disable to optionally override actual times if they make results worse.
565   int            mInterpolationTimeRange;      ///< Time into past history (ms) to use points to interpolate the first point.
566   bool           mScalarOnlyPredictionEnabled; ///< If enabled, prediction is done using velocity alone (no integration or acceleration).
567   bool           mTwoPointPredictionEnabled;   ///< If enabled, a second interpolated point is predicted and combined with the first to get more stable values.
568   int            mTwoPointPastInterpolateTime; ///< The target time in the past to generate the second interpolated point.
569   float          mTwoPointVelocityBias;        ///< The ratio of first and second interpolated points to use for velocity. 0.0f = 100% of first point. 1.0f = 100% of second point.
570   float          mTwoPointAccelerationBias;    ///< The ratio of first and second interpolated points to use for acceleration. 0.0f = 100% of first point. 1.0f = 100% of second point.
571   int            mMultiTapSmoothingRange;      ///< The range in time (ms) of points in the history to smooth the final output against.
572 };
573
574 } // namespace SceneGraph
575
576 } // namespace Internal
577
578 } // namespace Dali
579
580 #endif // DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H