Made imgui handle touch input as the webgui does

Also removed imgui-handling code in touchinteraction
This commit is contained in:
Mikael Pettersson
2020-03-11 13:23:46 +01:00
parent 754a7735f9
commit fb7036c497
6 changed files with 123 additions and 124 deletions
+18 -4
View File
@@ -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
-8
View File
@@ -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
+7
View File
@@ -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);
+71
View File
@@ -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);
+5 -16
View File
@@ -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__
+22 -96
View File
@@ -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));
}