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);