2022-10-03 02:41:33 -07:00
|
|
|
#include "mouse.h"
|
|
|
|
|
|
|
|
#include "color.h"
|
|
|
|
#include "core.h"
|
|
|
|
#include "dinput.h"
|
2022-10-04 23:23:27 -07:00
|
|
|
#include "input.h"
|
2022-10-03 02:41:33 -07:00
|
|
|
#include "memory.h"
|
2022-10-03 06:42:34 -07:00
|
|
|
#include "kb.h"
|
2022-10-03 02:41:33 -07:00
|
|
|
#include "vcr.h"
|
|
|
|
|
|
|
|
namespace fallout {
|
|
|
|
|
|
|
|
static void mousePrepareDefaultCursor();
|
|
|
|
static void _mouse_anim();
|
|
|
|
static void _mouse_clip();
|
|
|
|
|
|
|
|
// The default mouse cursor buffer.
|
|
|
|
//
|
|
|
|
// Initially it contains color codes, which will be replaced at startup
|
|
|
|
// according to loaded palette.
|
|
|
|
//
|
|
|
|
// Available color codes:
|
|
|
|
// - 0: transparent
|
|
|
|
// - 1: white
|
|
|
|
// - 15: black
|
|
|
|
//
|
|
|
|
// 0x51E250
|
|
|
|
static unsigned char gMouseDefaultCursor[MOUSE_DEFAULT_CURSOR_SIZE] = {
|
|
|
|
// clang-format off
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 0,
|
|
|
|
1, 15, 15, 15, 15, 15, 1, 0,
|
|
|
|
1, 15, 15, 15, 15, 1, 1, 0,
|
|
|
|
1, 15, 15, 15, 15, 1, 1, 0,
|
|
|
|
1, 15, 15, 15, 15, 15, 1, 1,
|
|
|
|
1, 15, 1, 1, 15, 15, 15, 1,
|
|
|
|
1, 1, 1, 1, 1, 15, 15, 1,
|
|
|
|
0, 0, 0, 0, 1, 1, 1, 1,
|
|
|
|
// clang-format on
|
|
|
|
};
|
|
|
|
|
|
|
|
// 0x51E290
|
|
|
|
static int _mouse_idling = 0;
|
|
|
|
|
|
|
|
// 0x51E294
|
|
|
|
static unsigned char* gMouseCursorData = NULL;
|
|
|
|
|
|
|
|
// 0x51E298
|
|
|
|
static unsigned char* _mouse_shape = NULL;
|
|
|
|
|
|
|
|
// 0x51E29C
|
|
|
|
static unsigned char* _mouse_fptr = NULL;
|
|
|
|
|
|
|
|
// 0x51E2A0
|
|
|
|
static double gMouseSensitivity = 1.0;
|
|
|
|
|
|
|
|
// 0x51E2AC
|
|
|
|
static int gMouseButtonsState = 0;
|
|
|
|
|
|
|
|
// 0x6AC790
|
|
|
|
static bool gCursorIsHidden;
|
|
|
|
|
|
|
|
// 0x6AC794
|
|
|
|
static int _raw_x;
|
|
|
|
|
|
|
|
// 0x6AC798
|
|
|
|
static int gMouseCursorHeight;
|
|
|
|
|
|
|
|
// 0x6AC79C
|
|
|
|
static int _raw_y;
|
|
|
|
|
|
|
|
// 0x6AC7A0
|
|
|
|
static int _raw_buttons;
|
|
|
|
|
|
|
|
// 0x6AC7A4
|
|
|
|
static int gMouseCursorY;
|
|
|
|
|
|
|
|
// 0x6AC7A8
|
|
|
|
static int gMouseCursorX;
|
|
|
|
|
|
|
|
// 0x6AC7AC
|
|
|
|
static int _mouse_disabled;
|
|
|
|
|
|
|
|
// 0x6AC7B0
|
|
|
|
static int gMouseEvent;
|
|
|
|
|
|
|
|
// 0x6AC7B4
|
|
|
|
static unsigned int _mouse_speed;
|
|
|
|
|
|
|
|
// 0x6AC7B8
|
|
|
|
static int _mouse_curr_frame;
|
|
|
|
|
|
|
|
// 0x6AC7BC
|
|
|
|
static bool gMouseInitialized;
|
|
|
|
|
|
|
|
// 0x6AC7C0
|
|
|
|
static int gMouseCursorPitch;
|
|
|
|
|
|
|
|
// 0x6AC7C4
|
|
|
|
static int gMouseCursorWidth;
|
|
|
|
|
|
|
|
// 0x6AC7C8
|
|
|
|
static int _mouse_num_frames;
|
|
|
|
|
|
|
|
// 0x6AC7CC
|
|
|
|
static int _mouse_hoty;
|
|
|
|
|
|
|
|
// 0x6AC7D0
|
|
|
|
static int _mouse_hotx;
|
|
|
|
|
|
|
|
// 0x6AC7D4
|
|
|
|
static unsigned int _mouse_idle_start_time;
|
|
|
|
|
|
|
|
// 0x6AC7D8
|
|
|
|
WindowDrawingProc2* _mouse_blit_trans;
|
|
|
|
|
|
|
|
// 0x6AC7DC
|
|
|
|
WINDOWDRAWINGPROC _mouse_blit;
|
|
|
|
|
|
|
|
// 0x6AC7E0
|
|
|
|
static char _mouse_trans;
|
|
|
|
|
|
|
|
static int gMouseWheelX = 0;
|
|
|
|
static int gMouseWheelY = 0;
|
|
|
|
|
|
|
|
// 0x4C9F40
|
|
|
|
int mouseInit()
|
|
|
|
{
|
|
|
|
gMouseInitialized = false;
|
|
|
|
_mouse_disabled = 0;
|
|
|
|
|
|
|
|
gCursorIsHidden = true;
|
|
|
|
|
|
|
|
mousePrepareDefaultCursor();
|
|
|
|
|
|
|
|
if (mouseSetFrame(NULL, 0, 0, 0, 0, 0, 0) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mouseDeviceAcquire()) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMouseInitialized = true;
|
|
|
|
gMouseCursorX = _scr_size.right / 2;
|
|
|
|
gMouseCursorY = _scr_size.bottom / 2;
|
|
|
|
_raw_x = _scr_size.right / 2;
|
|
|
|
_raw_y = _scr_size.bottom / 2;
|
|
|
|
_mouse_idle_start_time = _get_time();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C9FD8
|
|
|
|
void mouseFree()
|
|
|
|
{
|
|
|
|
mouseDeviceUnacquire();
|
|
|
|
|
|
|
|
if (gMouseCursorData != NULL) {
|
|
|
|
internal_free(gMouseCursorData);
|
|
|
|
gMouseCursorData = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouse_fptr != NULL) {
|
|
|
|
tickersRemove(_mouse_anim);
|
|
|
|
_mouse_fptr = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA01C
|
|
|
|
static void mousePrepareDefaultCursor()
|
|
|
|
{
|
|
|
|
for (int index = 0; index < 64; index++) {
|
|
|
|
switch (gMouseDefaultCursor[index]) {
|
|
|
|
case 0:
|
|
|
|
gMouseDefaultCursor[index] = _colorTable[0];
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
gMouseDefaultCursor[index] = _colorTable[8456];
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
gMouseDefaultCursor[index] = _colorTable[32767];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA0AC
|
|
|
|
int mouseSetFrame(unsigned char* a1, int width, int height, int pitch, int a5, int a6, char a7)
|
|
|
|
{
|
|
|
|
Rect rect;
|
|
|
|
unsigned char* v9;
|
|
|
|
int v11, v12;
|
|
|
|
int v7, v8;
|
|
|
|
|
|
|
|
v7 = a5;
|
|
|
|
v8 = a6;
|
|
|
|
v9 = a1;
|
|
|
|
|
|
|
|
if (a1 == NULL) {
|
|
|
|
// NOTE: Original code looks tail recursion optimization.
|
|
|
|
return mouseSetFrame(gMouseDefaultCursor, MOUSE_DEFAULT_CURSOR_WIDTH, MOUSE_DEFAULT_CURSOR_HEIGHT, MOUSE_DEFAULT_CURSOR_WIDTH, 1, 1, _colorTable[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cursorWasHidden = gCursorIsHidden;
|
|
|
|
if (!gCursorIsHidden && gMouseInitialized) {
|
|
|
|
gCursorIsHidden = true;
|
|
|
|
mouseGetRect(&rect);
|
|
|
|
windowRefreshAll(&rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width != gMouseCursorWidth || height != gMouseCursorHeight) {
|
|
|
|
unsigned char* buf = (unsigned char*)internal_malloc(width * height);
|
|
|
|
if (buf == NULL) {
|
|
|
|
if (!cursorWasHidden) {
|
|
|
|
mouseShowCursor();
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMouseCursorData != NULL) {
|
|
|
|
internal_free(gMouseCursorData);
|
|
|
|
}
|
|
|
|
|
|
|
|
gMouseCursorData = buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMouseCursorWidth = width;
|
|
|
|
gMouseCursorHeight = height;
|
|
|
|
gMouseCursorPitch = pitch;
|
|
|
|
_mouse_shape = v9;
|
|
|
|
_mouse_trans = a7;
|
|
|
|
|
|
|
|
if (_mouse_fptr) {
|
|
|
|
tickersRemove(_mouse_anim);
|
|
|
|
_mouse_fptr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
v11 = _mouse_hotx - v7;
|
|
|
|
_mouse_hotx = v7;
|
|
|
|
|
|
|
|
gMouseCursorX += v11;
|
|
|
|
|
|
|
|
v12 = _mouse_hoty - v8;
|
|
|
|
_mouse_hoty = v8;
|
|
|
|
|
|
|
|
gMouseCursorY += v12;
|
|
|
|
|
|
|
|
_mouse_clip();
|
|
|
|
|
|
|
|
if (!cursorWasHidden) {
|
|
|
|
mouseShowCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
_raw_x = gMouseCursorX;
|
|
|
|
_raw_y = gMouseCursorY;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Looks like this code is not reachable.
|
|
|
|
//
|
|
|
|
// 0x4CA2D0
|
|
|
|
static void _mouse_anim()
|
|
|
|
{
|
|
|
|
// 0x51E2A8
|
|
|
|
static unsigned int ticker = 0;
|
|
|
|
|
|
|
|
if (getTicksSince(ticker) >= _mouse_speed) {
|
|
|
|
ticker = _get_time();
|
|
|
|
|
|
|
|
if (++_mouse_curr_frame == _mouse_num_frames) {
|
|
|
|
_mouse_curr_frame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_mouse_shape = gMouseCursorWidth * _mouse_curr_frame * gMouseCursorHeight + _mouse_fptr;
|
|
|
|
|
|
|
|
if (!gCursorIsHidden) {
|
|
|
|
mouseShowCursor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA34C
|
|
|
|
void mouseShowCursor()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned char* v2;
|
|
|
|
int v7, v8;
|
|
|
|
int v9, v10;
|
|
|
|
int v4;
|
|
|
|
unsigned char v6;
|
|
|
|
int v3;
|
|
|
|
|
|
|
|
v2 = gMouseCursorData;
|
|
|
|
if (gMouseInitialized) {
|
|
|
|
if (!_mouse_blit_trans || !gCursorIsHidden) {
|
|
|
|
_win_get_mouse_buf(gMouseCursorData);
|
|
|
|
v2 = gMouseCursorData;
|
|
|
|
v3 = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < gMouseCursorHeight; i++) {
|
|
|
|
for (v4 = 0; v4 < gMouseCursorWidth; v4++) {
|
|
|
|
v6 = _mouse_shape[i * gMouseCursorPitch + v4];
|
|
|
|
if (v6 != _mouse_trans) {
|
|
|
|
v2[v3] = v6;
|
|
|
|
}
|
|
|
|
v3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMouseCursorX >= _scr_size.left) {
|
|
|
|
if (gMouseCursorWidth + gMouseCursorX - 1 <= _scr_size.right) {
|
|
|
|
v8 = gMouseCursorWidth;
|
|
|
|
v7 = 0;
|
|
|
|
} else {
|
|
|
|
v7 = 0;
|
|
|
|
v8 = _scr_size.right - gMouseCursorX + 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
v7 = _scr_size.left - gMouseCursorX;
|
|
|
|
v8 = gMouseCursorWidth - (_scr_size.left - gMouseCursorX);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMouseCursorY >= _scr_size.top) {
|
|
|
|
if (gMouseCursorHeight + gMouseCursorY - 1 <= _scr_size.bottom) {
|
|
|
|
v9 = 0;
|
|
|
|
v10 = gMouseCursorHeight;
|
|
|
|
} else {
|
|
|
|
v9 = 0;
|
|
|
|
v10 = _scr_size.bottom - gMouseCursorY + 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
v9 = _scr_size.top - gMouseCursorY;
|
|
|
|
v10 = gMouseCursorHeight - (_scr_size.top - gMouseCursorY);
|
|
|
|
}
|
|
|
|
|
|
|
|
gMouseCursorData = v2;
|
|
|
|
if (_mouse_blit_trans && gCursorIsHidden) {
|
|
|
|
_mouse_blit_trans(_mouse_shape, gMouseCursorPitch, gMouseCursorHeight, v7, v9, v8, v10, v7 + gMouseCursorX, v9 + gMouseCursorY, _mouse_trans);
|
|
|
|
} else {
|
|
|
|
_mouse_blit(gMouseCursorData, gMouseCursorWidth, gMouseCursorHeight, v7, v9, v8, v10, v7 + gMouseCursorX, v9 + gMouseCursorY);
|
|
|
|
}
|
|
|
|
|
|
|
|
v2 = gMouseCursorData;
|
|
|
|
gCursorIsHidden = false;
|
|
|
|
}
|
|
|
|
gMouseCursorData = v2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA534
|
|
|
|
void mouseHideCursor()
|
|
|
|
{
|
|
|
|
Rect rect;
|
|
|
|
|
|
|
|
if (gMouseInitialized) {
|
|
|
|
if (!gCursorIsHidden) {
|
|
|
|
rect.left = gMouseCursorX;
|
|
|
|
rect.top = gMouseCursorY;
|
|
|
|
rect.right = gMouseCursorX + gMouseCursorWidth - 1;
|
|
|
|
rect.bottom = gMouseCursorY + gMouseCursorHeight - 1;
|
|
|
|
|
|
|
|
gCursorIsHidden = true;
|
|
|
|
windowRefreshAll(&rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA59C
|
|
|
|
void _mouse_info()
|
|
|
|
{
|
|
|
|
if (!gMouseInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gCursorIsHidden) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouse_disabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int buttons = 0;
|
|
|
|
|
|
|
|
MouseData mouseData;
|
|
|
|
if (mouseDeviceGetData(&mouseData)) {
|
|
|
|
x = mouseData.x;
|
|
|
|
y = mouseData.y;
|
|
|
|
|
|
|
|
if (mouseData.buttons[0] == 1) {
|
|
|
|
buttons |= MOUSE_STATE_LEFT_BUTTON_DOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mouseData.buttons[1] == 1) {
|
|
|
|
buttons |= MOUSE_STATE_RIGHT_BUTTON_DOWN;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust for mouse senstivity.
|
|
|
|
x = (int)(x * gMouseSensitivity);
|
|
|
|
y = (int)(y * gMouseSensitivity);
|
|
|
|
|
|
|
|
if (gVcrState == VCR_STATE_PLAYING) {
|
|
|
|
if (((gVcrTerminateFlags & VCR_TERMINATE_ON_MOUSE_PRESS) != 0 && buttons != 0)
|
|
|
|
|| ((gVcrTerminateFlags & VCR_TERMINATE_ON_MOUSE_MOVE) != 0 && (x != 0 || y != 0))) {
|
|
|
|
gVcrPlaybackCompletionReason = VCR_PLAYBACK_COMPLETION_REASON_TERMINATED;
|
|
|
|
vcrStop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
buttons = gMouseButtonsState;
|
|
|
|
}
|
|
|
|
|
|
|
|
_mouse_simulate_input(x, y, buttons);
|
|
|
|
|
|
|
|
// TODO: Move to `_mouse_simulate_input`.
|
|
|
|
// TODO: Record wheel event in VCR.
|
|
|
|
gMouseWheelX = mouseData.wheelX;
|
|
|
|
gMouseWheelY = mouseData.wheelY;
|
|
|
|
|
|
|
|
if (gMouseWheelX != 0 || gMouseWheelY != 0) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_WHEEL;
|
|
|
|
_raw_buttons |= MOUSE_EVENT_WHEEL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA698
|
|
|
|
void _mouse_simulate_input(int delta_x, int delta_y, int buttons)
|
|
|
|
{
|
|
|
|
// 0x6AC7E4
|
|
|
|
static unsigned int previousRightButtonTimestamp;
|
|
|
|
|
|
|
|
// 0x6AC7E8
|
|
|
|
static unsigned int previousLeftButtonTimestamp;
|
|
|
|
|
|
|
|
// 0x6AC7EC
|
|
|
|
static int previousEvent;
|
|
|
|
|
|
|
|
if (!gMouseInitialized || gCursorIsHidden) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (delta_x || delta_y || buttons != gMouseButtonsState) {
|
|
|
|
if (gVcrState == 0) {
|
|
|
|
if (_vcr_buffer_index == VCR_BUFFER_CAPACITY - 1) {
|
|
|
|
vcrDump();
|
|
|
|
}
|
|
|
|
|
|
|
|
VcrEntry* vcrEntry = &(_vcr_buffer[_vcr_buffer_index]);
|
|
|
|
vcrEntry->type = VCR_ENTRY_TYPE_MOUSE_EVENT;
|
|
|
|
vcrEntry->time = _vcr_time;
|
|
|
|
vcrEntry->counter = _vcr_counter;
|
|
|
|
vcrEntry->mouseEvent.dx = delta_x;
|
|
|
|
vcrEntry->mouseEvent.dy = delta_y;
|
|
|
|
vcrEntry->mouseEvent.buttons = buttons;
|
|
|
|
|
|
|
|
_vcr_buffer_index++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (gMouseButtonsState == 0) {
|
|
|
|
if (!_mouse_idling) {
|
|
|
|
_mouse_idle_start_time = _get_time();
|
|
|
|
_mouse_idling = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMouseButtonsState = 0;
|
|
|
|
_raw_buttons = 0;
|
|
|
|
gMouseEvent = 0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_mouse_idling = 0;
|
|
|
|
gMouseButtonsState = buttons;
|
|
|
|
previousEvent = gMouseEvent;
|
|
|
|
gMouseEvent = 0;
|
|
|
|
|
|
|
|
if ((previousEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT) != 0) {
|
|
|
|
if ((buttons & 0x01) != 0) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_REPEAT;
|
|
|
|
|
|
|
|
if (getTicksSince(previousLeftButtonTimestamp) > BUTTON_REPEAT_TIME) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_DOWN;
|
|
|
|
previousLeftButtonTimestamp = _get_time();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_UP;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((buttons & 0x01) != 0) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_DOWN;
|
|
|
|
previousLeftButtonTimestamp = _get_time();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((previousEvent & MOUSE_EVENT_RIGHT_BUTTON_DOWN_REPEAT) != 0) {
|
|
|
|
if ((buttons & 0x02) != 0) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_REPEAT;
|
|
|
|
if (getTicksSince(previousRightButtonTimestamp) > BUTTON_REPEAT_TIME) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_DOWN;
|
|
|
|
previousRightButtonTimestamp = _get_time();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_UP;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (buttons & 0x02) {
|
|
|
|
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_DOWN;
|
|
|
|
previousRightButtonTimestamp = _get_time();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_raw_buttons = gMouseEvent;
|
|
|
|
|
|
|
|
if (delta_x != 0 || delta_y != 0) {
|
|
|
|
Rect mouseRect;
|
|
|
|
mouseRect.left = gMouseCursorX;
|
|
|
|
mouseRect.top = gMouseCursorY;
|
|
|
|
mouseRect.right = gMouseCursorWidth + gMouseCursorX - 1;
|
|
|
|
mouseRect.bottom = gMouseCursorHeight + gMouseCursorY - 1;
|
|
|
|
|
|
|
|
gMouseCursorX += delta_x;
|
|
|
|
gMouseCursorY += delta_y;
|
|
|
|
_mouse_clip();
|
|
|
|
|
|
|
|
windowRefreshAll(&mouseRect);
|
|
|
|
|
|
|
|
mouseShowCursor();
|
|
|
|
|
|
|
|
_raw_x = gMouseCursorX;
|
|
|
|
_raw_y = gMouseCursorY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA8C8
|
|
|
|
bool _mouse_in(int left, int top, int right, int bottom)
|
|
|
|
{
|
|
|
|
if (!gMouseInitialized) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gMouseCursorHeight + gMouseCursorY > top
|
|
|
|
&& right >= gMouseCursorX
|
|
|
|
&& gMouseCursorWidth + gMouseCursorX > left
|
|
|
|
&& bottom >= gMouseCursorY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA934
|
|
|
|
bool _mouse_click_in(int left, int top, int right, int bottom)
|
|
|
|
{
|
|
|
|
if (!gMouseInitialized) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _mouse_hoty + gMouseCursorY >= top
|
|
|
|
&& _mouse_hotx + gMouseCursorX <= right
|
|
|
|
&& _mouse_hotx + gMouseCursorX >= left
|
|
|
|
&& _mouse_hoty + gMouseCursorY <= bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA9A0
|
|
|
|
void mouseGetRect(Rect* rect)
|
|
|
|
{
|
|
|
|
rect->left = gMouseCursorX;
|
|
|
|
rect->top = gMouseCursorY;
|
|
|
|
rect->right = gMouseCursorWidth + gMouseCursorX - 1;
|
|
|
|
rect->bottom = gMouseCursorHeight + gMouseCursorY - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CA9DC
|
|
|
|
void mouseGetPosition(int* xPtr, int* yPtr)
|
|
|
|
{
|
|
|
|
*xPtr = _mouse_hotx + gMouseCursorX;
|
|
|
|
*yPtr = _mouse_hoty + gMouseCursorY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAA04
|
|
|
|
void _mouse_set_position(int a1, int a2)
|
|
|
|
{
|
|
|
|
gMouseCursorX = a1 - _mouse_hotx;
|
|
|
|
gMouseCursorY = a2 - _mouse_hoty;
|
|
|
|
_raw_y = a2 - _mouse_hoty;
|
|
|
|
_raw_x = a1 - _mouse_hotx;
|
|
|
|
_mouse_clip();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAA38
|
|
|
|
static void _mouse_clip()
|
|
|
|
{
|
|
|
|
if (_mouse_hotx + gMouseCursorX < _scr_size.left) {
|
|
|
|
gMouseCursorX = _scr_size.left - _mouse_hotx;
|
|
|
|
} else if (_mouse_hotx + gMouseCursorX > _scr_size.right) {
|
|
|
|
gMouseCursorX = _scr_size.right - _mouse_hotx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouse_hoty + gMouseCursorY < _scr_size.top) {
|
|
|
|
gMouseCursorY = _scr_size.top - _mouse_hoty;
|
|
|
|
} else if (_mouse_hoty + gMouseCursorY > _scr_size.bottom) {
|
|
|
|
gMouseCursorY = _scr_size.bottom - _mouse_hoty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAAA0
|
|
|
|
int mouseGetEvent()
|
|
|
|
{
|
|
|
|
return gMouseEvent;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAAA8
|
|
|
|
bool cursorIsHidden()
|
|
|
|
{
|
|
|
|
return gCursorIsHidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAB5C
|
|
|
|
void _mouse_get_raw_state(int* out_x, int* out_y, int* out_buttons)
|
|
|
|
{
|
|
|
|
MouseData mouseData;
|
|
|
|
if (!mouseDeviceGetData(&mouseData)) {
|
|
|
|
mouseData.x = 0;
|
|
|
|
mouseData.y = 0;
|
|
|
|
mouseData.buttons[0] = (gMouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) != 0;
|
|
|
|
mouseData.buttons[1] = (gMouseEvent & MOUSE_EVENT_RIGHT_BUTTON_DOWN) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_raw_buttons = 0;
|
|
|
|
_raw_x += mouseData.x;
|
|
|
|
_raw_y += mouseData.y;
|
|
|
|
|
|
|
|
if (mouseData.buttons[0] != 0) {
|
|
|
|
_raw_buttons |= MOUSE_EVENT_LEFT_BUTTON_DOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mouseData.buttons[1] != 0) {
|
|
|
|
_raw_buttons |= MOUSE_EVENT_RIGHT_BUTTON_DOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_x = _raw_x;
|
|
|
|
*out_y = _raw_y;
|
|
|
|
*out_buttons = _raw_buttons;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4CAC3C
|
|
|
|
void mouseSetSensitivity(double value)
|
|
|
|
{
|
|
|
|
if (value > 0 && value < 2.0) {
|
|
|
|
gMouseSensitivity = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mouseGetPositionInWindow(int win, int* x, int* y)
|
|
|
|
{
|
|
|
|
mouseGetPosition(x, y);
|
|
|
|
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
if (window != NULL) {
|
|
|
|
*x -= window->rect.left;
|
|
|
|
*y -= window->rect.top;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mouseHitTestInWindow(int win, int left, int top, int right, int bottom)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
if (window != NULL) {
|
|
|
|
left += window->rect.left;
|
|
|
|
top += window->rect.top;
|
|
|
|
right += window->rect.left;
|
|
|
|
bottom += window->rect.top;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _mouse_click_in(left, top, right, bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mouseGetWheel(int* x, int* y)
|
|
|
|
{
|
|
|
|
*x = gMouseWheelX;
|
|
|
|
*y = gMouseWheelY;
|
|
|
|
}
|
|
|
|
|
|
|
|
void convertMouseWheelToArrowKey(int* keyCodePtr)
|
|
|
|
{
|
|
|
|
if (*keyCodePtr == -1) {
|
|
|
|
if ((mouseGetEvent() & MOUSE_EVENT_WHEEL) != 0) {
|
|
|
|
int wheelX;
|
|
|
|
int wheelY;
|
|
|
|
mouseGetWheel(&wheelX, &wheelY);
|
|
|
|
|
|
|
|
if (wheelY > 0) {
|
|
|
|
*keyCodePtr = KEY_ARROW_UP;
|
|
|
|
} else if (wheelY < 0) {
|
|
|
|
*keyCodePtr = KEY_ARROW_DOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace fallout
|