diff --git a/CMakeLists_mingw.txt b/CMakeLists_mingw.txt
index 7fb25965c1..f3df7c65fe 100644
--- a/CMakeLists_mingw.txt
+++ b/CMakeLists_mingw.txt
@@ -1,20 +1,11 @@
SET(CMAKE_SYSTEM_NAME Windows)
-if (APPLE)
- SET(COMPILER_PREFIX i586-mingw32)
- SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
- SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-c++)
- SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
- SET(CMAKE_PKGCONFIG_EXECUTABLE i686-w64-mingw32-pkg-config)
- SET(PKG_CONFIG_EXECUTABLE i686-w64-mingw32-pkg-config)
-else()
- SET(COMPILER_PREFIX i686-w64-mingw32)
- SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
- SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-c++)
- SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
- SET(CMAKE_PKGCONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
- SET(PKG_CONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
-endif (APPLE)
+SET(COMPILER_PREFIX i686-w64-mingw32)
+SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
+SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-c++)
+SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
+SET(CMAKE_PKGCONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
+SET(PKG_CONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
# potential flags to make code more similar to MSVC:
# -fshort-wchar -fshort-enums -mms-bitfields
@@ -22,15 +13,19 @@ endif (APPLE)
set(CMAKE_C_FLAGS "-masm=intel -std=gnu99 -fpack-struct=2" CACHE STRING "" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc" CACHE STRING "" FORCE)
-include_directories("/usr/include/wine/windows/")
-
# find and include SDL2
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS})
+if(APPLE)
+ SET(TARGET_ENVIRONMENT /usr/local/mingw-w32-bin_i686-darwin/i686-w64-mingw32)
+else()
+ SET(TARGET_ENVIRONMENT /usr/i686-w64-mingw32)
+endif(APPLE)
+
# here is the target environment located
-#SET(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX})
+SET(CMAKE_FIND_ROOT_PATH ${TARGET_ENVIRONMENT})
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
diff --git a/install.sh b/install.sh
index 3439d41eef..f4d69fb956 100755
--- a/install.sh
+++ b/install.sh
@@ -49,18 +49,29 @@ if [[ `uname` == "Darwin" ]]; then
sudo ln -s $wine_path /usr/include
fi
- mingw_dmg=gcc-4.8.0-qt-4.8.4-for-mingw32.dmg
- mingw_path=/usr/local/gcc-4.8.0-qt-4.8.4-for-mingw32/win32-gcc/bin
- if [[ ! -f $cachedir/$mingw_dmg ]]; then
- wget http://crossgcc.rts-software.org/download/gcc-4.8.0-qt-4.8.4-win32/$mingw_dmg --output-document $cachedir/$mingw_dmg
+ mingw_name=mingw-w32-bin_i686-darwin
+ mingw_tar=$mingw_name"_20130531".tar.bz2
+ mingw_path=/usr/local/$mingw_name
+ if [[ ! -f $cachedir/$mingw_tar ]]; then
+ wget "https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win32/Automated Builds/$mingw_tar" --output-document $cachedir/$mingw_tar
fi
+ if [[ ! -d $ming_path ]]; then
- if [[ ! -d $mingw_path ]]; then
- echo "Open the DMG file and install its contents"
- open $cachedir/$mingw_dmg
+ pushd /usr/local/
+ sudo mkdir $mingw_name
+ popd
+
+ echo "Extracting contents of $mingw_tar to $mingw_path"
+ echo "Don't forget to add $mingw_path to your PATH variable!"
+ sudo tar -xyf $cachedir/$mingw_tar -C $mingw_path
+
+ pushd /usr/local
+ sudo chmod 755 $mingw_name
+ pushd $mingw_name
+ sudo find . -type d -exec chmod 755 {} \;
+ popd
+ popd
fi
-
- echo "You will need to add $mingw_path to your \$PATH"
elif [[ `uname` == "Linux" ]]; then
sudo apt-get install -y --force-yes binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686
fi
diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 76a1fdfc39..e7bad1ab81 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -28,6 +28,7 @@
+
@@ -74,6 +75,7 @@
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index 7f24637b5d..fc44f11882 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -159,6 +159,9 @@
Header Files
+
+ Header Files
+
@@ -377,6 +380,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/addresses.h b/src/addresses.h
index e371cafe26..8453892a07 100644
--- a/src/addresses.h
+++ b/src/addresses.h
@@ -261,6 +261,7 @@
#define RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_DAY 0x013580E7
#define RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_MONTH 0x013580E8
+#define RCT2_ADDRESS_MAP_MAXIMUM_X_Y 0x01358832
#define RCT2_ADDRESS_MAP_SIZE 0x01358834
#define RCT2_ADDRESS_PARK_SIZE 0x013580EA
diff --git a/src/editor.c b/src/editor.c
index ebccbb1e20..db3ead3c26 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -73,7 +73,7 @@ void editor_load()
RCT2_CALLPROC_EBPSAFE(0x0066EF38); // window_main_editor_create
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
- mainWindow->flags &= ~WF_3;
+ mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION;
RCT2_CALLPROC_EBPSAFE(0x006837E3);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
@@ -120,7 +120,7 @@ void trackdesigner_load()
RCT2_CALLPROC_EBPSAFE(0x0066EF38); // window_main_editor_create
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
- mainWindow->flags &= ~WF_3;
+ mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION;
RCT2_CALLPROC_EBPSAFE(0x006837E3);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
@@ -158,7 +158,7 @@ void trackmanager_load()
RCT2_CALLPROC_EBPSAFE(0x0066EF38); // window_main_editor_create
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
- mainWindow->flags &= ~WF_3;
+ mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION;
RCT2_CALLPROC_EBPSAFE(0x006837E3);
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
diff --git a/src/game.c b/src/game.c
index 5176330499..2ea9e63a97 100644
--- a/src/game.c
+++ b/src/game.c
@@ -25,6 +25,7 @@
#include "rct2.h"
#include "game.h"
#include "finance.h"
+#include "input.h"
#include "news_item.h"
#include "object.h"
#include "osinterface.h"
@@ -45,12 +46,7 @@
#include "window_tooltip.h"
-int _gameSpeed = 1;
-
-void game_handle_input();
-void game_handle_keyboard_input();
-
-void process_mouse_over(int x, int y);
+int gGameSpeed = 1;
typedef void(*draw_rain_func)(int left, int top, int width, int height);
@@ -129,161 +125,6 @@ const draw_rain_func draw_rain_function[] = {
&draw_heavy_rain // Heavy rain
};
-
-
-
-/**
-*
-* rct2: 0x006ED801
-*/
-void sub_0x6ED801(int x, int y){
- if (RCT2_GLOBAL(0x9DE518, uint32) & (1 << 3)){
- rct_window* w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16));
- if (w == NULL){
- tool_cancel();
- }
- else{
- RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UPDATE], x, y, 0, RCT2_GLOBAL(0x9DE546, uint16), (int)w, 0, 0);
- }
- }
-}
-
-/**
-*
-* rct2: 0x006ED990
-*/
-void sub_0x6ED990(char cursor_id){
- if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESIZING)
- {
- cursor_id = CURSOR_DIAGONAL_ARROWS; //resize icon
- }
-
- if (cursor_id == RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8))
- {
- return;
- }
- RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8) = cursor_id;
- RCT2_GLOBAL(0x14241BC, uint32) = 2;
- osinterface_set_cursor(cursor_id);
- RCT2_GLOBAL(0x14241BC, uint32) = 0;
-}
-
-/**
-*
-* rct2: 0x006ED833
-*/
-void process_mouse_over(int x, int y)
-{
- rct_window* window;
- rct_window* subWindow;
-
- int widgetId;
- int cursorId;
- int eax, ebx, ecx, edx, esi, edi, ebp;
-
- cursorId = CURSOR_ARROW;
- RCT2_GLOBAL(0x9A9808, sint16) = -1;
- window = window_find_from_point(x, y);
-
- if (window != NULL)
- {
- widgetId = window_find_widget_from_point(window, x, y);
- RCT2_GLOBAL(0x1420046, sint16) = (widgetId & 0xFFFF);
- if (widgetId != -1)
- {
-
- switch (window->widgets[widgetId].type){
- case WWT_VIEWPORT:
- if ((RCT2_GLOBAL(0x9DE518, int) & 0x8) == 0)
- {
- edx = cursorId;
- eax = x;
- ebx = y;
- //Find out if there is a clickable item under pointer
- RCT2_CALLFUNC_X(0X6ED9D0, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
-
- if ((ebx & 0xFF) == 2 || (ebx & 0xFF) == 8 || (ebx & 0xFF) == 3)
- {
- sub_0x6ED990(CURSOR_HAND_POINT);
- return;
- }
- break;
- }
- cursorId = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8);
- subWindow = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
- ebp = (int)subWindow;
- if (subWindow == NULL)
- {
- break;
- }
- ebx = ebx & 0xFFFFFF00;
- edi = cursorId;
- esi = (int) subWindow;
- RCT2_CALLFUNC_X(subWindow->event_handlers[WE_UNKNOWN_0E], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- cursorId = edi;
- if ((ebx & 0xFF) != 0)
- {
- sub_0x6ED990(cursorId);
- return;
- }
- break;
- case WWT_FRAME:
- case WWT_RESIZE:
- if (!(window->flags & 0x100))
- {
- break;
- }
- if (window->min_width == window->max_width && window->min_height == window->max_height)
- {
- break;
- }
- if (x < window->x + window->width - 0x13)
- {
- break;
- }
- if (y < window->y + window->height - 0x13)
- {
- break;
- }
- cursorId = CURSOR_DIAGONAL_ARROWS;
- break;
- case WWT_SCROLL:
- RCT2_GLOBAL(0x9DE558, uint16) = x;
- RCT2_GLOBAL(0x9DE55A, uint16) = y;
- int output_x, output_y, output_scroll_area, scroll_id;
- widget_scroll_get_part(window, window->widgets, x, y, &output_x, &output_y, &output_scroll_area, &scroll_id);
- cursorId = scroll_id;
- if (output_scroll_area != SCROLL_PART_VIEW)
- {
- cursorId = CURSOR_ARROW;
- break;
- }
- //Fall through to default
- default:
- ecx = x;
- edx = y;
- eax = widgetId;
- ebx = 0xFFFFFFFF;
- edi = (int)&window->widgets[widgetId];
-
- RCT2_CALLFUNC_X(window->event_handlers[WE_UNKNOWN_17], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- if (ebx == 0xFFFFFFFF)
- {
- cursorId = CURSOR_ARROW;
- break;
- }
- cursorId = ebx;
- break;
- }
- }
- }
- RCT2_CALLPROC_X(0x6EDE88, x, y, ecx, cursorId, esi, edi, ebp);
- //itemUnderCursor(&eax, &ebx, &ecx, &edx);
-
- sub_0x6ED990(cursorId);
- return;
-}
-
/**
*
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
@@ -458,8 +299,8 @@ void game_update()
if (eax > 4)
eax = 4;
- if (_gameSpeed > 1)
- eax = 1 << (_gameSpeed - 1);
+ if (gGameSpeed > 1)
+ eax = 1 << (gGameSpeed - 1);
if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) {
for (; eax > 0; eax--) {
@@ -563,1612 +404,6 @@ void game_logic_update()
}
}
-static void game_handle_input_mouse();
-static void game_get_next_input(int *x, int *y, int *state);
-
-/**
- *
- * rct2: 0x006EA627
- */
-void game_handle_input()
-{
- rct_window *w;
-
- if (RCT2_GLOBAL(0x009DEA64, uint16) & 2) {
- RCT2_GLOBAL(0x009DEA64, uint16) &= ~2;
- game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 2, 0);
- }
-
- if (RCT2_GLOBAL(0x009ABDF2, uint8) != 0) {
- for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
- RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_07], 0, 0, 0, 0, (int)w, 0, 0);
-
- RCT2_CALLPROC_EBPSAFE(0x006EA73F);
- RCT2_CALLPROC_EBPSAFE(0x006E8346); // update_cursor_position
-
- {
- // int eax, ebx, ecx, edx, esi, edi, ebp;
- int eax, ebx, ecx;
-
- for (;;) {
- game_get_next_input(&eax, &ebx, &ecx);
- if (ecx == 0)
- break;
-
- game_handle_input_mouse(eax, ebx, ecx & 0xFF);
- // RCT2_CALLPROC_X(0x006E8655, eax, ebx, ecx, 0, 0, 0, 0); // window_process_mouse_input
- }
-
- if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
- game_handle_input_mouse(eax, ebx, ecx);
- // RCT2_CALLPROC_X(0x006E8655, eax, ebx, 0, 0, 0, 0, 0); // window_process_mouse_input
- } else if (eax != 0x80000000) {
- eax = clamp(0, eax, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) - 1);
- ebx = clamp(0, ebx, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - 1);
-
- game_handle_input_mouse(eax, ebx, ecx);
- // RCT2_CALLPROC_X(0x006E8655, eax, ebx, 0, 0, 0, 0, 0); // window_process_mouse_input
- process_mouse_over(eax, ebx);
- //RCT2_CALLPROC_X(0x006ED833, eax, ebx, 0, 0, 0, 0, 0);
- sub_0x6ED801(eax, ebx);
- //RCT2_CALLPROC_EBPSAFE(0x006ED801);
- }
- }
- }
-
- for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
- RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_08], 0, 0, 0, 0,(int) w, 0, 0);
-}
-
-/**
- *
- * rct2: 0x006E83C7
- */
-static void game_get_next_input(int *x, int *y, int *state)
-{
- int eax, ebx, ecx, edx, esi, edi, ebp;
- RCT2_CALLFUNC_X(0x00407074, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- if (eax == 0) {
- *x = gCursorState.x;
- *y = gCursorState.y;
- *state = 0;
- return;
- }
-
- *x = RCT2_GLOBAL(eax + 0, sint32);
- *y = RCT2_GLOBAL(eax + 4, sint32);
- *state = RCT2_GLOBAL(eax + 8, sint32);
-
- //int eax, ebx, ecx, edx, esi, edi, ebp;
- //RCT2_CALLFUNC_X(0x006E83C7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- //*x = eax & 0xFFFF;
- //*y = ebx & 0xFFFF;
- //*state = ecx & 0xFF;
- //return;
-
- //int on_tutorial = RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8);
- //if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
- // if (on_tutorial == 1) {
-
- // } else {
- // RCT2_CALLPROC_EBPSAFE(0x00407074);
- // }
- // if (on_tutorial == 2) {
-
- // }
-
- //} else {
-
- //}
-}
-
-#include
-POINT _dragPosition;
-
-static void input_mouseover(int x, int y, rct_window *w, int widgetIndex);
-static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex);
-static void input_mouseover_widget_flatbutton_invalidate();
-static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex);
-
-/**
- * rct2: 0x006E876D
- *
- */
-void invalidate_scroll(){
- int window_no = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16);
- int window_cls = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
-
- rct_window* wind = window_find_by_id(window_cls, window_no);
- if (wind == NULL) return;
-
- int scroll_id = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
- //Reset to basic scroll
- wind->scrolls[scroll_id / sizeof(rct_scroll)].flags &= 0xFF11;
-
- window_invalidate_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16));
-}
-
-/**
- *
- * rct2: 0x006E8655
- */
-static void game_handle_input_mouse(int x, int y, int state)
-{
- rct_window *w;
- rct_widget *widget;
- int widgetIndex;
-
- // Get window and widget under cursor position
- w = window_find_from_point(x, y);
- widgetIndex = w == NULL ? -1 : window_find_widget_from_point(w, x, y);
- widget = widgetIndex == -1 ? 0 : &w->widgets[widgetIndex];
-
- switch (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8)) {
- case INPUT_STATE_RESET:
- window_tooltip_reset(x, y);
- // fall-through
- case INPUT_STATE_NORMAL:
- switch (state) {
- case 0:
- input_mouseover(x, y, w, widgetIndex);
- break;
- case 1:
- input_leftmousedown(x, y, w, widgetIndex);
- break;
- case 3:
- // Close tooltip
- window_close_by_id(5, 0);
-
- if (w != NULL)
- w = window_bring_to_front(w);
-
- if (widgetIndex == -1)
- break;
-
- if (widget->type == WWT_VIEWPORT) {
- if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9)
- break;
- w->flags &= ~(1 << 3);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_DRAG;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = w->classification;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = w->number;
- RCT2_GLOBAL(0x009DE540, sint16) = 0;
- // hide cursor
- // RCT2_CALLPROC_X(0x00407045, 0, 0, 0, 0, 0, 0, 0);
- // RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 5);
-
- GetCursorPos(&_dragPosition);
- ShowCursor(FALSE);
-
- } else if (widget->type == WWT_SCROLL) {
-
- }
-
- break;
- }
-
- break;
- case INPUT_STATE_WIDGET_PRESSED:
- RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
- break;
- case INPUT_STATE_DRAGGING:
- // RCT2_CALLPROC_X(0x006E8C5C, x, y, state, widgetIndex, w, widget, 0);
-
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
- if (w == NULL) {
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
- break;
- }
-
- if (state == 0) {
- y = clamp(29, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34);
- window_move_position(
- w,
- x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
- y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
- );
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
- } else if (state == 2) {
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint16);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- y = clamp(29, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34);
- window_move_position(
- w,
- x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
- y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
- );
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
-
- RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_18], 0, 0, x, y, (int)w, 0, 0);
- }
- break;
- case INPUT_STATE_VIEWPORT_DRAG:
- {
- int dx, dy;
-
- dx = x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16);
- dy = y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16);
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
- if (state == 0) {
- rct_viewport *viewport = w->viewport;
- RCT2_GLOBAL(0x009DE540, sint16) += RCT2_GLOBAL(0x009DE588, sint16);
- if (viewport == NULL) {
- ShowCursor(TRUE);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
- } else if (dx != 0 || dy != 0) {
- if (!(w->flags & (1 << 2))) {
- RCT2_GLOBAL(0x009DE540, sint16) = 1000;
- dx <<= viewport->zoom + 1;
- dy <<= viewport->zoom + 1;
- w->saved_view_x += dx;
- w->saved_view_y += dy;
- }
- }
- } else if (state == 4) {
- ShowCursor(TRUE);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
- if (RCT2_GLOBAL(0x009DE540, sint16) < 500) {
- // Right click
- {
- int eax, ebx, ecx, edx, esi, edi, ebp;
- eax = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16);
- ebx = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16);
- RCT2_CALLFUNC_X(0x006EDE88, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- switch (ebx & 0xFF) {
- case 2:
- if (*((uint8*)edx) == 0)
- RCT2_CALLPROC_X(0x006B4857, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 3:
- RCT2_CALLPROC_X(0x006CC056, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 5:
- RCT2_CALLPROC_X(0x006E08D2, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 6:
- RCT2_CALLPROC_X(0x006A614A, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 7:
- RCT2_CALLPROC_X(0x006A61AB, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 8:
- RCT2_CALLPROC_X(0x00666C0E, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 9:
- RCT2_CALLPROC_X(0x006E57A9, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 10:
- RCT2_CALLPROC_X(0x006B88DC, eax, 0, ecx, edx, 0, 0, 0);
- break;
- case 12:
- RCT2_CALLPROC_X(0x006BA233, eax, 0, ecx, edx, 0, 0, 0);
- break;
- default:
- break;
- }
- }
- }
- }
-
- //
- //
- SetCursorPos(_dragPosition.x, _dragPosition.y);
- // RCT2_CALLPROC_X(0x006E89C6, x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16), y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16), state, widgetIndex, w, widget, 0);
- break;
- }
- case INPUT_STATE_DROPDOWN_ACTIVE:
- RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
- break;
- case INPUT_STATE_VIEWPORT_LEFT:
- //RCT2_CALLPROC_X(0x006E87B4, x, y, state, widgetIndex, (int)w, (int)widget, 0);
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
- if (!w){
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
- break;
- }
-
- if (state == 0){
- if (!w->viewport){
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
- break;
- }
-
- if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) ||
- w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) ||
- !(RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3)))break;
-
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
-
- if (!w)break;
-
- RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
- }
- else if (state == 2){
-
- RCT2_GLOBAL(0x9DE51D, uint8) = 0;
- if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break;
- if ((RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3))){
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
- if (!w)break;
- RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UP], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
- }
- else{
- if ((RCT2_GLOBAL(0x9DE518, uint32)&(1 << 4)))break;
- rct_sprite* spr;
- int eax = x, ebx = y, ecx = state, esi = (int)w, edi = (int)widget, ebp = 0;
- RCT2_CALLFUNC_X(0X6ED9D0, &eax, &ebx, &ecx, (int*)&spr, &esi, &edi, &ebp);
- if ((ebx & 0xFF) == 2){
-
- if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE){
- //Open ride window
- RCT2_CALLPROC_X(0x6ACAC2, eax, ebx, ecx, (int)spr, esi, edi, ebp);
- }
- else if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_PEEP){
- window_peep_open(&spr->peep);
- }
- else if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_FLOATING_TEXT){
- //Unknown for now
- RCT2_CALLPROC_X(0x6E88D7, eax, ebx, ecx, (int)spr, esi, edi, ebp);
- }
- }
- else if ((ebx & 0xFF) == 3){
- rct_map_element* map_element = (rct_map_element*)spr;
-
- if (!((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE)){
- eax = RCT2_ADDRESS(0x0099BA64, uint8)[16 * map_element->properties.track.type];
- if (!(eax & 0x10)){//If not station track
- //Open ride window in overview mode.
- RCT2_CALLPROC_X(0x6ACC28, map_element->properties.track.ride_index, ebx, ecx, (int)map_element, esi, edi, ebp);
- break;
- }
- }
- //Open ride window in station view
- RCT2_CALLPROC_X(0x6ACCCE, map_element->properties.track.ride_index, (map_element->properties.track.sequence & 0x70) >> 4, ecx, (int)map_element, esi, edi, ebp);
- }
- else if ((ebx & 0xFF) == 8){
- window_park_entrance_open();
- }
- }
- }
- break;
- case INPUT_STATE_SCROLL_LEFT://0x006E8676
- //RCT2_CALLPROC_X(0x006E8676, x, y, state, widgetIndex, (int)w, (int)widget, 0);
- if (state == 0){
- if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){
- invalidate_scroll();
- return;
- }
- if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){
- invalidate_scroll();
- return;
- }
- if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){
- invalidate_scroll();
- return;
- }
-
- if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
- int temp_x = x;
- x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
- RCT2_CALLPROC_X(0x006E98F2, x, temp_x, state, w->number, (int)w, (int)widget, x);
- return;
- }
-
- if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){
- int temp_y = y;
- y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y;
- RCT2_CALLPROC_X(0x006E99A9, temp_y, y, state, w->number, (int)w, (int)widget, y);
- return;
- }
- int scroll_part, scroll_id;
- widget_scroll_get_part(w, widget, x, y, &x, &y, &scroll_part, &scroll_id);
-
- if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){
- invalidate_scroll();
- return;
- }
-
- switch (scroll_part){
- case SCROLL_PART_VIEW:
- RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], w->number / 18, y, x, y, (int)w, (int)widget, (int)w->event_handlers);
- break;
- case SCROLL_PART_HSCROLLBAR_LEFT:
- RCT2_CALLPROC_X(0x006E9A60, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_HSCROLLBAR_RIGHT:
- RCT2_CALLPROC_X(0x006E9ABF, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
- case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
- return;
- break;
- case SCROLL_PART_HSCROLLBAR_THUMB:
- case SCROLL_PART_VSCROLLBAR_TOP:
- RCT2_CALLPROC_X(0x006E9C37, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_VSCROLLBAR_BOTTOM:
- RCT2_CALLPROC_X(0x006E9C96, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
- case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
- return;
- break;
- default:
- return;
- }
- }else if (state==2){
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
- invalidate_scroll();
- return;
- }
- break;
- case INPUT_STATE_RESIZING:
- // RCT2_CALLPROC_X(0x006E8B46, x, y, state, widgetIndex, w, widget, 0);
-
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
- if (w == NULL) {
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
- break;
- }
-
- if (state != 0 && state != 2)
- break;
- if (state == 2) {
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint16);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- }
-
- if (y < RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 2) {
- window_resize(
- w,
- x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
- y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
- );
- }
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
- break;
- case 9:
- RCT2_CALLPROC_X(0x006E8ACB, x, y, state, widgetIndex, (int)w, (int)widget, 0);
- break;
- }
-}
-
-/**
- *
- * rct2: 0x006E9253
- */
-static void input_mouseover(int x, int y, rct_window *w, int widgetIndex)
-{
- // RCT2_CALLPROC_X(0x006E9253, x, y, state, widgetIndex, w, widget, 0);
-
- rct_windowclass windowClass = 255;
- rct_windownumber windowNumber = 0;
- rct_widget *widget;
-
- if (w != NULL) {
- windowClass = w->classification;
- windowNumber = w->number;
- widget = &w->widgets[widgetIndex];
- }
-
- input_mouseover_widget_check(windowClass, windowNumber, widgetIndex);
-
- if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL)
- {
- int eax, ebx, ecx, edx;
- widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
-
- if (ecx < 0)
- goto showTooltip;
- if (ecx == 0) {
- RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEOVER], edx, 0, eax, ebx, (int)w, 0, 0);
- goto showTooltip;
- } else {
-
- }
- } else {
- showTooltip:
- if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) == 255) {
- if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) < 500 ||
- (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) == x &&
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) == y)
- ) {
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = RCT2_GLOBAL(0x009DE588, uint16);
-
- int bp = 2000;
- if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) <= 1000)
- bp = 0;
- if (bp > RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16))
- return;
-
- window_tooltip_open(w, widgetIndex, x, y);
- // RCT2_CALLPROC_X(0x006EA10D, x, y, 0, widgetIndex, w, widget, 0); // window_tooltip_open();
- }
- } else {
- if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification ||
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number ||
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) != widgetIndex
- ) {
- window_tooltip_close();
- }
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) += RCT2_GLOBAL(0x009DE588, uint16);
- if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) < 8000)
- return;
- window_close_by_id(WC_TOOLTIP, 0);
- }
- }
-
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) = y;
-}
-
-/**
- *
- * rct2: 0x006E9269
- */
-static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex)
-{
- if (widgetIndex == -1) return; //Prevents invalid widgets being clicked source of bug is elsewhere
- // Check if widget cursor was over has changed
- if (windowClass != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) ||
- windowNumber != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) ||
- widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)
- ) {
- // Invalidate last widget cursor was on if widget is a flat button
- input_mouseover_widget_flatbutton_invalidate();
-
- // Set new cursor over widget
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) = windowClass;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) = windowNumber;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint16) = widgetIndex;
-
- // Invalidate new widget cursor is on if widget is a flat button
- if (windowClass != 255)
- input_mouseover_widget_flatbutton_invalidate();
- }
-}
-
-static void input_mouseover_widget_flatbutton_invalidate()
-{
- rct_window *w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber));
- if (w == NULL)
- return;
-
- RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
- if (w->widgets[RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)].type == WWT_FLATBTN)
- widget_invalidate(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber));
-}
-
-static void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct_widget* widget )
-{
-#ifdef _MSC_VER
- __asm {
- push address
- push widget
- push w
- push widgetIndex
- mov edi, widget
- mov edx, widgetIndex
- mov esi, w
- call[esp + 12]
- add esp, 16
- }
-#else
- __asm__("\
- push %[address]\n\
- mov edi, %[widget] \n\
- mov eax, %[w] \n\
- mov edx, %[widgetIndex] \n\
- push edi \n\
- push eax \n\
- push edx \n\
- mov esi, %[w] \n\
- call [esp+12] \n\
- add esp, 16 \n\
- " :[address] "+m" (address), [w] "+m" (w), [widget] "+m" (widget), [widgetIndex] "+m" (widgetIndex): : "eax", "esi", "edx", "edi"
- );
-#endif
-}
-
-/**
- * Horizontal scrollbar's "left" button held down, scroll it to the left
- * rct2: 0x006E9A60
- */
-static void input_hscrollbar_leftbutton(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 left;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- left = scroll->h_left;
- left -= 3;
- if (left < 0)
- left = 0;
- scroll->h_left = left;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-
-/**
- * Horizontal scrollbar's "right" button held down, scroll it to the right
- * rct2: 0x006E9ABF
- */
-static void input_hscrollbar_rightbutton(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 left, widgetWidth;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- left = scroll->h_left;
- left += 3;
-
- widgetWidth = widget->right - widget->left - 1;
- if (scroll->flags & VSCROLLBAR_VISIBLE)
- widgetWidth -= 11;
- widgetWidth *= -1;
- widgetWidth += scroll->h_right;
- if (widgetWidth < 0)
- widgetWidth = 0;
- if (left > widgetWidth)
- left = widgetWidth;
-
- scroll->h_left = left;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
- * Horizontal scrollbar's left trough was clicked
- * rct2: 0x006E9B47
- */
-static void input_hscrollbar_left_trough(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 left, widgetWidth;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- left = scroll->h_left;
-
- widgetWidth = widget->right - widget->left - 1;
- if (scroll->flags & VSCROLLBAR_VISIBLE)
- widgetWidth -= 11;
- left -= widgetWidth;
- if (left < 0)
- left = 0;
- scroll->h_left = left;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
- * Horizontal scrollbar's right trough was clicked
- * rct2: 0x006E9BB7
- */
-static void input_hscrollbar_right_trough(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 left, widgetWidth;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- left = scroll->h_left;
-
- widgetWidth = widget->right - widget->left - 1;
- if (scroll->flags & VSCROLLBAR_VISIBLE)
- widgetWidth -= 11;
- left += widgetWidth;
- widgetWidth *= -1;
- widgetWidth += scroll->h_right;
- if (widgetWidth < 0)
- widgetWidth = 0;
- if (left > widgetWidth)
- left = widgetWidth;
-
- scroll->h_left = left;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
- * Vertical scrollbar's "top" button held down, scroll it upwards
- * rct2: 0x006E9C37
- */
-static void input_vscrollbar_topbutton(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 top;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- top = scroll->v_top;
- top -= 3;
- if (top < 0)
- top = 0;
- scroll->v_top = top;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
-* Vertical scrollbar's "bottom" button held down, scroll it downwards
-* rct2: 0x006E9C96
-*/
-static void input_vscrollbar_bottombutton(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 top, widgetHeight;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- top = scroll->v_top;
- top += 3;
-
- widgetHeight = widget->bottom - widget->top - 1;
- if (scroll->flags & HSCROLLBAR_VISIBLE)
- widgetHeight -= 11;
- widgetHeight *= -1;
- widgetHeight += scroll->v_bottom;
- if (widgetHeight < 0)
- widgetHeight = 0;
- if (top > widgetHeight)
- top = widgetHeight;
-
- scroll->v_top = top;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
-* Vertical scrollbar's top trough was clicked
-* rct2: 0x006E9D1E
-*/
-static void input_vscrollbar_top_trough(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 top, widgetHeight;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- top = scroll->v_top;
-
- widgetHeight = widget->bottom - widget->top - 1;
- if (scroll->flags & HSCROLLBAR_VISIBLE)
- widgetHeight -= 11;
- top -= widgetHeight;
- if (top < 0)
- top = 0;
- scroll->v_top = top;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
-* Vertical scrollbar's bottom trough was clicked
-* rct2: 0x006E9D8E
-*/
-static void input_vscrollbar_bottom_trough(rct_window* w)
-{
- rct_windowclass windowClass;
- rct_windownumber windowNumber;
- rct_window* w2;
- rct_widget* widget;
- rct_scroll* scroll;
- uint16 widgetIndex;
- sint16 top, widgetHeight;
-
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
- windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
- w2 = window_find_by_id(windowClass, windowNumber);
-
- if (w2 == NULL)
- return;
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
-
- widget = &w->widgets[widgetIndex];
- scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
-
- top = scroll->v_top;
-
- widgetHeight = widget->bottom - widget->top - 1;
- if (scroll->flags & HSCROLLBAR_VISIBLE)
- widgetHeight -= 11;
- top += widgetHeight;
- widgetHeight *= -1;
- widgetHeight += scroll->v_bottom;
- if (widgetHeight < 0)
- widgetHeight = 0;
- if (top > widgetHeight)
- top = widgetHeight;
-
- scroll->v_top = top;
-
- widget_scroll_update_thumbs(w, widgetIndex);
-
- widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
- windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
- windowClass |= 0x80;
-
- window_invalidate_by_id(widgetIndex, windowClass);
-}
-
-/**
- *
- * rct2: 0x006E95F9
- */
-static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
-{
- // RCT2_CALLPROC_X(0x006E95F9, x, y, state, widgetIndex, w, widget, 0);
-
- rct_windowclass windowClass = 255;
- rct_windownumber windowNumber = 0;
- rct_widget *widget;
-
- if (w != NULL) {
- windowClass = w->classification;
- windowNumber = w->number;
- }
-
- window_close_by_id(WC_ERROR, 0);
- window_close_by_id(WC_TOOLTIP, 0);
-
- w = window_find_by_id(windowClass, windowNumber);
- if (w == NULL)
- return;
-
- w = window_bring_to_front(w);
- if (widgetIndex == -1)
- return;
-
- widget = &w->widgets[widgetIndex];
-
- switch (widget->type) {
- case WWT_FRAME:
- case WWT_RESIZE:
- if (!(w->flags & WF_RESIZABLE))
- break;
- if (w->min_width == w->max_width && w->min_height == w->max_height)
- break;
- if (x < w->x + w->width - 19 || y < w->y + w->height - 19)
- break;
-
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESIZING;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
- break;
- case WWT_VIEWPORT:
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_LEFT;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
- if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)))
- break;
-
- w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
- if (w == NULL)
- break;
-
- RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DOWN], x, y, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 4);
- break;
- case WWT_CAPTION:
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_DRAGGING;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
- break;
- case WWT_SCROLL:
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_LEFT;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x;
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y;
-
- int eax, ebx, ecx, edx;
- edx = 0; // safety
- widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
-
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) = ecx;
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32) = edx * 12;//We do this because scroll id is not all decompiled
- RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_15], RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32), ebx, ecx, edx, (int)w, (int)widget, 0);
- switch (ecx) {
- case SCROLL_PART_VIEW:
- RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEDOWN], edx / sizeof(rct_scroll), ebx, eax, ebx, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_HSCROLLBAR_LEFT: input_hscrollbar_leftbutton(w); break;
- case SCROLL_PART_HSCROLLBAR_RIGHT: input_hscrollbar_rightbutton(w); break;
- case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH: input_hscrollbar_left_trough(w); break;
- case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH: input_hscrollbar_right_trough(w); break;
- case SCROLL_PART_VSCROLLBAR_TOP: input_vscrollbar_topbutton(w); break;
- case SCROLL_PART_VSCROLLBAR_BOTTOM: input_vscrollbar_bottombutton(w); break;
- case SCROLL_PART_VSCROLLBAR_TOP_TROUGH: input_vscrollbar_top_trough(w); break;
- case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH: input_vscrollbar_bottom_trough(w); break;
- }
- break;
- default:
- // comment check as it disables the rotate station/building button in construction window
-// if (!widget_is_enabled(w, widgetIndex))
-// break;
- if (widget_is_disabled(w, widgetIndex))
- break;
-
- sound_play_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2);
-
- // Set new cursor down widget
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
- RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 0);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_WIDGET_PRESSED;
- RCT2_GLOBAL(0x009DE528, uint16) = 1;
-
- widget_invalidate(windowClass, windowNumber, widgetIndex);
- RCT2_CALLPROC_WE_MOUSE_DOWN(w->event_handlers[WE_MOUSE_DOWN], widgetIndex, w, widget);
- break;
- }
-}
-
-void game_handle_edge_scroll()
-{
- rct_window *mainWindow;
- int scrollX, scrollY;
-
- mainWindow = window_get_main();
- if (mainWindow == NULL)
- return;
- if ((mainWindow->flags & WF_2) || (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9))
- return;
- if (mainWindow->viewport == NULL)
- return;
-
- scrollX = 0;
- scrollY = 0;
-
- // Scroll left / right
- if (gCursorState.x == 0)
- scrollX = -1;
- else if (gCursorState.x == RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 1)
- scrollX = 1;
-
- // Scroll up / down
- if (gCursorState.y == 0)
- scrollY = -1;
- else if (gCursorState.y == RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 1)
- scrollY = 1;
-
- // Scroll viewport
- if (scrollX != 0) {
- mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
- }
- if (scrollY != 0) {
- mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
- }
-}
-
-#include
-
-void game_handle_key_scroll()
-{
- rct_window *mainWindow;
- int scrollX, scrollY;
-
- mainWindow = window_get_main();
- if (mainWindow == NULL)
- return;
- if ((mainWindow->flags & WF_2) || (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9))
- return;
- if (mainWindow->viewport == NULL)
- return;
-
- scrollX = 0;
- scrollY = 0;
-
- // Scroll left / right
- if (gKeysState[SDL_SCANCODE_LEFT])
- scrollX = -1;
- else if (gKeysState[SDL_SCANCODE_RIGHT])
- scrollX = 1;
-
- // Scroll up / down
- if (gKeysState[SDL_SCANCODE_UP])
- scrollY = -1;
- else if (gKeysState[SDL_SCANCODE_DOWN])
- scrollY = 1;
-
- // Scroll viewport
- if (scrollX != 0) {
- mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
- }
- if (scrollY != 0) {
- mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
- }
-}
-
-/**
- *
- * rct2: 0x00406CD2
- */
-int get_next_key()
-{
- int i;
- for (i = 0; i < 221; i++) {
- if (gKeysPressed[i]) {
- gKeysPressed[i] = 0;
- return i;
- }
- }
-
- return 0;
-}
-
-void handle_shortcut_command(int shortcutIndex)
-{
- rct_window *window;
-
- switch (shortcutIndex) {
- case SHORTCUT_CLOSE_TOP_MOST_WINDOW:
- window_close_top();
- break;
- case SHORTCUT_CLOSE_ALL_FLOATING_WINDOWS:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2))
- window_close_all();
- else if (RCT2_GLOBAL(0x0141F570, uint8) == 1)
- window_close_top();
- break;
- case SHORTCUT_CANCEL_CONSTRUCTION_MODE:
- window = window_find_by_id(WC_ERROR, 0);
- if (window != NULL)
- window_close(window);
- else if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3))
- tool_cancel();
- break;
- case SHORTCUT_PAUSE_GAME:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 10)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 0, WE_MOUSE_UP);
- }
- }
- break;
- case SHORTCUT_ZOOM_VIEW_OUT:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 2, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_ZOOM_VIEW_IN:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 3, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_ROTATE_VIEW:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 4, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_ROTATE_CONSTRUCTION_OBJECT:
- RCT2_CALLPROC_EBPSAFE(0x006E4182);
- break;
- case SHORTCUT_UNDERGROUND_VIEW_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_REMOVE_BASE_LAND_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_HIDE_BASE;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_REMOVE_VERTICAL_LAND_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_HIDE_VERTICAL;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_SEE_THROUGH_RIDES_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_RIDES;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_SEE_THROUGH_SCENERY_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_SCENERY;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_INVISIBLE_SUPPORTS_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_SUPPORTS;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_INVISIBLE_PEOPLE_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_PEEPS;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_HEIGHT_MARKS_ON_LAND_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_LAND_HEIGHTS;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_HEIGHT_MARKS_ON_RIDE_TRACKS_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_TRACK_HEIGHTS;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_HEIGHT_MARKS_ON_PATHS_TOGGLE:
- window = window_get_main();
- if (window != NULL) {
- window->viewport->flags ^= VIEWPORT_FLAG_PATH_HEIGHTS;
- window_invalidate(window);
- }
- break;
- case SHORTCUT_ADJUST_LAND:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 7, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_ADJUST_WATER:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 8, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_BUILD_SCENERY:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 9, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_BUILD_PATHS:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 10, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_BUILD_NEW_RIDE:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 11, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_SHOW_FINANCIAL_INFORMATION:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C))
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800))
- window_finances_open();
- break;
- case SHORTCUT_SHOW_RESEARCH_INFORMATION:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
- // Open new ride window
- RCT2_CALLPROC_EBPSAFE(0x006B3CFF);
- window = window_find_by_id(WC_CONSTRUCT_RIDE, 0);
- if (window != NULL)
- RCT2_CALLPROC_WE_MOUSE_DOWN(window->event_handlers[WE_MOUSE_DOWN], 10, window, NULL);
- }
- break;
- case SHORTCUT_SHOW_RIDES_LIST:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 12, WE_MOUSE_UP);
- }
- }
- break;
- case SHORTCUT_SHOW_PARK_INFORMATION:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 13, WE_MOUSE_UP);
- }
- }
- break;
- case SHORTCUT_SHOW_GUEST_LIST:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 15, WE_MOUSE_UP);
- }
- }
- break;
- case SHORTCUT_SHOW_STAFF_LIST:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 14, WE_MOUSE_UP);
- }
- }
- break;
- case SHORTCUT_SHOW_RECENT_MESSAGES:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E))
- window_news_open();
- break;
- case SHORTCUT_SHOW_MAP:
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
- window = window_find_by_id(WC_TOP_TOOLBAR, 0);
- if (window != NULL) {
- window_invalidate(window);
- window_event_helper(window, 6, WE_MOUSE_UP);
- }
- }
- }
- break;
- case SHORTCUT_SCREENSHOT:
- RCT2_CALLPROC_EBPSAFE(0x006E4034); // set screenshot countdown to 2
- break;
-
- // New
- case SHORTCUT_REDUCE_GAME_SPEED:
- game_reduce_game_speed();
- break;
- case SHORTCUT_INCREASE_GAME_SPEED:
- game_increase_game_speed();
- break;
- }
-}
-
-void game_increase_game_speed()
-{
- _gameSpeed = min(8, _gameSpeed + 1);
-}
-
-void game_reduce_game_speed()
-{
- _gameSpeed = max(1, _gameSpeed - 1);
-}
-
-/**
- *
- * rct2: 0x006E3E68
- */
-void handle_shortcut(int key)
-{
- int i;
- for (i = 0; i < SHORTCUT_COUNT; i++) {
- if (key == gShortcutKeys[i]) {
- handle_shortcut_command(i);
- break;
- }
- }
-}
-
-/**
- *
- * rct2: 0x006E3E91
- */
-void set_shortcut(int key)
-{
- int i;
-
- // Unmap shortcut that already uses this key
- for (i = 0; i < 32; i++) {
- if (key == gShortcutKeys[i]) {
- gShortcutKeys[i] = 0xFFFF;
- break;
- }
- }
-
- // Map shortcut to this key
- gShortcutKeys[RCT2_GLOBAL(0x009DE511, uint8)] = key;
- window_close_by_id(WC_CHANGE_KEYBOARD_SHORTCUT, 0);
- window_invalidate_by_id(WC_KEYBOARD_SHORTCUT_LIST, 0);
- config_save();
-}
-
-/**
- *
- * rct2: 0x006E3B43
- */
-void game_handle_keyboard_input()
-{
- rct_window *w;
- int key;
-
- // Handle mouse scrolling
- if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
- if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0)
- if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 1)
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3))
- game_handle_edge_scroll();
-
- // Handle modifier keys and key scrolling
- RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0;
- if (RCT2_GLOBAL(0x009E2B64, uint32) != 1) {
- if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT])
- RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 1;
- if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL])
- RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 2;
- if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
- game_handle_key_scroll();
- }
-
-
- // Handle key input
- while ((key = get_next_key()) != 0) {
- if (key == 255)
- continue;
-
- key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8;
-
- w = window_find_by_id(WC_CHANGE_KEYBOARD_SHORTCUT, 0);
- if (w != NULL)
- set_shortcut(key);
- else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1)
- tutorial_stop();
- else
- handle_shortcut(key);
- }
-
- if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
- return;
-
- // Tutorial and the modifier key
- if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) {
- int eax, ebx, ecx, edx, esi, edi, ebp;
- RCT2_CALLFUNC_X(0x0066EEB4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- eax &= 0xFF;
- RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = eax;
- if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4) {
- window_tooltip_close();
- if ((w = window_get_main()) != NULL) {
- RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
- RCT2_GLOBAL(0x009DEA72, uint16)++;
- }
- }
- } else {
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) {
- window_tooltip_close();
- if ((w = window_get_main()) != NULL) {
- RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
- RCT2_GLOBAL(0x009DEA72, uint16)++;
- }
- }
-
- // Write tutorial input
- RCT2_CALLPROC_X(0x0066EEE1, RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8), 0, 0, 0, 0, 0, 0);
- }
-}
-
/**
*
* rct2: 0x0069C62C
diff --git a/src/game.h b/src/game.h
index 5c0771ca58..0e1a95035b 100644
--- a/src/game.h
+++ b/src/game.h
@@ -84,6 +84,8 @@ enum GAME_COMMAND {
typedef void (GAME_COMMAND_POINTER)(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
+extern int gGameSpeed;
+
void game_create_windows();
void game_update();
void game_logic_update();
diff --git a/src/input.c b/src/input.c
new file mode 100644
index 0000000000..1d10cc4e05
--- /dev/null
+++ b/src/input.c
@@ -0,0 +1,1765 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#include
+#include
+#include "addresses.h"
+#include "audio.h"
+#include "config.h"
+#include "game.h"
+#include "input.h"
+#include "map.h"
+#include "osinterface.h"
+#include "sprite.h"
+#include "tutorial.h"
+#include "viewport.h"
+#include "widget.h"
+#include "window.h"
+#include "window_tooltip.h"
+
+POINT _dragPosition;
+
+static void game_get_next_input(int *x, int *y, int *state);
+static void input_mouseover(int x, int y, rct_window *w, int widgetIndex);
+static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex);
+static void input_mouseover_widget_flatbutton_invalidate();
+void process_mouse_over(int x, int y);
+void sub_6ED801(int x, int y);
+void invalidate_scroll();
+
+#pragma region Scroll bar input
+
+/**
+ * Horizontal scrollbar's "left" button held down, scroll it to the left
+ * rct2: 0x006E9A60
+ */
+static void input_hscrollbar_leftbutton(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 left;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ left = scroll->h_left;
+ left -= 3;
+ if (left < 0)
+ left = 0;
+ scroll->h_left = left;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+
+/**
+ * Horizontal scrollbar's "right" button held down, scroll it to the right
+ * rct2: 0x006E9ABF
+ */
+static void input_hscrollbar_rightbutton(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 left, widgetWidth;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ left = scroll->h_left;
+ left += 3;
+
+ widgetWidth = widget->right - widget->left - 1;
+ if (scroll->flags & VSCROLLBAR_VISIBLE)
+ widgetWidth -= 11;
+ widgetWidth *= -1;
+ widgetWidth += scroll->h_right;
+ if (widgetWidth < 0)
+ widgetWidth = 0;
+ if (left > widgetWidth)
+ left = widgetWidth;
+
+ scroll->h_left = left;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+/**
+ * Horizontal scrollbar's left trough was clicked
+ * rct2: 0x006E9B47
+ */
+static void input_hscrollbar_left_trough(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 left, widgetWidth;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ left = scroll->h_left;
+
+ widgetWidth = widget->right - widget->left - 1;
+ if (scroll->flags & VSCROLLBAR_VISIBLE)
+ widgetWidth -= 11;
+ left -= widgetWidth;
+ if (left < 0)
+ left = 0;
+ scroll->h_left = left;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+/**
+ * Horizontal scrollbar's right trough was clicked
+ * rct2: 0x006E9BB7
+ */
+static void input_hscrollbar_right_trough(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 left, widgetWidth;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ left = scroll->h_left;
+
+ widgetWidth = widget->right - widget->left - 1;
+ if (scroll->flags & VSCROLLBAR_VISIBLE)
+ widgetWidth -= 11;
+ left += widgetWidth;
+ widgetWidth *= -1;
+ widgetWidth += scroll->h_right;
+ if (widgetWidth < 0)
+ widgetWidth = 0;
+ if (left > widgetWidth)
+ left = widgetWidth;
+
+ scroll->h_left = left;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+/**
+ * Vertical scrollbar's "top" button held down, scroll it upwards
+ * rct2: 0x006E9C37
+ */
+static void input_vscrollbar_topbutton(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 top;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ top = scroll->v_top;
+ top -= 3;
+ if (top < 0)
+ top = 0;
+ scroll->v_top = top;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+/**
+* Vertical scrollbar's "bottom" button held down, scroll it downwards
+* rct2: 0x006E9C96
+*/
+static void input_vscrollbar_bottombutton(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 top, widgetHeight;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ top = scroll->v_top;
+ top += 3;
+
+ widgetHeight = widget->bottom - widget->top - 1;
+ if (scroll->flags & HSCROLLBAR_VISIBLE)
+ widgetHeight -= 11;
+ widgetHeight *= -1;
+ widgetHeight += scroll->v_bottom;
+ if (widgetHeight < 0)
+ widgetHeight = 0;
+ if (top > widgetHeight)
+ top = widgetHeight;
+
+ scroll->v_top = top;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+/**
+* Vertical scrollbar's top trough was clicked
+* rct2: 0x006E9D1E
+*/
+static void input_vscrollbar_top_trough(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 top, widgetHeight;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ top = scroll->v_top;
+
+ widgetHeight = widget->bottom - widget->top - 1;
+ if (scroll->flags & HSCROLLBAR_VISIBLE)
+ widgetHeight -= 11;
+ top -= widgetHeight;
+ if (top < 0)
+ top = 0;
+ scroll->v_top = top;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+/**
+* Vertical scrollbar's bottom trough was clicked
+* rct2: 0x006E9D8E
+*/
+static void input_vscrollbar_bottom_trough(rct_window* w)
+{
+ rct_windowclass windowClass;
+ rct_windownumber windowNumber;
+ rct_window* w2;
+ rct_widget* widget;
+ rct_scroll* scroll;
+ uint16 widgetIndex;
+ sint16 top, widgetHeight;
+
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ windowNumber = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ w2 = window_find_by_id(windowClass, windowNumber);
+
+ if (w2 == NULL)
+ return;
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16);
+
+ widget = &w->widgets[widgetIndex];
+ scroll = w->scrolls + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+
+ top = scroll->v_top;
+
+ widgetHeight = widget->bottom - widget->top - 1;
+ if (scroll->flags & HSCROLLBAR_VISIBLE)
+ widgetHeight -= 11;
+ top += widgetHeight;
+ widgetHeight *= -1;
+ widgetHeight += scroll->v_bottom;
+ if (widgetHeight < 0)
+ widgetHeight = 0;
+ if (top > widgetHeight)
+ top = widgetHeight;
+
+ scroll->v_top = top;
+
+ widget_scroll_update_thumbs(w, widgetIndex);
+
+ widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint8);
+ windowClass = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+ windowClass |= 0x80;
+
+ window_invalidate_by_id(widgetIndex, windowClass);
+}
+
+#pragma endregion
+
+/**
+ *
+ * rct2: 0x006E95F9
+ */
+static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
+{
+ // RCT2_CALLPROC_X(0x006E95F9, x, y, state, widgetIndex, w, widget, 0);
+
+ rct_windowclass windowClass = 255;
+ rct_windownumber windowNumber = 0;
+ rct_widget *widget;
+
+ if (w != NULL) {
+ windowClass = w->classification;
+ windowNumber = w->number;
+ }
+
+ window_close_by_id(WC_ERROR, 0);
+ window_close_by_id(WC_TOOLTIP, 0);
+
+ w = window_find_by_id(windowClass, windowNumber);
+ if (w == NULL)
+ return;
+
+ w = window_bring_to_front(w);
+ if (widgetIndex == -1)
+ return;
+
+ widget = &w->widgets[widgetIndex];
+
+ switch (widget->type) {
+ case WWT_FRAME:
+ case WWT_RESIZE:
+ if (!(w->flags & WF_RESIZABLE))
+ break;
+ if (w->min_width == w->max_width && w->min_height == w->max_height)
+ break;
+ if (x < w->x + w->width - 19 || y < w->y + w->height - 19)
+ break;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESIZING;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
+ break;
+ case WWT_VIEWPORT:
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_LEFT;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
+ if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3)))
+ break;
+
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
+ if (w == NULL)
+ break;
+
+ RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DOWN], x, y, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
+ RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 4);
+ break;
+ case WWT_CAPTION:
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_DRAGGING;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
+ break;
+ case WWT_SCROLL:
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_LEFT;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y;
+
+ int eax, ebx, ecx, edx;
+ edx = 0; // safety
+ widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) = ecx;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32) = edx * 12;//We do this because scroll id is not all decompiled
+ RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_15], RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32), ebx, ecx, edx, (int)w, (int)widget, 0);
+ switch (ecx) {
+ case SCROLL_PART_VIEW:
+ RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEDOWN], edx / sizeof(rct_scroll), ebx, eax, ebx, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_HSCROLLBAR_LEFT: input_hscrollbar_leftbutton(w); break;
+ case SCROLL_PART_HSCROLLBAR_RIGHT: input_hscrollbar_rightbutton(w); break;
+ case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH: input_hscrollbar_left_trough(w); break;
+ case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH: input_hscrollbar_right_trough(w); break;
+ case SCROLL_PART_VSCROLLBAR_TOP: input_vscrollbar_topbutton(w); break;
+ case SCROLL_PART_VSCROLLBAR_BOTTOM: input_vscrollbar_bottombutton(w); break;
+ case SCROLL_PART_VSCROLLBAR_TOP_TROUGH: input_vscrollbar_top_trough(w); break;
+ case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH: input_vscrollbar_bottom_trough(w); break;
+ }
+ break;
+ default:
+ // comment check as it disables the rotate station/building button in construction window
+// if (!widget_is_enabled(w, widgetIndex))
+// break;
+ if (widget_is_disabled(w, widgetIndex))
+ break;
+
+ sound_play_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2);
+
+ // Set new cursor down widget
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
+ RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 0);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_WIDGET_PRESSED;
+ RCT2_GLOBAL(0x009DE528, uint16) = 1;
+
+ widget_invalidate(windowClass, windowNumber, widgetIndex);
+ RCT2_CALLPROC_WE_MOUSE_DOWN(w->event_handlers[WE_MOUSE_DOWN], widgetIndex, w, widget);
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x006E8655
+ */
+static void game_handle_input_mouse(int x, int y, int state)
+{
+ rct_window *w;
+ rct_widget *widget;
+ int widgetIndex;
+
+ // Get window and widget under cursor position
+ w = window_find_from_point(x, y);
+ widgetIndex = w == NULL ? -1 : window_find_widget_from_point(w, x, y);
+ widget = widgetIndex == -1 ? 0 : &w->widgets[widgetIndex];
+
+ switch (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8)) {
+ case INPUT_STATE_RESET:
+ window_tooltip_reset(x, y);
+ // fall-through
+ case INPUT_STATE_NORMAL:
+ switch (state) {
+ case 0:
+ input_mouseover(x, y, w, widgetIndex);
+ break;
+ case 1:
+ input_leftmousedown(x, y, w, widgetIndex);
+ break;
+ case 3:
+ // Close tooltip
+ window_close_by_id(5, 0);
+
+ if (w != NULL)
+ w = window_bring_to_front(w);
+
+ if (widgetIndex == -1)
+ break;
+
+ if (widget->type == WWT_VIEWPORT) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9)
+ break;
+ w->flags &= ~(1 << 3);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_DRAG;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = w->classification;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = w->number;
+ RCT2_GLOBAL(0x009DE540, sint16) = 0;
+ // hide cursor
+ // RCT2_CALLPROC_X(0x00407045, 0, 0, 0, 0, 0, 0, 0);
+ // RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 5);
+
+ GetCursorPos(&_dragPosition);
+ ShowCursor(FALSE);
+
+ } else if (widget->type == WWT_SCROLL) {
+
+ }
+
+ break;
+ }
+
+ break;
+ case INPUT_STATE_WIDGET_PRESSED:
+ RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
+ break;
+ case INPUT_STATE_DRAGGING:
+ // RCT2_CALLPROC_X(0x006E8C5C, x, y, state, widgetIndex, w, widget, 0);
+
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
+ if (w == NULL) {
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
+ break;
+ }
+
+ if (state == 0) {
+ y = clamp(29, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34);
+ window_move_position(
+ w,
+ x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
+ y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
+ );
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
+ } else if (state == 2) {
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ y = clamp(29, y, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34);
+ window_move_position(
+ w,
+ x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
+ y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
+ );
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
+
+ RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_18], 0, 0, x, y, (int)w, 0, 0);
+ }
+ break;
+ case INPUT_STATE_VIEWPORT_DRAG:
+ {
+ int dx, dy;
+
+ POINT newDragPosition;
+ GetCursorPos(&newDragPosition);
+
+ dx = newDragPosition.x - _dragPosition.x;
+ dy = newDragPosition.y - _dragPosition.y;
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
+ if (state == 0) {
+ rct_viewport *viewport = w->viewport;
+ RCT2_GLOBAL(0x009DE540, sint16) += RCT2_GLOBAL(0x009DE588, sint16);
+ if (viewport == NULL) {
+ ShowCursor(TRUE);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
+ } else if (dx != 0 || dy != 0) {
+ if (!(w->flags & (1 << 2))) {
+ RCT2_GLOBAL(0x009DE540, sint16) = 1000;
+ dx <<= viewport->zoom + 1;
+ dy <<= viewport->zoom + 1;
+ w->saved_view_x += dx;
+ w->saved_view_y += dy;
+ }
+ }
+ } else if (state == 4) {
+ ShowCursor(TRUE);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
+ if (RCT2_GLOBAL(0x009DE540, sint16) < 500) {
+ // Right click
+ {
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ eax = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16);
+ ebx = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16);
+ RCT2_CALLFUNC_X(0x006EDE88, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ switch (ebx & 0xFF) {
+ case 2:
+ if (*((uint8*)edx) == 0)
+ RCT2_CALLPROC_X(0x006B4857, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 3:
+ RCT2_CALLPROC_X(0x006CC056, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 5:
+ RCT2_CALLPROC_X(0x006E08D2, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 6:
+ RCT2_CALLPROC_X(0x006A614A, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 7:
+ RCT2_CALLPROC_X(0x006A61AB, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 8:
+ RCT2_CALLPROC_X(0x00666C0E, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 9:
+ RCT2_CALLPROC_X(0x006E57A9, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 10:
+ RCT2_CALLPROC_X(0x006B88DC, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ case 12:
+ RCT2_CALLPROC_X(0x006BA233, eax, 0, ecx, edx, 0, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ //
+ SetCursorPos(_dragPosition.x, _dragPosition.y);
+ // RCT2_CALLPROC_X(0x006E89C6, x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16), y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16), state, widgetIndex, w, widget, 0);
+ break;
+ }
+ case INPUT_STATE_DROPDOWN_ACTIVE:
+ RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
+ break;
+ case INPUT_STATE_VIEWPORT_LEFT:
+ //RCT2_CALLPROC_X(0x006E87B4, x, y, state, widgetIndex, (int)w, (int)widget, 0);
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
+ if (!w){
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
+ break;
+ }
+
+ if (state == 0){
+ if (!w->viewport){
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
+ break;
+ }
+
+ if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) ||
+ w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) ||
+ !(RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3)))break;
+
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
+
+ if (!w)break;
+
+ RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
+ }
+ else if (state == 2){
+
+ RCT2_GLOBAL(0x9DE51D, uint8) = 0;
+ if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break;
+ if ((RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3))){
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
+ if (!w)break;
+ RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UP], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
+ }
+ else{
+ if ((RCT2_GLOBAL(0x9DE518, uint32)&(1 << 4)))break;
+ rct_sprite* spr;
+ int eax = x, ebx = y, ecx = state, esi = (int)w, edi = (int)widget, ebp = 0;
+ RCT2_CALLFUNC_X(0X6ED9D0, &eax, &ebx, &ecx, (int*)&spr, &esi, &edi, &ebp);
+ if ((ebx & 0xFF) == 2){
+
+ if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE){
+ //Open ride window
+ RCT2_CALLPROC_X(0x6ACAC2, eax, ebx, ecx, (int)spr, esi, edi, ebp);
+ }
+ else if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_PEEP){
+ window_peep_open(&spr->peep);
+ }
+ else if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_FLOATING_TEXT){
+ //Unknown for now
+ RCT2_CALLPROC_X(0x6E88D7, eax, ebx, ecx, (int)spr, esi, edi, ebp);
+ }
+ }
+ else if ((ebx & 0xFF) == 3){
+ rct_map_element* map_element = (rct_map_element*)spr;
+
+ if (!((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE)){
+ eax = RCT2_ADDRESS(0x0099BA64, uint8)[16 * map_element->properties.track.type];
+ if (!(eax & 0x10)){//If not station track
+ //Open ride window in overview mode.
+ RCT2_CALLPROC_X(0x6ACC28, map_element->properties.track.ride_index, ebx, ecx, (int)map_element, esi, edi, ebp);
+ break;
+ }
+ }
+ //Open ride window in station view
+ RCT2_CALLPROC_X(0x6ACCCE, map_element->properties.track.ride_index, (map_element->properties.track.sequence & 0x70) >> 4, ecx, (int)map_element, esi, edi, ebp);
+ }
+ else if ((ebx & 0xFF) == 8){
+ window_park_entrance_open();
+ }
+ }
+ }
+ break;
+ case INPUT_STATE_SCROLL_LEFT://0x006E8676
+ //RCT2_CALLPROC_X(0x006E8676, x, y, state, widgetIndex, (int)w, (int)widget, 0);
+ if (state == 0){
+ if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){
+ invalidate_scroll();
+ return;
+ }
+ if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){
+ invalidate_scroll();
+ return;
+ }
+ if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){
+ invalidate_scroll();
+ return;
+ }
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
+ int temp_x = x;
+ x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
+ RCT2_CALLPROC_X(0x006E98F2, x, temp_x, state, w->number, (int)w, (int)widget, x);
+ return;
+ }
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){
+ int temp_y = y;
+ y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y;
+ RCT2_CALLPROC_X(0x006E99A9, temp_y, y, state, w->number, (int)w, (int)widget, y);
+ return;
+ }
+ int scroll_part, scroll_id;
+ widget_scroll_get_part(w, widget, x, y, &x, &y, &scroll_part, &scroll_id);
+
+ if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){
+ invalidate_scroll();
+ return;
+ }
+
+ switch (scroll_part){
+ case SCROLL_PART_VIEW:
+ RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], w->number / 18, y, x, y, (int)w, (int)widget, (int)w->event_handlers);
+ break;
+ case SCROLL_PART_HSCROLLBAR_LEFT:
+ RCT2_CALLPROC_X(0x006E9A60, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_HSCROLLBAR_RIGHT:
+ RCT2_CALLPROC_X(0x006E9ABF, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
+ case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
+ return;
+ break;
+ case SCROLL_PART_HSCROLLBAR_THUMB:
+ case SCROLL_PART_VSCROLLBAR_TOP:
+ RCT2_CALLPROC_X(0x006E9C37, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_VSCROLLBAR_BOTTOM:
+ RCT2_CALLPROC_X(0x006E9C96, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
+ case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
+ return;
+ break;
+ default:
+ return;
+ }
+ }else if (state==2){
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
+ invalidate_scroll();
+ return;
+ }
+ break;
+ case INPUT_STATE_RESIZING:
+ // RCT2_CALLPROC_X(0x006E8B46, x, y, state, widgetIndex, w, widget, 0);
+
+ w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber));
+ if (w == NULL) {
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
+ break;
+ }
+
+ if (state != 0 && state != 2)
+ break;
+ if (state == 2) {
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
+ }
+
+ if (y < RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 2) {
+ window_resize(
+ w,
+ x - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16),
+ y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16)
+ );
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y;
+ break;
+ case 9:
+ RCT2_CALLPROC_X(0x006E8ACB, x, y, state, widgetIndex, (int)w, (int)widget, 0);
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x006E9253
+ */
+static void input_mouseover(int x, int y, rct_window *w, int widgetIndex)
+{
+ rct_windowclass windowClass = 255;
+ rct_windownumber windowNumber = 0;
+ rct_widget *widget;
+
+ if (w != NULL) {
+ windowClass = w->classification;
+ windowNumber = w->number;
+ widget = &w->widgets[widgetIndex];
+ }
+
+ input_mouseover_widget_check(windowClass, windowNumber, widgetIndex);
+
+ if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL)
+ {
+ int eax, ebx, ecx, edx;
+ widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
+
+ if (ecx < 0)
+ goto showTooltip;
+ if (ecx == 0) {
+ RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEOVER], edx, 0, eax, ebx, (int)w, 0, 0);
+ goto showTooltip;
+ } else {
+
+ }
+ } else {
+ showTooltip:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) == 255) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) < 500 ||
+ (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) == x &&
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) == y)
+ ) {
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = RCT2_GLOBAL(0x009DE588, uint16);
+
+ int bp = 2000;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) <= 1000)
+ bp = 0;
+ if (bp > RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16))
+ return;
+
+ window_tooltip_open(w, widgetIndex, x, y);
+ // RCT2_CALLPROC_X(0x006EA10D, x, y, 0, widgetIndex, w, widget, 0); // window_tooltip_open();
+ }
+ } else {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification ||
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number ||
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) != widgetIndex
+ ) {
+ window_tooltip_close();
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) += RCT2_GLOBAL(0x009DE588, uint16);
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) < 8000)
+ return;
+ window_close_by_id(WC_TOOLTIP, 0);
+ }
+ }
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) = x;
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) = y;
+}
+
+/**
+ *
+ * rct2: 0x006E9269
+ */
+static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex)
+{
+ if (widgetIndex == -1) return; //Prevents invalid widgets being clicked source of bug is elsewhere
+ // Check if widget cursor was over has changed
+ if (windowClass != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) ||
+ windowNumber != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) ||
+ widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)
+ ) {
+ // Invalidate last widget cursor was on if widget is a flat button
+ input_mouseover_widget_flatbutton_invalidate();
+
+ // Set new cursor over widget
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) = windowClass;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) = windowNumber;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint16) = widgetIndex;
+
+ // Invalidate new widget cursor is on if widget is a flat button
+ if (windowClass != 255)
+ input_mouseover_widget_flatbutton_invalidate();
+ }
+}
+
+static void input_mouseover_widget_flatbutton_invalidate()
+{
+ rct_window *w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber));
+ if (w == NULL)
+ return;
+
+ RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
+ if (w->widgets[RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)].type == WWT_FLATBTN)
+ widget_invalidate(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber));
+}
+
+void game_handle_edge_scroll()
+{
+ rct_window *mainWindow;
+ int scrollX, scrollY;
+
+ mainWindow = window_get_main();
+ if (mainWindow == NULL)
+ return;
+ if ((mainWindow->flags & WF_2) || (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9))
+ return;
+ if (mainWindow->viewport == NULL)
+ return;
+
+ scrollX = 0;
+ scrollY = 0;
+
+ // Scroll left / right
+ if (gCursorState.x == 0)
+ scrollX = -1;
+ else if (gCursorState.x == RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 1)
+ scrollX = 1;
+
+ // Scroll up / down
+ if (gCursorState.y == 0)
+ scrollY = -1;
+ else if (gCursorState.y == RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 1)
+ scrollY = 1;
+
+ // Scroll viewport
+ if (scrollX != 0) {
+ mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
+ RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
+ }
+ if (scrollY != 0) {
+ mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
+ RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
+ }
+}
+
+void game_handle_key_scroll()
+{
+ rct_window *mainWindow;
+ int scrollX, scrollY;
+
+ mainWindow = window_get_main();
+ if (mainWindow == NULL)
+ return;
+ if ((mainWindow->flags & WF_2) || (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 9))
+ return;
+ if (mainWindow->viewport == NULL)
+ return;
+
+ scrollX = 0;
+ scrollY = 0;
+
+ // Scroll left / right
+ if (gKeysState[SDL_SCANCODE_LEFT])
+ scrollX = -1;
+ else if (gKeysState[SDL_SCANCODE_RIGHT])
+ scrollX = 1;
+
+ // Scroll up / down
+ if (gKeysState[SDL_SCANCODE_UP])
+ scrollY = -1;
+ else if (gKeysState[SDL_SCANCODE_DOWN])
+ scrollY = 1;
+
+ // Scroll viewport
+ if (scrollX != 0) {
+ mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
+ RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
+ }
+ if (scrollY != 0) {
+ mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
+ RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 7);
+ }
+}
+
+/**
+ *
+ * rct2: 0x00406CD2
+ */
+int get_next_key()
+{
+ int i;
+ for (i = 0; i < 221; i++) {
+ if (gKeysPressed[i]) {
+ gKeysPressed[i] = 0;
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+void handle_shortcut_command(int shortcutIndex)
+{
+ rct_window *window;
+
+ switch (shortcutIndex) {
+ case SHORTCUT_CLOSE_TOP_MOST_WINDOW:
+ window_close_top();
+ break;
+ case SHORTCUT_CLOSE_ALL_FLOATING_WINDOWS:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2))
+ window_close_all();
+ else if (RCT2_GLOBAL(0x0141F570, uint8) == 1)
+ window_close_top();
+ break;
+ case SHORTCUT_CANCEL_CONSTRUCTION_MODE:
+ window = window_find_by_id(WC_ERROR, 0);
+ if (window != NULL)
+ window_close(window);
+ else if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3))
+ tool_cancel();
+ break;
+ case SHORTCUT_PAUSE_GAME:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 10)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 0, WE_MOUSE_UP);
+ }
+ }
+ break;
+ case SHORTCUT_ZOOM_VIEW_OUT:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 2, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_ZOOM_VIEW_IN:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 3, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_ROTATE_VIEW:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 8)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 4, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_ROTATE_CONSTRUCTION_OBJECT:
+ RCT2_CALLPROC_EBPSAFE(0x006E4182);
+ break;
+ case SHORTCUT_UNDERGROUND_VIEW_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_REMOVE_BASE_LAND_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_HIDE_BASE;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_REMOVE_VERTICAL_LAND_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_HIDE_VERTICAL;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_SEE_THROUGH_RIDES_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_RIDES;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_SEE_THROUGH_SCENERY_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_SCENERY;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_INVISIBLE_SUPPORTS_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_SUPPORTS;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_INVISIBLE_PEOPLE_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_PEEPS;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_HEIGHT_MARKS_ON_LAND_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_LAND_HEIGHTS;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_HEIGHT_MARKS_ON_RIDE_TRACKS_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_TRACK_HEIGHTS;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_HEIGHT_MARKS_ON_PATHS_TOGGLE:
+ window = window_get_main();
+ if (window != NULL) {
+ window->viewport->flags ^= VIEWPORT_FLAG_PATH_HEIGHTS;
+ window_invalidate(window);
+ }
+ break;
+ case SHORTCUT_ADJUST_LAND:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 7, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_ADJUST_WATER:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 8, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_BUILD_SCENERY:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 9, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_BUILD_PATHS:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 10, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_BUILD_NEW_RIDE:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 11, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_SHOW_FINANCIAL_INFORMATION:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C))
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800))
+ window_finances_open();
+ break;
+ case SHORTCUT_SHOW_RESEARCH_INFORMATION:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
+ // Open new ride window
+ RCT2_CALLPROC_EBPSAFE(0x006B3CFF);
+ window = window_find_by_id(WC_CONSTRUCT_RIDE, 0);
+ if (window != NULL)
+ RCT2_CALLPROC_WE_MOUSE_DOWN(window->event_handlers[WE_MOUSE_DOWN], 10, window, NULL);
+ }
+ break;
+ case SHORTCUT_SHOW_RIDES_LIST:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 12, WE_MOUSE_UP);
+ }
+ }
+ break;
+ case SHORTCUT_SHOW_PARK_INFORMATION:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 13, WE_MOUSE_UP);
+ }
+ }
+ break;
+ case SHORTCUT_SHOW_GUEST_LIST:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 15, WE_MOUSE_UP);
+ }
+ }
+ break;
+ case SHORTCUT_SHOW_STAFF_LIST:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 14, WE_MOUSE_UP);
+ }
+ }
+ break;
+ case SHORTCUT_SHOW_RECENT_MESSAGES:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E))
+ window_news_open();
+ break;
+ case SHORTCUT_SHOW_MAP:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) || RCT2_GLOBAL(0x0141F570, uint8) == 1) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C)) {
+ window = window_find_by_id(WC_TOP_TOOLBAR, 0);
+ if (window != NULL) {
+ window_invalidate(window);
+ window_event_helper(window, 6, WE_MOUSE_UP);
+ }
+ }
+ }
+ break;
+ case SHORTCUT_SCREENSHOT:
+ RCT2_CALLPROC_EBPSAFE(0x006E4034); // set screenshot countdown to 2
+ break;
+
+ // New
+ case SHORTCUT_REDUCE_GAME_SPEED:
+ game_reduce_game_speed();
+ break;
+ case SHORTCUT_INCREASE_GAME_SPEED:
+ game_increase_game_speed();
+ break;
+ }
+}
+
+void game_increase_game_speed()
+{
+ gGameSpeed = min(8, gGameSpeed + 1);
+}
+
+void game_reduce_game_speed()
+{
+ gGameSpeed = max(1, gGameSpeed - 1);
+}
+
+/**
+ *
+ * rct2: 0x006E3E68
+ */
+void handle_shortcut(int key)
+{
+ int i;
+ for (i = 0; i < SHORTCUT_COUNT; i++) {
+ if (key == gShortcutKeys[i]) {
+ handle_shortcut_command(i);
+ break;
+ }
+ }
+}
+
+/**
+ *
+ * rct2: 0x006E3E91
+ */
+void set_shortcut(int key)
+{
+ int i;
+
+ // Unmap shortcut that already uses this key
+ for (i = 0; i < 32; i++) {
+ if (key == gShortcutKeys[i]) {
+ gShortcutKeys[i] = 0xFFFF;
+ break;
+ }
+ }
+
+ // Map shortcut to this key
+ gShortcutKeys[RCT2_GLOBAL(0x009DE511, uint8)] = key;
+ window_close_by_id(WC_CHANGE_KEYBOARD_SHORTCUT, 0);
+ window_invalidate_by_id(WC_KEYBOARD_SHORTCUT_LIST, 0);
+ config_save();
+}
+
+/**
+ *
+ * rct2: 0x006E3B43
+ */
+void game_handle_keyboard_input()
+{
+ rct_window *w;
+ int key;
+
+ // Handle mouse scrolling
+ if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 1)
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3))
+ game_handle_edge_scroll();
+
+ // Handle modifier keys and key scrolling
+ RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0;
+ if (RCT2_GLOBAL(0x009E2B64, uint32) != 1) {
+ if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT])
+ RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 1;
+ if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL])
+ RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 2;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
+ game_handle_key_scroll();
+ }
+
+
+ // Handle key input
+ while ((key = get_next_key()) != 0) {
+ if (key == 255)
+ continue;
+
+ key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8;
+
+ w = window_find_by_id(WC_CHANGE_KEYBOARD_SHORTCUT, 0);
+ if (w != NULL)
+ set_shortcut(key);
+ else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1)
+ tutorial_stop();
+ else
+ handle_shortcut(key);
+ }
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
+ return;
+
+ // Tutorial and the modifier key
+ if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) {
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ RCT2_CALLFUNC_X(0x0066EEB4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ eax &= 0xFF;
+ RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = eax;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4) {
+ window_tooltip_close();
+ if ((w = window_get_main()) != NULL) {
+ RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
+ RCT2_GLOBAL(0x009DEA72, uint16)++;
+ }
+ }
+ } else {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) {
+ window_tooltip_close();
+ if ((w = window_get_main()) != NULL) {
+ RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
+ RCT2_GLOBAL(0x009DEA72, uint16)++;
+ }
+ }
+
+ // Write tutorial input
+ RCT2_CALLPROC_X(0x0066EEE1, RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8), 0, 0, 0, 0, 0, 0);
+ }
+}
+
+/**
+ *
+ * rct2: 0x006EA627
+ */
+void game_handle_input()
+{
+ rct_window *w;
+
+ if (RCT2_GLOBAL(0x009DEA64, uint16) & 2) {
+ RCT2_GLOBAL(0x009DEA64, uint16) &= ~2;
+ game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 2, 0);
+ }
+
+ if (RCT2_GLOBAL(0x009ABDF2, uint8) != 0) {
+ for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
+ RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_07], 0, 0, 0, 0, (int)w, 0, 0);
+
+ RCT2_CALLPROC_EBPSAFE(0x006EA73F);
+ RCT2_CALLPROC_EBPSAFE(0x006E8346); // update_cursor_position
+
+ {
+ // int eax, ebx, ecx, edx, esi, edi, ebp;
+ int eax, ebx, ecx;
+
+ for (;;) {
+ game_get_next_input(&eax, &ebx, &ecx);
+ if (ecx == 0)
+ break;
+
+ game_handle_input_mouse(eax, ebx, ecx & 0xFF);
+ // RCT2_CALLPROC_X(0x006E8655, eax, ebx, ecx, 0, 0, 0, 0); // window_process_mouse_input
+ }
+
+ if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
+ game_handle_input_mouse(eax, ebx, ecx);
+ // RCT2_CALLPROC_X(0x006E8655, eax, ebx, 0, 0, 0, 0, 0); // window_process_mouse_input
+ } else if (eax != 0x80000000) {
+ eax = clamp(0, eax, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) - 1);
+ ebx = clamp(0, ebx, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - 1);
+
+ game_handle_input_mouse(eax, ebx, ecx);
+ // RCT2_CALLPROC_X(0x006E8655, eax, ebx, 0, 0, 0, 0, 0); // window_process_mouse_input
+ process_mouse_over(eax, ebx);
+ //RCT2_CALLPROC_X(0x006ED833, eax, ebx, 0, 0, 0, 0, 0);
+ sub_6ED801(eax, ebx);
+ //RCT2_CALLPROC_EBPSAFE(0x006ED801);
+ }
+ }
+ }
+
+ for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
+ RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_08], 0, 0, 0, 0,(int) w, 0, 0);
+}
+
+/**
+ *
+ * rct2: 0x006E83C7
+ */
+static void game_get_next_input(int *x, int *y, int *state)
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ RCT2_CALLFUNC_X(0x00407074, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ if (eax == 0) {
+ *x = gCursorState.x;
+ *y = gCursorState.y;
+ *state = 0;
+ return;
+ }
+
+ *x = RCT2_GLOBAL(eax + 0, sint32);
+ *y = RCT2_GLOBAL(eax + 4, sint32);
+ *state = RCT2_GLOBAL(eax + 8, sint32);
+
+ //int eax, ebx, ecx, edx, esi, edi, ebp;
+ //RCT2_CALLFUNC_X(0x006E83C7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ //*x = eax & 0xFFFF;
+ //*y = ebx & 0xFFFF;
+ //*state = ecx & 0xFF;
+ //return;
+
+ //int on_tutorial = RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8);
+ //if (RCT2_GLOBAL(0x009DE518, uint32) & (1 << 5)) {
+ // if (on_tutorial == 1) {
+
+ // } else {
+ // RCT2_CALLPROC_EBPSAFE(0x00407074);
+ // }
+ // if (on_tutorial == 2) {
+
+ // }
+
+ //} else {
+
+ //}
+}
+
+/**
+ *
+ * rct2: 0x006ED801
+ */
+void sub_6ED801(int x, int y){
+ if (RCT2_GLOBAL(0x9DE518, uint32) & (1 << 3)){
+ rct_window* w = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16));
+ if (w == NULL){
+ tool_cancel();
+ }
+ else{
+ RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UPDATE], x, y, 0, RCT2_GLOBAL(0x9DE546, uint16), (int)w, 0, 0);
+ }
+ }
+}
+
+/**
+*
+* rct2: 0x006ED990
+*/
+void sub_6ED990(char cursor_id){
+ if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESIZING)
+ {
+ cursor_id = CURSOR_DIAGONAL_ARROWS; //resize icon
+ }
+
+ if (cursor_id == RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8))
+ {
+ return;
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8) = cursor_id;
+ RCT2_GLOBAL(0x14241BC, uint32) = 2;
+ osinterface_set_cursor(cursor_id);
+ RCT2_GLOBAL(0x14241BC, uint32) = 0;
+}
+
+/**
+*
+* rct2: 0x006ED833
+*/
+void process_mouse_over(int x, int y)
+{
+ rct_window* window;
+ rct_window* subWindow;
+
+ int widgetId;
+ int cursorId;
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+
+ cursorId = CURSOR_ARROW;
+ RCT2_GLOBAL(0x9A9808, sint16) = -1;
+ window = window_find_from_point(x, y);
+
+ if (window != NULL)
+ {
+ widgetId = window_find_widget_from_point(window, x, y);
+ RCT2_GLOBAL(0x1420046, sint16) = (widgetId & 0xFFFF);
+ if (widgetId != -1)
+ {
+
+ switch (window->widgets[widgetId].type){
+ case WWT_VIEWPORT:
+ if ((RCT2_GLOBAL(0x9DE518, int) & 0x8) == 0)
+ {
+ edx = cursorId;
+ eax = x;
+ ebx = y;
+ //Find out if there is a clickable item under pointer
+ RCT2_CALLFUNC_X(0X6ED9D0, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+
+ if ((ebx & 0xFF) == 2 || (ebx & 0xFF) == 8 || (ebx & 0xFF) == 3)
+ {
+ sub_6ED990(CURSOR_HAND_POINT);
+ return;
+ }
+ break;
+ }
+ cursorId = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8);
+ subWindow = window_find_by_id(RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber));
+ ebp = (int)subWindow;
+ if (subWindow == NULL)
+ {
+ break;
+ }
+ ebx = ebx & 0xFFFFFF00;
+ edi = cursorId;
+ esi = (int) subWindow;
+ RCT2_CALLFUNC_X(subWindow->event_handlers[WE_UNKNOWN_0E], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ cursorId = edi;
+ if ((ebx & 0xFF) != 0)
+ {
+ sub_6ED990(cursorId);
+ return;
+ }
+ break;
+ case WWT_FRAME:
+ case WWT_RESIZE:
+ if (!(window->flags & 0x100))
+ {
+ break;
+ }
+ if (window->min_width == window->max_width && window->min_height == window->max_height)
+ {
+ break;
+ }
+ if (x < window->x + window->width - 0x13)
+ {
+ break;
+ }
+ if (y < window->y + window->height - 0x13)
+ {
+ break;
+ }
+ cursorId = CURSOR_DIAGONAL_ARROWS;
+ break;
+ case WWT_SCROLL:
+ RCT2_GLOBAL(0x9DE558, uint16) = x;
+ RCT2_GLOBAL(0x9DE55A, uint16) = y;
+ int output_x, output_y, output_scroll_area, scroll_id;
+ widget_scroll_get_part(window, window->widgets, x, y, &output_x, &output_y, &output_scroll_area, &scroll_id);
+ cursorId = scroll_id;
+ if (output_scroll_area != SCROLL_PART_VIEW)
+ {
+ cursorId = CURSOR_ARROW;
+ break;
+ }
+ //Fall through to default
+ default:
+ ecx = x;
+ edx = y;
+ eax = widgetId;
+ ebx = 0xFFFFFFFF;
+ edi = (int)&window->widgets[widgetId];
+
+ RCT2_CALLFUNC_X(window->event_handlers[WE_UNKNOWN_17], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ if (ebx == 0xFFFFFFFF)
+ {
+ cursorId = CURSOR_ARROW;
+ break;
+ }
+ cursorId = ebx;
+ break;
+ }
+ }
+ }
+ RCT2_CALLPROC_X(0x6EDE88, x, y, ecx, cursorId, esi, edi, ebp);
+ //itemUnderCursor(&eax, &ebx, &ecx, &edx);
+
+ sub_6ED990(cursorId);
+ return;
+}
+
+/**
+ *
+ * rct2: 0x006E876D
+ */
+void invalidate_scroll()
+{
+ int window_no = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16);
+ int window_cls = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8);
+
+ rct_window* wind = window_find_by_id(window_cls, window_no);
+ if (wind == NULL) return;
+
+ int scroll_id = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32);
+ //Reset to basic scroll
+ wind->scrolls[scroll_id / sizeof(rct_scroll)].flags &= 0xFF11;
+
+ window_invalidate_by_id(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16));
+}
\ No newline at end of file
diff --git a/src/input.h b/src/input.h
new file mode 100644
index 0000000000..a7a1d8ebb6
--- /dev/null
+++ b/src/input.h
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+void game_handle_input();
+void game_handle_keyboard_input();
+
+#endif
\ No newline at end of file
diff --git a/src/map.c b/src/map.c
index 39fcdbef7d..c82fd6dc48 100644
--- a/src/map.c
+++ b/src/map.c
@@ -102,7 +102,7 @@ void map_init()
RCT2_GLOBAL(0x013CE774, sint16) = 0;
RCT2_GLOBAL(0x013CE776, sint16) = 0;
RCT2_GLOBAL(0x01358830, sint16) = 4768;
- RCT2_GLOBAL(0x01358832, sint16) = 5054;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) = 5054;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16) = 150;
RCT2_GLOBAL(0x01358836, sint16) = 4767;
RCT2_GLOBAL(0x01359208, sint16) = 7;
@@ -141,7 +141,7 @@ void map_update_tile_pointers()
/**
* Return the absolute height of an element, given its (x,y) coordinates
- *
+ *
* rct2: 0x00662783
*/
int map_element_height(int x, int y)
@@ -168,7 +168,7 @@ int map_element_height(int x, int y)
// Remove the extra height bit
slope &= 0xF;
- uint8 quad, quad_extra; // which quadrant the element is in?
+ sint8 quad, quad_extra; // which quadrant the element is in?
// quad_extra is for extra height tiles
uint8 xl, yl; // coordinates across this tile
@@ -198,7 +198,7 @@ int map_element_height(int x, int y)
quad = TILE_SIZE - yl - xl;
break;
case 8: // NW corner up
- quad = xl - yl;
+ quad = yl - xl;
break;
}
// If the element is in the quadrant with the slope, raise its height
@@ -210,7 +210,7 @@ int map_element_height(int x, int y)
// One side up
switch (slope) {
case 3: // E side up
- height += xl / 2;
+ height += xl / 2 + 1;
break;
case 6: // S side up
height += (TILE_SIZE - yl) / 2;
@@ -233,15 +233,15 @@ int map_element_height(int x, int y)
break;
case 11: // SW corner down
quad_extra = xl + yl;
- quad = xl + yl - TILE_SIZE;
+ quad = xl + yl - TILE_SIZE - 1;
break;
case 13: // SE corner down
quad_extra = TILE_SIZE - xl + yl;
- quad = xl - yl;
+ quad = yl - xl;
break;
case 14: // NE corner down
quad_extra = (TILE_SIZE - xl) + (TILE_SIZE - yl);
- quad = TILE_SIZE - yl - xl;
+ quad = TILE_SIZE - yl - xl - 1;
break;
}
@@ -255,7 +255,6 @@ int map_element_height(int x, int y)
// so we move *down* the slope
if (quad < 0) {
height += quad / 2;
- height += 0xFF00;
}
}
diff --git a/src/map.h b/src/map.h
index 069c0d52c9..8aa4e171fd 100644
--- a/src/map.h
+++ b/src/map.h
@@ -24,8 +24,8 @@
#include "rct2.h"
typedef struct {
- uint8 slope;
- uint8 terrain;
+ uint8 slope; //4
+ uint8 terrain; //5
uint8 grass_length;
uint8 ownership;
} rct_map_element_surface_properties;
@@ -92,10 +92,10 @@ typedef union {
* size: 0x08
*/
typedef struct {
- uint8 type;
- uint8 flags;
- uint8 base_height;
- uint8 clearance_height;
+ uint8 type; //0
+ uint8 flags; //1
+ uint8 base_height; //2
+ uint8 clearance_height; //3
rct_map_element_properties properties;
} rct_map_element;
@@ -177,6 +177,8 @@ enum {
#define MAP_ELEMENT_WATER_HEIGHT_MASK 0x1F
#define MAP_ELEMENT_SURFACE_TERRAIN_MASK 0xE0
+#define MAP_MINIMUM_X_Y -256
+
#define MAX_MAP_ELEMENTS 196608
#define MAX_TILE_MAP_ELEMENT_POINTERS (256 * 256)
diff --git a/src/viewport.c b/src/viewport.c
index 8a00f235e4..b5de1c435e 100644
--- a/src/viewport.c
+++ b/src/viewport.c
@@ -18,9 +18,11 @@
* along with this program. If not, see .
*****************************************************************************/
+#include
#include "addresses.h"
#include "config.h"
#include "gfx.h"
+#include "map.h"
#include "string_ids.h"
#include "sprite.h"
#include "sprites.h"
@@ -219,13 +221,166 @@ void viewport_update_pointers()
*vp = NULL;
}
+void sub_689174(sint16* x, sint16* y, uint8 curr_rotation){
+ //RCT2_CALLFUNC_X(0x00689174, (int*)&x, (int*)&y, &ecx, &curr_rotation, (int*)&window, (int*)&viewport, &ebp);
+
+ sint16 start_x = *x;
+ sint16 start_y = *y;
+ sint16 height = 0;
+ switch (curr_rotation){
+ case 0:
+ for (int i = 0; i < 6; ++i){
+
+ *x = start_y - start_x / 2 + height;
+ *y = start_y + start_x / 2 + height;
+
+ height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
+ }
+ break;
+ case 1:
+ for (int i = 0; i < 6; ++i){
+ *x = -start_y - start_x / 2 - height;
+ *y = start_y - start_x / 2 + height;
+
+ height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
+ }
+ break;
+ case 2:
+ for (int i = 0; i < 6; ++i){
+ *x = -start_y + start_x / 2 - height;
+ *y = -start_y - start_x / 2 - height;
+
+ height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
+ }
+ break;
+ case 3:
+ for (int i = 0; i < 6; ++i){
+ *x = start_x / 2 + start_y + height;
+ *y = start_x / 2 - start_y - height;
+
+ height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y);
+ }
+ break;
+ }
+}
+
/**
*
* rct2: 0x006E7A3A
*/
void viewport_update_position(rct_window *window)
{
- RCT2_CALLPROC_X(0x006E7A3A, 0, 0, 0, 0, (int)window, 0, 0);
+ //RCT2_CALLPROC_X(0x006E7A3A, 0, 0, 0, 0, (int)window, 0, 0);
+
+ RCT2_CALLPROC_X(window->event_handlers[WE_RESIZE], 0, 0, 0, 0, (int)window, 0, 0);
+
+ rct_viewport* viewport = window->viewport;
+ if (!viewport)return;
+
+ if (window->viewport_target_sprite != -1){
+ rct_sprite* sprite = &g_sprite_list[window->viewport_target_sprite];
+
+ int height = map_element_height(sprite->unknown.x, sprite->unknown.y) - 16;
+ int underground = sprite->unknown.z < height;
+
+ RCT2_CALLPROC_X(0x6E7A15, sprite->unknown.x, sprite->unknown.y, sprite->unknown.z, underground, (int)window, (int)viewport, 0);
+
+ int center_x, center_y;
+ center_2d_coordinates(sprite->unknown.x, sprite->unknown.y, sprite->unknown.z, ¢er_x, ¢er_y, window->viewport);
+
+ RCT2_CALLPROC_X(0x6E7DE1, center_x, center_y, 0, 0, (int)window, (int)viewport, 0);
+ window_invalidate(window);//Added to force a redraw.
+ return;
+ }
+
+
+ sint16 x = viewport->view_width / 2 + window->saved_view_x;
+ sint16 y = viewport->view_height / 2 + window->saved_view_y;
+
+ int curr_rotation = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
+ sub_689174(&x, &y, curr_rotation);
+
+ RCT2_CALLPROC_X(0x006E7A15, x, y, 0, 0, (int)window, (int)viewport, 0);
+
+ //Clamp to the map minimum value
+ int at_map_edge = 0;
+ if (x < MAP_MINIMUM_X_Y){
+ x = MAP_MINIMUM_X_Y;
+ at_map_edge = 1;
+ }
+ if (y < MAP_MINIMUM_X_Y){
+ y = MAP_MINIMUM_X_Y;
+ at_map_edge = 1;
+ }
+
+ //Clamp to the map maximum value (scenario specific)
+ if (x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){
+ x = RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16);
+ at_map_edge = 1;
+ }
+ if (y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){
+ y = RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16);
+ at_map_edge = 1;
+ }
+
+ if (at_map_edge) {
+ // The &0xFFFF is to prevent the sign extension messing the
+ // function up.
+ int z = map_element_height(x & 0xFFFF, y & 0xFFFF);
+ int _2d_x, _2d_y;
+ center_2d_coordinates(x, y, z, &_2d_x, &_2d_y, viewport);
+
+ if (window->saved_view_x > 0){
+ _2d_x = min(_2d_x, window->saved_view_x);
+ }
+ else{
+ _2d_x = max(_2d_x, window->saved_view_x);
+ }
+
+ if (window->saved_view_y > 0){
+ _2d_y = min(_2d_y, window->saved_view_y);
+ }
+ else{
+ _2d_y = max(_2d_y, window->saved_view_y);
+ }
+
+ window->saved_view_x = _2d_x;
+ window->saved_view_y = _2d_y;
+ }
+
+ x = window->saved_view_x;
+ y = window->saved_view_y;
+ if (window->flags & WF_SCROLLING_TO_LOCATION){
+ // Moves the viewport if focusing in on an item
+ uint8 flags = 0;
+ x -= viewport->view_x;
+ if (x < 0){
+ x = -x;
+ flags |= 1;
+ }
+ y -= viewport->view_y;
+ if (y < 0){
+ y = -y;
+ flags |= 2;
+ }
+ x = (x + 7)/8;
+ y = (y + 7)/8;
+
+ //If we are at the final zoom position
+ if (!x && !y){
+ window->flags &= ~WF_SCROLLING_TO_LOCATION;
+ }
+ if (flags & 1){
+ x = -x;
+ }
+ if (flags & 2){
+ y = -y;
+ }
+ x += viewport->view_x;
+ y += viewport->view_y;
+ }
+
+ RCT2_CALLPROC_X(0x6E7DE1, x, y, 0, 0, (int)window, (int)viewport, 0);
}
void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom);
diff --git a/src/window.c b/src/window.c
index 50b7be7162..da0de66626 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1465,3 +1465,34 @@ void window_resize_gui_scenario_editor(int width, int height)
}
}
+
+void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct_widget* widget )
+{
+#ifdef _MSC_VER
+ __asm {
+ push address
+ push widget
+ push w
+ push widgetIndex
+ mov edi, widget
+ mov edx, widgetIndex
+ mov esi, w
+ call[esp + 12]
+ add esp, 16
+ }
+#else
+ __asm__("\
+ push %[address]\n\
+ mov edi, %[widget] \n\
+ mov eax, %[w] \n\
+ mov edx, %[widgetIndex] \n\
+ push edi \n\
+ push eax \n\
+ push edx \n\
+ mov esi, %[w] \n\
+ call [esp+12] \n\
+ add esp, 16 \n\
+ " :[address] "+m" (address), [w] "+m" (w), [widget] "+m" (widget), [widgetIndex] "+m" (widgetIndex): : "eax", "esi", "edx", "edi"
+ );
+#endif
+}
\ No newline at end of file
diff --git a/src/window.h b/src/window.h
index bab8718775..61ab0d9e01 100644
--- a/src/window.h
+++ b/src/window.h
@@ -260,7 +260,7 @@ typedef enum {
WF_STICK_TO_BACK = (1 << 0),
WF_STICK_TO_FRONT = (1 << 1),
WF_2 = (1 << 2),
- WF_3 = (1 << 3),
+ WF_SCROLLING_TO_LOCATION = (1 << 3),
WF_TRANSPARENT = (1 << 4),
WF_5 = (1 << 5),
WF_RESIZABLE = (1 << 8),
@@ -457,6 +457,7 @@ void window_new_ride_init_vars();
void window_staff_init_vars();
void window_event_helper(rct_window* w, short widgetIndex, WINDOW_EVENTS event);
+void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct_widget* widget);
#ifdef _MSC_VER
#define window_get_register(w) \
diff --git a/src/window_new_ride.c b/src/window_new_ride.c
index 2d8eebdd10..1269f7d395 100644
--- a/src/window_new_ride.c
+++ b/src/window_new_ride.c
@@ -680,6 +680,7 @@ static void window_new_ride_scrollmouseover()
return;
item = window_new_ride_scroll_get_ride_list_item_at(w, x, y);
+
if (w->new_ride.highlighted_ride_id == *((sint16*)&item))
return;
diff --git a/src/window_peep.c b/src/window_peep.c
index f0bc914724..8c7ef1601a 100644
--- a/src/window_peep.c
+++ b/src/window_peep.c
@@ -521,10 +521,10 @@ void window_peep_viewport_init(rct_window* w){
void window_peep_overview_paint(){
rct_window *w;
rct_drawpixelinfo *dpi;
- rct_widget *labelWidget;
+ //rct_widget *labelWidget;
window_paint_get_registers(w, dpi);
- RCT2_CALLPROC_X(0x696887, 0, 0, 0, 0, w, dpi, 0);
+ RCT2_CALLPROC_X(0x696887, 0, 0, 0, 0, (int)w, (int)dpi, 0);
return;
window_draw_widgets(w, dpi);