From 6f63da86b49c4d9901caac427e83b8dda136287c Mon Sep 17 00:00:00 2001 From: Stefan Seibert Date: Tue, 18 Feb 2020 10:39:48 +0100 Subject: [PATCH 01/17] Exposed linear flight factor as property --- include/openspace/interaction/orbitalnavigator.h | 3 ++- src/interaction/orbitalnavigator.cpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/openspace/interaction/orbitalnavigator.h b/include/openspace/interaction/orbitalnavigator.h index c6671c8d6f..623cc5fd3f 100644 --- a/include/openspace/interaction/orbitalnavigator.h +++ b/include/openspace/interaction/orbitalnavigator.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -143,8 +144,8 @@ private: properties::FloatProperty _followAnchorNodeRotationDistance; properties::FloatProperty _minimumAllowedDistance; properties::FloatProperty _flightDestinationDistance; + properties::DoubleProperty _flightDestinationFactor; properties::BoolProperty _applyLinearFlight; - properties::FloatProperty _velocitySensitivity; properties::FloatProperty _mouseSensitivity; diff --git a/src/interaction/orbitalnavigator.cpp b/src/interaction/orbitalnavigator.cpp index 773aca85ea..91258ed584 100644 --- a/src/interaction/orbitalnavigator.cpp +++ b/src/interaction/orbitalnavigator.cpp @@ -34,7 +34,6 @@ namespace { constexpr const double AngleEpsilon = 1E-7; constexpr const double DistanceRatioAimThreshold = 1E-4; - constexpr const double FlightDestinationFactor = 1E-4; constexpr const openspace::properties::Property::PropertyInfo AnchorInfo = { "Anchor", @@ -155,6 +154,12 @@ namespace { "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 StereoInterpolationTimeInfo = { "StereoInterpolationTime", @@ -232,6 +237,7 @@ OrbitalNavigator::OrbitalNavigator() , _velocitySensitivity(VelocityZoomControlInfo, 0.02f, 0.01f, 0.15f) , _applyLinearFlight(ApplyLinearFlightInfo, false) , _flightDestinationDistance(FlightDestinationDistanceInfo, 2e8f, 0.0f, 1e10f) + , _flightDestinationFactor(FlightDestinationFactorInfo, 1E-4) , _mouseSensitivity(MouseSensitivityInfo, 15.0f, 1.0f, 50.f) , _joystickSensitivity(JoystickSensitivityInfo, 10.0f, 1.0f, 50.f) , _websocketSensitivity(WebsocketSensitivityInfo, 10.0f, 1.0f, 50.f) @@ -362,6 +368,7 @@ OrbitalNavigator::OrbitalNavigator() addProperty(_minimumAllowedDistance); addProperty(_velocitySensitivity); addProperty(_flightDestinationDistance); + addProperty(_flightDestinationFactor); addProperty(_applyLinearFlight); addProperty(_useAdaptiveStereoscopicDepth); @@ -440,7 +447,7 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) { double distFromCameraToFocus = glm::distance(prevCameraPosition, anchorPos) - nodeRadius; // 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 if (abs(distFromCameraToFocus - _flightDestinationDistance.value()) > arrivalThreshold) { From e94a08f86618eed37fb961e12f03931efa741978 Mon Sep 17 00:00:00 2001 From: Stefan Seibert Date: Tue, 18 Feb 2020 10:52:31 +0100 Subject: [PATCH 02/17] Added min and max --- src/interaction/orbitalnavigator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interaction/orbitalnavigator.cpp b/src/interaction/orbitalnavigator.cpp index 91258ed584..efcd4bace1 100644 --- a/src/interaction/orbitalnavigator.cpp +++ b/src/interaction/orbitalnavigator.cpp @@ -237,7 +237,7 @@ OrbitalNavigator::OrbitalNavigator() , _velocitySensitivity(VelocityZoomControlInfo, 0.02f, 0.01f, 0.15f) , _applyLinearFlight(ApplyLinearFlightInfo, false) , _flightDestinationDistance(FlightDestinationDistanceInfo, 2e8f, 0.0f, 1e10f) - , _flightDestinationFactor(FlightDestinationFactorInfo, 1E-4) + , _flightDestinationFactor(FlightDestinationFactorInfo, 1E-4, 1E-6, 0.5) , _mouseSensitivity(MouseSensitivityInfo, 15.0f, 1.0f, 50.f) , _joystickSensitivity(JoystickSensitivityInfo, 10.0f, 1.0f, 50.f) , _websocketSensitivity(WebsocketSensitivityInfo, 10.0f, 1.0f, 50.f) From 38d0f46ca605823c3aaad18ee3f6ddf9b316953f Mon Sep 17 00:00:00 2001 From: stefanseibert Date: Wed, 4 Mar 2020 15:57:34 +0100 Subject: [PATCH 03/17] Added a way to customize renderable distance labels unit --- modules/base/rendering/renderablelabels.cpp | 18 ++++++ modules/base/rendering/renderablelabels.h | 2 + .../rendering/renderabledistancelabel.cpp | 57 +++++++++++++++++-- .../rendering/renderabledistancelabel.h | 2 + 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/modules/base/rendering/renderablelabels.cpp b/modules/base/rendering/renderablelabels.cpp index e661982bc0..2fa6c17ba4 100644 --- a/modules/base/rendering/renderablelabels.cpp +++ b/modules/base/rendering/renderablelabels.cpp @@ -784,4 +784,22 @@ float RenderableLabels::unit(int unit) const { } } +std::string RenderableLabels::toString(int unit) const { + switch (static_cast(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 diff --git a/modules/base/rendering/renderablelabels.h b/modules/base/rendering/renderablelabels.h index 7be35abaef..c35d52d451 100644 --- a/modules/base/rendering/renderablelabels.h +++ b/modules/base/rendering/renderablelabels.h @@ -74,6 +74,8 @@ protected: float unit(int unit) const; + std::string toString(int unit) const; + // Data may require some type of transformation prior the spice transformation being // applied. glm::dmat4 _transformationMatrix = glm::dmat4(1.0); diff --git a/modules/vislab/rendering/renderabledistancelabel.cpp b/modules/vislab/rendering/renderabledistancelabel.cpp index 1d2cac67b8..47508e3114 100644 --- a/modules/vislab/rendering/renderabledistancelabel.cpp +++ b/modules/vislab/rendering/renderabledistancelabel.cpp @@ -42,6 +42,20 @@ namespace { "Property to track a nodeline. When tracking the label text will be updating the " "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 { @@ -58,6 +72,18 @@ documentation::Documentation RenderableDistanceLabel::Documentation() { Optional::No, 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() { RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictionary) : RenderableLabels(dictionary) , _nodelineId(NodeLineInfo) + , _distanceUnit(DistanceUnitInfo, 1, 0, 11) + , _customUnitDescriptor(CustomUnitDescriptorInfo) { documentation::testSpecificationAndThrow( Documentation(), @@ -76,6 +104,16 @@ RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictio _nodelineId = dictionary.value(NodeLineInfo.identifier); addProperty(_nodelineId); } + if (dictionary.hasKey(DistanceUnitInfo.identifier)) { + _distanceUnit = static_cast( + dictionary.value(DistanceUnitInfo.identifier) + ); + addProperty(_distanceUnit); + } + if (dictionary.hasKey(CustomUnitDescriptorInfo.identifier)) { + _customUnitDescriptor = dictionary.value(CustomUnitDescriptorInfo.identifier); + addProperty(_customUnitDescriptor); + } } void RenderableDistanceLabel::update(const UpdateData&) { @@ -87,7 +125,6 @@ void RenderableDistanceLabel::update(const UpdateData&) { SceneGraphNode* nodelineNode = RE.scene()->sceneGraphNode(_nodelineId); if (nodelineNode) { - // Calculate distance RenderableNodeLine* nodeline = dynamic_cast( nodelineNode->renderable() ); @@ -97,15 +134,23 @@ void RenderableDistanceLabel::update(const UpdateData&) { return; } - double myDistance = nodeline->distance(); + // Get used unit scale + const float scale = unit(_distanceUnit); - // Format string - float scale = unit(Kilometer); - std::string distanceText = std::to_string(std::round(myDistance / scale)); + // Get unit descriptor text + std::string unitDescriptor = toString(_distanceUnit); + 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(distanceText.find(".")); std::string subStr = distanceText.substr(pos); 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); // Update placement of label with transformation matrix diff --git a/modules/vislab/rendering/renderabledistancelabel.h b/modules/vislab/rendering/renderabledistancelabel.h index 42f0f4165d..effb4efe71 100644 --- a/modules/vislab/rendering/renderabledistancelabel.h +++ b/modules/vislab/rendering/renderabledistancelabel.h @@ -40,6 +40,8 @@ public: private: properties::StringProperty _nodelineId; + properties::IntProperty _distanceUnit; + properties::StringProperty _customUnitDescriptor; bool _errorThrown = false; }; From c46beadcf96dd765f20e2c0dc807cf191acf579c Mon Sep 17 00:00:00 2001 From: stefanseibert Date: Fri, 6 Mar 2020 10:48:01 +0100 Subject: [PATCH 04/17] style change --- modules/vislab/rendering/renderabledistancelabel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/vislab/rendering/renderabledistancelabel.cpp b/modules/vislab/rendering/renderabledistancelabel.cpp index 47508e3114..eac120946d 100644 --- a/modules/vislab/rendering/renderabledistancelabel.cpp +++ b/modules/vislab/rendering/renderabledistancelabel.cpp @@ -107,7 +107,7 @@ RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictio if (dictionary.hasKey(DistanceUnitInfo.identifier)) { _distanceUnit = static_cast( dictionary.value(DistanceUnitInfo.identifier) - ); + ); addProperty(_distanceUnit); } if (dictionary.hasKey(CustomUnitDescriptorInfo.identifier)) { From 4e9aae3f78292985e227109c3c25649ffb121238 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 09:09:58 +0100 Subject: [PATCH 05/17] Read out timestamps from actual touchevent rather than doing it from the message pumping. This produces less scattered timestamps as we now get the timestamp from the touch monitor driver. --- modules/touch/src/win32_touch.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/modules/touch/src/win32_touch.cpp b/modules/touch/src/win32_touch.cpp index 9507b5ef8a..9796247790 100644 --- a/modules/touch/src/win32_touch.cpp +++ b/modules/touch/src/win32_touch.cpp @@ -46,6 +46,11 @@ namespace { HHOOK gMouseHook = nullptr; bool gStarted = false; std::chrono::microseconds gStartTime = std::chrono::microseconds(0); + const long long gFrequency = []() -> long long { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return frequency.QuadPart; + }(); std::unordered_map< UINT32, std::unique_ptr @@ -80,9 +85,9 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) { } using namespace std::chrono; - const microseconds timestamp = duration_cast( - high_resolution_clock::now().time_since_epoch() - ) - gStartTime; + const microseconds timestamp = duration( + info.PerformanceCount * std::micro::den / gFrequency) - gStartTime; + RECT rect; GetClientRect(pStruct->hwnd, reinterpret_cast(&rect)); @@ -100,7 +105,7 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) { static_cast(info.pointerId), xPos, yPos, - static_cast(timestamp.count())/1'000'000.0 + static_cast(timestamp.count()) / 1'000'000.0 ); if (info.pointerFlags & POINTER_FLAG_DOWN) { @@ -213,8 +218,10 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow) if (!gStarted) { gStarted = true; - gStartTime = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch() + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + gStartTime = std::chrono::duration( + count.QuadPart * std::micro::den / gFrequency ); #ifdef ENABLE_TUIOMESSAGES gTuioServer = new TUIO::TuioServer("localhost", 3333); From b9210a65fdf335abe16cc0415f0d30c7d2c04006 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 09:52:30 +0100 Subject: [PATCH 06/17] Changed (and simplified) some internal logic of the touch class --- include/openspace/util/touch.h | 4 +++- src/util/touch.cpp | 29 ++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/include/openspace/util/touch.h b/include/openspace/util/touch.h index cb9a6e71da..a7f8500a93 100644 --- a/include/openspace/util/touch.h +++ b/include/openspace/util/touch.h @@ -46,7 +46,7 @@ struct TouchInput { float y; float dx = 0.f; // movement in x 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 }; class TouchInputHolder { @@ -56,6 +56,7 @@ public: // tryAddInput: // Succeeds upon a different input than last. // Fails upon a too similar input as last. + // Updates time for the last input if same position. bool tryAddInput(TouchInput input); void clearInputs(); @@ -72,6 +73,7 @@ public: double gestureTime() const; size_t numInputs() const; + const TouchInput& firstInput() const; const TouchInput& latestInput() const; const std::deque& peekInputs() const; diff --git a/src/util/touch.cpp b/src/util/touch.cpp index aa0ef75ddd..d5381daa01 100644 --- a/src/util/touch.cpp +++ b/src/util/touch.cpp @@ -78,27 +78,35 @@ TouchInputHolder::TouchInputHolder(TouchInput input) {} bool TouchInputHolder::tryAddInput(TouchInput input) { + if(_inputs.empty()) { + _inputs.emplace_front(input); + return true; + } constexpr const double ONE_MS = 0.001; const TouchInput& lastInput = latestInput(); input.dx = input.x - lastInput.x; input.dy = input.y - lastInput.y; - const bool sameTimeAsLastInput = (input.timestamp - lastInput.timestamp) > ONE_MS; - bool wasInserted = false; - if (isMoving()) { + const bool sameTimeAsLastInput = (input.timestamp - lastInput.timestamp) < ONE_MS; + bool successful = false; + if (!sameTimeAsLastInput && isMoving()) { _inputs.emplace_front(input); - wasInserted = true; + successful = true; } - else if (sameTimeAsLastInput && input.isMoving()) { + else if (!sameTimeAsLastInput && input.isMoving()) { _inputs.emplace_front(input); - wasInserted = true; + successful = true; + } + else if (!sameTimeAsLastInput){ + _inputs.front().timestamp = input.timestamp; + successful = true; } constexpr const int MaxInputs = 128; if (_inputs.size() > MaxInputs) { _inputs.pop_back(); } - return wasInserted; + return successful; } void TouchInputHolder::clearInputs() { @@ -142,8 +150,7 @@ bool TouchInputHolder::isMoving() const { if (_inputs.size() <= 1) { return false; } - const TouchInput& currentInput = _inputs[0]; - return currentInput.dx != 0.f || currentInput.dy != 0.f; + return latestInput().isMoving(); } float TouchInputHolder::gestureDistance() const { @@ -174,6 +181,10 @@ size_t TouchInputHolder::numInputs() const { return _inputs.size(); } +const TouchInput& TouchInputHolder::firstInput() const { + return _inputs.back(); +} + const TouchInput& TouchInputHolder::latestInput() const { return _inputs.front(); } From a991a8052544b10f1810441465f9a1a47f665942 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 09:57:07 +0100 Subject: [PATCH 07/17] Made pinch input default to continuous zoom - Added a directTouch bool field to touch step function - Some logic of how to gather accumulated zoom value --- modules/touch/include/touchinteraction.h | 6 +- modules/touch/src/touchinteraction.cpp | 106 +++++++++++++---------- modules/touch/touchmodule.cpp | 2 +- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/modules/touch/include/touchinteraction.h b/modules/touch/include/touchinteraction.h index 8faed8bbfb..b4e89ffeb7 100644 --- a/modules/touch/include/touchinteraction.h +++ b/modules/touch/include/touchinteraction.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -96,7 +97,7 @@ public: std::vector& lastProcessed); // 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 void resetAfterInput(); @@ -202,7 +203,7 @@ private: double pinchConsecZoomFactor = 0; //int stepVelUpdate = 0; #endif - + std::array _pinchInputs; // Class variables VelocityStates _vel; VelocityStates _lastVel; @@ -242,4 +243,3 @@ private: } // openspace namespace #endif // __OPENSPACE_MODULE_TOUCH___TOUCH_INTERACTION___H__ - diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index b12795b9e6..31c6c44be5 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -307,6 +307,8 @@ TouchInteraction::TouchInteraction() { "Ignore GUI", "Disable GUI touch interaction", "" }, false ) + , _pinchInputs({ TouchInput(0x0, 0x0, 0.0, 0.0, 0.0), + TouchInput(0x0, 0x0, 0.0, 0.0, 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) } , _constTimeDecay_secs(ConstantTimeDecaySecsInfo, 1.75f, 0.1f, 4.0f) @@ -494,7 +496,7 @@ void TouchInteraction::directControl(const std::vector& list) _vel.pan = glm::dvec2(par.at(4), par.at(5)); } } - step(1.0); + step(1.0, true); // Reset velocities after setting new camera state _lastVel = _vel; @@ -777,6 +779,16 @@ int TouchInteraction::interpretInteraction(const std::vector& return ROLL; } 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; } } @@ -818,6 +830,10 @@ void TouchInteraction::computeVelocities(const std::vector& li const TouchInputHolder& inputHolder = list.at(0); switch (action) { case ROT: { // add rotation velocity + const auto inputs = inputHolder.peekInputs(); + if(inputs.size() > 1 ){ + const float dt = inputs[0].timestamp - inputs[1].timestamp; + } _vel.orbit += glm::dvec2(inputHolder.speedX() * _sensitivity.orbit.x, inputHolder.speedY() * _sensitivity.orbit.y); @@ -830,51 +846,25 @@ void TouchInteraction::computeVelocities(const std::vector& li case PINCH: { // add zooming velocity - dependant on distance difference between contact // points this/last frame - double distance = std::accumulate( - list.begin(), - list.end(), - 0.0, - [&](double d, const TouchInputHolder& c) { - const glm::vec2 currPos = { c.latestInput().x, c.latestInput().y }; - return d + glm::distance(currPos, _centroid); - } - ) / list.size(); - double lastDistance = std::accumulate( - lastProcessed.begin(), - lastProcessed.end(), - 0.f, - [&](float d, const TouchInput& p) { - const glm::vec2 lastPos = { p.x, p.y }; - return d + glm::distance(lastPos, _centroid); - } - ) / lastProcessed.size(); + const TouchInput& startFinger0 = _pinchInputs[0].firstInput(); + const TouchInput& startFinger1 = _pinchInputs[1].firstInput(); + double distToCentroidStart = + glm::length(glm::dvec2(startFinger0.x, startFinger0.y) - + glm::dvec2(startFinger1.x, startFinger1.y)) / 2.0; - glm::dvec3 camPos = _camera->positionVec3(); - glm::dvec3 centerPos = anchor->worldPosition(); - glm::dvec3 currDistanceToFocusNode = camPos - centerPos; + const TouchInput& endFinger0 = _pinchInputs[0].latestInput(); + const TouchInput& endFinger1 = _pinchInputs[1].latestInput(); + double distToCentroidEnd = + glm::length(glm::dvec2(endFinger0.x, endFinger0.y) - + glm::dvec2(endFinger1.x, endFinger1.y)) / 2.0; - const double distanceFromFocusSurface = - length(currDistanceToFocusNode) - anchor->boundingSphere(); - double zoomFactor = (distance - lastDistance); + double zoomFactor = 0.01*(distToCentroidEnd - distToCentroidStart); #ifdef TOUCH_DEBUG_PROPERTIES pinchConsecCt++; pinchConsecZoomFactor += zoomFactor; #endif - _constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom); - if (distanceFromFocusSurface > 0.1) { - const double ratioOfDistanceToNodeVsSurface = - length(currDistanceToFocusNode) / distanceFromFocusSurface; - if (ratioOfDistanceToNodeVsSurface > _zoomSensitivityDistanceThreshold) { - zoomFactor *= pow( - std::abs(distanceFromFocusSurface), - static_cast(_zoomSensitivityExponential) - ); - } - } - else { - zoomFactor = 1.0; - } + _constTimeDecayCoeff.zoom = 1.0; _vel.zoom = zoomFactor * _zoomSensitivityProportionalDist * std::max(_touchScreenSize.value() * 0.1, 1.0); break; @@ -917,7 +907,7 @@ void TouchInteraction::computeVelocities(const std::vector& li break; } case PAN: { - // add local rotation velocity + // add local rotation velocity _vel.pan += glm::dvec2(inputHolder.speedX() * _sensitivity.pan.x, inputHolder.speedY() * _sensitivity.pan.y); double panVelocityAvg = glm::distance(_vel.pan.x, _vel.pan.y); @@ -925,7 +915,7 @@ void TouchInteraction::computeVelocities(const std::vector& li break; } case PICK: { - // pick something in the scene as focus node + // pick something in the scene as focus node if (_pickingSelected) { setFocusNode(_pickingSelected); @@ -992,7 +982,7 @@ double TouchInteraction::computeTapZoomDistance(double zoomGain) { // Main update call, calculates the new orientation and position for the camera depending // on _vel and dt. Called every frame -void TouchInteraction::step(double dt) { +void TouchInteraction::step(double dt, bool directTouch) { using namespace glm; const SceneGraphNode* anchor = @@ -1103,11 +1093,30 @@ void TouchInteraction::step(double dt) { _loggerCat, _zoomOutLimit.value() )); } + const double currentPosDistance = length(centerToCamera); //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(_zoomSensitivityExponential) + ); + } + } + else { + zoomVelocity = 1.0; + } + } + + const glm::dvec3 zoomDistanceIncrement = directionToCenter * zoomVelocity * dt; const double newPosDistance = length(centerToCamera + zoomDistanceIncrement); - const double currentPosDistance = length(centerToCamera); // Possible with other navigations performed outside touch interaction const bool currentPosViolatingZoomOutLimit = @@ -1116,8 +1125,11 @@ void TouchInteraction::step(double dt) { (newPosDistance >= _zoomOutLimit.value()); bool willNewPositionViolateZoomInLimit = (newPosDistance < zoomInBounds); + bool willNewPositionViolateDirection = + (currentPosDistance <= length(zoomDistanceIncrement)); if (!willNewPositionViolateZoomInLimit + && !willNewPositionViolateDirection && !willNewPositionViolateZoomOutLimit) { camPos += zoomDistanceIncrement; } @@ -1218,7 +1230,6 @@ void TouchInteraction::resetAfterInput() { module.touchInput.active = false; module.touchInput.action = 0; } - _lmSuccess = true; // Ensure that _guiON is consistent with properties in OnScreenGUI and _guiON = module.gui.isEnabled(); @@ -1228,6 +1239,11 @@ void TouchInteraction::resetAfterInput() { _lastVel.zoom = 0.0; _lastVel.roll = 0.0; _lastVel.pan = glm::dvec2(0.0); + + _constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom); + _pinchInputs[0].clearInputs(); + _pinchInputs[1].clearInputs(); + _selected.clear(); _pickingSelected = nullptr; } diff --git a/modules/touch/touchmodule.cpp b/modules/touch/touchmodule.cpp index 73a12cbbfc..1672b2cf42 100644 --- a/modules/touch/touchmodule.cpp +++ b/modules/touch/touchmodule.cpp @@ -221,7 +221,7 @@ void TouchModule::internalInitialize(const ghoul::Dictionary& /*dictionary*/){ global::callback::touchUpdated.push_back( [this](TouchInput i) { updateOrAddTouchInput(i); - return true; + return true; } ); From fd0a9743a2e81348ebfdb8a3156ff0da5f9c096e Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 10:25:31 +0100 Subject: [PATCH 08/17] Touch: Added a firstInput so that if we ever get more than max amount of inputs in our Deque, we will still have our first point stored (for pinching around a start-centroid mainly) --- include/openspace/util/touch.h | 1 + src/util/touch.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/openspace/util/touch.h b/include/openspace/util/touch.h index a7f8500a93..a7e8bc0735 100644 --- a/include/openspace/util/touch.h +++ b/include/openspace/util/touch.h @@ -80,6 +80,7 @@ public: private: //A deque of recorded inputs. Adding newer points to the front of the queue std::deque _inputs; + TouchInput _firstInput; size_t _touchDeviceId; size_t _fingerId; diff --git a/src/util/touch.cpp b/src/util/touch.cpp index d5381daa01..f08c5cab03 100644 --- a/src/util/touch.cpp +++ b/src/util/touch.cpp @@ -73,6 +73,7 @@ float TouchInput::angleToPos(float otherX, float otherY) const { TouchInputHolder::TouchInputHolder(TouchInput input) : _inputs{ input } + , _firstInput(input) , _touchDeviceId(input.touchDeviceId) , _fingerId(input.fingerId) {} @@ -182,7 +183,7 @@ size_t TouchInputHolder::numInputs() const { } const TouchInput& TouchInputHolder::firstInput() const { - return _inputs.back(); + return _firstInput; } const TouchInput& TouchInputHolder::latestInput() const { From 7b282ae77c2a8ca53674f8dfa729c0b1135ff84b Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 17:58:14 +0100 Subject: [PATCH 09/17] Replaced magic value with a property and added a quick and dirty aspect ratio to the pinch-zoom handling --- modules/touch/include/touchinteraction.h | 1 + modules/touch/src/touchinteraction.cpp | 33 +++++++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/touch/include/touchinteraction.h b/modules/touch/include/touchinteraction.h index b4e89ffeb7..f1713c2f20 100644 --- a/modules/touch/include/touchinteraction.h +++ b/modules/touch/include/touchinteraction.h @@ -167,6 +167,7 @@ private: properties::IntProperty _deceleratesPerSecond; properties::FloatProperty _touchScreenSize; properties::FloatProperty _tapZoomFactor; + properties::FloatProperty _pinchZoomFactor; properties::FloatProperty _nodeRadiusThreshold; properties::FloatProperty _rollAngleThreshold; properties::FloatProperty _orbitSpeedThreshold; diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index 31c6c44be5..0f0c575870 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -117,6 +117,11 @@ namespace { "" // @TODO Missing documentation }; + constexpr openspace::properties::Property::PropertyInfo PinchZoomFactorInfo = { + "PinchZoomFactor", "Scaling distance travelled on pinch", + "" // @TODO Missing documentation + }; + constexpr openspace::properties::Property::PropertyInfo DirectManipulationInfo = { "DirectManipulationRadius", "Radius a planet has to have to activate direct-manipulation", @@ -264,6 +269,7 @@ TouchInteraction::TouchInteraction() , _deceleratesPerSecond(DecelatesPerSecondInfo, 240, 60, 300) , _touchScreenSize(TouchScreenSizeInfo, 55.0f, 5.5f, 150.0f) , _tapZoomFactor(TapZoomFactorInfo, 0.2f, 0.f, 0.5f) + , _pinchZoomFactor(PinchZoomFactorInfo, 0.01f, 0.f, 0.2f) , _nodeRadiusThreshold(DirectManipulationInfo, 0.2f, 0.0f, 1.0f) , _rollAngleThreshold(RollThresholdInfo, 0.025f, 0.f, 0.05f) , _orbitSpeedThreshold(OrbitSpinningThreshold, 0.005f, 0.f, 0.01f) @@ -322,6 +328,7 @@ TouchInteraction::TouchInteraction() addProperty(_deceleratesPerSecond); addProperty(_touchScreenSize); addProperty(_tapZoomFactor); + addProperty(_pinchZoomFactor); addProperty(_nodeRadiusThreshold); addProperty(_rollAngleThreshold); addProperty(_orbitSpeedThreshold); @@ -828,12 +835,11 @@ void TouchInteraction::computeVelocities(const std::vector& li #endif const TouchInputHolder& inputHolder = list.at(0); + const glm::ivec2 windowSize = global::windowDelegate.currentWindowSize(); + const float aspectRatio = + static_cast(windowSize.x) / static_cast(windowSize.y); switch (action) { case ROT: { // add rotation velocity - const auto inputs = inputHolder.peekInputs(); - if(inputs.size() > 1 ){ - const float dt = inputs[0].timestamp - inputs[1].timestamp; - } _vel.orbit += glm::dvec2(inputHolder.speedX() * _sensitivity.orbit.x, inputHolder.speedY() * _sensitivity.orbit.y); @@ -845,28 +851,30 @@ void TouchInteraction::computeVelocities(const std::vector& li } case PINCH: { // add zooming velocity - dependant on distance difference between contact - // points this/last frame + // points this/first frame const TouchInput& startFinger0 = _pinchInputs[0].firstInput(); const TouchInput& startFinger1 = _pinchInputs[1].firstInput(); double distToCentroidStart = - glm::length(glm::dvec2(startFinger0.x, startFinger0.y) - - glm::dvec2(startFinger1.x, startFinger1.y)) / 2.0; + glm::length(glm::dvec2(startFinger0.x * aspectRatio, startFinger0.y) - + glm::dvec2(startFinger1.x * aspectRatio, startFinger1.y)) / 2.0; const TouchInput& endFinger0 = _pinchInputs[0].latestInput(); const TouchInput& endFinger1 = _pinchInputs[1].latestInput(); double distToCentroidEnd = - glm::length(glm::dvec2(endFinger0.x, endFinger0.y) - - glm::dvec2(endFinger1.x, endFinger1.y)) / 2.0; + glm::length(glm::dvec2(endFinger0.x * aspectRatio, endFinger0.y) - + glm::dvec2(endFinger1.x * aspectRatio, endFinger1.y)) / 2.0; - double zoomFactor = 0.01*(distToCentroidEnd - distToCentroidStart); + double zoomFactor = distToCentroidEnd - distToCentroidStart; #ifdef TOUCH_DEBUG_PROPERTIES pinchConsecCt++; pinchConsecZoomFactor += zoomFactor; #endif _constTimeDecayCoeff.zoom = 1.0; - _vel.zoom = zoomFactor * _zoomSensitivityProportionalDist * - std::max(_touchScreenSize.value() * 0.1, 1.0); + _vel.zoom = zoomFactor * + _pinchZoomFactor * + _zoomSensitivityProportionalDist * + std::max(_touchScreenSize.value() * 0.1, 1.0); break; } case ROLL: { @@ -1256,6 +1264,7 @@ void TouchInteraction::resetToDefault() { _deceleratesPerSecond.set(240); _touchScreenSize.set(55.0f); _tapZoomFactor.set(0.2f); + _pinchZoomFactor.set(0.01f); _nodeRadiusThreshold.set(0.2f); _rollAngleThreshold.set(0.025f); _orbitSpeedThreshold.set(0.005f); From 42462ccfab57bce7b0d6ab602092adde1eb39219 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 18:22:50 +0100 Subject: [PATCH 10/17] Minor cleanup for code clarity --- modules/touch/src/touchinteraction.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index 0f0c575870..01634ea46a 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -852,17 +852,18 @@ void TouchInteraction::computeVelocities(const std::vector& li case PINCH: { // add zooming velocity - dependant on distance difference between contact // points this/first frame + using namespace glm; const TouchInput& startFinger0 = _pinchInputs[0].firstInput(); const TouchInput& startFinger1 = _pinchInputs[1].firstInput(); - double distToCentroidStart = - glm::length(glm::dvec2(startFinger0.x * aspectRatio, startFinger0.y) - - glm::dvec2(startFinger1.x * aspectRatio, startFinger1.y)) / 2.0; + const dvec2 startVec0 = dvec2(startFinger0.x * aspectRatio, startFinger0.y); + const dvec2 startVec1 = dvec2(startFinger1.x * aspectRatio, startFinger1.y); + double distToCentroidStart = length(startVec0 - startVec1) / 2.0; const TouchInput& endFinger0 = _pinchInputs[0].latestInput(); const TouchInput& endFinger1 = _pinchInputs[1].latestInput(); - double distToCentroidEnd = - glm::length(glm::dvec2(endFinger0.x * aspectRatio, endFinger0.y) - - glm::dvec2(endFinger1.x * aspectRatio, endFinger1.y)) / 2.0; + const dvec2 endVec0 = dvec2(endFinger0.x * aspectRatio, endFinger0.y); + const dvec2 endVec1 = dvec2(endFinger1.x * aspectRatio, endFinger1.y); + double distToCentroidEnd = length(endVec0 - endVec1) / 2.0; double zoomFactor = distToCentroidEnd - distToCentroidStart; #ifdef TOUCH_DEBUG_PROPERTIES From 0808ebb1b4b7fc8d6658084d9dc3e4c86ee5f081 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Tue, 10 Mar 2020 18:34:11 +0100 Subject: [PATCH 11/17] Added documentation for the pinchzoomfactor property --- modules/touch/src/touchinteraction.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index 01634ea46a..cf36a632e5 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -118,8 +118,10 @@ namespace { }; constexpr openspace::properties::Property::PropertyInfo PinchZoomFactorInfo = { - "PinchZoomFactor", "Scaling distance travelled on pinch", - "" // @TODO Missing documentation + "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 = { @@ -1106,7 +1108,7 @@ void TouchInteraction::step(double dt, bool directTouch) { //Apply the velocity to update camera position double zoomVelocity = _vel.zoom; - if(!directTouch) { + if (!directTouch) { const double distanceFromSurface = length(currentPosDistance) - anchor->boundingSphere(); if (distanceFromSurface > 0.1) { From c9e35cbee4c13907c32225df6c7f921d6bc6a5e9 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Thu, 12 Mar 2020 15:12:29 +0100 Subject: [PATCH 12/17] Changed back from windows API calls to stl calls for timings Should be the same under-the-hood but produces more consistent code --- modules/touch/src/win32_touch.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/touch/src/win32_touch.cpp b/modules/touch/src/win32_touch.cpp index 9796247790..948a242941 100644 --- a/modules/touch/src/win32_touch.cpp +++ b/modules/touch/src/win32_touch.cpp @@ -40,12 +40,13 @@ #define ENABLE_DIRECTMSG namespace { + using namespace std::chrono; constexpr const char* _loggerCat = "win32_touch"; HHOOK gTouchHook = nullptr; std::thread* gMouseHookThread; HHOOK gMouseHook = nullptr; 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); @@ -84,9 +85,13 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) { break; } - using namespace std::chrono; - const microseconds timestamp = duration( - info.PerformanceCount * std::micro::den / gFrequency) - gStartTime; + //Implementation from microsoft STL of high_resolution_clock(steady_clock): + const long long freq = gFrequency; + const long long whole = (info.PerformanceCount / freq) * std::micro::den; + const long long part = (info.PerformanceCount % freq) * + std::micro::den / freq; + const microseconds timestamp = + duration(whole + part) - gStartTime; RECT rect; GetClientRect(pStruct->hwnd, reinterpret_cast(&rect)); @@ -218,11 +223,8 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow) if (!gStarted) { gStarted = true; - LARGE_INTEGER count; - QueryPerformanceCounter(&count); - gStartTime = std::chrono::duration( - count.QuadPart * std::micro::den / gFrequency - ); + gStartTime = + duration_cast(high_resolution_clock::now().time_since_epoch()); #ifdef ENABLE_TUIOMESSAGES gTuioServer = new TUIO::TuioServer("localhost", 3333); TUIO::TuioTime::initSession(); From c9b5ffd0213fda6a0492f19d54877b55b2e430d0 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Thu, 13 Feb 2020 09:58:56 +0100 Subject: [PATCH 13/17] Changed webbrowser to use cef touch events rather than injected mouse events. --- modules/webbrowser/include/browserinstance.h | 5 +- modules/webbrowser/include/eventhandler.h | 2 + modules/webbrowser/src/browserinstance.cpp | 14 +---- modules/webbrowser/src/eventhandler.cpp | 57 ++++++++++---------- 4 files changed, 35 insertions(+), 43 deletions(-) diff --git a/modules/webbrowser/include/browserinstance.h b/modules/webbrowser/include/browserinstance.h index b96e701da8..071accc2aa 100644 --- a/modules/webbrowser/include/browserinstance.h +++ b/modules/webbrowser/include/browserinstance.h @@ -84,10 +84,7 @@ public: void draw(); void close(bool force = false); - void sendTouchPressEvent(const CefMouseEvent & event, - CefBrowserHost::MouseButtonType button, const int clickCount); - void sendResleasePressEvent(const CefMouseEvent & event, - CefBrowserHost::MouseButtonType button, const int clickCount); + void sendTouchEvent(const CefTouchEvent& event) const; bool sendKeyEvent(const CefKeyEvent& event); bool sendMouseClickEvent(const CefMouseEvent& event, diff --git a/modules/webbrowser/include/eventhandler.h b/modules/webbrowser/include/eventhandler.h index 406b27813d..918667b420 100644 --- a/modules/webbrowser/include/eventhandler.h +++ b/modules/webbrowser/include/eventhandler.h @@ -84,6 +84,8 @@ private: */ CefMouseEvent mouseEvent(KeyModifier mods = KeyModifier::NoModifier); + CefTouchEvent touchEvent(const TouchInput& input, + const cef_touch_event_type_t eventType) const; /** * Find the CEF key event to use for a given action. * diff --git a/modules/webbrowser/src/browserinstance.cpp b/modules/webbrowser/src/browserinstance.cpp index 52016fe15f..0f7ec357b7 100644 --- a/modules/webbrowser/src/browserinstance.cpp +++ b/modules/webbrowser/src/browserinstance.cpp @@ -149,18 +149,8 @@ bool BrowserInstance::sendMouseClickEvent(const CefMouseEvent& event, return hasContent(event.x, event.y); } -void BrowserInstance::sendTouchPressEvent(const CefMouseEvent& event, - CefBrowserHost::MouseButtonType button, - const int clickCount) -{ - _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); +void BrowserInstance::sendTouchEvent(const CefTouchEvent& event) const{ + _browser->GetHost()->SendTouchEvent(event); } bool BrowserInstance::sendMouseMoveEvent(const CefMouseEvent& event) { diff --git a/modules/webbrowser/src/eventhandler.cpp b/modules/webbrowser/src/eventhandler.cpp index 0ee3e8f7a3..d9dc17424f 100644 --- a/modules/webbrowser/src/eventhandler.cpp +++ b/modules/webbrowser/src/eventhandler.cpp @@ -208,15 +208,11 @@ void EventHandler::initialize() { } if (_validTouchStates.empty()) { - _mousePosition.x = windowPos.x; - _mousePosition.y = windowPos.y; - _leftButton.down = true; - _browserInstance->sendMouseClickEvent( - mouseEvent(), - MBT_LEFT, - false, - BrowserInstance::SingleClick + CefTouchEvent event = touchEvent( + input, + cef_touch_event_type_t::CEF_TET_PRESSED ); + _browserInstance->sendTouchEvent(event); _validTouchStates.emplace_back(input); } else { @@ -245,11 +241,11 @@ void EventHandler::initialize() { ); if (it == _validTouchStates.cbegin()) { - glm::vec2 windowPos = input.currentWindowCoordinates(); - _mousePosition.x = windowPos.x; - _mousePosition.y = windowPos.y; - _leftButton.down = true; - _browserInstance->sendMouseMoveEvent(mouseEvent()); + CefTouchEvent event = touchEvent( + input, + cef_touch_event_type_t::CEF_TET_MOVED + ); + _browserInstance->sendTouchEvent(event); return true; } else if (it != _validTouchStates.cend()){ @@ -280,20 +276,12 @@ void EventHandler::initialize() { if (found == _validTouchStates.cend()) { return; } - + CefTouchEvent event = touchEvent( + input, + cef_touch_event_type_t::CEF_TET_RELEASED + ); + _browserInstance->sendTouchEvent(event); _validTouchStates.erase(found); - if (_validTouchStates.empty()) { - glm::vec2 windowPos = input.currentWindowCoordinates(); - _mousePosition.x = windowPos.x; - _mousePosition.y = windowPos.y; - _leftButton.down = false; - _browserInstance->sendMouseClickEvent( - mouseEvent(), - MBT_LEFT, - true, - BrowserInstance::SingleClick - ); - } } ); } @@ -337,7 +325,7 @@ bool EventHandler::mouseButtonCallback(MouseButton button, MouseAction action, bool EventHandler::isDoubleClick(const MouseButtonState& button) const { // check time using namespace std::chrono; - + auto now = high_resolution_clock::now(); milliseconds maxTimeDifference(doubleClickTime()); auto requiredTime = button.lastClickTime + maxTimeDifference; @@ -438,6 +426,21 @@ CefMouseEvent EventHandler::mouseEvent(KeyModifier mods) { return event; } +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(input.fingerId); + event.x = windowPos.x; + event.y = windowPos.y; + event.type = eventType; + //TODO: We should probably use key mods for touch as well: + // event.modifiers = mods; + event.pointer_type = cef_pointer_type_t::CEF_POINTER_TYPE_TOUCH; + return event; +} + void EventHandler::setBrowserInstance(BrowserInstance* browserInstance) { LDEBUG("Setting browser instance."); _browserInstance = browserInstance; From 3210dfd31582326f60c6e78caa3885db445c937d Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Fri, 21 Feb 2020 13:32:54 +0100 Subject: [PATCH 14/17] Made these changes only apply on Win32 builds --- modules/webbrowser/include/browserinstance.h | 2 + modules/webbrowser/include/eventhandler.h | 11 ++++++ modules/webbrowser/src/browserinstance.cpp | 2 + modules/webbrowser/src/eventhandler.cpp | 39 ++++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/modules/webbrowser/include/browserinstance.h b/modules/webbrowser/include/browserinstance.h index 071accc2aa..5e74c6806c 100644 --- a/modules/webbrowser/include/browserinstance.h +++ b/modules/webbrowser/include/browserinstance.h @@ -84,7 +84,9 @@ public: void draw(); void close(bool force = false); +#ifdef WIN32 void sendTouchEvent(const CefTouchEvent& event) const; +#endif bool sendKeyEvent(const CefKeyEvent& event); bool sendMouseClickEvent(const CefMouseEvent& event, diff --git a/modules/webbrowser/include/eventhandler.h b/modules/webbrowser/include/eventhandler.h index 918667b420..e08f2fbfc7 100644 --- a/modules/webbrowser/include/eventhandler.h +++ b/modules/webbrowser/include/eventhandler.h @@ -84,8 +84,19 @@ private: */ 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. * diff --git a/modules/webbrowser/src/browserinstance.cpp b/modules/webbrowser/src/browserinstance.cpp index 0f7ec357b7..14eaaef9b0 100644 --- a/modules/webbrowser/src/browserinstance.cpp +++ b/modules/webbrowser/src/browserinstance.cpp @@ -149,9 +149,11 @@ bool BrowserInstance::sendMouseClickEvent(const CefMouseEvent& event, return hasContent(event.x, event.y); } +#ifdef WIN32 void BrowserInstance::sendTouchEvent(const CefTouchEvent& event) const{ _browser->GetHost()->SendTouchEvent(event); } +#endif bool BrowserInstance::sendMouseMoveEvent(const CefMouseEvent& event) { constexpr const bool DidNotLeaveWindow = false; diff --git a/modules/webbrowser/src/eventhandler.cpp b/modules/webbrowser/src/eventhandler.cpp index d9dc17424f..33c6db3a98 100644 --- a/modules/webbrowser/src/eventhandler.cpp +++ b/modules/webbrowser/src/eventhandler.cpp @@ -208,11 +208,23 @@ void EventHandler::initialize() { } 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.y = windowPos.y; + _leftButton.down = true; + _browserInstance->sendMouseClickEvent( + mouseEvent(), + MBT_LEFT, + false, + BrowserInstance::SingleClick + ); +#endif _validTouchStates.emplace_back(input); } else { @@ -241,11 +253,20 @@ void EventHandler::initialize() { ); 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(); + _mousePosition.x = windowPos.x; + _mousePosition.y = windowPos.y; + _leftButton.down = true; + _browserInstance->sendMouseMoveEvent(mouseEvent()); +#endif return true; } else if (it != _validTouchStates.cend()){ @@ -276,12 +297,28 @@ void EventHandler::initialize() { if (found == _validTouchStates.cend()) { return; } +#ifdef WIN32 CefTouchEvent event = touchEvent( input, cef_touch_event_type_t::CEF_TET_RELEASED ); _browserInstance->sendTouchEvent(event); +#endif _validTouchStates.erase(found); +#ifndef WIN32 + if (_validTouchStates.empty()) { + glm::vec2 windowPos = input.currentWindowCoordinates(); + _mousePosition.x = windowPos.x; + _mousePosition.y = windowPos.y; + _leftButton.down = false; + _browserInstance->sendMouseClickEvent( + mouseEvent(), + MBT_LEFT, + true, + BrowserInstance::SingleClick + ); + } +#endif } ); } @@ -426,6 +463,7 @@ CefMouseEvent EventHandler::mouseEvent(KeyModifier mods) { return event; } +#ifdef WIN32 CefTouchEvent EventHandler::touchEvent(const TouchInput& input, const cef_touch_event_type_t eventType) const { @@ -440,6 +478,7 @@ CefTouchEvent EventHandler::touchEvent(const TouchInput& input, event.pointer_type = cef_pointer_type_t::CEF_POINTER_TYPE_TOUCH; return event; } +#endif void EventHandler::setBrowserInstance(BrowserInstance* browserInstance) { LDEBUG("Setting browser instance."); From fa5bbc5a44b3c55474a6594d8be31ce8f25150c7 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Wed, 11 Mar 2020 14:06:23 +0100 Subject: [PATCH 15/17] Added keymodifiers to touch event handling --- modules/webbrowser/src/eventhandler.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/webbrowser/src/eventhandler.cpp b/modules/webbrowser/src/eventhandler.cpp index 33c6db3a98..b7f4d55c96 100644 --- a/modules/webbrowser/src/eventhandler.cpp +++ b/modules/webbrowser/src/eventhandler.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -473,8 +475,12 @@ CefTouchEvent EventHandler::touchEvent(const TouchInput& input, event.x = windowPos.x; event.y = windowPos.y; event.type = eventType; - //TODO: We should probably use key mods for touch as well: - // event.modifiers = mods; + const std::vector> &keyModVec = + global::navigationHandler.inputState().pressedKeys(); + for (auto keyModPair : keyModVec) { + const KeyModifier mods = keyModVec[0].second; + event.modifiers |= static_cast(mapToCefModifiers(mods)); + } event.pointer_type = cef_pointer_type_t::CEF_POINTER_TYPE_TOUCH; return event; } From 1c57f8ad21815f41236744fd1ef935b1b3b5d383 Mon Sep 17 00:00:00 2001 From: Mikael Date: Wed, 25 Mar 2020 10:01:56 +0100 Subject: [PATCH 16/17] Added more explanatory comments of the Touch-implementation --- include/openspace/util/touch.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/openspace/util/touch.h b/include/openspace/util/touch.h index a7e8bc0735..3d1e1bf8a4 100644 --- a/include/openspace/util/touch.h +++ b/include/openspace/util/touch.h @@ -32,6 +32,9 @@ 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 { TouchInput(size_t touchDeviceId, size_t fingerId, float x, float y, double timestamp); glm::vec2 screenCoordinates(glm::vec2 resolution) const; @@ -49,17 +52,22 @@ struct TouchInput { 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 { public: TouchInputHolder(TouchInput input); - // tryAddInput: // Succeeds upon a different input than last. // Fails upon a too similar input as last. // Updates time for the last input if same position. bool tryAddInput(TouchInput input); + 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; size_t touchDeviceId() const; From 5209de548421076709aef2c79a40c40a9e2a4fce Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 28 Mar 2020 20:32:53 +0100 Subject: [PATCH 17/17] Some coding style fixes --- modules/touch/src/touchinteraction.cpp | 36 ++++++++++++++------------ 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index cf36a632e5..099296c3c2 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -118,10 +118,10 @@ namespace { }; 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." + "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 = { @@ -285,7 +285,12 @@ TouchInteraction::TouchInteraction() 0.25f ) , _zoomBoundarySphereMultiplier(ZoomBoundarySphereMultiplierInfo, 1.001f, 1.f, 1.01f) - , _zoomOutLimit(ZoomOutLimitInfo, std::numeric_limits::max(), 1000.0, std::numeric_limits::max()) + , _zoomOutLimit( + ZoomOutLimitInfo, + std::numeric_limits::max(), + 1000.0, + std::numeric_limits::max() + ) , _zoomInLimit(ZoomInLimitInfo, -1.0, 0.0, std::numeric_limits::max()) , _inputStillThreshold(InputSensitivityInfo, 0.0005f, 0.f, 0.001f) // used to void wrongly interpreted roll interactions @@ -315,10 +320,9 @@ TouchInteraction::TouchInteraction() { "Ignore GUI", "Disable GUI touch interaction", "" }, false ) - , _pinchInputs({ TouchInput(0x0, 0x0, 0.0, 0.0, 0.0), - TouchInput(0x0, 0x0, 0.0, 0.0, 0.0) }) + , _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) } - , _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) // calculated with two vectors with known diff in length, then // projDiffLength/diffLength. @@ -790,11 +794,10 @@ int TouchInteraction::interpretInteraction(const std::vector& else { const bool sameInput0 = _pinchInputs[0].holdsInput(list[0].latestInput()); const bool sameInput1 = _pinchInputs[1].holdsInput(list[1].latestInput()); - if(sameInput0 && sameInput1) - { + if (sameInput0 && sameInput1) { _pinchInputs[0].tryAddInput(list[0].latestInput()); _pinchInputs[1].tryAddInput(list[1].latestInput()); - }else{ + } else { _pinchInputs[0] = TouchInputHolder(list[0].latestInput()); _pinchInputs[1] = TouchInputHolder(list[1].latestInput()); } @@ -1131,17 +1134,18 @@ void TouchInteraction::step(double dt, bool directTouch) { // Possible with other navigations performed outside touch interaction const bool currentPosViolatingZoomOutLimit = - (currentPosDistance >= _zoomOutLimit.value()); + (currentPosDistance >= _zoomOutLimit); const bool willNewPositionViolateZoomOutLimit = - (newPosDistance >= _zoomOutLimit.value()); + (newPosDistance >= _zoomOutLimit); bool willNewPositionViolateZoomInLimit = (newPosDistance < zoomInBounds); bool willNewPositionViolateDirection = (currentPosDistance <= length(zoomDistanceIncrement)); - if (!willNewPositionViolateZoomInLimit - && !willNewPositionViolateDirection - && !willNewPositionViolateZoomOutLimit) { + if (!willNewPositionViolateZoomInLimit && + !willNewPositionViolateDirection && + !willNewPositionViolateZoomOutLimit) + { camPos += zoomDistanceIncrement; } else if (currentPosViolatingZoomOutLimit) {