Merge branch 'master' into feature/imgui-touchhandling

# Conflicts:
#	modules/touch/src/touchinteraction.cpp
This commit is contained in:
Alexander Bock
2020-03-28 20:41:47 +01:00
16 changed files with 311 additions and 103 deletions

View File

@@ -36,6 +36,7 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
#include <openspace/properties/triggerproperty.h>
#include <ghoul/glm.h>
#include <glm/gtx/quaternion.hpp>
@@ -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;

View File

@@ -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;
@@ -46,19 +49,25 @@ 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
};
// 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;
@@ -72,12 +81,14 @@ public:
double gestureTime() const;
size_t numInputs() const;
const TouchInput& firstInput() const;
const TouchInput& latestInput() const;
const std::deque<TouchInput>& peekInputs() const;
private:
//A deque of recorded inputs. Adding newer points to the front of the queue
std::deque<TouchInput> _inputs;
TouchInput _firstInput;
size_t _touchDeviceId;
size_t _fingerId;

View File

@@ -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

View File

@@ -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);

View File

@@ -35,6 +35,7 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/vector/ivec2property.h>
#include <openspace/properties/vector/vec4property.h>
#include <array>
#include <chrono>
#include <memory>
@@ -94,7 +95,7 @@ public:
std::vector<TouchInput>& 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();
@@ -159,6 +160,7 @@ private:
properties::IntProperty _deceleratesPerSecond;
properties::FloatProperty _touchScreenSize;
properties::FloatProperty _tapZoomFactor;
properties::FloatProperty _pinchZoomFactor;
properties::FloatProperty _nodeRadiusThreshold;
properties::FloatProperty _rollAngleThreshold;
properties::FloatProperty _orbitSpeedThreshold;
@@ -193,7 +195,7 @@ private:
double pinchConsecZoomFactor = 0;
//int stepVelUpdate = 0;
#endif
std::array<TouchInputHolder, 2> _pinchInputs;
// Class variables
VelocityStates _vel;
VelocityStates _lastVel;

View File

@@ -116,6 +116,13 @@ namespace {
"" // @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 = {
"DirectManipulationRadius",
"Radius a planet has to have to activate direct-manipulation",
@@ -257,6 +264,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)
@@ -270,7 +278,12 @@ TouchInteraction::TouchInteraction()
0.25f
)
, _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())
, _inputStillThreshold(InputSensitivityInfo, 0.0005f, 0.f, 0.001f)
// used to void wrongly interpreted roll interactions
@@ -290,8 +303,9 @@ TouchInteraction::TouchInteraction()
0.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) }
, _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.
@@ -303,6 +317,7 @@ TouchInteraction::TouchInteraction()
addProperty(_deceleratesPerSecond);
addProperty(_touchScreenSize);
addProperty(_tapZoomFactor);
addProperty(_pinchZoomFactor);
addProperty(_nodeRadiusThreshold);
addProperty(_rollAngleThreshold);
addProperty(_orbitSpeedThreshold);
@@ -442,7 +457,7 @@ void TouchInteraction::directControl(const std::vector<TouchInputHolder>& 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;
@@ -720,6 +735,15 @@ int TouchInteraction::interpretInteraction(const std::vector<TouchInputHolder>&
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;
}
}
@@ -759,6 +783,9 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li
#endif
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) {
case ROT: { // add rotation velocity
_vel.orbit += glm::dvec2(inputHolder.speedX() *
@@ -772,54 +799,31 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& 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();
// points this/first frame
using namespace glm;
const TouchInput& startFinger0 = _pinchInputs[0].firstInput();
const TouchInput& startFinger1 = _pinchInputs[1].firstInput();
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;
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();
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;
const double distanceFromFocusSurface =
length(currDistanceToFocusNode) - anchor->boundingSphere();
double zoomFactor = (distance - lastDistance);
double zoomFactor = 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<float>(_zoomSensitivityExponential)
);
}
}
else {
zoomFactor = 1.0;
}
_vel.zoom = zoomFactor * _zoomSensitivityProportionalDist *
std::max(_touchScreenSize.value() * 0.1, 1.0);
_constTimeDecayCoeff.zoom = 1.0;
_vel.zoom = zoomFactor *
_pinchZoomFactor *
_zoomSensitivityProportionalDist *
std::max(_touchScreenSize.value() * 0.1, 1.0);
break;
}
case ROLL: {
@@ -860,7 +864,7 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& 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);
@@ -868,7 +872,7 @@ void TouchInteraction::computeVelocities(const std::vector<TouchInputHolder>& li
break;
}
case PICK: {
// pick something in the scene as focus node
// pick something in the scene as focus node
if (_pickingSelected) {
setFocusNode(_pickingSelected);
@@ -935,7 +939,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 =
@@ -1046,22 +1050,45 @@ 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<float>(_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 =
(currentPosDistance >= _zoomOutLimit.value());
(currentPosDistance >= _zoomOutLimit);
const bool willNewPositionViolateZoomOutLimit =
(newPosDistance >= _zoomOutLimit.value());
(newPosDistance >= _zoomOutLimit);
bool willNewPositionViolateZoomInLimit =
(newPosDistance < zoomInBounds);
bool willNewPositionViolateDirection =
(currentPosDistance <= length(zoomDistanceIncrement));
if (!willNewPositionViolateZoomInLimit
&& !willNewPositionViolateZoomOutLimit) {
if (!willNewPositionViolateZoomInLimit &&
!willNewPositionViolateDirection &&
!willNewPositionViolateZoomOutLimit)
{
camPos += zoomDistanceIncrement;
}
else if (currentPosViolatingZoomOutLimit) {
@@ -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;
// Reset variables
@@ -1155,6 +1196,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;
}
@@ -1167,6 +1213,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);

View File

@@ -40,12 +40,18 @@
#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);
return frequency.QuadPart;
}();
std::unordered_map<
UINT32,
std::unique_ptr<openspace::TouchInputHolder>
@@ -79,10 +85,14 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
break;
}
using namespace std::chrono;
const microseconds timestamp = duration_cast<microseconds>(
high_resolution_clock::now().time_since_epoch()
) - 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<UINT64, std::micro>(whole + part) - gStartTime;
RECT rect;
GetClientRect(pStruct->hwnd, reinterpret_cast<LPRECT>(&rect));
@@ -100,7 +110,7 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
static_cast<size_t>(info.pointerId),
xPos,
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) {
@@ -213,9 +223,8 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow)
if (!gStarted) {
gStarted = true;
gStartTime = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
);
gStartTime =
duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch());
#ifdef ENABLE_TUIOMESSAGES
gTuioServer = new TUIO::TuioServer("localhost", 3333);
TUIO::TuioTime::initSession();

