mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-21 18:38:20 -05:00
Made imgui handle touch input as the webgui does
Also removed imgui-handling code in touchinteraction
This commit is contained in:
@@ -171,10 +171,6 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
uint32_t mouseButtons = delegate.mouseButtons(2);
|
||||
|
||||
const double dt = std::max(delegate.averageDeltaTime(), 0.0);
|
||||
if (touchInput.active && mouseButtons == 0) {
|
||||
mouseButtons = touchInput.action;
|
||||
mousePosition = touchInput.pos;
|
||||
}
|
||||
// We don't do any collection of immediate mode user interface, so it
|
||||
// is fine to open and close a frame immediately
|
||||
gui.startFrame(
|
||||
@@ -252,6 +248,24 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
global::callback::touchDetected.emplace_back(
|
||||
[&](TouchInput input) -> bool {
|
||||
return gui.touchDetectedCallback(input);
|
||||
}
|
||||
);
|
||||
|
||||
global::callback::touchUpdated.emplace_back(
|
||||
[&](TouchInput input) -> bool {
|
||||
return gui.touchUpdatedCallback(input);
|
||||
}
|
||||
);
|
||||
|
||||
global::callback::touchExit.emplace_back(
|
||||
[&](TouchInput input) {
|
||||
gui.touchExitCallback(input);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -31,13 +31,6 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
// This should be moved into the touch module ---abock
|
||||
struct Touch {
|
||||
bool active;
|
||||
glm::vec2 pos = glm::vec2(0.f);
|
||||
uint32_t action = 0;
|
||||
};
|
||||
|
||||
class ImGUIModule : public OpenSpaceModule {
|
||||
public:
|
||||
constexpr static const char* Name = "ImGUI";
|
||||
@@ -45,7 +38,6 @@ public:
|
||||
ImGUIModule();
|
||||
|
||||
gui::GUI gui;
|
||||
Touch touchInput = { false, glm::vec2(0), 0 };
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/util/keys.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
#include <openspace/util/touch.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/uniformcache.h>
|
||||
@@ -89,6 +90,10 @@ public:
|
||||
bool keyCallback(Key key, KeyModifier modifier, KeyAction action);
|
||||
bool charCallback(unsigned int character, KeyModifier modifier);
|
||||
|
||||
bool touchDetectedCallback(TouchInput input);
|
||||
bool touchUpdatedCallback(TouchInput input);
|
||||
void touchExitCallback(TouchInput input);
|
||||
|
||||
void startFrame(float deltaTime, const glm::vec2& windowSize,
|
||||
const glm::vec2& dpiScaling, const glm::vec2& mousePos,
|
||||
uint32_t mouseButtonsPressed);
|
||||
@@ -169,6 +174,8 @@ private:
|
||||
properties::Property::Visibility::Developer;
|
||||
|
||||
std::vector<ImGuiContext*> _contexts;
|
||||
|
||||
std::vector<TouchInput> _validTouchStates;
|
||||
};
|
||||
|
||||
void CaptionText(const char* text);
|
||||
|
||||
@@ -637,6 +637,77 @@ bool GUI::charCallback(unsigned int character, KeyModifier) {
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool GUI::touchDetectedCallback(TouchInput input) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
bool consumeEvent = ImGui::IsPosHoveringAnyWindow({windowPos.x, windowPos.y});
|
||||
|
||||
if(!consumeEvent) {
|
||||
return false;
|
||||
}
|
||||
if(_validTouchStates.empty()) {
|
||||
io.MousePos = {windowPos.x, windowPos.y};
|
||||
io.MouseClicked[0] = true;
|
||||
}
|
||||
_validTouchStates.push_back(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUI::touchUpdatedCallback(TouchInput input) {
|
||||
if(_validTouchStates.empty()) {
|
||||
return false;
|
||||
}
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
auto it = std::find_if(
|
||||
_validTouchStates.cbegin(),
|
||||
_validTouchStates.cend(),
|
||||
[&](const TouchInput& state){
|
||||
return state.fingerId == input.fingerId &&
|
||||
state.touchDeviceId == input.touchDeviceId;
|
||||
}
|
||||
);
|
||||
|
||||
if (it == _validTouchStates.cbegin()) {
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
io.MousePos = {windowPos.x, windowPos.y};
|
||||
io.MouseClicked[0] = true;
|
||||
return true;
|
||||
}
|
||||
else if (it != _validTouchStates.cend()){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GUI::touchExitCallback(TouchInput input) {
|
||||
if (_validTouchStates.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto found = std::find_if(
|
||||
_validTouchStates.cbegin(),
|
||||
_validTouchStates.cend(),
|
||||
[&](const TouchInput& state){
|
||||
return state.fingerId == input.fingerId &&
|
||||
state.touchDeviceId == input.touchDeviceId;
|
||||
}
|
||||
);
|
||||
|
||||
if (found == _validTouchStates.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
_validTouchStates.erase(found);
|
||||
if (_validTouchStates.empty()) {
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
io.MousePos = {windowPos.x, windowPos.y};
|
||||
io.MouseClicked[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GUI::render() {
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
|
||||
|
||||
@@ -79,16 +79,14 @@ public:
|
||||
|
||||
/* Main function call
|
||||
* 1 Checks if doubleTap occured
|
||||
* 2 Goes through the guiMode() function
|
||||
* 3 Continues if GUI isn't on
|
||||
* 4 If the node in focus is large enough and all contact points have selected it,
|
||||
* 2 If the node in focus is large enough and all contact points have selected it,
|
||||
* calls directControl() function for direct-manipulation
|
||||
* 5 Updates std::vector<SelectedBody> _selected (only if LMA successfully
|
||||
* 3 Updates std::vector<SelectedBody> _selected (only if LMA successfully
|
||||
* converged, avoids interaction to snap on LMA fails)
|
||||
* 6 If directControl() wasn't called this frame, interpret the incoming
|
||||
* 4 If directControl() wasn't called this frame, interpret the incoming
|
||||
* list and decide what type of interaction this frame should do
|
||||
* 7 Compute the new total velocities after interaction
|
||||
* 8 Evaluate if directControl should be called next frame- true if all contact points
|
||||
* 5 Compute the new total velocities after interaction
|
||||
* 6 Evaluate if directControl should be called next frame- true if all contact points
|
||||
* select the same node and said node is larger than _nodeRadiusThreshold
|
||||
*/
|
||||
|
||||
@@ -114,11 +112,6 @@ public:
|
||||
void setCamera(Camera* camera);
|
||||
|
||||
private:
|
||||
/* Returns true if we have the GUI window open. If so, emulates the incoming touch
|
||||
* input to a mouse such that we can interact with the GUI
|
||||
*/
|
||||
bool isGuiMode(glm::dvec2 screenPosition, size_t numFingers);
|
||||
|
||||
/* Function that calculates the new camera state such that it minimizes the L2 error
|
||||
* in screenspace
|
||||
* between contact points and surface coordinates projected to clip space using LMA
|
||||
@@ -181,10 +174,8 @@ private:
|
||||
properties::BoolProperty _panEnabled;
|
||||
properties::FloatProperty _interpretPan;
|
||||
properties::FloatProperty _slerpTime;
|
||||
properties::IVec2Property _guiButton;
|
||||
properties::Vec4Property _friction;
|
||||
properties::FloatProperty _pickingRadiusMinimum;
|
||||
properties::BoolProperty _ignoreGui;
|
||||
properties::FloatProperty _constTimeDecay_secs;
|
||||
|
||||
#ifdef TOUCH_DEBUG_PROPERTIES
|
||||
@@ -220,7 +211,6 @@ private:
|
||||
bool _doubleTap = false;
|
||||
bool _zoomOutTap = false;
|
||||
bool _lmSuccess = true;
|
||||
bool _guiON = false;
|
||||
std::vector<DirectInputSolver::SelectedBody> _selected;
|
||||
SceneGraphNode* _pickingSelected = nullptr;
|
||||
DirectInputSolver _solver;
|
||||
@@ -242,4 +232,3 @@ private:
|
||||
} // openspace namespace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_TOUCH___TOUCH_INTERACTION___H__
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <modules/globebrowsing/src/renderableglobe.h>
|
||||
#endif
|
||||
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
#include <modules/touch/include/touchinteraction.h>
|
||||
#include <modules/touch/include/directinputsolver.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
@@ -205,12 +204,6 @@ namespace {
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo GuiButtonSizeInfo = {
|
||||
"GuiButtonSize",
|
||||
"GUI button size in pixels",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FrictionInfo = {
|
||||
"Friction",
|
||||
"Friction for different interactions (orbit, zoom, roll, pan)",
|
||||
@@ -285,12 +278,6 @@ TouchInteraction::TouchInteraction()
|
||||
, _panEnabled(PanModeInfo, false)
|
||||
, _interpretPan(PanDeltaDistanceInfo, 0.015f, 0.f, 0.1f)
|
||||
, _slerpTime(SlerpTimeInfo, 3.f, 0.1f, 5.f)
|
||||
, _guiButton(
|
||||
GuiButtonSizeInfo,
|
||||
glm::ivec2(32, 64),
|
||||
glm::ivec2(8, 16),
|
||||
glm::ivec2(128, 256)
|
||||
)
|
||||
, _friction(
|
||||
FrictionInfo,
|
||||
glm::vec4(0.025f, 0.025f, 0.02f, 0.02f),
|
||||
@@ -303,10 +290,6 @@ TouchInteraction::TouchInteraction()
|
||||
0.f,
|
||||
1.f
|
||||
)
|
||||
, _ignoreGui( // @TODO Missing documentation
|
||||
{ "Ignore GUI", "Disable GUI touch interaction", "" },
|
||||
false
|
||||
)
|
||||
, _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)
|
||||
@@ -336,10 +319,8 @@ TouchInteraction::TouchInteraction()
|
||||
addProperty(_panEnabled);
|
||||
addProperty(_interpretPan);
|
||||
addProperty(_slerpTime);
|
||||
addProperty(_guiButton);
|
||||
addProperty(_friction);
|
||||
addProperty(_pickingRadiusMinimum);
|
||||
addProperty(_ignoreGui);
|
||||
|
||||
#ifdef TOUCH_DEBUG_PROPERTIES
|
||||
addPropertySubOwner(_debugProperties);
|
||||
@@ -401,69 +382,36 @@ void TouchInteraction::updateStateFromInput(const std::vector<TouchInputHolder>&
|
||||
}
|
||||
|
||||
size_t numFingers = list.size();
|
||||
if (!isGuiMode(pos, numFingers)) {
|
||||
bool isTransitionBetweenModes = (_wasPrevModeDirectTouch != _directTouchMode);
|
||||
if (isTransitionBetweenModes) {
|
||||
_vel.orbit = glm::dvec2(0.0);
|
||||
_vel.zoom = 0.0;
|
||||
_vel.roll = 0.0;
|
||||
_vel.pan = glm::dvec2(0.0);
|
||||
resetAfterInput();
|
||||
}
|
||||
bool isTransitionBetweenModes = (_wasPrevModeDirectTouch != _directTouchMode);
|
||||
if (isTransitionBetweenModes) {
|
||||
_vel.orbit = glm::dvec2(0.0);
|
||||
_vel.zoom = 0.0;
|
||||
_vel.roll = 0.0;
|
||||
_vel.pan = glm::dvec2(0.0);
|
||||
resetAfterInput();
|
||||
}
|
||||
|
||||
if (_directTouchMode && _selected.size() > 0 && numFingers == _selected.size()) {
|
||||
if (_directTouchMode && _selected.size() > 0 && numFingers == _selected.size()) {
|
||||
#ifdef TOUCH_DEBUG_PROPERTIES
|
||||
_debugProperties.interactionMode = "Direct";
|
||||
_debugProperties.interactionMode = "Direct";
|
||||
#endif
|
||||
directControl(list);
|
||||
}
|
||||
if (_lmSuccess) {
|
||||
findSelectedNode(list);
|
||||
}
|
||||
directControl(list);
|
||||
}
|
||||
if (_lmSuccess) {
|
||||
findSelectedNode(list);
|
||||
}
|
||||
|
||||
if (!_directTouchMode) {
|
||||
if (!_directTouchMode) {
|
||||
#ifdef TOUCH_DEBUG_PROPERTIES
|
||||
_debugProperties.interactionMode = "Velocities";
|
||||
_debugProperties.interactionMode = "Velocities";
|
||||
#endif
|
||||
computeVelocities(list, lastProcessed);
|
||||
}
|
||||
|
||||
_wasPrevModeDirectTouch = _directTouchMode;
|
||||
// evaluates if current frame is in directTouchMode (will be used next frame)
|
||||
_directTouchMode =
|
||||
(_currentRadius > _nodeRadiusThreshold && _selected.size() == numFingers);
|
||||
}
|
||||
}
|
||||
|
||||
bool TouchInteraction::isGuiMode(glm::dvec2 screenPosition, size_t numFingers) {
|
||||
if (_ignoreGui) {
|
||||
return false;
|
||||
computeVelocities(list, lastProcessed);
|
||||
}
|
||||
|
||||
ImGUIModule& module = *(global::moduleEngine.module<ImGUIModule>());
|
||||
_guiON = module.gui.isEnabled();
|
||||
|
||||
if (_tap && numFingers == 1 &&
|
||||
std::abs(screenPosition.x) < _guiButton.value().x &&
|
||||
std::abs(screenPosition.y) < _guiButton.value().y)
|
||||
{
|
||||
// pressed invisible button
|
||||
_guiON = !_guiON;
|
||||
module.gui.setEnabled(_guiON);
|
||||
|
||||
LINFO(fmt::format(
|
||||
"GUI mode is {}. Inside box by: ({}%, {}%)",
|
||||
_guiON ? "activated" : "deactivated",
|
||||
static_cast<int>(100 * (screenPosition.x / _guiButton.value().x)),
|
||||
static_cast<int>(100 * (screenPosition.y / _guiButton.value().y))
|
||||
));
|
||||
}
|
||||
else if (_guiON) {
|
||||
// emulate touch input as a mouse
|
||||
module.touchInput = { _guiON, screenPosition, 1 };
|
||||
}
|
||||
|
||||
return _guiON;
|
||||
_wasPrevModeDirectTouch = _directTouchMode;
|
||||
// evaluates if current frame is in directTouchMode (will be used next frame)
|
||||
_directTouchMode =
|
||||
(_currentRadius > _nodeRadiusThreshold && _selected.size() == numFingers);
|
||||
}
|
||||
|
||||
void TouchInteraction::directControl(const std::vector<TouchInputHolder>& list) {
|
||||
@@ -506,11 +454,6 @@ void TouchInteraction::directControl(const std::vector<TouchInputHolder>& list)
|
||||
else {
|
||||
// prevents touch to infinitely be active (due to windows bridge case where event
|
||||
// doesnt get consumed sometimes when LMA fails to converge)
|
||||
Touch touch;
|
||||
touch.active = true;
|
||||
touch.pos = glm::dvec2(0.0);
|
||||
touch.action = 1;
|
||||
global::moduleEngine.module<ImGUIModule>()->touchInput = touch;
|
||||
resetAfterInput();
|
||||
}
|
||||
}
|
||||
@@ -1204,24 +1147,8 @@ void TouchInteraction::resetAfterInput() {
|
||||
_vel.orbit = _lastVel.orbit * spinDelta;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// Ensure that _guiON is consistent with properties in OnScreenGUI and
|
||||
_guiON = module.gui.isEnabled();
|
||||
|
||||
// Reset variables
|
||||
_lastVel.orbit = glm::dvec2(0.0);
|
||||
@@ -1249,7 +1176,6 @@ void TouchInteraction::resetToDefault() {
|
||||
_centroidStillThreshold.set(0.0018f);
|
||||
_interpretPan.set(0.015f);
|
||||
_slerpTime.set(3.0f);
|
||||
_guiButton.set(glm::ivec2(32, 64));
|
||||
_friction.set(glm::vec4(0.025, 0.025, 0.02, 0.02));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user