mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-06-25 05:58:30 +02:00
83ad5e66de
This is quite simple - whenever the user uses their keyboard or controller, we hide the mouse cursor. Whenever they move the mouse, we show it again. This makes it so the cursor gets out of the way when they play the game, but reappears when they need it. There is also a timeout, to prevent strobing if the user decides to use the keyboard/controller and mouse at the same time. There is no timeout from hiding the mouse cursor, but there is a timeout from showing the mouse cursor - this because it's okay if the mouse lingers for a few frames when you start using the keyboard, but really annoying if the mouse doesn't instantly appear when you move it.
466 lines
8.6 KiB
C++
466 lines
8.6 KiB
C++
#define KEY_DEFINITION
|
|
#include "KeyPoll.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <utf8/unchecked.h>
|
|
|
|
#include "Exit.h"
|
|
#include "Game.h"
|
|
#include "Graphics.h"
|
|
#include "Music.h"
|
|
|
|
int inline KeyPoll::getThreshold(void)
|
|
{
|
|
switch (sensitivity)
|
|
{
|
|
case 0:
|
|
return 28000;
|
|
case 1:
|
|
return 16000;
|
|
case 2:
|
|
return 8000;
|
|
case 3:
|
|
return 4000;
|
|
case 4:
|
|
return 2000;
|
|
}
|
|
|
|
return 8000;
|
|
|
|
}
|
|
|
|
KeyPoll::KeyPoll(void)
|
|
{
|
|
xVel = 0;
|
|
yVel = 0;
|
|
// 0..5
|
|
sensitivity = 2;
|
|
|
|
keybuffer="";
|
|
leftbutton=0; rightbutton=0; middlebutton=0;
|
|
mx=0; my=0;
|
|
resetWindow = 0;
|
|
pressedbackspace=false;
|
|
|
|
linealreadyemptykludge = false;
|
|
|
|
isActive = true;
|
|
}
|
|
|
|
void KeyPoll::enabletextentry(void)
|
|
{
|
|
keybuffer="";
|
|
SDL_StartTextInput();
|
|
}
|
|
|
|
void KeyPoll::disabletextentry(void)
|
|
{
|
|
SDL_StopTextInput();
|
|
}
|
|
|
|
bool KeyPoll::textentry(void)
|
|
{
|
|
return SDL_IsTextInputActive() == SDL_TRUE;
|
|
}
|
|
|
|
void KeyPoll::toggleFullscreen(void)
|
|
{
|
|
if (graphics.screenbuffer != NULL)
|
|
{
|
|
graphics.screenbuffer->toggleFullScreen();
|
|
}
|
|
|
|
keymap.clear(); /* we lost the input due to a new window. */
|
|
if (game.glitchrunnermode)
|
|
{
|
|
game.press_left = false;
|
|
game.press_right = false;
|
|
game.press_action = true;
|
|
game.press_map = false;
|
|
}
|
|
}
|
|
|
|
static int changemousestate(
|
|
int timeout,
|
|
const bool show,
|
|
const bool hide
|
|
) {
|
|
int prev;
|
|
int new_;
|
|
|
|
if (timeout > 0)
|
|
{
|
|
return --timeout;
|
|
}
|
|
|
|
/* If we want to both show and hide at the same time, prioritize showing */
|
|
if (show)
|
|
{
|
|
new_ = SDL_ENABLE;
|
|
}
|
|
else if (hide)
|
|
{
|
|
new_ = SDL_DISABLE;
|
|
}
|
|
else
|
|
{
|
|
return timeout;
|
|
}
|
|
|
|
prev = SDL_ShowCursor(SDL_QUERY);
|
|
|
|
if (prev == new_)
|
|
{
|
|
return timeout;
|
|
}
|
|
|
|
SDL_ShowCursor(new_);
|
|
|
|
switch (new_)
|
|
{
|
|
case SDL_DISABLE:
|
|
timeout = 0;
|
|
break;
|
|
case SDL_ENABLE:
|
|
timeout = 30;
|
|
break;
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
void KeyPoll::Poll(void)
|
|
{
|
|
static int mousetoggletimeout = 0;
|
|
bool showmouse = false;
|
|
bool hidemouse = false;
|
|
bool altpressed = false;
|
|
bool fullscreenkeybind = false;
|
|
SDL_Event evt;
|
|
while (SDL_PollEvent(&evt))
|
|
{
|
|
switch (evt.type)
|
|
{
|
|
/* Keyboard Input */
|
|
case SDL_KEYDOWN:
|
|
{
|
|
keymap[evt.key.keysym.sym] = true;
|
|
|
|
if (evt.key.keysym.sym == SDLK_BACKSPACE)
|
|
{
|
|
pressedbackspace = true;
|
|
}
|
|
|
|
#ifdef __APPLE__ /* OSX prefers the command keys over the alt keys. -flibit */
|
|
altpressed = keymap[SDLK_LGUI] || keymap[SDLK_RGUI];
|
|
#else
|
|
altpressed = keymap[SDLK_LALT] || keymap[SDLK_RALT];
|
|
#endif
|
|
bool returnpressed = evt.key.keysym.sym == SDLK_RETURN;
|
|
bool fpressed = evt.key.keysym.sym == SDLK_f;
|
|
bool f11pressed = evt.key.keysym.sym == SDLK_F11;
|
|
if ((altpressed && (returnpressed || fpressed)) || f11pressed)
|
|
{
|
|
fullscreenkeybind = true;
|
|
}
|
|
|
|
if (textentry())
|
|
{
|
|
if (evt.key.keysym.sym == SDLK_BACKSPACE && !keybuffer.empty())
|
|
{
|
|
std::string::iterator iter = keybuffer.end();
|
|
utf8::unchecked::prior(iter);
|
|
keybuffer = keybuffer.substr(0, iter - keybuffer.begin());
|
|
if (keybuffer.empty())
|
|
{
|
|
linealreadyemptykludge = true;
|
|
}
|
|
}
|
|
else if ( evt.key.keysym.sym == SDLK_v &&
|
|
keymap[SDLK_LCTRL] )
|
|
{
|
|
char* text = SDL_GetClipboardText();
|
|
if (text != NULL)
|
|
{
|
|
keybuffer += text;
|
|
SDL_free(text);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case SDL_KEYUP:
|
|
keymap[evt.key.keysym.sym] = false;
|
|
if (evt.key.keysym.sym == SDLK_BACKSPACE)
|
|
{
|
|
pressedbackspace = false;
|
|
}
|
|
break;
|
|
case SDL_TEXTINPUT:
|
|
if (!altpressed)
|
|
{
|
|
keybuffer += evt.text.text;
|
|
}
|
|
break;
|
|
|
|
/* Mouse Input */
|
|
case SDL_MOUSEMOTION:
|
|
mx = evt.motion.x;
|
|
my = evt.motion.y;
|
|
break;
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
switch (evt.button.button)
|
|
{
|
|
case SDL_BUTTON_LEFT:
|
|
mx = evt.button.x;
|
|
my = evt.button.y;
|
|
leftbutton = 1;
|
|
break;
|
|
case SDL_BUTTON_RIGHT:
|
|
mx = evt.button.x;
|
|
my = evt.button.y;
|
|
rightbutton = 1;
|
|
break;
|
|
case SDL_BUTTON_MIDDLE:
|
|
mx = evt.button.x;
|
|
my = evt.button.y;
|
|
middlebutton = 1;
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_MOUSEBUTTONUP:
|
|
switch (evt.button.button)
|
|
{
|
|
case SDL_BUTTON_LEFT:
|
|
mx = evt.button.x;
|
|
my = evt.button.y;
|
|
leftbutton=0;
|
|
break;
|
|
case SDL_BUTTON_RIGHT:
|
|
mx = evt.button.x;
|
|
my = evt.button.y;
|
|
rightbutton=0;
|
|
break;
|
|
case SDL_BUTTON_MIDDLE:
|
|
mx = evt.button.x;
|
|
my = evt.button.y;
|
|
middlebutton=0;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
/* Controller Input */
|
|
case SDL_CONTROLLERBUTTONDOWN:
|
|
buttonmap[(SDL_GameControllerButton) evt.cbutton.button] = true;
|
|
break;
|
|
case SDL_CONTROLLERBUTTONUP:
|
|
buttonmap[(SDL_GameControllerButton) evt.cbutton.button] = false;
|
|
break;
|
|
case SDL_CONTROLLERAXISMOTION:
|
|
{
|
|
const int threshold = getThreshold();
|
|
switch (evt.caxis.axis)
|
|
{
|
|
case SDL_CONTROLLER_AXIS_LEFTX:
|
|
if ( evt.caxis.value > -threshold &&
|
|
evt.caxis.value < threshold )
|
|
{
|
|
xVel = 0;
|
|
}
|
|
else
|
|
{
|
|
xVel = (evt.caxis.value > 0) ? 1 : -1;
|
|
}
|
|
break;
|
|
case SDL_CONTROLLER_AXIS_LEFTY:
|
|
if ( evt.caxis.value > -threshold &&
|
|
evt.caxis.value < threshold )
|
|
{
|
|
yVel = 0;
|
|
}
|
|
else
|
|
{
|
|
yVel = (evt.caxis.value > 0) ? 1 : -1;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case SDL_CONTROLLERDEVICEADDED:
|
|
{
|
|
SDL_GameController *toOpen = SDL_GameControllerOpen(evt.cdevice.which);
|
|
printf(
|
|
"Opened SDL_GameController ID #%i, %s\n",
|
|
evt.cdevice.which,
|
|
SDL_GameControllerName(toOpen)
|
|
);
|
|
controllers[SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(toOpen))] = toOpen;
|
|
break;
|
|
}
|
|
case SDL_CONTROLLERDEVICEREMOVED:
|
|
{
|
|
SDL_GameController *toClose = controllers[evt.cdevice.which];
|
|
controllers.erase(evt.cdevice.which);
|
|
printf("Closing %s\n", SDL_GameControllerName(toClose));
|
|
SDL_GameControllerClose(toClose);
|
|
break;
|
|
}
|
|
|
|
/* Window Events */
|
|
case SDL_WINDOWEVENT:
|
|
switch (evt.window.event)
|
|
{
|
|
/* Window Resize */
|
|
case SDL_WINDOWEVENT_RESIZED:
|
|
if (SDL_GetWindowFlags(
|
|
SDL_GetWindowFromID(evt.window.windowID)
|
|
) & SDL_WINDOW_INPUT_FOCUS)
|
|
{
|
|
resetWindow = true;
|
|
}
|
|
break;
|
|
|
|
/* Window Focus */
|
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
if (!game.disablepause)
|
|
{
|
|
isActive = true;
|
|
music.resume();
|
|
music.resumeef();
|
|
}
|
|
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0)
|
|
{
|
|
if (wasFullscreen)
|
|
{
|
|
graphics.screenbuffer->isWindowed = false;
|
|
SDL_SetWindowFullscreen(
|
|
SDL_GetWindowFromID(evt.window.windowID),
|
|
SDL_WINDOW_FULLSCREEN_DESKTOP
|
|
);
|
|
}
|
|
}
|
|
SDL_DisableScreenSaver();
|
|
break;
|
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
if (!game.disablepause)
|
|
{
|
|
isActive = false;
|
|
music.pause();
|
|
music.pauseef();
|
|
}
|
|
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0)
|
|
{
|
|
wasFullscreen = !graphics.screenbuffer->isWindowed;
|
|
graphics.screenbuffer->isWindowed = true;
|
|
SDL_SetWindowFullscreen(
|
|
SDL_GetWindowFromID(evt.window.windowID),
|
|
0
|
|
);
|
|
}
|
|
SDL_EnableScreenSaver();
|
|
break;
|
|
|
|
/* Mouse Focus */
|
|
case SDL_WINDOWEVENT_ENTER:
|
|
SDL_DisableScreenSaver();
|
|
break;
|
|
case SDL_WINDOWEVENT_LEAVE:
|
|
SDL_EnableScreenSaver();
|
|
break;
|
|
}
|
|
break;
|
|
|
|
/* Quit Event */
|
|
case SDL_QUIT:
|
|
VVV_exit(0);
|
|
break;
|
|
}
|
|
|
|
switch (evt.type)
|
|
{
|
|
case SDL_KEYDOWN:
|
|
if (evt.key.repeat == 0)
|
|
{
|
|
hidemouse = true;
|
|
}
|
|
break;
|
|
case SDL_TEXTINPUT:
|
|
case SDL_CONTROLLERBUTTONDOWN:
|
|
case SDL_CONTROLLERAXISMOTION:
|
|
hidemouse = true;
|
|
break;
|
|
case SDL_MOUSEMOTION:
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
showmouse = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
mousetoggletimeout = changemousestate(
|
|
mousetoggletimeout,
|
|
showmouse,
|
|
hidemouse
|
|
);
|
|
|
|
if (fullscreenkeybind)
|
|
{
|
|
toggleFullscreen();
|
|
}
|
|
}
|
|
|
|
bool KeyPoll::isDown(SDL_Keycode key)
|
|
{
|
|
return keymap[key];
|
|
}
|
|
|
|
bool KeyPoll::isDown(std::vector<SDL_GameControllerButton> buttons)
|
|
{
|
|
for (size_t i = 0; i < buttons.size(); i += 1)
|
|
{
|
|
if (buttonmap[buttons[i]])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool KeyPoll::isDown(SDL_GameControllerButton button)
|
|
{
|
|
return buttonmap[button];
|
|
}
|
|
|
|
bool KeyPoll::controllerButtonDown(void)
|
|
{
|
|
for (
|
|
SDL_GameControllerButton button = SDL_CONTROLLER_BUTTON_A;
|
|
button < SDL_CONTROLLER_BUTTON_DPAD_UP;
|
|
button = (SDL_GameControllerButton) (button + 1)
|
|
) {
|
|
if (isDown(button))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool KeyPoll::controllerWantsLeft(bool includeVert)
|
|
{
|
|
return ( buttonmap[SDL_CONTROLLER_BUTTON_DPAD_LEFT] ||
|
|
xVel < 0 ||
|
|
( includeVert &&
|
|
( buttonmap[SDL_CONTROLLER_BUTTON_DPAD_UP] ||
|
|
yVel < 0 ) ) );
|
|
}
|
|
|
|
bool KeyPoll::controllerWantsRight(bool includeVert)
|
|
{
|
|
return ( buttonmap[SDL_CONTROLLER_BUTTON_DPAD_RIGHT] ||
|
|
xVel > 0 ||
|
|
( includeVert &&
|
|
( buttonmap[SDL_CONTROLLER_BUTTON_DPAD_DOWN] ||
|
|
yVel > 0 ) ) );
|
|
}
|