View File

@@ -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;
}
);

View File

@@ -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<std::string>(NodeLineInfo.identifier);
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&) {
@@ -87,7 +125,6 @@ void RenderableDistanceLabel::update(const UpdateData&) {
SceneGraphNode* nodelineNode = RE.scene()->sceneGraphNode(_nodelineId);
if (nodelineNode) {
// Calculate distance
RenderableNodeLine* nodeline = dynamic_cast<RenderableNodeLine*>(
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<int>(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

View File

@@ -40,6 +40,8 @@ public:
private:
properties::StringProperty _nodelineId;
properties::IntProperty _distanceUnit;
properties::StringProperty _customUnitDescriptor;
bool _errorThrown = false;
};

View File

@@ -84,10 +84,9 @@ 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);
#ifdef WIN32
void sendTouchEvent(const CefTouchEvent& event) const;
#endif
bool sendKeyEvent(const CefKeyEvent& event);
bool sendMouseClickEvent(const CefMouseEvent& event,

View File

@@ -84,6 +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.
*

View File

@@ -149,19 +149,11 @@ 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);
#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;

View File

@@ -28,6 +28,8 @@
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/interaction/interactionmonitor.h>
#include <ghoul/logging/logmanager.h>
#include <fmt/format.h>
@@ -208,6 +210,13 @@ 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;
@@ -217,6 +226,7 @@ void EventHandler::initialize() {
false,
BrowserInstance::SingleClick
);
#endif
_validTouchStates.emplace_back(input);
}
else {
@@ -245,11 +255,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()){
@@ -280,8 +299,15 @@ 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;
@@ -294,6 +320,7 @@ void EventHandler::initialize() {
BrowserInstance::SingleClick
);
}
#endif
}
);
}
@@ -337,7 +364,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 +465,27 @@ CefMouseEvent EventHandler::mouseEvent(KeyModifier mods) {
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) {
LDEBUG("Setting browser instance.");
_browserInstance = browserInstance;

View File

@@ -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, 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)
@@ -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) {

View File

@@ -73,32 +73,41 @@ float TouchInput::angleToPos(float otherX, float otherY) const {
TouchInputHolder::TouchInputHolder(TouchInput input)
: _inputs{ input }
, _firstInput(input)
, _touchDeviceId(input.touchDeviceId)
, _fingerId(input.fingerId)
{}
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 +151,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 +182,10 @@ size_t TouchInputHolder::numInputs() const {
return _inputs.size();
}
const TouchInput& TouchInputHolder::firstInput() const {
return _firstInput;
}
const TouchInput& TouchInputHolder::latestInput() const {
return _inputs.front();
}