Extract mouse

This commit is contained in:
Alexander Batalov 2022-10-03 12:41:33 +03:00
parent a541d0f24a
commit b5681984cd
30 changed files with 791 additions and 770 deletions

View File

@ -153,6 +153,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/mmx.h" "src/mmx.h"
"src/mouse_manager.cc" "src/mouse_manager.cc"
"src/mouse_manager.h" "src/mouse_manager.h"
"src/mouse.cc"
"src/mouse.h"
"src/movie_effect.cc" "src/movie_effect.cc"
"src/movie_effect.h" "src/movie_effect.h"
"src/movie_lib.cc" "src/movie_lib.cc"

View File

@ -19,6 +19,7 @@
#include "interface.h" #include "interface.h"
#include "item.h" #include "item.h"
#include "map.h" #include "map.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "party_member.h" #include "party_member.h"
#include "perk.h" #include "perk.h"

View File

@ -27,6 +27,7 @@
#include "map.h" #include "map.h"
#include "memory.h" #include "memory.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "palette.h" #include "palette.h"
#include "perk.h" #include "perk.h"

View File

@ -19,6 +19,7 @@
#include "game_sound.h" #include "game_sound.h"
#include "memory.h" #include "memory.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "options.h" #include "options.h"
#include "palette.h" #include "palette.h"

View File

