Merge pull request #4842 from Web-eWorks/input-capture-mode

Improve Mouse Capture Handling
master
Webster Sheets 2020-03-24 15:42:32 -04:00 committed by GitHub
commit a34b23623b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 69 additions and 41 deletions

View File

@ -30,7 +30,7 @@ jobs:
# Make sure to include the base we want to merge into
- run: |
git fetch --no-tags --depth=1 origin ${{ github.base_ref }}
git fetch --no-tags --depth=1 origin ${{ github.base_ref }}:${{ github.base_ref }}
# Run the clang-format command (in $GITHUB_WORKSPACE, which is where the repo is checked out to)
- name: Run clang-format

View File

@ -74,4 +74,8 @@ ui.registerModule('mainMenu', function()
drawModals(1)
end)
ui.registerModule('modal', function()
drawModals(1)
end)
return ModalWindow

View File

@ -297,6 +297,8 @@ ui.registerHandler('game', function(delta_t)
end
end
end
callModules('modal')
end)
return gameView

View File

@ -252,6 +252,7 @@ local function showMainMenu()
end)
callModules('mainMenu')
callModules('modal')
end -- showMainMenu
ui.registerHandler('mainMenu',function(delta)

View File

@ -2,9 +2,6 @@
CLANG_FORMAT=$(which clang-format)
# Github Actions compatibility
if [[ $GITHUB_WORKSPACE ]]; then cd $GIT_WORKSPACE; fi
# if PATCH_MODE is set to 0, then set it to the empty string so $PATCH_MODE continues to work
if ((PATCH_MODE == 0)); then PATCH_MODE=""; fi

View File

@ -287,3 +287,14 @@ float Input::JoystickAxisState(int joystick, int axis)
return joysticks[joystick].axes[axis];
}
void Input::SetCapturingMouse(bool grabbed)
{
// early-out to avoid changing (possibly) expensive WM state
if (grabbed == m_capturingMouse)
return;
SDL_SetWindowGrab(Pi::renderer->GetSDLWindow(), SDL_bool(grabbed));
SDL_SetRelativeMouseMode(SDL_bool(grabbed));
m_capturingMouse = grabbed;
}

View File

@ -132,6 +132,16 @@ public:
memcpy(motion, mouseMotion, sizeof(int) * 2);
}
// Capturing the mouse hides the cursor, puts the mouse into relative mode,
// and passes all mouse inputs to the input system, regardless of whether
// ImGui is using them or not.
bool IsCapturingMouse() const { return m_capturingMouse; }
// Set whether the application would like to capture the mouse.
// To avoid contention between different classes, please only call this when the state
// has actually changed.
void SetCapturingMouse(bool enabled);
sigc::signal<void, SDL_Keysym *> onKeyPress;
sigc::signal<void, SDL_Keysym *> onKeyRelease;
sigc::signal<void, int, int, int> onMouseButtonUp;
@ -146,6 +156,7 @@ private:
int keyModState;
char mouseButton[6];
int mouseMotion[2];
bool m_capturingMouse;
bool joystickEnabled;
bool mouseYInvert;

View File

