1 #ifndef DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H
2 #define DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H
5 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <dali/devel-api/threading/mutex.h>
23 #include <dali/public-api/common/vector-wrapper.h>
24 #include <dali/internal/event/events/pan-gesture/pan-gesture-impl.h>
25 #include <dali/internal/update/common/property-owner.h>
26 #include <dali/internal/update/gestures/gesture-properties.h>
36 struct PanGestureProfiling;
42 * The latest pan gesture information is stored in this scene object.
44 class PanGesture : public PropertyOwner
57 SMOOTHING_NONE, // No smoothing.
58 SMOOTHING_LAST_VALUE, // Smooth between last value and latest value.
59 SMOOTHING_MULTI_TAP, // Uses multitap smoothing, only available with Prediction mode 2.
62 static const PredictionMode DEFAULT_PREDICTION_MODE;
63 static const int NUM_PREDICTION_MODES;
65 static const SmoothingMode DEFAULT_SMOOTHING_MODE;
66 static const int NUM_SMOOTHING_MODES;
68 // Latest Pan Information
71 * Only stores the information we actually require from Dali::PanGesture
76 * Stores the velocity, displacement and position.
85 Info(const Info& rhs) = default;
90 Info& operator=( const Info& rhs )
94 velocity = rhs.velocity;
95 displacement = rhs.displacement;
96 position = rhs.position;
105 Vector2 displacement;
114 state( GestureState::CLEAR ),
122 PanInfo( const PanInfo& rhs )
126 screen( rhs.screen ),
132 * Assignment operator
134 PanInfo& operator=( const PanInfo& rhs )
149 * Assignment operator
150 * @param[in] gesture A Dali::Gesture
152 PanInfo& operator=( const Internal::PanGesture& rhs )
154 time = rhs.GetTime();
155 state = rhs.GetState();
157 local.velocity = rhs.GetVelocity();
158 local.displacement = rhs.GetDisplacement();
159 local.position = rhs.GetPosition();
161 screen.velocity = rhs.GetScreenVelocity();
162 screen.displacement = rhs.GetScreenDisplacement();
163 screen.position = rhs.GetScreenPosition();
176 using PanInfoHistory = std::vector<PanInfo>;
177 using PanInfoHistoryIter = PanInfoHistory::iterator;
178 using PanInfoHistoryConstIter = PanInfoHistory::const_iterator;
181 static const unsigned int PAN_GESTURE_HISTORY = 30u;
186 * Create a new PanGesture
188 static PanGesture* New();
193 ~PanGesture() override;
196 * Adds a PanGesture to the internal circular-buffer waiting to be handled by UpdateProperties.
197 * @param[in] gesture The latest pan gesture.
199 void AddGesture( const Internal::PanGesture& gesture );
202 * @brief Removes pan events from the history that are older than maxAge, leaving at least minEvents
204 * @param[in] panHistory The pan event history container
205 * @param[in] currentTime The current frame time
206 * @param[in] maxAge Maximum age of an event before removing (in millis)
207 * @param[in] minEvents The minimum number of events to leave in history, oldest events are removed before newest
209 void RemoveOldHistory(PanInfoHistory& panHistory, unsigned int currentTime, unsigned int maxAge, unsigned int minEvents);
212 * Uses elapsed time and time stamps
214 void PredictionMode1(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistory& panHistory, unsigned int lastVSyncTime, unsigned int nextVSyncTime);
217 * Blends two points together.
218 * The blend value ranges are:
219 * 0.0f = use 100% of current value.
220 * 1.0f = use half-way average of current and last value.
222 * @param[in,out] gesture Pass in current gesture, outputs result of blend.
223 * @param[in] lastGesture Pass in gesture to blend between.
225 void BlendPoints( PanInfo& gesture, PanInfo& lastGesture, float blendValue );
228 * Called by the update manager so that we can update the value of our properties.
229 * @param[in] nextRenderTime The estimated time of the next render (in milliseconds).
230 * @return true, if properties were updated.
232 bool UpdateProperties( unsigned int lastRenderTime, unsigned int nextRenderTime );
235 * Retrieves a reference to the panning flag property.
236 * @return The panning flag property.
238 const GesturePropertyBool& GetPanningProperty() const;
241 * Retrieves a reference to the screen position property.
242 * @return The screen position property.
244 const GesturePropertyVector2& GetScreenPositionProperty() const;
247 * Retrieves a reference to the screen velocity property.
248 * @return The screen velocity property.
250 const GesturePropertyVector2& GetScreenVelocityProperty() const;
253 * Retrieves a reference to the screen displacement property.
254 * @return The screen displacement property.
256 const GesturePropertyVector2& GetScreenDisplacementProperty() const;
259 * Retrieves a reference to the local position property.
260 * @return The local position property.
262 const GesturePropertyVector2& GetLocalPositionProperty() const;
265 * Retrieves a reference to the local displacement property.
266 * @return The local displacement property.
268 const GesturePropertyVector2& GetLocalDisplacementProperty() const;
271 * Retrieves a reference to the local velocity property.
272 * @return The local velocity property.
274 const GesturePropertyVector2& GetLocalVelocityProperty() const;
277 * @brief Sets the prediction mode of the pan gesture
279 * @param[in] mode The prediction mode
281 void SetPredictionMode(PredictionMode mode);
284 * @brief Sets the prediction amount of the pan gesture
286 * @param[in] amount The prediction amount in milliseconds
288 void SetPredictionAmount(unsigned int amount);
291 * @brief Sets the upper bound of the prediction amount for clamping
293 * @param[in] amount The prediction amount in milliseconds
295 void SetMaximumPredictionAmount(unsigned int amount);
298 * @brief Sets the lower bound of the prediction amount for clamping
300 * @param[in] amount The prediction amount in milliseconds
302 void SetMinimumPredictionAmount(unsigned int amount);
305 * @brief Sets the amount of prediction interpolation to adjust when the pan velocity is changed
307 * @param[in] amount The prediction amount in milliseconds
309 void SetPredictionAmountAdjustment(unsigned int amount);
312 * @brief Sets the prediction mode of the pan gesture
314 * @param[in] mode The prediction mode
316 void SetSmoothingMode(SmoothingMode mode);
319 * @brief Sets the amount of smoothing to apply for the current smoothing mode
321 * @param[in] amount The amount of smoothing [0.0f,1.0f]
323 void SetSmoothingAmount(float amount);
326 * @brief Sets whether to use actual times of the real gesture and frames or not.
328 * @param[in] value True = use actual times, False = use perfect values
330 void SetUseActualTimes( bool value );
333 * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating.
335 * @param[in] value Time range in ms
337 void SetInterpolationTimeRange( int value );
340 * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration.
342 * @param[in] value True = use scalar prediction only
344 void SetScalarOnlyPredictionEnabled( bool value );
347 * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values.
349 * @param[in] value True = use two point prediction
351 void SetTwoPointPredictionEnabled( bool value );
354 * @brief Sets the time in the past to interpolate the second point when using two point interpolation.
356 * @param[in] value Time in past in ms
358 void SetTwoPointInterpolatePastTime( int value );
361 * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity.
363 * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
365 void SetTwoPointVelocityBias( float value );
368 * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration.
370 * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
372 void SetTwoPointAccelerationBias( float value );
375 * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled).
377 * @param[in] value Time in past in ms
379 void SetMultitapSmoothingRange( int value );
382 * Called to provide pan-gesture profiling information.
384 void EnableProfiling();
387 * Reset default properties, custom ones not supported due to this being the only object in scene side
388 * @param updateBufferIndex index to use
390 void ResetDefaultProperties( BufferIndex updateBufferIndex );
395 * Protected constructor.
400 PanGesture(const PanGesture&);
404 // Struct to keep pairs of local and screen data together.
405 // TODO: This can encapsulate some functionality also.
406 using RelativeVectors = struct
415 * Houses new code to process input events and generate an output point.
417 * @param[in] lastVSyncTime The time of the last render (in milliseconds)
418 * @param[in] nextVSyncTime The estimated time of the next render (in milliseconds)
420 bool NewAlgorithm( unsigned int lastVSyncTime, unsigned int nextVSyncTime );
423 * Gets the (absolute) time difference between two times.
424 * This is limited by minimumDelta, so it can be safe to use as a divisor.
425 * This function is wrapped so that the behviour can be overridden to return a "perfect" time difference (overrideDifference).
427 * @param[in] timeA The first time to calculate from
428 * @param[in] timeB The second time to calculate from
429 * @param[in] minimumDelta The smallest amount the difference can become
430 * @param[in] overrideDifference The time difference to return if using perfect times
432 inline float GetDivisibleTimeDifference( int timeA, int timeB, float minimumDelta, float overrideDifference );
435 * This limits the change currentAcceleration can have over lastAcceleration by the specified changeLimit value.
437 * @param[in] currentAcceleration The acceleration to modify
438 * @param[in] lastAcceleration The acceleration to limit against
439 * @param[in] changeLimit The maximum change (in either direction)
441 void LimitAccelerationChange( RelativeVectors& currentAcceleration, RelativeVectors& lastAcceleration, float changeLimit );
444 * Reads all events received this frame into a linear buffer.
445 * A lock is held while this is done.
447 unsigned int ReadFrameEvents();
450 * Converts between input rate and internal rate (typically 60Hz internally).
451 * Also writes to the pan history container.
452 * TODO: Does not need to return the gesture if it is in the history also, but currently it's used.
453 * (if rate conversion does not generate a point there are points still in history, but this can been done with a bool property).
455 * @param[out] rateConvertedGesture Result gesture for this frame is writen here.
456 * @param[in] eventsThisFrame Number of events to convert
457 * @param[in] currentFrameTime Time of the frame we will render to
458 * @param[in] lastFrameTime Time of the last rendered frame
459 * @param[out] justStarted Set to true if we are now starting a new gesture
460 * @param[out] justFinished Set to true if we are now finishing a gesture
462 bool InputRateConversion( PanInfo& rateConvertedGesture, unsigned int eventsThisFrame,
463 unsigned int currentFrameTime, unsigned int lastFrameTime, bool& justStarted, bool& justFinished );
466 * Generates an interpolated point at the specified point in time.
468 * @param[in] history of points to use
469 * @param[in] currentTime Time of the frame we will render to
470 * @param[in] targetTime Time of the point to generate
471 * @param[in] range Range of time (each side of target time) to use points from
472 * @param[out] outPoint Generated point
473 * @param[out] acceleration Generated acceleration
474 * @param[in] outputTimeGranularity Time difference between output point (typically 60Hz)
475 * @param[in] eraseUnused Set to true to clean up any history not used by the function
477 bool InterpolatePoint( PanInfoHistory& history, unsigned int currentTime, unsigned int targetTime, unsigned int range,
478 PanInfo& outPoint, RelativeVectors& acceleration, int outputTimeGranularity, bool eraseUnused );
481 * Predicts a point in the future, based on the supplied point and acceleration.
482 * Other user configuration settings are considered.
484 * @param[in] startPoint Starting point to use. Position and velocity are taken from here.
485 * @param[in] accelerationToUse The acceleration to use.
486 * @param[out] predictedPoint Generated predicted point
487 * @param[in] currentFrameTime Time of the frame we will render to
488 * @param[in] previousFrameTime Time of the last rendered frame
489 * @param[in] noPreviousData Set to true if we are just starting a gesture
491 void PredictionMode2( PanInfo& startPoint, RelativeVectors& accelerationToUse,
492 PanInfo& predictedPoint, unsigned int currentFrameTime, unsigned int previousFrameTime, bool noPreviousData );
497 PanGesture& operator=(const PanGesture&);
499 // Defines information to be gathered by the gesture reading code.
500 struct FrameGestureInfo
502 PanGesture::PanInfo frameGesture;
504 unsigned int eventsThisFrame;
509 : acceleration( 0.0f ),
510 eventsThisFrame( 0 ),
511 justStarted( false ),
512 justFinished( false )
518 * Reads gestures from input, builds history.
519 * @param[out] info Written to with information about gestures read this frame.
520 * @param[in] currentTimestamp The time of this frame.
522 bool ReadGestures( FrameGestureInfo& info, unsigned int currentTimestamp );
525 * Reads gestures from input and resamples data, builds history.
526 * @param[out] info Written to with information about gestures read this frame.
527 * @param[in] currentTimestamp The time of this frame.
529 bool ReadAndResampleGestures( FrameGestureInfo& info, unsigned int currentTimestamp );
534 GesturePropertyBool mPanning; ///< panning flag
535 GesturePropertyVector2 mScreenPosition; ///< screenPosition
536 GesturePropertyVector2 mScreenDisplacement; ///< screenDisplacement
537 GesturePropertyVector2 mScreenVelocity; ///< screenVelocity
538 GesturePropertyVector2 mLocalPosition; ///< localPosition
539 GesturePropertyVector2 mLocalDisplacement; ///< localDisplacement
540 GesturePropertyVector2 mLocalVelocity; ///< localVelocity
542 PanInfoHistory mPanHistory;
543 PanInfoHistory mPredictionHistory;
544 PanInfo mGestures[PAN_GESTURE_HISTORY]; ///< Circular buffer storing the 4 most recent gestures.
545 PanInfo mReadGestures[PAN_GESTURE_HISTORY]; ///< Linear buffer storing the most recent gestures (to reduce read lock time).
546 PanInfo mLastGesture; ///< The last gesture. (last update frame).
547 PanInfo mTargetGesture; ///< The most recent input gesture, if the current used gesture does not match.
548 PanInfo mLastUnmodifiedGesture; ///< The last gesture before any processing was done on it.
549 PanInfo mLastSecondInterpolatedPoint; ///< Stores the last second interpolated point we generated.
550 PanInfo mLastFrameReadGesture; ///< Stores the last gesture read.
551 PanInfo mLastPredictedPoint; ///< Stores the last predicted point we generated.
552 RelativeVectors mLastAcceleration; ///< Stores the acceleration value from the acceleration limiting last frame.
553 RelativeVectors mLastInterpolatedAcceleration; ///< Stores the second interpolated point acceleration value from the last frame.
554 RelativeVectors mLastInitialAcceleration; ///< Stores the initial acceleration value from the last frame.
556 volatile unsigned int mWritePosition; ///< The next PanInfo buffer to write to. (starts at 0).
557 unsigned int mReadPosition; ///< The next PanInfo buffer to read. (starts at 0).
558 bool mNotAtTarget; ///< Keeps track of if the last gesture used was the most recent received.
559 bool mInGesture; ///< True if the gesture is currently being handled i.e. between STARTED <-> FINISHED/CANCELLED.
560 bool mPredictionAmountOverridden;
561 bool mSmoothingAmountOverridden;
563 PanGestureProfiling* mProfiling; ///< NULL unless pan-gesture profiling information is required.
564 Dali::Mutex mMutex; ///< Mutex to lock access.
566 // Environment variables:
568 PredictionMode mPredictionMode; ///< The pan gesture prediction mode
569 unsigned int mPredictionAmount; ///< how far into future to predict in milliseconds
570 unsigned int mCurrentPredictionAmount; ///< the current prediction amount used by the prediction algorithm
571 unsigned int mMaxPredictionAmount; ///< the maximum prediction amount used by the prediction algorithm
572 unsigned int mMinPredictionAmount; ///< the minimum prediction amount used by the prediction algorithm
573 unsigned int mPredictionAmountAdjustment; ///< the prediction amount to adjust in milliseconds when pan velocity changes
574 SmoothingMode mSmoothingMode; ///< The pan gesture prediction mode
575 float mSmoothingAmount; ///< How much smoothing to apply [0.0f,1.0f]
576 bool mUseActualTimes; ///< Disable to optionally override actual times if they make results worse.
577 int mInterpolationTimeRange; ///< Time into past history (ms) to use points to interpolate the first point.
578 bool mScalarOnlyPredictionEnabled; ///< If enabled, prediction is done using velocity alone (no integration or acceleration).
579 bool mTwoPointPredictionEnabled; ///< If enabled, a second interpolated point is predicted and combined with the first to get more stable values.
580 int mTwoPointPastInterpolateTime; ///< The target time in the past to generate the second interpolated point.
581 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.
582 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.
583 int mMultiTapSmoothingRange; ///< The range in time (ms) of points in the history to smooth the final output against.
586 } // namespace SceneGraph
588 } // namespace Internal
592 #endif // DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H