dxx-rebirth/common/arch/sdl/mouse.cpp

258 lines
5.7 KiB
C++
Raw Normal View History

2014-06-01 17:55:23 +00:00
/*
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
2006-03-20 17:12:09 +00:00
/*
*
* SDL mouse driver
2006-03-20 17:12:09 +00:00
*
*/
#include <string.h>
2013-06-30 02:22:56 +00:00
#include <SDL.h>
2006-03-20 17:12:09 +00:00
2012-07-01 02:54:33 +00:00
#include "maths.h"
2006-03-20 17:12:09 +00:00
#include "timer.h"
#include "event.h"
#include "window.h"
2006-03-20 17:12:09 +00:00
#include "mouse.h"
#include "playsave.h"
2014-07-20 01:09:55 +00:00
#include "dxxerror.h"
#include "args.h"
#include "gr.h"
2006-03-20 17:12:09 +00:00
inline namespace dcx {
2015-05-09 17:39:03 +00:00
namespace {
struct flushable_mouseinfo
{
int delta_x, delta_y, delta_z;
2015-05-09 17:39:03 +00:00
int z;
};
struct mouseinfo : flushable_mouseinfo
{
int x,y;
int cursor_enabled;
fix64 cursor_time;
2015-05-09 17:39:03 +00:00
array<fix64, MOUSE_MAX_BUTTONS> time_lastpressed;
};
}
static mouseinfo Mouse;
2006-03-20 17:12:09 +00:00
2015-11-26 02:56:54 +00:00
d_event_mousebutton::d_event_mousebutton(const event_type etype, const unsigned b) :
d_event{etype}, button(b)
2015-05-28 03:08:39 +00:00
{
}
void mouse_init(void)
2006-03-20 17:12:09 +00:00
{
2014-07-04 03:50:00 +00:00
Mouse = {};
}
void mouse_close(void)
{
SDL_ShowCursor(SDL_ENABLE);
2006-03-20 17:12:09 +00:00
}
2015-05-28 03:08:38 +00:00
static void maybe_send_z_move(const unsigned button)
{
d_event_mouse_moved event{};
event.type = EVENT_MOUSE_MOVED;
if (button == MBTN_Z_UP)
{
Mouse.delta_z += Z_SENSITIVITY;
Mouse.z += Z_SENSITIVITY;
event.dz = Z_SENSITIVITY;
}
else if (button == MBTN_Z_DOWN)
{
Mouse.delta_z -= Z_SENSITIVITY;
Mouse.z -= Z_SENSITIVITY;
event.dz = -1*Z_SENSITIVITY;
}
else
return;
event_send(event);
}
static void send_singleclick(const bool pressed, const unsigned button)
2015-05-28 03:08:38 +00:00
{
2015-05-28 03:08:39 +00:00
const d_event_mousebutton event{pressed ? EVENT_MOUSE_BUTTON_DOWN : EVENT_MOUSE_BUTTON_UP, button};
2015-05-28 03:08:38 +00:00
con_printf(CON_DEBUG, "Sending event %s, button %d, coords %d,%d,%d",
pressed ? "EVENT_MOUSE_BUTTON_DOWN" : "EVENT_MOUSE_BUTTON_UP", event.button, Mouse.x, Mouse.y, Mouse.z);
event_send(event);
}
static void maybe_send_doubleclick(const fix64 now, const unsigned button)
{
auto &when = Mouse.time_lastpressed[button];
const auto then = when;
when = now;
if (now > then + F1_0/5)
return;
2015-05-28 03:08:39 +00:00
const d_event_mousebutton event{EVENT_MOUSE_DOUBLE_CLICKED, button};
2015-05-28 03:08:38 +00:00
con_printf(CON_DEBUG, "Sending event EVENT_MOUSE_DOUBLE_CLICKED, button %d, coords %d,%d", button, Mouse.x, Mouse.y);
event_send(event);
}
void mouse_button_handler(SDL_MouseButtonEvent *mbe)
2006-03-20 17:12:09 +00:00
{
2015-07-18 21:01:56 +00:00
if (unlikely(CGameArg.CtlNoMouse))
2015-05-28 03:08:38 +00:00
return;
2006-03-20 17:12:09 +00:00
// to bad, SDL buttons use a different mapping as descent expects,
// this is at least true and tested for the first three buttons
static const array<int, 17> button_remap{{
2007-06-11 15:54:09 +00:00
MBTN_LEFT,
MBTN_MIDDLE,
MBTN_RIGHT,
MBTN_Z_UP,
MBTN_Z_DOWN,
MBTN_PITCH_BACKWARD,
MBTN_PITCH_FORWARD,
MBTN_BANK_LEFT,
MBTN_BANK_RIGHT,
MBTN_HEAD_LEFT,
MBTN_HEAD_RIGHT,
MBTN_11,
MBTN_12,
MBTN_13,
MBTN_14,
MBTN_15,
MBTN_16
}};
2015-05-28 03:08:38 +00:00
const unsigned button_idx = mbe->button - 1; // -1 since SDL seems to start counting at 1
if (unlikely(button_idx >= button_remap.size()))
return;
2015-05-28 03:08:38 +00:00
const auto now = timer_query();
2015-05-28 03:08:38 +00:00
const auto button = button_remap[button_idx];
const auto mbe_state = mbe->state;
2015-05-28 03:08:38 +00:00
Mouse.cursor_time = now;
const auto pressed = mbe_state != SDL_RELEASED;
if (pressed) {
2015-05-28 03:08:38 +00:00
maybe_send_z_move(button);
2006-03-20 17:12:09 +00:00
}
send_singleclick(pressed, button);
//Double-click support
if (pressed)
{
2015-05-28 03:08:38 +00:00
maybe_send_doubleclick(now, button);
}
2006-03-20 17:12:09 +00:00
}
void mouse_motion_handler(SDL_MouseMotionEvent *mme)
2006-03-20 17:12:09 +00:00
{
d_event_mouse_moved event;
2015-07-18 21:01:56 +00:00
if (CGameArg.CtlNoMouse)
return;
Mouse.cursor_time = timer_query();
2006-03-20 17:12:09 +00:00
Mouse.x += mme->xrel;
Mouse.y += mme->yrel;
event.type = EVENT_MOUSE_MOVED;
event.dx = mme->xrel;
event.dy = mme->yrel;
event.dz = 0; // handled in mouse_button_handler
2013-12-07 00:47:27 +00:00
//con_printf(CON_DEBUG, "Sending event EVENT_MOUSE_MOVED, relative motion %d,%d,%d",
// event.dx, event.dy, event.dz);
2014-10-04 21:47:13 +00:00
event_send(event);
2006-03-20 17:12:09 +00:00
}
void mouse_flush() // clears all mice events...
{
// event_poll();
2015-05-09 17:39:03 +00:00
static_cast<flushable_mouseinfo &>(Mouse) = {};
2006-03-20 17:12:09 +00:00
SDL_GetMouseState(&Mouse.x, &Mouse.y); // necessary because polling only gives us the delta.
}
//========================================================================
void mouse_get_pos( int *x, int *y, int *z )
2006-03-20 17:12:09 +00:00
{
//event_poll(); // Have to assume this is called in event_process, because event_poll can cause a window to close (depending on what the user does)
2006-03-20 17:12:09 +00:00
*x=Mouse.x;
*y=Mouse.y;
*z=Mouse.z;
}
2014-08-06 02:10:49 +00:00
window_event_result mouse_in_window(window *wind)
{
2015-01-17 18:31:40 +00:00
auto &canv = window_get_canvas(*wind);
return (static_cast<unsigned>(Mouse.x) - canv.cv_bitmap.bm_x <= canv.cv_bitmap.bm_w) &&
(static_cast<unsigned>(Mouse.y) - canv.cv_bitmap.bm_y <= canv.cv_bitmap.bm_h) ? window_event_result::handled : window_event_result::ignored;
}
void mouse_get_delta( int *dx, int *dy, int *dz )
2006-03-20 17:12:09 +00:00
{
Giving credits function ability to use custom creditfile (again); Made laser-offset for laser exclusive so Prox mines won't go tru doors; Preventing cycling tru cockpit modes while dead, but allowing to load a state; Implemented D2X' lighting code to D1X (faster, better, sexier - weeee); Try to hop over some errors regarding walls/doors in levels instead of using -1 indexes for arrays; Made the briefing text ptr a bit more failsafe in case the file is corrupt/non-standard; Made scores use the menu screen even in GAME OVER; Fixed bug in neighbour fields of Weapon Keys table; Added the Weapon Keys stuff to TABLE_CREATION; Fixed bug where D2X did not recall applied resolution in the resolutions menu; Simpler check to create DEMO_DIR; Seperated X/Y sensitivity for mouse and joystick; Flush controls when Automap toggles so keypress won't deactivate it again; Made FrameCount in Demos aligned to the Dropframe condition; Added KEy to ttoggle playback text off; Gracefully exit demo code if demo is corrupt; Removed that new percent counter because many old demos seem to have corrupted last frames; Closing endlevel data file if IFF error so the mission still can be freed; Fixed Cruising for keyboard which was not aligned to FPS correctly; Used mouse delta scaling in kconfig.c instead of mouse.c to not screw up when delta is requested in non-ingame situations - it actually belongs to the controls IMHO; Now support up to 8 joysticks; Changed some leftover malloc's to d_malloc and free to d_free
2008-10-16 17:27:02 +00:00
*dz = Mouse.delta_z;
Mouse.delta_x = 0;
Mouse.delta_y = 0;
Mouse.delta_z = 0;
2015-05-09 17:39:03 +00:00
SDL_GetRelativeMouseState(dx, dy);
2006-03-20 17:12:09 +00:00
}
2015-05-28 03:08:38 +00:00
template <bool noactivate>
static void mouse_change_cursor()
{
2015-07-18 21:01:56 +00:00
Mouse.cursor_enabled = (!noactivate && !CGameArg.CtlNoMouse && !CGameArg.CtlNoCursor);
if (!Mouse.cursor_enabled)
SDL_ShowCursor(SDL_DISABLE);
}
2015-05-28 03:08:38 +00:00
void mouse_enable_cursor()
{
mouse_change_cursor<false>();
}
void mouse_disable_cursor()
{
mouse_change_cursor<true>();
}
// If we want to display/hide cursor, do so if not already and also hide it automatically after some time.
void mouse_cursor_autohide()
{
static fix64 hidden_time = 0;
2015-05-09 17:39:03 +00:00
const auto is_showing = SDL_ShowCursor(SDL_QUERY);
int result;
if (Mouse.cursor_enabled)
{
2015-05-09 17:39:03 +00:00
const auto now = timer_query();
const auto cursor_time = Mouse.cursor_time;
const auto recent_cursor_time = cursor_time + (F1_0*2) >= now;
if (is_showing)
{
2015-05-09 17:39:03 +00:00
if (recent_cursor_time)
return;
hidden_time = now;
result = SDL_DISABLE;
}
else
{
if (!(recent_cursor_time && hidden_time + (F1_0/2) < now))
return;
result = SDL_ENABLE;
}
}
else
{
2015-05-09 17:39:03 +00:00
if (!is_showing)
return;
result = SDL_DISABLE;
}
2015-05-09 17:39:03 +00:00
SDL_ShowCursor(result);
}
}