|
|
@@ -1,5 +1,5 @@
|
|
|
//
|
|
|
-// Copyright (c) 2008-2014 the Urho3D project.
|
|
|
+// Copyright (c) 2008-2015 the Urho3D project.
|
|
|
//
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
@@ -41,6 +41,9 @@
|
|
|
#include <cstring>
|
|
|
|
|
|
#include <SDL/include/SDL.h>
|
|
|
+#ifdef EMSCRIPTEN
|
|
|
+#include <emscripten/html5.h>
|
|
|
+#endif
|
|
|
|
|
|
#include "../DebugNew.h"
|
|
|
|
|
|
@@ -77,6 +80,115 @@ UIElement* TouchState::GetTouchedElement()
|
|
|
return touchedElement_.Get();
|
|
|
}
|
|
|
|
|
|
+#ifdef EMSCRIPTEN
|
|
|
+#define EM_TRUE 1
|
|
|
+
|
|
|
+/// Glue between Urho Input and Emscripten HTML5
|
|
|
+/** HTML5 (Emscripten) is limited in the way it handles input. The EmscriptenInput class attempts to provide the glue between Urho3D Input behavior and HTML5, where SDL currently fails to do so.
|
|
|
+ *
|
|
|
+ * Mouse Input:
|
|
|
+ * - The OS mouse cursor position can't be set.
|
|
|
+ * - The mouse can be trapped within play area via 'PointerLock API', which requires a request and interaction between the user and browser.
|
|
|
+ * - To request mouse lock, call SetMouseMode(MM_RELATIVE). The E_MOUSEMODECHANGED event will be sent if/when the user confirms the request.
|
|
|
+ * NOTE: The request must be initiated by the user (eg: on mouse button down/up, key down/up).
|
|
|
+ * - The user can press 'escape' key and browser will force user out of pointer lock. Urho will send the E_MOUSEMODECHANGED event.
|
|
|
+ * - SetMouseMode(MM_ABSOLUTE) will leave pointer lock.
|
|
|
+ * - MM_WRAP is unsupported.
|
|
|
+ *
|
|
|
+ * Touch Input:
|
|
|
+ */
|
|
|
+/// % Emscripten Input glue. Intended to be used by the Input subsystem only.
|
|
|
+class EmscriptenInput
|
|
|
+{
|
|
|
+public:
|
|
|
+ /// Constructor, expecting pointer to constructing Input instance.
|
|
|
+ EmscriptenInput(Input* inputInst);
|
|
|
+
|
|
|
+ /// Static callback method for Pointer Lock API. Handles change in Pointer Lock state and sends events for mouse mode change.
|
|
|
+ static EM_BOOL PointerLockCallback(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData);
|
|
|
+ /// Static callback method for tracking lose focus event.
|
|
|
+ static EM_BOOL LoseFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData);
|
|
|
+ /// Static callback method for tracking gain focus event.
|
|
|
+ static EM_BOOL GainFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData);
|
|
|
+
|
|
|
+ /// Send request to user to gain pointer lock. This requires a user-browser interaction on the first call.
|
|
|
+ void RequestPointerLock();
|
|
|
+ /// Send request to exit pointer lock. This has the benefit of not requiring the user-browser interaction on the next pointer lock request.
|
|
|
+ void ExitPointerLock();
|
|
|
+ /// Returns whether the page is visible.
|
|
|
+ bool IsVisible();
|
|
|
+
|
|
|
+private:
|
|
|
+ /// Instance of Input subsystem that constructed this instance.
|
|
|
+ Input* inputInst_;
|
|
|
+};
|
|
|
+
|
|
|
+EmscriptenInput::EmscriptenInput(Input* inputInst)
|
|
|
+{
|
|
|
+ inputInst_ = inputInst;
|
|
|
+ emscripten_set_pointerlockchange_callback(NULL, (void*)inputInst, false, EmscriptenInput::PointerLockCallback);
|
|
|
+
|
|
|
+ // Handle focus changes:
|
|
|
+ emscripten_set_blur_callback(NULL, (void*)inputInst, false, EmscriptenInput::LoseFocus);
|
|
|
+ emscripten_set_focus_callback(NULL, (void*)inputInst, false, EmscriptenInput::GainFocus);
|
|
|
+}
|
|
|
+
|
|
|
+void EmscriptenInput::RequestPointerLock()
|
|
|
+{
|
|
|
+ emscripten_request_pointerlock(NULL, true);
|
|
|
+}
|
|
|
+
|
|
|
+void EmscriptenInput::ExitPointerLock()
|
|
|
+{
|
|
|
+ inputInst_->emscriptenExitingPointerLock_ = true;
|
|
|
+ emscripten_exit_pointerlock();
|
|
|
+}
|
|
|
+
|
|
|
+bool EmscriptenInput::IsVisible()
|
|
|
+{
|
|
|
+ EmscriptenVisibilityChangeEvent visibilityStatus;
|
|
|
+ if (emscripten_get_visibility_status(&visibilityStatus) >= EMSCRIPTEN_RESULT_SUCCESS)
|
|
|
+ return visibilityStatus.hidden >= EM_TRUE ? false : true;
|
|
|
+
|
|
|
+ // Assume visible
|
|
|
+ LOGWARNING("Could not determine visibility status.");
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+EM_BOOL EmscriptenInput::PointerLockCallback(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData)
|
|
|
+{
|
|
|
+ Input* inputInst = (Input*)userData;
|
|
|
+ if (keyEvent->isActive >= EM_TRUE)
|
|
|
+ {
|
|
|
+ // Pointer Lock is now active
|
|
|
+ inputInst->emscriptenEnteredPointerLock_ = true;
|
|
|
+ inputInst->SetMouseModeEmscripten(MM_RELATIVE);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Pointer Lock is now inactive
|
|
|
+ inputInst->SetMouseModeEmscripten(MM_ABSOLUTE);
|
|
|
+ }
|
|
|
+ return EM_TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+EM_BOOL EmscriptenInput::LoseFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData)
|
|
|
+{
|
|
|
+ Input* inputInst = (Input*)userData;
|
|
|
+ if (eventType == EMSCRIPTEN_EVENT_BLUR)
|
|
|
+ inputInst->LoseFocus();
|
|
|
+ return EM_TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+EM_BOOL EmscriptenInput::GainFocus(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData)
|
|
|
+{
|
|
|
+ Input* inputInst = (Input*)userData;
|
|
|
+ if (eventType == EMSCRIPTEN_EVENT_FOCUS)
|
|
|
+ inputInst->GainFocus();
|
|
|
+ return EM_TRUE;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
void JoystickState::Initialize(unsigned numButtons, unsigned numAxes, unsigned numHats)
|
|
|
{
|
|
|
buttons_.Resize(numButtons);
|
|
|
@@ -111,6 +223,10 @@ Input::Input(Context* context) :
|
|
|
lastMouseVisible_(false),
|
|
|
mouseGrabbed_(false),
|
|
|
mouseMode_(MM_ABSOLUTE),
|
|
|
+#ifdef EMSCRIPTEN
|
|
|
+ emscriptenExitingPointerLock_(false),
|
|
|
+ emscriptenEnteredPointerLock_(false),
|
|
|
+#endif
|
|
|
lastVisibleMousePosition_(MOUSE_POSITION_OFFSCREEN),
|
|
|
touchEmulation_(false),
|
|
|
inputFocus_(false),
|
|
|
@@ -124,12 +240,20 @@ Input::Input(Context* context) :
|
|
|
|
|
|
SubscribeToEvent(E_SCREENMODE, HANDLER(Input, HandleScreenMode));
|
|
|
|
|
|
+ #ifdef EMSCRIPTEN
|
|
|
+ emscriptenInput_ = new EmscriptenInput(this);
|
|
|
+ #endif
|
|
|
+
|
|
|
// Try to initialize right now, but skip if screen mode is not yet set
|
|
|
Initialize();
|
|
|
}
|
|
|
|
|
|
Input::~Input()
|
|
|
{
|
|
|
+ #ifdef EMSCRIPTEN
|
|
|
+ delete emscriptenInput_;
|
|
|
+ emscriptenInput_ = 0;
|
|
|
+ #endif
|
|
|
}
|
|
|
|
|
|
void Input::Update()
|
|
|
@@ -159,16 +283,48 @@ void Input::Update()
|
|
|
}
|
|
|
|
|
|
// Check and handle SDL events
|
|
|
+
|
|
|
+ if (!inputFocus_)
|
|
|
+ {
|
|
|
+ // While there is no input focus, don't process key, mouse, touch or joystick events.
|
|
|
+ SDL_PumpEvents();
|
|
|
+ SDL_FlushEvents(SDL_KEYDOWN, SDL_MULTIGESTURE);
|
|
|
+ }
|
|
|
+
|
|
|
SDL_Event evt;
|
|
|
while (SDL_PollEvent(&evt))
|
|
|
HandleSDLEvent(&evt);
|
|
|
|
|
|
+ // Check for focus change this frame
|
|
|
+ SDL_Window* window = graphics_->GetImpl()->GetWindow();
|
|
|
+ unsigned flags = window ? SDL_GetWindowFlags(window) & (SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS) : 0;
|
|
|
+#ifndef EMSCRIPTEN
|
|
|
+ if (window)
|
|
|
+ {
|
|
|
+#if defined(REQUIRE_CLICK_TO_FOCUS)
|
|
|
+ if (!inputFocus_ && (graphics_->GetFullscreen() || mouseVisible_) && flags == (SDL_WINDOW_INPUT_FOCUS |
|
|
|
+ SDL_WINDOW_MOUSE_FOCUS))
|
|
|
+#else
|
|
|
+ if (!inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS))
|
|
|
+#endif
|
|
|
+ focusedThisFrame_ = true;
|
|
|
+
|
|
|
+ if (focusedThisFrame_)
|
|
|
+ GainFocus();
|
|
|
+
|
|
|
+ if (inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS) == 0)
|
|
|
+ LoseFocus();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return;
|
|
|
+
|
|
|
+ // Handle mouse mode MM_WRAP
|
|
|
if (mouseVisible_ && mouseMode_ == MM_WRAP)
|
|
|
{
|
|
|
IntVector2 mpos;
|
|
|
SDL_GetMouseState(&mpos.x_, &mpos.y_);
|
|
|
|
|
|
- int buffer = 5;
|
|
|
+ const int buffer = 5;
|
|
|
int width = graphics_->GetWidth() - buffer * 2;
|
|
|
int height = graphics_->GetHeight() - buffer * 2;
|
|
|
|
|
|
@@ -203,36 +359,27 @@ void Input::Update()
|
|
|
SDL_FlushEvent(SDL_MOUSEMOTION);
|
|
|
}
|
|
|
}
|
|
|
+ #else
|
|
|
+ if (!window)
|
|
|
+ return;
|
|
|
|
|
|
- // Check for activation and inactivation from SDL window flags. Must nullcheck the window pointer because it may have
|
|
|
- // been closed due to input events
|
|
|
- SDL_Window* window = graphics_->GetImpl()->GetWindow();
|
|
|
- unsigned flags = window ? SDL_GetWindowFlags(window) & (SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS) : 0;
|
|
|
- if (window)
|
|
|
+ if (emscriptenExitingPointerLock_)
|
|
|
{
|
|
|
-#ifdef REQUIRE_CLICK_TO_FOCUS
|
|
|
- if (!inputFocus_ && (graphics_->GetFullscreen() || mouseVisible_) && flags == (SDL_WINDOW_INPUT_FOCUS |
|
|
|
- SDL_WINDOW_MOUSE_FOCUS))
|
|
|
-#else
|
|
|
- if (!inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS))
|
|
|
-#endif
|
|
|
- focusedThisFrame_ = true;
|
|
|
-
|
|
|
- if (focusedThisFrame_)
|
|
|
- GainFocus();
|
|
|
-
|
|
|
- if (inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS) == 0)
|
|
|
- LoseFocus();
|
|
|
- }
|
|
|
- else
|
|
|
+ // Suppress mouse jump when exiting Pointer Lock
|
|
|
+ IntVector2 mousePosition = GetMousePosition();
|
|
|
+ mouseMove_ = IntVector2::ZERO;
|
|
|
+ lastMousePosition_ = lastVisibleMousePosition_;
|
|
|
+ emscriptenExitingPointerLock_ = false;
|
|
|
return;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
|
|
|
// Check for relative mode mouse move
|
|
|
- if (!touchEmulation_ && (graphics_->GetExternalWindow() || (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
|
|
|
+ if (!touchEmulation_ && mouseMode_ != MM_RELATIVE && (graphics_->GetExternalWindow() || (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
|
|
|
{
|
|
|
IntVector2 mousePosition = GetMousePosition();
|
|
|
mouseMove_ = mousePosition - lastMousePosition_;
|
|
|
-
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
if (graphics_->GetExternalWindow())
|
|
|
lastMousePosition_ = mousePosition;
|
|
|
else
|
|
|
@@ -245,7 +392,12 @@ void Input::Update()
|
|
|
lastMousePosition_ = center;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ #else
|
|
|
+ if (mouseMode_ == MM_ABSOLUTE)
|
|
|
+ {
|
|
|
+ lastMousePosition_ = mousePosition;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
// Send mouse move event if necessary
|
|
|
if (mouseMove_ != IntVector2::ZERO)
|
|
|
{
|
|
|
@@ -304,17 +456,25 @@ void Input::SetMouseVisible(bool enable, bool suppressEvent)
|
|
|
if (!mouseVisible_ && inputFocus_)
|
|
|
{
|
|
|
SDL_ShowCursor(SDL_FALSE);
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
// Recenter the mouse cursor manually when hiding it to avoid erratic mouse move for one frame
|
|
|
lastVisibleMousePosition_ = GetMousePosition();
|
|
|
IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
|
|
|
SetMousePosition(center);
|
|
|
lastMousePosition_ = center;
|
|
|
+ #else
|
|
|
+ lastVisibleMousePosition_ = GetMousePosition();
|
|
|
+ lastMousePosition_ = lastVisibleMousePosition_;
|
|
|
+ #endif
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
SDL_ShowCursor(SDL_TRUE);
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
if (lastVisibleMousePosition_.x_ != MOUSE_POSITION_OFFSCREEN.x_ && lastVisibleMousePosition_.y_ != MOUSE_POSITION_OFFSCREEN.y_)
|
|
|
SetMousePosition(lastVisibleMousePosition_);
|
|
|
+ lastMousePosition_ = lastVisibleMousePosition_;
|
|
|
+ #endif
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -334,6 +494,50 @@ void Input::SetMouseVisible(bool enable, bool suppressEvent)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+void Input::ResetMouseVisible()
|
|
|
+{
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
+ SetMouseVisible(lastMouseVisible_, true);
|
|
|
+ #else
|
|
|
+ SetMouseVisibleEmscripten(lastMouseVisible_);
|
|
|
+ #endif
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef EMSCRIPTEN
|
|
|
+void Input::SetMouseVisibleEmscripten(bool enable)
|
|
|
+{
|
|
|
+ if (enable != mouseVisible_)
|
|
|
+ {
|
|
|
+ mouseVisible_ = enable;
|
|
|
+ SDL_ShowCursor(enable ? SDL_TRUE : SDL_FALSE);
|
|
|
+
|
|
|
+ if (!mouseVisible_)
|
|
|
+ lastVisibleMousePosition_ = GetMousePosition();
|
|
|
+
|
|
|
+ lastMousePosition_ = lastVisibleMousePosition_;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Input::SetMouseModeEmscripten(MouseMode mode)
|
|
|
+{
|
|
|
+ mouseMode_ = mode;
|
|
|
+
|
|
|
+ if (mode == MM_RELATIVE)
|
|
|
+ {
|
|
|
+ SetMouseVisibleEmscripten(false);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ResetMouseVisible();
|
|
|
+ }
|
|
|
+ suppressNextMouseMove_ = true;
|
|
|
+
|
|
|
+ VariantMap& eventData = GetEventDataMap();
|
|
|
+ eventData[MouseModeChanged::P_MODE] = mode;
|
|
|
+ SendEvent(E_MOUSEMODECHANGED, eventData);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
void Input::SetMouseGrabbed(bool grab)
|
|
|
{
|
|
|
mouseGrabbed_ = grab;
|
|
|
@@ -345,47 +549,70 @@ void Input::SetMouseMode(MouseMode mode)
|
|
|
{
|
|
|
MouseMode previousMode = mouseMode_;
|
|
|
mouseMode_ = mode;
|
|
|
+ suppressNextMouseMove_ = true;
|
|
|
+ SDL_Window* window = graphics_->GetImpl()->GetWindow();
|
|
|
// Handle changing away from previous mode
|
|
|
if (previousMode == MM_RELATIVE)
|
|
|
{
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
/// \todo Use SDL_SetRelativeMouseMode() for MM_RELATIVE mode
|
|
|
ResetMouseVisible();
|
|
|
+ #else
|
|
|
+ emscriptenInput_->ExitPointerLock();
|
|
|
+ #endif
|
|
|
|
|
|
- // Send updated mouse position:
|
|
|
- using namespace MouseMove;
|
|
|
-
|
|
|
- VariantMap& eventData = GetEventDataMap();
|
|
|
- eventData[P_X] = lastVisibleMousePosition_.x_;
|
|
|
- eventData[P_Y] = lastVisibleMousePosition_.y_;
|
|
|
- eventData[P_DX] = mouseMove_.x_;
|
|
|
- eventData[P_DY] = mouseMove_.y_;
|
|
|
- eventData[P_BUTTONS] = mouseButtonDown_;
|
|
|
- eventData[P_QUALIFIERS] = GetQualifiers();
|
|
|
- SendEvent(E_MOUSEMOVE, eventData);
|
|
|
+ SDL_SetWindowGrab(window, SDL_FALSE);
|
|
|
}
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
else if (previousMode == MM_WRAP)
|
|
|
{
|
|
|
- SDL_Window* window = graphics_->GetImpl()->GetWindow();
|
|
|
SDL_SetWindowGrab(window, SDL_FALSE);
|
|
|
}
|
|
|
+ #endif
|
|
|
|
|
|
// Handle changing to new mode
|
|
|
if (mode == MM_ABSOLUTE)
|
|
|
+ {
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
SetMouseGrabbed(false);
|
|
|
+ VariantMap& eventData = GetEventDataMap();
|
|
|
+ eventData[MouseModeChanged::P_MODE] = mode;
|
|
|
+ SendEvent(E_MOUSEMODECHANGED, eventData);
|
|
|
+ #else
|
|
|
+ // Deferred mouse mode change to PointerLock callback
|
|
|
+ #endif
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
SetMouseGrabbed(true);
|
|
|
|
|
|
if (mode == MM_RELATIVE)
|
|
|
{
|
|
|
+ SDL_SetWindowGrab(window, SDL_TRUE);
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
SetMouseVisible(false, true);
|
|
|
+
|
|
|
+ VariantMap& eventData = GetEventDataMap();
|
|
|
+ eventData[MouseModeChanged::P_MODE] = mode;
|
|
|
+ SendEvent(E_MOUSEMODECHANGED, eventData);
|
|
|
+ #else
|
|
|
+ // Defer mouse mode change to PointerLock callback
|
|
|
+ mouseMode_ = previousMode;
|
|
|
+ emscriptenInput_->RequestPointerLock();
|
|
|
+ #endif
|
|
|
+
|
|
|
}
|
|
|
+ #ifndef EMSCRIPTEN
|
|
|
else if (mode == MM_WRAP)
|
|
|
{
|
|
|
/// \todo When SDL 2.0.4 is integrated, use SDL_CaptureMouse() and global mouse functions for MM_WRAP mode.
|
|
|
- SDL_Window* window = graphics_->GetImpl()->GetWindow();
|
|
|
SDL_SetWindowGrab(window, SDL_TRUE);
|
|
|
+
|
|
|
+ VariantMap& eventData = GetEventDataMap();
|
|
|
+ eventData[MouseModeChanged::P_MODE] = mode;
|
|
|
+ SendEvent(E_MOUSEMODECHANGED, eventData);
|
|
|
}
|
|
|
+ #endif
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -722,18 +949,19 @@ unsigned Input::LoadGestures(Deserializer& source)
|
|
|
return SDL_LoadDollarTemplates(-1, wrapper.GetRWOps());
|
|
|
}
|
|
|
|
|
|
+
|
|
|
bool Input::RemoveGesture(unsigned gestureID)
|
|
|
{
|
|
|
-#ifndef EMSCRIPTEN
|
|
|
- return SDL_RemoveDollarTemplate(gestureID) != 0;
|
|
|
-#else
|
|
|
+#if defined(EMSCRIPTEN)
|
|
|
return false;
|
|
|
+#else
|
|
|
+ return SDL_RemoveDollarTemplate(gestureID) != 0;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void Input::RemoveAllGestures()
|
|
|
{
|
|
|
-#ifndef EMSCRIPTEN
|
|
|
+#if !defined(EMSCRIPTEN)
|
|
|
SDL_RemoveAllDollarTemplates();
|
|
|
#endif
|
|
|
}
|
|
|
@@ -957,8 +1185,16 @@ void Input::Initialize()
|
|
|
mouseVisible_ = true;
|
|
|
|
|
|
// Set the initial activation
|
|
|
- focusedThisFrame_ = true;
|
|
|
initialized_ = true;
|
|
|
+#ifndef EMSCRIPTEN
|
|
|
+ focusedThisFrame_ = true;
|
|
|
+#else
|
|
|
+ // Note: Page visibility and focus are slightly different, however we can't query last focus with Emscripten (1.29.0)
|
|
|
+ if (emscriptenInput_->IsVisible())
|
|
|
+ GainFocus();
|
|
|
+ else
|
|
|
+ LoseFocus();
|
|
|
+#endif
|
|
|
|
|
|
ResetJoysticks();
|
|
|
ResetState();
|
|
|
@@ -1145,6 +1381,18 @@ void Input::SetMouseButton(int button, bool newState)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#ifdef EMSCRIPTEN
|
|
|
+ if (emscriptenEnteredPointerLock_)
|
|
|
+ {
|
|
|
+ // Suppress mouse jump on initial Pointer Lock
|
|
|
+ IntVector2 mousePosition = GetMousePosition();
|
|
|
+ lastMousePosition_ = mousePosition;
|
|
|
+ mouseMove_ = IntVector2::ZERO;
|
|
|
+ suppressNextMouseMove_ = true;
|
|
|
+ emscriptenEnteredPointerLock_ = false;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
// If we do not have focus yet, do not react to the mouse button down
|
|
|
if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
|
|
|
return;
|
|
|
@@ -1254,21 +1502,22 @@ void Input::HandleSDLEvent(void* sdlEvent)
|
|
|
switch (evt.type)
|
|
|
{
|
|
|
case SDL_KEYDOWN:
|
|
|
- // Convert to uppercase to match Win32 virtual key codes
|
|
|
- #ifndef EMSCRIPTEN
|
|
|
- SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, true);
|
|
|
- #else
|
|
|
- SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, 0, true);
|
|
|
- #endif
|
|
|
- break;
|
|
|
-
|
|
|
- case SDL_KEYUP:
|
|
|
- #ifndef EMSCRIPTEN
|
|
|
- SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, false);
|
|
|
- #else
|
|
|
- SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, 0, false);
|
|
|
- #endif
|
|
|
- break;
|
|
|
+ // Convert to uppercase to match Win32 virtual key codes
|
|
|
+#if defined (EMSCRIPTEN)
|
|
|
+ SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, 0, true);
|
|
|
+#else
|
|
|
+ SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, true);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SDL_KEYUP:
|
|
|
+#if defined(EMSCRIPTEN)
|
|
|
+ SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, 0, false);
|
|
|
+#else
|
|
|
+ SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, false);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
case SDL_TEXTINPUT:
|
|
|
{
|
|
|
textInput_ = &evt.text.text[0];
|