@ -406,7 +406,9 @@ void ModelViewer::ChangeCameraPreset(SDL_Keycode key, SDL_Keymod mod)
void ModelViewer::ToggleViewControlMode()
{
m_options.mouselookEnabled = !m_options.mouselookEnabled;
m_renderer->SetGrab(m_options.mouselookEnabled);
// FIXME: update modelviewer to use Input::SetCaptureMouse instead
SDL_SetWindowGrab(m_renderer->GetSDLWindow(), SDL_bool(m_options.mouselookEnabled));
SDL_SetRelativeMouseMode(SDL_bool(m_options.mouselookEnabled));
if (m_options.mouselookEnabled) {
m_viewRot = matrix3x3f::RotateY(DEG2RAD(m_rotY)) * matrix3x3f::RotateX(DEG2RAD(Clamp(m_rotX, -90.0f, 90.0f)));
@ -430,7 +432,9 @@ void ModelViewer::ClearModel()
m_scaleModel.reset();
m_options.mouselookEnabled = false;
m_renderer->SetGrab(false);
// FIXME: update modelviewer to use Input::SetCaptureMouse instead
SDL_SetWindowGrab(m_renderer->GetSDLWindow(), SDL_bool(m_options.mouselookEnabled));
SDL_SetRelativeMouseMode(SDL_bool(m_options.mouselookEnabled));
m_viewPos = vector3f(0.0f, 0.0f, 10.0f);
ResetCamera();
}
@ -833,7 +837,7 @@ void ModelViewer::PollEvents()
break;
default:
break; //shuts up -Wswitch
} //keysym switch
} //keysym switch
m_keyStates[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:

View File

@ -885,7 +885,8 @@ void Pi::HandleEvents()
Pi::pigui->ProcessEvent(&event);
if (Pi::pigui->WantCaptureMouse()) {
// Input system takes priority over mouse events when capturing the mouse
if (Pi::pigui->WantCaptureMouse() && !Pi::input.IsCapturingMouse()) {
// don't process mouse event any further, imgui already handled it
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
@ -959,7 +960,7 @@ void Pi::TombStoneLoop()
float _time = 0;
do {
Pi::HandleEvents();
Pi::renderer->SetGrab(false);
Pi::input.SetCapturingMouse(false);
// render the scene
Pi::BeginRenderTarget();
@ -1264,9 +1265,6 @@ void Pi::MainLoop()
currentView->Update();
currentView->Draw3D();
// hide cursor for ship control. Do this before imgui runs, to prevent the mouse pointer from jumping
Pi::SetMouseGrab(input.MouseButtonState(SDL_BUTTON_RIGHT) | input.MouseButtonState(SDL_BUTTON_MIDDLE));
// XXX HandleEvents at the moment must be after view->Draw3D and before
// Gui::Draw so that labels drawn to screen can have mouse events correctly
// detected. Gui::Draw wipes memory of label positions.
@ -1399,11 +1397,11 @@ float Pi::GetMoveSpeedShiftModifier()
void Pi::SetMouseGrab(bool on)
{
if (!doingMouseGrab && on) {
Pi::renderer->SetGrab(true);
Pi::input.SetCapturingMouse(true);
Pi::ui->SetMousePointerEnabled(false);
doingMouseGrab = true;
} else if (doingMouseGrab && !on) {
Pi::renderer->SetGrab(false);
Pi::input.SetCapturingMouse(false);
Pi::ui->SetMousePointerEnabled(true);
doingMouseGrab = false;
}

View File

@ -48,10 +48,4 @@ namespace Graphics {
m_textureCache.clear();
}
void Renderer::SetGrab(const bool grabbed)
{
SDL_SetWindowGrab(m_window, SDL_bool(grabbed));
SDL_SetRelativeMouseMode(SDL_bool(grabbed));
}
} // namespace Graphics

View File

@ -205,8 +205,6 @@ namespace Graphics {
Stats &GetStats() { return m_stats; }
void SetGrab(const bool grabbed);
protected:
int m_width;
int m_height;

View File

@ -4,6 +4,7 @@
#include "PiGui.h"
#include "Pi.h"
#include "graphics/opengl/TextureGL.h" // nasty, usage of GL is implementation specific
#include "imgui/imgui.h"
// Use GLEW instead of GL3W.
#define IMGUI_IMPL_OPENGL_LOADER_GLEW 1
#include "imgui/examples/imgui_impl_opengl3.h"
@ -375,15 +376,13 @@ void *PiGui::makeTexture(unsigned char *pixels, int width, int height)
void PiGui::NewFrame(SDL_Window *window)
{
PROFILE_SCOPED()
// Ask ImGui to hide OS cursor if GUI is not being drawn:
// it will do this if MouseDrawCursor is true. After the frame
// is created, we set the actual cursor draw state.
#if 0 // Mouse cursors are set via the OS facilities.
// See also below.
if (!Pi::DrawGUI) {
ImGui::GetIO().MouseDrawCursor = true;
// Ask ImGui to hide OS cursor if we're capturing it for input:
// it will do this if GetMouseCursor == ImGuiMouseCursor_None.
if (Pi::input.IsCapturingMouse()) {
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
}
#endif
switch (Pi::renderer->GetRendererType()) {
default:
case Graphics::RENDERER_DUMMY:
@ -398,14 +397,6 @@ void PiGui::NewFrame(SDL_Window *window)
Pi::renderer->CheckRenderErrors(__FUNCTION__, __LINE__);
ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
#if 0 // Mouse cursors are set via the OS facilities.
// We may want to revisit this at a later date.
if(Pi::DoingMouseGrab() || !Pi::DrawGUI) {
ImGui::GetIO().MouseDrawCursor = false;
} else {
ImGui::GetIO().MouseDrawCursor = true;
}
#endif
}
void PiGui::RunHandler(double delta, std::string handler)

View File

@ -134,6 +134,7 @@ void PlayerShipController::StaticUpdate(const float timeStep)
matrix4x4d m;
int mouseMotion[2];
// have to use this function. SDL mouse position event is bugged in windows
SDL_GetRelativeMouseState(mouseMotion + 0, mouseMotion + 1); // call to flush
if (m_ship->GetFlightState() == Ship::FLYING) {
@ -238,7 +239,6 @@ void PlayerShipController::PollControls(const float timeStep, const bool force_r
const float linearThrustPower = (InputBindings.thrustLowPower->IsActive() ? m_lowThrustPower : 1.0f);
// have to use this function. SDL mouse position event is bugged in windows
if (Pi::input.MouseButtonState(SDL_BUTTON_RIGHT)) {
// use ship rotation relative to system, unchanged by frame transitions
matrix3x3d rot = m_ship->GetOrientRelTo(Frame::GetFrame(m_ship->GetFrame())->GetNonRotFrame());
@ -246,6 +246,7 @@ void PlayerShipController::PollControls(const float timeStep, const bool force_r
m_mouseDir = -rot.VectorZ();
m_mouseX = m_mouseY = 0;
m_mouseActive = true;
Pi::input.SetCapturingMouse(true);
}
vector3d objDir = m_mouseDir * rot;
@ -267,8 +268,12 @@ void PlayerShipController::PollControls(const float timeStep, const bool force_r
matrix3x3d mrot = matrix3x3d::RotateY(modx) * matrix3x3d::RotateX(mody);
m_mouseDir = (rot * (mrot * objDir)).Normalized();
}
} else
} else {
if (m_mouseActive)
Pi::input.SetCapturingMouse(false);
m_mouseActive = false;
}
if (m_flightControlState == CONTROL_FIXSPEED) {
double oldSpeed = m_setSpeed;

View File

@ -206,13 +206,24 @@ void ShipViewController::Update()
Pi::input.GetMouseMotion(mouseMotion);
// external camera mouselook
if (Pi::input.MouseButtonState(SDL_BUTTON_MIDDLE) && !headtracker_input_priority) {
bool mouse_down = Pi::input.MouseButtonState(SDL_BUTTON_MIDDLE);
if (mouse_down && !headtracker_input_priority) {
if (!m_mouseActive) {
m_mouseActive = true;
Pi::input.SetCapturingMouse(true);
}
// invert the mouse input to convert between screen coordinates and
// right-hand coordinate system rotation.
cam->YawCamera(-mouseMotion[0] * MOUSELOOK_SPEED);
cam->PitchCamera(-mouseMotion[1] * MOUSELOOK_SPEED);
}
if (!mouse_down && m_mouseActive) {
m_mouseActive = false;
Pi::input.SetCapturingMouse(false);
}
m_activeCameraController->Update();
}

View File

@ -47,6 +47,7 @@ private:
CameraController *m_activeCameraController; //one of the above
bool headtracker_input_priority;
bool m_mouseActive;
void MouseWheel(bool up);