@ -13,6 +13,7 @@
#include "interface.h" #include "interface.h"
#include "memory.h" #include "memory.h"
#include "mmx.h" #include "mmx.h"
#include "mouse.h"
#include "text_font.h" #include "text_font.h"
#include "vcr.h" #include "vcr.h"
#include "win32.h" #include "win32.h"
@ -35,51 +36,6 @@ int gKeyboardKeyRepeatRate = 80;
// 0x51E240 // 0x51E240
int gKeyboardKeyRepeatDelay = 500; int gKeyboardKeyRepeatDelay = 500;
// 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
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
int _mouse_idling = 0;
// 0x51E294
unsigned char* gMouseCursorData = NULL;
// 0x51E298
unsigned char* _mouse_shape = NULL;
// 0x51E29C
unsigned char* _mouse_fptr = NULL;
// 0x51E2A0
double gMouseSensitivity = 1.0;
// 0x51E2A8
unsigned int _ticker_ = 0;
// 0x51E2AC
int gMouseButtonsState = 0;
// NOTE: This value is never set, so it's impossible to understand it's // NOTE: This value is never set, so it's impossible to understand it's
// meaning. // meaning.
// //
@ -179,81 +135,6 @@ TickerListNode* gTickerListHead;
// 0x6AC788 // 0x6AC788
unsigned int gTickerLastTimestamp; unsigned int gTickerLastTimestamp;
// 0x6AC790
bool gCursorIsHidden;
// x (1)
// 0x6AC794
int _raw_x;
// 0x6AC798
int gMouseCursorHeight;
// y (1)
// 0x6AC79C
int _raw_y;
// mouse event (1)
// 0x6AC7A0
int _raw_buttons;
// 0x6AC7A4
int gMouseCursorY;
// 0x6AC7A8
int gMouseCursorX;
// 0x6AC7AC
int _mouse_disabled;
// 0x6AC7B0
int gMouseEvent;
// 0x6AC7B4
unsigned int _mouse_speed;
// 0x6AC7B8
int _mouse_curr_frame;
// 0x6AC7BC
bool gMouseInitialized;
// 0x6AC7C0
int gMouseCursorPitch;
// 0x6AC7C4
int gMouseCursorWidth;
// 0x6AC7C8
int _mouse_num_frames;
// 0x6AC7CC
int _mouse_hoty;
// 0x6AC7D0
int _mouse_hotx;
// 0x6AC7D4
unsigned int _mouse_idle_start_time;
// 0x6AC7D8
WindowDrawingProc2* _mouse_blit_trans;
// 0x6AC7DC
WINDOWDRAWINGPROC _mouse_blit;
// 0x6AC7E0
unsigned char _mouse_trans;
// 0x6AC7E4
int gMouseRightButtonDownTimestamp;
// 0x6AC7E8
int gMouseLeftButtonDownTimestamp;
// 0x6AC7EC
int gMousePreviousEvent;
// 0x6AC7F0 // 0x6AC7F0
unsigned short gSixteenBppPalette[256]; unsigned short gSixteenBppPalette[256];
@ -333,9 +214,6 @@ SDL_Renderer* gSdlRenderer = NULL;
SDL_Texture* gSdlTexture = NULL; SDL_Texture* gSdlTexture = NULL;
SDL_Surface* gSdlTextureSurface = NULL; SDL_Surface* gSdlTextureSurface = NULL;
static int gMouseWheelX = 0;
static int gMouseWheelY = 0;
// 0x4C8A70 // 0x4C8A70
int coreInit(int a1) int coreInit(int a1)
{ {
@ -1416,528 +1294,6 @@ void _GNW95_lost_focus()
} }
} }
// 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
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, int 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
void _mouse_anim()
{
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)
{
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;
gMousePreviousEvent = gMouseEvent;
gMouseEvent = 0;
if ((gMousePreviousEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT) != 0) {
if ((buttons & 0x01) != 0) {
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_REPEAT;
if (getTicksSince(gMouseLeftButtonDownTimestamp) > BUTTON_REPEAT_TIME) {
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_DOWN;
gMouseLeftButtonDownTimestamp = _get_time();
}
} else {
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_UP;
}
} else {
if ((buttons & 0x01) != 0) {
gMouseEvent |= MOUSE_EVENT_LEFT_BUTTON_DOWN;
gMouseLeftButtonDownTimestamp = _get_time();
}
}
if ((gMousePreviousEvent & MOUSE_EVENT_RIGHT_BUTTON_DOWN_REPEAT) != 0) {
if ((buttons & 0x02) != 0) {
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_REPEAT;
if (getTicksSince(gMouseRightButtonDownTimestamp) > BUTTON_REPEAT_TIME) {
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_DOWN;
gMouseRightButtonDownTimestamp = _get_time();
}
} else {
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_UP;
}
} else {
if (buttons & 0x02) {
gMouseEvent |= MOUSE_EVENT_RIGHT_BUTTON_DOWN;
gMouseRightButtonDownTimestamp = _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
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;
}
}
// 0x4CACD0 // 0x4CACD0
void mmxSetEnabled(bool a1) void mmxSetEnabled(bool a1)
{ {
@ -4445,53 +3801,6 @@ int screenGetVisibleHeight()
return screenGetHeight() - windowBottomMargin; return screenGetHeight() - windowBottomMargin;
} }
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;
}
}
}
}
static void idleImpl() static void idleImpl()
{ {
SDL_Delay(125); SDL_Delay(125);

View File

@ -10,28 +10,6 @@
namespace fallout { namespace fallout {
#define MOUSE_DEFAULT_CURSOR_WIDTH 8
#define MOUSE_DEFAULT_CURSOR_HEIGHT 8
#define MOUSE_DEFAULT_CURSOR_SIZE (MOUSE_DEFAULT_CURSOR_WIDTH * MOUSE_DEFAULT_CURSOR_HEIGHT)
#define MOUSE_STATE_LEFT_BUTTON_DOWN 0x01
#define MOUSE_STATE_RIGHT_BUTTON_DOWN 0x02
#define MOUSE_EVENT_LEFT_BUTTON_DOWN 0x01
#define MOUSE_EVENT_RIGHT_BUTTON_DOWN 0x02
#define MOUSE_EVENT_LEFT_BUTTON_REPEAT 0x04
#define MOUSE_EVENT_RIGHT_BUTTON_REPEAT 0x08
#define MOUSE_EVENT_LEFT_BUTTON_UP 0x10
#define MOUSE_EVENT_RIGHT_BUTTON_UP 0x20
#define MOUSE_EVENT_ANY_BUTTON_DOWN (MOUSE_EVENT_LEFT_BUTTON_DOWN | MOUSE_EVENT_RIGHT_BUTTON_DOWN)
#define MOUSE_EVENT_ANY_BUTTON_REPEAT (MOUSE_EVENT_LEFT_BUTTON_REPEAT | MOUSE_EVENT_RIGHT_BUTTON_REPEAT)
#define MOUSE_EVENT_ANY_BUTTON_UP (MOUSE_EVENT_LEFT_BUTTON_UP | MOUSE_EVENT_RIGHT_BUTTON_UP)
#define MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT (MOUSE_EVENT_LEFT_BUTTON_DOWN | MOUSE_EVENT_LEFT_BUTTON_REPEAT)
#define MOUSE_EVENT_RIGHT_BUTTON_DOWN_REPEAT (MOUSE_EVENT_RIGHT_BUTTON_DOWN | MOUSE_EVENT_RIGHT_BUTTON_REPEAT)
#define MOUSE_EVENT_WHEEL 0x40
#define BUTTON_REPEAT_TIME 250
#define KEY_STATE_UP 0 #define KEY_STATE_UP 0
#define KEY_STATE_DOWN 1 #define KEY_STATE_DOWN 1
#define KEY_STATE_REPEAT 2 #define KEY_STATE_REPEAT 2
@ -410,14 +388,6 @@ extern FocusFunc* _focus_func;
extern int gKeyboardKeyRepeatRate; extern int gKeyboardKeyRepeatRate;
extern int gKeyboardKeyRepeatDelay; extern int gKeyboardKeyRepeatDelay;
extern bool _keyboard_hooked; extern bool _keyboard_hooked;
extern unsigned char gMouseDefaultCursor[MOUSE_DEFAULT_CURSOR_SIZE];
extern int _mouse_idling;
extern unsigned char* gMouseCursorData;
extern unsigned char* _mouse_shape;
extern unsigned char* _mouse_fptr;
extern double gMouseSensitivity;
extern unsigned int _ticker_;
extern int gMouseButtonsState;
extern void (*_update_palette_func)(); extern void (*_update_palette_func)();
extern bool gMmxEnabled; extern bool gMmxEnabled;
@ -450,30 +420,6 @@ extern int gInputEventQueueWriteIndex;
extern bool gRunLoopDisabled; extern bool gRunLoopDisabled;
extern TickerListNode* gTickerListHead; extern TickerListNode* gTickerListHead;
extern unsigned int gTickerLastTimestamp; extern unsigned int gTickerLastTimestamp;
extern bool gCursorIsHidden;
extern int _raw_x;
extern int gMouseCursorHeight;
extern int _raw_y;
extern int _raw_buttons;
extern int gMouseCursorY;
extern int gMouseCursorX;
extern int _mouse_disabled;
extern int gMouseEvent;
extern unsigned int _mouse_speed;
extern int _mouse_curr_frame;
extern bool gMouseInitialized;
extern int gMouseCursorPitch;
extern int gMouseCursorWidth;
extern int _mouse_num_frames;
extern int _mouse_hoty;
extern int _mouse_hotx;
extern unsigned int _mouse_idle_start_time;
extern WindowDrawingProc2* _mouse_blit_trans;
extern WINDOWDRAWINGPROC _mouse_blit;
extern unsigned char _mouse_trans;
extern int gMouseRightButtonDownTimestamp;
extern int gMouseLeftButtonDownTimestamp;
extern int gMousePreviousEvent;
extern unsigned short gSixteenBppPalette[256]; extern unsigned short gSixteenBppPalette[256];
extern Rect _scr_size; extern Rect _scr_size;
extern int gRedMask; extern int gRedMask;
@ -539,25 +485,6 @@ void _GNW95_process_message();
void _GNW95_clear_time_stamps(); void _GNW95_clear_time_stamps();
void _GNW95_process_key(KeyboardData* data); void _GNW95_process_key(KeyboardData* data);
void _GNW95_lost_focus(); void _GNW95_lost_focus();
int mouseInit();
void mouseFree();
void mousePrepareDefaultCursor();
int mouseSetFrame(unsigned char* a1, int width, int height, int pitch, int a5, int a6, int a7);
void _mouse_anim();
void mouseShowCursor();
void mouseHideCursor();
void _mouse_info();
void _mouse_simulate_input(int delta_x, int delta_y, int buttons);
bool _mouse_in(int left, int top, int right, int bottom);
bool _mouse_click_in(int left, int top, int right, int bottom);
void mouseGetRect(Rect* rect);
void mouseGetPosition(int* out_x, int* out_y);
void _mouse_set_position(int a1, int a2);
void _mouse_clip();
int mouseGetEvent();
bool cursorIsHidden();
void _mouse_get_raw_state(int* out_x, int* out_y, int* out_buttons);
void mouseSetSensitivity(double value);
void mmxSetEnabled(bool a1); void mmxSetEnabled(bool a1);
int _init_mode_320_200(); int _init_mode_320_200();
int _init_mode_320_400(); int _init_mode_320_400();
@ -606,10 +533,6 @@ int keyboardPeekEvent(int index, KeyboardEvent** keyboardEventPtr);
int screenGetWidth(); int screenGetWidth();
int screenGetHeight(); int screenGetHeight();
int screenGetVisibleHeight(); int screenGetVisibleHeight();
void mouseGetPositionInWindow(int win, int* x, int* y);
bool mouseHitTestInWindow(int win, int left, int top, int right, int bottom);
void mouseGetWheel(int* x, int* y);
void convertMouseWheelToArrowKey(int* keyCodePtr);
} // namespace fallout } // namespace fallout

View File

@ -12,6 +12,7 @@
#include "game_mouse.h" #include "game_mouse.h"
#include "memory.h" #include "memory.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "palette.h" #include "palette.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "sound.h" #include "sound.h"

View File

@ -14,6 +14,7 @@
#include "game.h" #include "game.h"
#include "game_sound.h" #include "game_sound.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "text_font.h" #include "text_font.h"
#include "window_manager.h" #include "window_manager.h"

View File

@ -4,6 +4,7 @@
#include "core.h" #include "core.h"
#include "memory_manager.h" #include "memory_manager.h"
#include "mouse.h"
#include "movie.h" #include "movie.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "text_font.h" #include "text_font.h"

View File

@ -22,6 +22,7 @@
#include "game_sound.h" #include "game_sound.h"
#include "map.h" #include "map.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "palette.h" #include "palette.h"
#include "pipboy.h" #include "pipboy.h"

View File

@ -41,6 +41,7 @@
#include "loadsave.h" #include "loadsave.h"
#include "map.h" #include "map.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "movie.h" #include "movie.h"
#include "movie_effect.h" #include "movie_effect.h"
#include "object.h" #include "object.h"

View File

@ -24,6 +24,7 @@
#include "item.h" #include "item.h"
#include "lips.h" #include "lips.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "party_member.h" #include "party_member.h"
#include "perk.h" #include "perk.h"

View File

@ -17,6 +17,7 @@
#include "game_sound.h" #include "game_sound.h"
#include "interface.h" #include "interface.h"
#include "item.h" #include "item.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "proto.h" #include "proto.h"
#include "proto_instance.h" #include "proto_instance.h"

View File

@ -11,6 +11,7 @@
#include "game_config.h" #include "game_config.h"
#include "game_mouse.h" #include "game_mouse.h"
#include "game_sound.h" #include "game_sound.h"
#include "mouse.h"
#include "movie.h" #include "movie.h"
#include "movie_effect.h" #include "movie_effect.h"
#include "palette.h" #include "palette.h"

View File

@ -22,6 +22,7 @@
#include "geometry.h" #include "geometry.h"
#include "item.h" #include "item.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "proto.h" #include "proto.h"

View File

@ -8,6 +8,7 @@
#include "interpreter_extra.h" #include "interpreter_extra.h"
#include "memory_manager.h" #include "memory_manager.h"
#include "mouse_manager.h" #include "mouse_manager.h"
#include "mouse.h"
#include "nevs.h" #include "nevs.h"
#include "select_file_list.h" #include "select_file_list.h"
#include "sound.h" #include "sound.h"

View File

@ -28,6 +28,7 @@
#include "light.h" #include "light.h"
#include "map.h" #include "map.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "party_member.h" #include "party_member.h"
#include "perk.h" #include "perk.h"

View File

@ -33,6 +33,7 @@
#include "map.h" #include "map.h"
#include "memory.h" #include "memory.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "options.h" #include "options.h"
#include "party_member.h" #include "party_member.h"

View File

@ -23,6 +23,7 @@
#include "game_sound.h" #include "game_sound.h"
#include "loadsave.h" #include "loadsave.h"
#include "map.h" #include "map.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "options.h" #include "options.h"
#include "palette.h" #include "palette.h"

704
src/mouse.cc Normal file
View File

@ -0,0 +1,704 @@
#include "mouse.h"
#include "color.h"
#include "core.h"
#include "dinput.h"
#include "memory.h"
#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

58
src/mouse.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef FALLOUT_MOUSE_H_
#define FALLOUT_MOUSE_H_
#include "geometry.h"
#include "window.h"
namespace fallout {
#define MOUSE_DEFAULT_CURSOR_WIDTH 8
#define MOUSE_DEFAULT_CURSOR_HEIGHT 8
#define MOUSE_DEFAULT_CURSOR_SIZE (MOUSE_DEFAULT_CURSOR_WIDTH * MOUSE_DEFAULT_CURSOR_HEIGHT)
#define MOUSE_STATE_LEFT_BUTTON_DOWN 0x01
#define MOUSE_STATE_RIGHT_BUTTON_DOWN 0x02
#define MOUSE_EVENT_LEFT_BUTTON_DOWN 0x01
#define MOUSE_EVENT_RIGHT_BUTTON_DOWN 0x02
#define MOUSE_EVENT_LEFT_BUTTON_REPEAT 0x04
#define MOUSE_EVENT_RIGHT_BUTTON_REPEAT 0x08
#define MOUSE_EVENT_LEFT_BUTTON_UP 0x10
#define MOUSE_EVENT_RIGHT_BUTTON_UP 0x20
#define MOUSE_EVENT_ANY_BUTTON_DOWN (MOUSE_EVENT_LEFT_BUTTON_DOWN | MOUSE_EVENT_RIGHT_BUTTON_DOWN)
#define MOUSE_EVENT_ANY_BUTTON_REPEAT (MOUSE_EVENT_LEFT_BUTTON_REPEAT | MOUSE_EVENT_RIGHT_BUTTON_REPEAT)
#define MOUSE_EVENT_ANY_BUTTON_UP (MOUSE_EVENT_LEFT_BUTTON_UP | MOUSE_EVENT_RIGHT_BUTTON_UP)
#define MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT (MOUSE_EVENT_LEFT_BUTTON_DOWN | MOUSE_EVENT_LEFT_BUTTON_REPEAT)
#define MOUSE_EVENT_RIGHT_BUTTON_DOWN_REPEAT (MOUSE_EVENT_RIGHT_BUTTON_DOWN | MOUSE_EVENT_RIGHT_BUTTON_REPEAT)
#define MOUSE_EVENT_WHEEL 0x40
#define BUTTON_REPEAT_TIME 250
extern WindowDrawingProc2* _mouse_blit_trans;
extern WINDOWDRAWINGPROC _mouse_blit;
int mouseInit();
void mouseFree();
int mouseSetFrame(unsigned char* a1, int width, int height, int pitch, int a5, int a6, char a7);
void mouseShowCursor();
void mouseHideCursor();
void _mouse_info();
void _mouse_simulate_input(int delta_x, int delta_y, int buttons);
bool _mouse_in(int left, int top, int right, int bottom);
bool _mouse_click_in(int left, int top, int right, int bottom);
void mouseGetRect(Rect* rect);
void mouseGetPosition(int* out_x, int* out_y);
void _mouse_set_position(int a1, int a2);
int mouseGetEvent();
bool cursorIsHidden();
void _mouse_get_raw_state(int* out_x, int* out_y, int* out_buttons);
void mouseSetSensitivity(double value);
void mouseGetPositionInWindow(int win, int* x, int* y);
bool mouseHitTestInWindow(int win, int left, int top, int right, int bottom);
void mouseGetWheel(int* x, int* y);
void convertMouseWheelToArrowKey(int* keyCodePtr);
} // namespace fallout
#endif /* FALLOUT_MOUSE_H_ */

View File

@ -7,6 +7,7 @@
#include "db.h" #include "db.h"
#include "debug.h" #include "debug.h"
#include "memory_manager.h" #include "memory_manager.h"
#include "mouse.h"
#include "platform_compat.h" #include "platform_compat.h"
namespace fallout { namespace fallout {

View File

@ -23,6 +23,7 @@
#include "loadsave.h" #include "loadsave.h"
#include "memory.h" #include "memory.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "scripts.h" #include "scripts.h"
#include "text_font.h" #include "text_font.h"

View File

@ -25,6 +25,7 @@
#include "map.h" #include "map.h"
#include "memory.h" #include "memory.h"
#include "message.h" #include "message.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "party_member.h" #include "party_member.h"
#include "platform_compat.h" #include "platform_compat.h"

View File

@ -6,6 +6,7 @@
#include "db.h" #include "db.h"
#include "game.h" #include "game.h"
#include "game_config.h" #include "game_config.h"
#include "mouse.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "vcr.h" #include "vcr.h"

View File

@ -4,6 +4,7 @@
#include "core.h" #include "core.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
namespace fallout { namespace fallout {

View File

@ -12,6 +12,7 @@
#include "interpreter_lib.h" #include "interpreter_lib.h"
#include "memory_manager.h" #include "memory_manager.h"
#include "mouse_manager.h" #include "mouse_manager.h"
#include "mouse.h"
#include "movie.h" #include "movie.h"
#include "platform_compat.h" #include "platform_compat.h"
#include "text_font.h" #include "text_font.h"

View File

@ -11,6 +11,7 @@
#include "debug.h" #include "debug.h"
#include "draw.h" #include "draw.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "palette.h" #include "palette.h"
#include "pointer_registry.h" #include "pointer_registry.h"
#include "text_font.h" #include "text_font.h"

View File

@ -9,6 +9,7 @@
#include "core.h" #include "core.h"
#include "draw.h" #include "draw.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "text_font.h" #include "text_font.h"
#include "window_manager.h" #include "window_manager.h"

View File

@ -28,6 +28,7 @@
#include "interface.h" #include "interface.h"
#include "item.h" #include "item.h"
#include "memory.h" #include "memory.h"
#include "mouse.h"
#include "object.h" #include "object.h"
#include "party_member.h" #include "party_member.h"
#include "perk.h" #include "perk.h"