Commit 66716a36 authored by Alexander Bock's avatar Alexander Bock
Browse files

Merge branch 'master' into feature/imgui-touchhandling

# Conflicts:
#	modules/touch/src/touchinteraction.cpp
parents fb7036c4 c6d3a181
Showing with 313 additions and 105 deletions
+313 -105
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <openspace/properties/stringproperty.h> #include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h> #include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h> #include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
#include <openspace/properties/triggerproperty.h> #include <openspace/properties/triggerproperty.h>
#include <ghoul/glm.h> #include <ghoul/glm.h>
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
...@@ -143,8 +144,8 @@ private: ...@@ -143,8 +144,8 @@ private:
properties::FloatProperty _followAnchorNodeRotationDistance; properties::FloatProperty _followAnchorNodeRotationDistance;
properties::FloatProperty _minimumAllowedDistance; properties::FloatProperty _minimumAllowedDistance;
properties::FloatProperty _flightDestinationDistance; properties::FloatProperty _flightDestinationDistance;
properties::DoubleProperty _flightDestinationFactor;
properties::BoolProperty _applyLinearFlight; properties::BoolProperty _applyLinearFlight;
properties::FloatProperty _velocitySensitivity; properties::FloatProperty _velocitySensitivity;
properties::FloatProperty _mouseSensitivity; properties::FloatProperty _mouseSensitivity;
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
namespace openspace { namespace openspace {
// The TouchInput represents a single finger/device-input at a specific point in time.
// the fingerId and touchDeviceId coupled with the timestamp allows this to be compared
// with other TouchInputs in order to calculate gesture-like behaviour.
struct TouchInput { struct TouchInput {
TouchInput(size_t touchDeviceId, size_t fingerId, float x, float y, double timestamp); TouchInput(size_t touchDeviceId, size_t fingerId, float x, float y, double timestamp);
glm::vec2 screenCoordinates(glm::vec2 resolution) const; glm::vec2 screenCoordinates(glm::vec2 resolution) const;
...@@ -46,19 +49,25 @@ struct TouchInput { ...@@ -46,19 +49,25 @@ struct TouchInput {
float y; float y;
float dx = 0.f; // movement in x direction since last touch input float dx = 0.f; // movement in x direction since last touch input
float dy = 0.f; // movement in y direction since last touch input float dy = 0.f; // movement in y direction since last touch input
double timestamp; // timestamp in seconds from global touch initialization double timestamp; // timestamp in seconds from global touch initialization
}; };
// The TouchInputHolder holds one or many TouchInputs, in order to track the history of
// the finger/input device
class TouchInputHolder { class TouchInputHolder {
public: public:
TouchInputHolder(TouchInput input); TouchInputHolder(TouchInput input);
// tryAddInput:
// Succeeds upon a different input than last. // Succeeds upon a different input than last.
// Fails upon a too similar input as last. // Fails upon a too similar input as last.
// Updates time for the last input if same position.
bool tryAddInput(TouchInput input); bool tryAddInput(TouchInput input);
void clearInputs(); void clearInputs();
// Checks whether or not this Holder actually holds a specific input (based on IDs)
// Succeeds when `input` is held by this Holder
// Fails if `input` is not held by this Holder
bool holdsInput(const TouchInput &input) const; bool holdsInput(const TouchInput &input) const;
size_t touchDeviceId() const; size_t touchDeviceId() const;
...@@ -72,12 +81,14 @@ public: ...@@ -72,12 +81,14 @@ public:
double gestureTime() const; double gestureTime() const;
size_t numInputs() const; size_t numInputs() const;
const TouchInput& firstInput() const;
const TouchInput& latestInput() const; const TouchInput& latestInput() const;
const std::deque<TouchInput>& peekInputs() const; const std::deque<TouchInput>& peekInputs() const;
private: private:
//A deque of recorded inputs. Adding newer points to the front of the queue //A deque of recorded inputs. Adding newer points to the front of the queue
std::deque<TouchInput> _inputs; std::deque<TouchInput> _inputs;
TouchInput _firstInput;
size_t _touchDeviceId; size_t _touchDeviceId;
size_t _fingerId; size_t _fingerId;
......
...@@ -784,4 +784,22 @@ float RenderableLabels::unit(int unit) const { ...@@ -784,4 +784,22 @@ float RenderableLabels::unit(int unit) const {
} }
} }
std::string RenderableLabels::toString(int unit) const {
switch (static_cast<Unit>(unit)) {
case Meter: return MeterUnit;
case Kilometer: return KilometerUnit;
case Megameter: return MegameterUnit;
case Gigameter: return GigameterUnit;
case AU: return AstronomicalUnit;
case Terameter: return TerameterUnit;
case Petameter: return PetameterUnit;
case Parsec: return ParsecUnit;
case Kiloparsec: return KiloparsecUnit;
case Megaparsec: return MegaparsecUnit;
case Gigaparsec: return GigaparsecUnit;
case GigalightYears: return GigalightyearUnit;
default: throw std::logic_error("Missing case label");
}
}
} // namespace openspace } // namespace openspace
...@@ -74,6 +74,8 @@ protected: ...@@ -74,6 +74,8 @@ protected:
float unit(int unit) const; float unit(int unit) const;
std::string toString(int unit) const;
// Data may require some type of transformation prior the spice transformation being // Data may require some type of transformation prior the spice transformation being
// applied. // applied.
glm::dmat4 _transformationMatrix = glm::dmat4(1.0); glm::dmat4 _transformationMatrix = glm::dmat4(1.0);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <openspace/properties/stringproperty.h> #include <openspace/properties/stringproperty.h>
#include <openspace/properties/vector/ivec2property.h> #include <openspace/properties/vector/ivec2property.h>
#include <openspace/properties/vector/vec4property.h> #include <openspace/properties/vector/vec4property.h>
#include <array>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
...@@ -94,7 +95,7 @@ public: ...@@ -94,7 +95,7 @@ public:
std::vector<TouchInput>& lastProcessed); std::vector<TouchInput>& lastProcessed);
// Calculates the new camera state with velocities and time since last frame // Calculates the new camera state with velocities and time since last frame
void step(double dt); void step(double dt, bool directTouch = false);
// Called each frame we have no new input, used to reset data // Called each frame we have no new input, used to reset data
void resetAfterInput(); void resetAfterInput();
...@@ -159,6 +160,7 @@ private: ...@@ -159,6 +160,7 @@ private:
properties::IntProperty _deceleratesPerSecond; properties::IntProperty _deceleratesPerSecond;
properties::FloatProperty _touchScreenSize; properties::FloatProperty _touchScreenSize;
properties::FloatProperty _tapZoomFactor; properties::FloatProperty _tapZoomFactor;
properties::FloatProperty _pinchZoomFactor;
properties::FloatProperty _nodeRadiusThreshold; properties::FloatProperty _nodeRadiusThreshold;
properties::FloatProperty _rollAngleThreshold; properties::FloatProperty _rollAngleThreshold;
properties::FloatProperty _orbitSpeedThreshold; properties::FloatProperty _orbitSpeedThreshold;
...@@ -193,7 +195,7 @@ private: ...@@ -193,7 +195,7 @@ private:
double pinchConsecZoomFactor = 0; double pinchConsecZoomFactor = 0;
//int stepVelUpdate = 0; //int stepVelUpdate = 0;
#endif #endif
std::array<TouchInputHolder, 2> _pinchInputs;
// Class variables // Class variables
VelocityStates _vel; VelocityStates _vel;
VelocityStates _lastVel; VelocityStates _lastVel;
......
...@@ -116,6 +116,13 @@ namespace { ...@@ -116,6 +116,13 @@ namespace {
"" // @TODO Missing documentation "" // @TODO Missing documentation
}; };
constexpr openspace::properties::Property::PropertyInfo PinchZoomFactorInfo = {
"PinchZoomFactor",
"Scaling distance travelled on pinch",
"This value is used to reduce the amount of pinching needed. A linear kind of "
"sensitivity that will alter the pinch-zoom speed."
};
constexpr openspace::properties::Property::PropertyInfo DirectManipulationInfo = { constexpr openspace::properties::Property::PropertyInfo DirectManipulationInfo = {
"DirectManipulationRadius", "DirectManipulationRadius",
"Radius a planet has to have to activate direct-manipulation", "Radius a planet has to have to activate direct-manipulation",
...@@ -257,6 +264,7 @@ TouchInteraction::TouchInteraction() ...@@ -257,6 +264,7 @@ TouchInteraction::TouchInteraction()
, _deceleratesPerSecond(DecelatesPerSecondInfo, 240, 60, 300) , _deceleratesPerSecond(DecelatesPerSecondInfo, 240, 60, 300)
, _touchScreenSize(TouchScreenSizeInfo, 55.0f, 5.5f, 150.0f) , _touchScreenSize(TouchScreenSizeInfo, 55.0f, 5.5f, 150.0f)
, _tapZoomFactor(TapZoomFactorInfo, 0.2f, 0.f, 0.5f) , _tapZoomFactor(TapZoomFactorInfo, 0.2f, 0.f, 0.5f)
, _pinchZoomFactor(PinchZoomFactorInfo, 0.01f, 0.f, 0.2f)
, _nodeRadiusThreshold(DirectManipulationInfo, 0.2f, 0.0f, 1.0f) , _nodeRadiusThreshold(DirectManipulationInfo, 0.2f, 0.0f, 1.0f)
, _rollAngleThreshold(RollThresholdInfo, 0.025f, 0.f, 0.05f) , _rollAngleThreshold(RollThresholdInfo, 0.025f, 0.f, 0.05f)
, _orbitSpeedThreshold(OrbitSpinningThreshold, 0.005f, 0.f, 0.01f) , _orbitSpeedThreshold(OrbitSpinningThreshold, 0.005f, 0.f, 0.01f)
...@@ -270,7 +278,12 @@ TouchInteraction::TouchInteraction() ...@@ -270,7 +278,12 @@ TouchInteraction::TouchInteraction()
0.25f 0.25f
) )
, _zoomBoundarySphereMultiplier(ZoomBoundarySphereMultiplierInfo, 1.001f, 1.f, 1.01f) , _zoomBoundarySphereMultiplier(ZoomBoundarySphereMultiplierInfo, 1.001f, 1.f, 1.01f)
, _zoomOutLimit(ZoomOutLimitInfo, std::numeric_limits<double>::max(), 1000.0, std::numeric_limits<double>::max()) , _zoomOutLimit(
ZoomOutLimitInfo,
std::numeric_limits<double>::max(),
1000.0,
std::numeric_limits<double>::max()
)
, _zoomInLimit(ZoomInLimitInfo, -1.0, 0.0, std::numeric_limits<double>::max()) , _zoomInLimit(ZoomInLimitInfo, -1.0, 0.0, std::numeric_limits<double>::max())
, _inputStillThreshold(InputSensitivityInfo, 0.0005f, 0.f, 0.001f) , _inputStillThreshold(InputSensitivityInfo, 0.0005f, 0.f, 0.001f)
// used to void wrongly interpreted roll interactions // used to void wrongly interpreted roll interactions
...@@ -290,8 +303,9 @@ TouchInteraction::TouchInteraction() ...@@ -290,8 +303,9 @@ TouchInteraction::TouchInteraction()
0.f, 0.f,
1.f 1.f
) )
, _pinchInputs({ TouchInput(0, 0, 0.0, 0.0, 0.0), TouchInput(0, 0, 0.0, 0.0, 0.0) })
, _vel{ glm::dvec2(0.0), 0.0, 0.0, glm::dvec2(0.0) } , _vel{ glm::dvec2(0.0), 0.0, 0.0, glm::dvec2(0.0) }
, _sensitivity{ glm::dvec2(0.08, 0.045), 12.0 /*4.0*/, 2.75, glm::dvec2(0.08, 0.045) } , _sensitivity{ glm::dvec2(0.08, 0.045), 12.0, 2.75, glm::dvec2(0.08, 0.045) }
, _constTimeDecay_secs(ConstantTimeDecaySecsInfo, 1.75f, 0.1f, 4.0f) , _constTimeDecay_secs(ConstantTimeDecaySecsInfo, 1.75f, 0.1f, 4.0f)
// calculated with two vectors with known diff in length, then // calculated with two vectors with known diff in length, then
// projDiffLength/diffLength. // projDiffLength/diffLength.
...@@ -303,6 +317,7 @@ TouchInteraction::TouchInteraction() ...@@ -303,6 +317,7 @@ TouchInteraction::TouchInteraction()
addProperty(_deceleratesPerSecond); addProperty(_deceleratesPerSecond);
addProperty(_touchScreenSize); addProperty(_touchScreenSize);
addProperty(_tapZoomFactor); addProperty(_tapZoomFactor);
addProperty(_pinchZoomFactor);
addProperty(_nodeRadiusThreshold); addProperty(_nodeRadiusThreshold);
addProperty(_rollAngleThreshold); addProperty(_rollAngleThreshold);
addProperty(_orbitSpeedThreshold); addProperty(_orbitSpeedThreshold);
...@@ -442,7 +457,7 @@ void TouchInteraction::directControl(const std::vector<TouchInputHolder>& list) ...@@ -442,7 +457,7 @@ void TouchInteraction::directControl(const std::vector<TouchInputHolder>& list)
_vel.pan = glm::dvec2(par.at(4), par.at(5)); _vel.pan = glm::dvec2(par.at(4), par.at(5));
} }
} }
step(1.0); step(1.0, true);
// Reset velocities after setting new camera state // Reset velocities after setting new camera state
_lastVel = _vel; _lastVel = _vel;
...@@ -720,6 +735,15 @@ int TouchInteraction::interpretInteraction(const std::vector<TouchInputHolder>& ...@@ -720,6 +735,15 @@ int TouchInteraction::interpretInteraction(const std::vector<TouchInputHolder>&
return ROLL; return ROLL;
} }
else { else {
const bool sameInput0 = _pinchInputs[0].holdsInput(list[0].latestInput());
const bool sameInput1 = _pinchInputs[1].holdsInput(list[1].latestInput());
if (sameInput0 && sameInput1) {
_pinchInputs[0].tryAddInput(list[0].latestInput());
_pinchInputs[1].tryAddInput(list[1].latestInput());
} else {
_pinchInputs[0] = TouchInputHolder(list[0].latestInput());
_pinchInputs[1] = TouchInputHolder(list[1].latestInput());
}
return PINCH; return PINCH;
} }
} }
...@@ -759,6 +783,9 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li ...@@ -759,6 +783,9 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li
#endif #endif
const TouchInputHolder& inputHolder = list.at(0); const TouchInputHolder& inputHolder = list.at(0);
const glm::ivec2 windowSize = global::windowDelegate.currentWindowSize();
const float aspectRatio =
static_cast<float>(windowSize.x) / static_cast<float>(windowSize.y);
switch (action) { switch (action) {
case ROT: { // add rotation velocity case ROT: { // add rotation velocity
_vel.orbit += glm::dvec2(inputHolder.speedX() * _vel.orbit += glm::dvec2(inputHolder.speedX() *
...@@ -772,54 +799,31 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li ...@@ -772,54 +799,31 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li
} }
case PINCH: { case PINCH: {
// add zooming velocity - dependant on distance difference between contact // add zooming velocity - dependant on distance difference between contact
// points this/last frame // points this/first frame
double distance = std::accumulate( using namespace glm;
list.begin(), const TouchInput& startFinger0 = _pinchInputs[0].firstInput();
list.end(), const TouchInput& startFinger1 = _pinchInputs[1].firstInput();
0.0, const dvec2 startVec0 = dvec2(startFinger0.x * aspectRatio, startFinger0.y);
[&](double d, const TouchInputHolder& c) { const dvec2 startVec1 = dvec2(startFinger1.x * aspectRatio, startFinger1.y);
const glm::vec2 currPos = { c.latestInput().x, c.latestInput().y }; double distToCentroidStart = length(startVec0 - startVec1) / 2.0;
return d + glm::distance(currPos, _centroid);
} const TouchInput& endFinger0 = _pinchInputs[0].latestInput();
) / list.size(); const TouchInput& endFinger1 = _pinchInputs[1].latestInput();
double lastDistance = std::accumulate( const dvec2 endVec0 = dvec2(endFinger0.x * aspectRatio, endFinger0.y);
lastProcessed.begin(), const dvec2 endVec1 = dvec2(endFinger1.x * aspectRatio, endFinger1.y);
lastProcessed.end(), double distToCentroidEnd = length(endVec0 - endVec1) / 2.0;
0.f,
[&](float d, const TouchInput& p) { double zoomFactor = distToCentroidEnd - distToCentroidStart;
const glm::vec2 lastPos = { p.x, p.y };
return d + glm::distance(lastPos, _centroid);
}
) / lastProcessed.size();
glm::dvec3 camPos = _camera->positionVec3();
glm::dvec3 centerPos = anchor->worldPosition();
glm::dvec3 currDistanceToFocusNode = camPos - centerPos;
const double distanceFromFocusSurface =
length(currDistanceToFocusNode) - anchor->boundingSphere();
double zoomFactor = (distance - lastDistance);
#ifdef TOUCH_DEBUG_PROPERTIES #ifdef TOUCH_DEBUG_PROPERTIES
pinchConsecCt++; pinchConsecCt++;
pinchConsecZoomFactor += zoomFactor; pinchConsecZoomFactor += zoomFactor;
#endif #endif
_constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom); _constTimeDecayCoeff.zoom = 1.0;
if (distanceFromFocusSurface > 0.1) { _vel.zoom = zoomFactor *
const double ratioOfDistanceToNodeVsSurface = _pinchZoomFactor *
length(currDistanceToFocusNode) / distanceFromFocusSurface; _zoomSensitivityProportionalDist *
if (ratioOfDistanceToNodeVsSurface > _zoomSensitivityDistanceThreshold) { std::max(_touchScreenSize.value() * 0.1, 1.0);
zoomFactor *= pow(
std::abs(distanceFromFocusSurface),
static_cast<float>(_zoomSensitivityExponential)
);
}
}
else {
zoomFactor = 1.0;
}
_vel.zoom = zoomFactor * _zoomSensitivityProportionalDist *
std::max(_touchScreenSize.value() * 0.1, 1.0);
break; break;
} }
case ROLL: { case ROLL: {
...@@ -860,7 +864,7 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li ...@@ -860,7 +864,7 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li
break; break;
} }
case PAN: { case PAN: {
// add local rotation velocity // add local rotation velocity
_vel.pan += glm::dvec2(inputHolder.speedX() * _vel.pan += glm::dvec2(inputHolder.speedX() *
_sensitivity.pan.x, inputHolder.speedY() * _sensitivity.pan.y); _sensitivity.pan.x, inputHolder.speedY() * _sensitivity.pan.y);
double panVelocityAvg = glm::distance(_vel.pan.x, _vel.pan.y); double panVelocityAvg = glm::distance(_vel.pan.x, _vel.pan.y);
...@@ -868,7 +872,7 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li ...@@ -868,7 +872,7 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li
break; break;
} }
case PICK: { case PICK: {
// pick something in the scene as focus node // pick something in the scene as focus node
if (_pickingSelected) { if (_pickingSelected) {
setFocusNode(_pickingSelected); setFocusNode(_pickingSelected);
...@@ -935,7 +939,7 @@ double TouchInteraction::computeTapZoomDistance(double zoomGain) { ...@@ -935,7 +939,7 @@ double TouchInteraction::computeTapZoomDistance(double zoomGain) {
// Main update call, calculates the new orientation and position for the camera depending // Main update call, calculates the new orientation and position for the camera depending
// on _vel and dt. Called every frame // on _vel and dt. Called every frame
void TouchInteraction::step(double dt) { void TouchInteraction::step(double dt, bool directTouch) {
using namespace glm; using namespace glm;
const SceneGraphNode* anchor = const SceneGraphNode* anchor =
...@@ -1046,22 +1050,45 @@ void TouchInteraction::step(double dt) { ...@@ -1046,22 +1050,45 @@ void TouchInteraction::step(double dt) {
_loggerCat, _zoomOutLimit.value() _loggerCat, _zoomOutLimit.value()
)); ));
} }
const double currentPosDistance = length(centerToCamera);
//Apply the velocity to update camera position //Apply the velocity to update camera position
glm::dvec3 zoomDistanceIncrement = directionToCenter * _vel.zoom * dt; double zoomVelocity = _vel.zoom;
if (!directTouch) {
const double distanceFromSurface =
length(currentPosDistance) - anchor->boundingSphere();
if (distanceFromSurface > 0.1) {
const double ratioOfDistanceToNodeVsSurface =
length(currentPosDistance) / distanceFromSurface;
if (ratioOfDistanceToNodeVsSurface > _zoomSensitivityDistanceThreshold) {
zoomVelocity *= pow(
std::abs(distanceFromSurface),
static_cast<float>(_zoomSensitivityExponential)
);
}
}
else {
zoomVelocity = 1.0;
}
}
const glm::dvec3 zoomDistanceIncrement = directionToCenter * zoomVelocity * dt;
const double newPosDistance = length(centerToCamera + zoomDistanceIncrement); const double newPosDistance = length(centerToCamera + zoomDistanceIncrement);
const double currentPosDistance = length(centerToCamera);
// Possible with other navigations performed outside touch interaction // Possible with other navigations performed outside touch interaction
const bool currentPosViolatingZoomOutLimit = const bool currentPosViolatingZoomOutLimit =
(currentPosDistance >= _zoomOutLimit.value()); (currentPosDistance >= _zoomOutLimit);
const bool willNewPositionViolateZoomOutLimit = const bool willNewPositionViolateZoomOutLimit =
(newPosDistance >= _zoomOutLimit.value()); (newPosDistance >= _zoomOutLimit);
bool willNewPositionViolateZoomInLimit = bool willNewPositionViolateZoomInLimit =
(newPosDistance < zoomInBounds); (newPosDistance < zoomInBounds);
bool willNewPositionViolateDirection =
(currentPosDistance <= length(zoomDistanceIncrement));
if (!willNewPositionViolateZoomInLimit if (!willNewPositionViolateZoomInLimit &&
&& !willNewPositionViolateZoomOutLimit) { !willNewPositionViolateDirection &&
!willNewPositionViolateZoomOutLimit)
{
camPos += zoomDistanceIncrement; camPos += zoomDistanceIncrement;
} }
else if (currentPosViolatingZoomOutLimit) { else if (currentPosViolatingZoomOutLimit) {
...@@ -1148,6 +1175,20 @@ void TouchInteraction::resetAfterInput() { ...@@ -1148,6 +1175,20 @@ void TouchInteraction::resetAfterInput() {
} }
} }
// Reset emulated mouse values
ImGUIModule& module = *(global::moduleEngine.module<ImGUIModule>());
if (_guiON) {
bool activeLastFrame = module.touchInput.action;
module.touchInput.active = false;
if (activeLastFrame) {
module.touchInput.active = true;
module.touchInput.action = 0;
}
}
else {
module.touchInput.active = false;
module.touchInput.action = 0;
}
_lmSuccess = true; _lmSuccess = true;
// Reset variables // Reset variables
...@@ -1155,6 +1196,11 @@ void TouchInteraction::resetAfterInput() { ...@@ -1155,6 +1196,11 @@ void TouchInteraction::resetAfterInput() {
_lastVel.zoom = 0.0; _lastVel.zoom = 0.0;
_lastVel.roll = 0.0; _lastVel.roll = 0.0;
_lastVel.pan = glm::dvec2(0.0); _lastVel.pan = glm::dvec2(0.0);
_constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom);
_pinchInputs[0].clearInputs();
_pinchInputs[1].clearInputs();
_selected.clear(); _selected.clear();
_pickingSelected = nullptr; _pickingSelected = nullptr;
} }
...@@ -1167,6 +1213,7 @@ void TouchInteraction::resetToDefault() { ...@@ -1167,6 +1213,7 @@ void TouchInteraction::resetToDefault() {
_deceleratesPerSecond.set(240); _deceleratesPerSecond.set(240);
_touchScreenSize.set(55.0f); _touchScreenSize.set(55.0f);
_tapZoomFactor.set(0.2f); _tapZoomFactor.set(0.2f);
_pinchZoomFactor.set(0.01f);
_nodeRadiusThreshold.set(0.2f); _nodeRadiusThreshold.set(0.2f);
_rollAngleThreshold.set(0.025f); _rollAngleThreshold.set(0.025f);
_orbitSpeedThreshold.set(0.005f); _orbitSpeedThreshold.set(0.005f);
......
...@@ -40,12 +40,18 @@ ...@@ -40,12 +40,18 @@
#define ENABLE_DIRECTMSG #define ENABLE_DIRECTMSG
namespace { namespace {
using namespace std::chrono;
constexpr const char* _loggerCat = "win32_touch"; constexpr const char* _loggerCat = "win32_touch";
HHOOK gTouchHook = nullptr; HHOOK gTouchHook = nullptr;
std::thread* gMouseHookThread; std::thread* gMouseHookThread;
HHOOK gMouseHook = nullptr; HHOOK gMouseHook = nullptr;
bool gStarted = false; bool gStarted = false;
std::chrono::microseconds gStartTime = std::chrono::microseconds(0); microseconds gStartTime = microseconds(0);
const long long gFrequency = []() -> long long {
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency.QuadPart;
}();
std::unordered_map< std::unordered_map<
UINT32, UINT32,
std::unique_ptr<openspace::TouchInputHolder> std::unique_ptr<openspace::TouchInputHolder>
...@@ -79,10 +85,14 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) { ...@@ -79,10 +85,14 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
break; break;
} }
using namespace std::chrono; //Implementation from microsoft STL of high_resolution_clock(steady_clock):
const microseconds timestamp = duration_cast<microseconds>( const long long freq = gFrequency;
high_resolution_clock::now().time_since_epoch() const long long whole = (info.PerformanceCount / freq) * std::micro::den;
) - gStartTime; const long long part = (info.PerformanceCount % freq) *
std::micro::den / freq;
const microseconds timestamp =
duration<UINT64, std::micro>(whole + part) - gStartTime;
RECT rect; RECT rect;
GetClientRect(pStruct->hwnd, reinterpret_cast<LPRECT>(&rect)); GetClientRect(pStruct->hwnd, reinterpret_cast<LPRECT>(&rect));
...@@ -100,7 +110,7 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) { ...@@ -100,7 +110,7 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
static_cast<size_t>(info.pointerId), static_cast<size_t>(info.pointerId),
xPos, xPos,
yPos, yPos,
static_cast<double>(timestamp.count())/1'000'000.0 static_cast<double>(timestamp.count()) / 1'000'000.0
); );
if (info.pointerFlags & POINTER_FLAG_DOWN) { if (info.pointerFlags & POINTER_FLAG_DOWN) {
...@@ -213,9 +223,8 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow) ...@@ -213,9 +223,8 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow)
if (!gStarted) { if (!gStarted) {
gStarted = true; gStarted = true;
gStartTime = std::chrono::duration_cast<std::chrono::microseconds>( gStartTime =
std::chrono::high_resolution_clock::now().time_since_epoch() duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch());
);
#ifdef ENABLE_TUIOMESSAGES #ifdef ENABLE_TUIOMESSAGES
gTuioServer = new TUIO::TuioServer("localhost", 3333); gTuioServer = new TUIO::TuioServer("localhost", 3333);
TUIO::TuioTime::initSession(); TUIO::TuioTime::initSession();
......
...@@ -221,7 +221,7 @@ void TouchModule::internalInitialize(const ghoul::Dictionary& /*dictionary*/){ ...@@ -221,7 +221,7 @@ void TouchModule::internalInitialize(const ghoul::Dictionary& /*dictionary*/){
global::callback::touchUpdated.push_back( global::callback::touchUpdated.push_back(
[this](TouchInput i) { [this](TouchInput i) {
updateOrAddTouchInput(i); updateOrAddTouchInput(i);
return true; return true;
} }
); );
......
...@@ -42,6 +42,20 @@ namespace { ...@@ -42,6 +42,20 @@ namespace {
"Property to track a nodeline. When tracking the label text will be updating the " "Property to track a nodeline. When tracking the label text will be updating the "
"distance from the nodeline start and end." "distance from the nodeline start and end."
}; };
constexpr openspace::properties::Property::PropertyInfo DistanceUnitInfo = {
"DistanceUnit",
"Distance Unit",
"Property to define the unit in which the distance should be displayed."
"Defaults to 'km' if not specified."
};
constexpr openspace::properties::Property::PropertyInfo CustomUnitDescriptorInfo = {
"CustomUnitDescriptor",
"Custom Unit Descriptor",
"Property to define a custom unit descriptor to use to describe the distance value."
"Defaults to the units SI descriptor if not specified."
};
} }
namespace openspace { namespace openspace {
...@@ -58,6 +72,18 @@ documentation::Documentation RenderableDistanceLabel::Documentation() { ...@@ -58,6 +72,18 @@ documentation::Documentation RenderableDistanceLabel::Documentation() {
Optional::No, Optional::No,
NodeLineInfo.description NodeLineInfo.description
}, },
{
DistanceUnitInfo.identifier,
new IntVerifier,
Optional::Yes,
DistanceUnitInfo.description
},
{
CustomUnitDescriptorInfo.identifier,
new StringVerifier,
Optional::Yes,
CustomUnitDescriptorInfo.description
}
} }
}; };
} }
...@@ -65,6 +91,8 @@ documentation::Documentation RenderableDistanceLabel::Documentation() { ...@@ -65,6 +91,8 @@ documentation::Documentation RenderableDistanceLabel::Documentation() {
RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictionary) RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictionary)
: RenderableLabels(dictionary) : RenderableLabels(dictionary)
, _nodelineId(NodeLineInfo) , _nodelineId(NodeLineInfo)
, _distanceUnit(DistanceUnitInfo, 1, 0, 11)
, _customUnitDescriptor(CustomUnitDescriptorInfo)
{ {
documentation::testSpecificationAndThrow( documentation::testSpecificationAndThrow(
Documentation(), Documentation(),
...@@ -76,6 +104,16 @@ RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictio ...@@ -76,6 +104,16 @@ RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictio
_nodelineId = dictionary.value<std::string>(NodeLineInfo.identifier); _nodelineId = dictionary.value<std::string>(NodeLineInfo.identifier);
addProperty(_nodelineId); addProperty(_nodelineId);
} }
if (dictionary.hasKey(DistanceUnitInfo.identifier)) {
_distanceUnit = static_cast<int>(
dictionary.value<double>(DistanceUnitInfo.identifier)
);
addProperty(_distanceUnit);
}
if (dictionary.hasKey(CustomUnitDescriptorInfo.identifier)) {
_customUnitDescriptor = dictionary.value<std::string>(CustomUnitDescriptorInfo.identifier);
addProperty(_customUnitDescriptor);
}
} }
void RenderableDistanceLabel::update(const UpdateData&) { void RenderableDistanceLabel::update(const UpdateData&) {
...@@ -87,7 +125,6 @@ void RenderableDistanceLabel::update(const UpdateData&) { ...@@ -87,7 +125,6 @@ void RenderableDistanceLabel::update(const UpdateData&) {
SceneGraphNode* nodelineNode = RE.scene()->sceneGraphNode(_nodelineId); SceneGraphNode* nodelineNode = RE.scene()->sceneGraphNode(_nodelineId);
if (nodelineNode) { if (nodelineNode) {
// Calculate distance
RenderableNodeLine* nodeline = dynamic_cast<RenderableNodeLine*>( RenderableNodeLine* nodeline = dynamic_cast<RenderableNodeLine*>(
nodelineNode->renderable() nodelineNode->renderable()
); );
...@@ -97,15 +134,23 @@ void RenderableDistanceLabel::update(const UpdateData&) { ...@@ -97,15 +134,23 @@ void RenderableDistanceLabel::update(const UpdateData&) {
return; return;
} }
double myDistance = nodeline->distance(); // Get used unit scale
const float scale = unit(_distanceUnit);
// Format string // Get unit descriptor text
float scale = unit(Kilometer); std::string unitDescriptor = toString(_distanceUnit);
std::string distanceText = std::to_string(std::round(myDistance / scale)); if (!_customUnitDescriptor.value().empty()) {
unitDescriptor = _customUnitDescriptor.value();
}
// Get distance as string and remove fractional part
std::string distanceText = std::to_string(std::round(nodeline->distance() / scale));
int pos = static_cast<int>(distanceText.find(".")); int pos = static_cast<int>(distanceText.find("."));
std::string subStr = distanceText.substr(pos); std::string subStr = distanceText.substr(pos);
distanceText.erase(pos, subStr.size()); distanceText.erase(pos, subStr.size());
std::string finalText = distanceText + " Km";
// Create final label text and set it
const std::string finalText = distanceText + " " + unitDescriptor;
setLabelText(finalText); setLabelText(finalText);
// Update placement of label with transformation matrix // Update placement of label with transformation matrix
......
...@@ -40,6 +40,8 @@ public: ...@@ -40,6 +40,8 @@ public:
private: private:
properties::StringProperty _nodelineId; properties::StringProperty _nodelineId;
properties::IntProperty _distanceUnit;
properties::StringProperty _customUnitDescriptor;
bool _errorThrown = false; bool _errorThrown = false;
}; };
......
...@@ -84,10 +84,9 @@ public: ...@@ -84,10 +84,9 @@ public:
void draw(); void draw();
void close(bool force = false); void close(bool force = false);
void sendTouchPressEvent(const CefMouseEvent & event, #ifdef WIN32
CefBrowserHost::MouseButtonType button, const int clickCount); void sendTouchEvent(const CefTouchEvent& event) const;
void sendResleasePressEvent(const CefMouseEvent & event, #endif
CefBrowserHost::MouseButtonType button, const int clickCount);
bool sendKeyEvent(const CefKeyEvent& event); bool sendKeyEvent(const CefKeyEvent& event);
bool sendMouseClickEvent(const CefMouseEvent& event, bool sendMouseClickEvent(const CefMouseEvent& event,
......
...@@ -84,6 +84,19 @@ private: ...@@ -84,6 +84,19 @@ private:
*/ */
CefMouseEvent mouseEvent(KeyModifier mods = KeyModifier::NoModifier); CefMouseEvent mouseEvent(KeyModifier mods = KeyModifier::NoModifier);
#ifdef WIN32
/**
* Build a CEF touch event based on our internal structure
*
* Note: as of 02/21/2020 we are using an older version of CEF on OSX
* than WIN32.
* This version does not handle the CefTouchEvent type and does
* not have any internal touch handling.
*/
CefTouchEvent touchEvent(const TouchInput& input,
const cef_touch_event_type_t eventType) const;
#endif
/** /**
* Find the CEF key event to use for a given action. * Find the CEF key event to use for a given action.
* *
......
...@@ -149,19 +149,11 @@ bool BrowserInstance::sendMouseClickEvent(const CefMouseEvent& event, ...@@ -149,19 +149,11 @@ bool BrowserInstance::sendMouseClickEvent(const CefMouseEvent& event,
return hasContent(event.x, event.y); return hasContent(event.x, event.y);
} }
void BrowserInstance::sendTouchPressEvent(const CefMouseEvent& event, #ifdef WIN32
CefBrowserHost::MouseButtonType button, void BrowserInstance::sendTouchEvent(const CefTouchEvent& event) const{
const int clickCount) _browser->GetHost()->SendTouchEvent(event);
{
_browser->GetHost()->SendMouseClickEvent(event, button, false, clickCount);
}
void BrowserInstance::sendResleasePressEvent(const CefMouseEvent& event,
CefBrowserHost::MouseButtonType button,
const int clickCount)
{
_browser->GetHost()->SendMouseClickEvent(event, button, true, clickCount);
} }
#endif
bool BrowserInstance::sendMouseMoveEvent(const CefMouseEvent& event) { bool BrowserInstance::sendMouseMoveEvent(const CefMouseEvent& event) {
constexpr const bool DidNotLeaveWindow = false; constexpr const bool DidNotLeaveWindow = false;
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <openspace/engine/globalscallbacks.h> #include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/globals.h> #include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h> #include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/interaction/interactionmonitor.h> #include <openspace/interaction/interactionmonitor.h>
#include <ghoul/logging/logmanager.h> #include <ghoul/logging/logmanager.h>
#include <fmt/format.h> #include <fmt/format.h>
...@@ -208,6 +210,13 @@ void EventHandler::initialize() { ...@@ -208,6 +210,13 @@ void EventHandler::initialize() {
} }
if (_validTouchStates.empty()) { if (_validTouchStates.empty()) {
#ifdef WIN32
CefTouchEvent event = touchEvent(
input,
cef_touch_event_type_t::CEF_TET_PRESSED
);
_browserInstance->sendTouchEvent(event);
#else
_mousePosition.x = windowPos.x; _mousePosition.x = windowPos.x;
_mousePosition.y = windowPos.y; _mousePosition.y = windowPos.y;
_leftButton.down = true; _leftButton.down = true;
...@@ -217,6 +226,7 @@ void EventHandler::initialize() { ...@@ -217,6 +226,7 @@ void EventHandler::initialize() {
false, false,
BrowserInstance::SingleClick BrowserInstance::SingleClick
); );
#endif
_validTouchStates.emplace_back(input); _validTouchStates.emplace_back(input);
} }
else { else {
...@@ -245,11 +255,20 @@ void EventHandler::initialize() { ...@@ -245,11 +255,20 @@ void EventHandler::initialize() {
); );
if (it == _validTouchStates.cbegin()) { if (it == _validTouchStates.cbegin()) {
#ifdef WIN32
CefTouchEvent event = touchEvent(
input,
cef_touch_event_type_t::CEF_TET_MOVED
);
_browserInstance->sendTouchEvent(event);
#else
glm::vec2 windowPos = input.currentWindowCoordinates(); glm::vec2 windowPos = input.currentWindowCoordinates();
_mousePosition.x = windowPos.x; _mousePosition.x = windowPos.x;
_mousePosition.y = windowPos.y; _mousePosition.y = windowPos.y;
_leftButton.down = true; _leftButton.down = true;
_browserInstance->sendMouseMoveEvent(mouseEvent()); _browserInstance->sendMouseMoveEvent(mouseEvent());
#endif
return true; return true;
} }
else if (it != _validTouchStates.cend()){ else if (it != _validTouchStates.cend()){
...@@ -280,8 +299,15 @@ void EventHandler::initialize() { ...@@ -280,8 +299,15 @@ void EventHandler::initialize() {
if (found == _validTouchStates.cend()) { if (found == _validTouchStates.cend()) {
return; return;
} }
#ifdef WIN32
CefTouchEvent event = touchEvent(
input,
cef_touch_event_type_t::CEF_TET_RELEASED
);
_browserInstance->sendTouchEvent(event);
#endif
_validTouchStates.erase(found); _validTouchStates.erase(found);
#ifndef WIN32
if (_validTouchStates.empty()) { if (_validTouchStates.empty()) {
glm::vec2 windowPos = input.currentWindowCoordinates(); glm::vec2 windowPos = input.currentWindowCoordinates();
_mousePosition.x = windowPos.x; _mousePosition.x = windowPos.x;
...@@ -294,6 +320,7 @@ void EventHandler::initialize() { ...@@ -294,6 +320,7 @@ void EventHandler::initialize() {
BrowserInstance::SingleClick BrowserInstance::SingleClick
); );
} }
#endif
} }
); );
} }
...@@ -337,7 +364,7 @@ bool EventHandler::mouseButtonCallback(MouseButton button, MouseAction action, ...@@ -337,7 +364,7 @@ bool EventHandler::mouseButtonCallback(MouseButton button, MouseAction action,
bool EventHandler::isDoubleClick(const MouseButtonState& button) const { bool EventHandler::isDoubleClick(const MouseButtonState& button) const {
// check time // check time
using namespace std::chrono; using namespace std::chrono;
auto now = high_resolution_clock::now(); auto now = high_resolution_clock::now();
milliseconds maxTimeDifference(doubleClickTime()); milliseconds maxTimeDifference(doubleClickTime());
auto requiredTime = button.lastClickTime + maxTimeDifference; auto requiredTime = button.lastClickTime + maxTimeDifference;
...@@ -438,6 +465,27 @@ CefMouseEvent EventHandler::mouseEvent(KeyModifier mods) { ...@@ -438,6 +465,27 @@ CefMouseEvent EventHandler::mouseEvent(KeyModifier mods) {
return event; return event;
} }
#ifdef WIN32
CefTouchEvent EventHandler::touchEvent(const TouchInput& input,
const cef_touch_event_type_t eventType) const
{
const glm::vec2 windowPos = input.currentWindowCoordinates();
CefTouchEvent event = {};
event.id = static_cast<int>(input.fingerId);
event.x = windowPos.x;
event.y = windowPos.y;
event.type = eventType;
const std::vector<std::pair<Key, KeyModifier>> &keyModVec =
global::navigationHandler.inputState().pressedKeys();
for (auto keyModPair : keyModVec) {
const KeyModifier mods = keyModVec[0].second;
event.modifiers |= static_cast<uint32_t>(mapToCefModifiers(mods));
}
event.pointer_type = cef_pointer_type_t::CEF_POINTER_TYPE_TOUCH;
return event;
}
#endif
void EventHandler::setBrowserInstance(BrowserInstance* browserInstance) { void EventHandler::setBrowserInstance(BrowserInstance* browserInstance) {
LDEBUG("Setting browser instance."); LDEBUG("Setting browser instance.");
_browserInstance = browserInstance; _browserInstance = browserInstance;
......
...@@ -34,7 +34,6 @@ namespace { ...@@ -34,7 +34,6 @@ namespace {
constexpr const double AngleEpsilon = 1E-7; constexpr const double AngleEpsilon = 1E-7;
constexpr const double DistanceRatioAimThreshold = 1E-4; constexpr const double DistanceRatioAimThreshold = 1E-4;
constexpr const double FlightDestinationFactor = 1E-4;
constexpr const openspace::properties::Property::PropertyInfo AnchorInfo = { constexpr const openspace::properties::Property::PropertyInfo AnchorInfo = {
"Anchor", "Anchor",
...@@ -155,6 +154,12 @@ namespace { ...@@ -155,6 +154,12 @@ namespace {
"The final distance we want to fly to, with regards to the anchor node." "The final distance we want to fly to, with regards to the anchor node."
}; };
constexpr openspace::properties::Property::PropertyInfo FlightDestinationFactorInfo = {
"FlightDestinationFactor",
"Flight Destination Factor",
"The minimal distance factor that we need to reach to end linear flight."
};
constexpr openspace::properties::Property::PropertyInfo constexpr openspace::properties::Property::PropertyInfo
StereoInterpolationTimeInfo = { StereoInterpolationTimeInfo = {
"StereoInterpolationTime", "StereoInterpolationTime",
...@@ -232,6 +237,7 @@ OrbitalNavigator::OrbitalNavigator() ...@@ -232,6 +237,7 @@ OrbitalNavigator::OrbitalNavigator()
, _velocitySensitivity(VelocityZoomControlInfo, 0.02f, 0.01f, 0.15f) , _velocitySensitivity(VelocityZoomControlInfo, 0.02f, 0.01f, 0.15f)
, _applyLinearFlight(ApplyLinearFlightInfo, false) , _applyLinearFlight(ApplyLinearFlightInfo, false)
, _flightDestinationDistance(FlightDestinationDistanceInfo, 2e8f, 0.0f, 1e10f) , _flightDestinationDistance(FlightDestinationDistanceInfo, 2e8f, 0.0f, 1e10f)
, _flightDestinationFactor(FlightDestinationFactorInfo, 1E-4, 1E-6, 0.5)
, _mouseSensitivity(MouseSensitivityInfo, 15.0f, 1.0f, 50.f) , _mouseSensitivity(MouseSensitivityInfo, 15.0f, 1.0f, 50.f)
, _joystickSensitivity(JoystickSensitivityInfo, 10.0f, 1.0f, 50.f) , _joystickSensitivity(JoystickSensitivityInfo, 10.0f, 1.0f, 50.f)
, _websocketSensitivity(WebsocketSensitivityInfo, 10.0f, 1.0f, 50.f) , _websocketSensitivity(WebsocketSensitivityInfo, 10.0f, 1.0f, 50.f)
...@@ -362,6 +368,7 @@ OrbitalNavigator::OrbitalNavigator() ...@@ -362,6 +368,7 @@ OrbitalNavigator::OrbitalNavigator()
addProperty(_minimumAllowedDistance); addProperty(_minimumAllowedDistance);
addProperty(_velocitySensitivity); addProperty(_velocitySensitivity);
addProperty(_flightDestinationDistance); addProperty(_flightDestinationDistance);
addProperty(_flightDestinationFactor);
addProperty(_applyLinearFlight); addProperty(_applyLinearFlight);
addProperty(_useAdaptiveStereoscopicDepth); addProperty(_useAdaptiveStereoscopicDepth);
...@@ -440,7 +447,7 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) { ...@@ -440,7 +447,7 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
double distFromCameraToFocus = glm::distance(prevCameraPosition, anchorPos) - nodeRadius; double distFromCameraToFocus = glm::distance(prevCameraPosition, anchorPos) - nodeRadius;
// Make the approximation delta size depending on the flight distance // Make the approximation delta size depending on the flight distance
double arrivalThreshold = _flightDestinationDistance.value() * FlightDestinationFactor; double arrivalThreshold = _flightDestinationDistance.value() * _flightDestinationFactor;
// Fly towards the flight destination distance. When getting closer than arrivalThreshold terminate the flight // Fly towards the flight destination distance. When getting closer than arrivalThreshold terminate the flight
if (abs(distFromCameraToFocus - _flightDestinationDistance.value()) > arrivalThreshold) { if (abs(distFromCameraToFocus - _flightDestinationDistance.value()) > arrivalThreshold) {
......
...@@ -73,32 +73,41 @@ float TouchInput::angleToPos(float otherX, float otherY) const { ...@@ -73,32 +73,41 @@ float TouchInput::angleToPos(float otherX, float otherY) const {
TouchInputHolder::TouchInputHolder(TouchInput input) TouchInputHolder::TouchInputHolder(TouchInput input)
: _inputs{ input } : _inputs{ input }
, _firstInput(input)
, _touchDeviceId(input.touchDeviceId) , _touchDeviceId(input.touchDeviceId)
, _fingerId(input.fingerId) , _fingerId(input.fingerId)
{} {}
bool TouchInputHolder::tryAddInput(TouchInput input) { bool TouchInputHolder::tryAddInput(TouchInput input) {
if(_inputs.empty()) {
_inputs.emplace_front(input);
return true;
}
constexpr const double ONE_MS = 0.001; constexpr const double ONE_MS = 0.001;
const TouchInput& lastInput = latestInput(); const TouchInput& lastInput = latestInput();
input.dx = input.x - lastInput.x; input.dx = input.x - lastInput.x;
input.dy = input.y - lastInput.y; input.dy = input.y - lastInput.y;
const bool sameTimeAsLastInput = (input.timestamp - lastInput.timestamp) > ONE_MS; const bool sameTimeAsLastInput = (input.timestamp - lastInput.timestamp) < ONE_MS;
bool wasInserted = false; bool successful = false;
if (isMoving()) { if (!sameTimeAsLastInput && isMoving()) {
_inputs.emplace_front(input); _inputs.emplace_front(input);
wasInserted = true; successful = true;
} }
else if (sameTimeAsLastInput && input.isMoving()) { else if (!sameTimeAsLastInput && input.isMoving()) {
_inputs.emplace_front(input); _inputs.emplace_front(input);
wasInserted = true; successful = true;
}
else if (!sameTimeAsLastInput){
_inputs.front().timestamp = input.timestamp;
successful = true;
} }
constexpr const int MaxInputs = 128; constexpr const int MaxInputs = 128;
if (_inputs.size() > MaxInputs) { if (_inputs.size() > MaxInputs) {
_inputs.pop_back(); _inputs.pop_back();
} }
return wasInserted; return successful;
} }
void TouchInputHolder::clearInputs() { void TouchInputHolder::clearInputs() {
...@@ -142,8 +151,7 @@ bool TouchInputHolder::isMoving() const { ...@@ -142,8 +151,7 @@ bool TouchInputHolder::isMoving() const {
if (_inputs.size() <= 1) { if (_inputs.size() <= 1) {
return false; return false;
} }
const TouchInput& currentInput = _inputs[0]; return latestInput().isMoving();
return currentInput.dx != 0.f || currentInput.dy != 0.f;
} }
float TouchInputHolder::gestureDistance() const { float TouchInputHolder::gestureDistance() const {
...@@ -174,6 +182,10 @@ size_t TouchInputHolder::numInputs() const { ...@@ -174,6 +182,10 @@ size_t TouchInputHolder::numInputs() const {
return _inputs.size(); return _inputs.size();
} }
const TouchInput& TouchInputHolder::firstInput() const {
return _firstInput;
}
const TouchInput& TouchInputHolder::latestInput() const { const TouchInput& TouchInputHolder::latestInput() const {
return _inputs.front(); return _inputs.front();
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment