From 13b56f68d3f71b9e90cb67a05dda9cfd0985d88d Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sun, 9 Nov 2014 17:18:51 +0000 Subject: [PATCH] add window snapping --- src/config.c | 10 ++- src/config.h | 1 + src/input.c | 40 +++++----- src/interface/window.c | 165 +++++++++++++++++++++++++++++++++++++++++ src/interface/window.h | 3 + 5 files changed, 197 insertions(+), 22 deletions(-) diff --git a/src/config.c b/src/config.c index 7a80011547..de97f9544e 100644 --- a/src/config.c +++ b/src/config.c @@ -79,7 +79,7 @@ general_configuration_t gGeneral_config_default = { SCREENSHOT_FORMAT_PNG, // screenshot_format "", // game_path MEASUREMENT_FORMAT_IMPERIAL, // measurement_format - TEMPERATURE_FORMAT_F, // temperature_format + TEMPERATURE_FORMAT_C, // temperature_format CURRENCY_POUNDS, // currency_format 0, // construction_marker_colour 1, // edge_scrolling @@ -90,7 +90,8 @@ general_configuration_t gGeneral_config_default = { 0, // fullscreen mode (default: windowed) -1, // window_width -1, // window_height - LANGUAGE_ENGLISH_UK // language + LANGUAGE_ENGLISH_UK, // language + 5 // window_snap_proximity }; sound_configuration_t gSound_config; @@ -257,6 +258,8 @@ void config_write_ini_general(FILE *fp) fprintf(fp, "window_height = %d\n", gGeneral_config.window_height); fprintf(fp, "language = %d\n", gGeneral_config.language); + + fprintf(fp, "window_snap_proximity = %d\n", gGeneral_config.window_snap_proximity); } /** @@ -543,6 +546,9 @@ static void config_general(char *setting, char *value){ else if (strcmp(setting, "language") == 0) { gGeneral_config.language = atoi(value); } + else if (strcmp(setting, "window_snap_proximity") == 0) { + gGeneral_config.window_snap_proximity = clamp(0, atoi(value), 255); + } } /** diff --git a/src/config.h b/src/config.h index 08dcd03b95..0fff44272e 100644 --- a/src/config.h +++ b/src/config.h @@ -133,6 +133,7 @@ typedef struct general_configuration { sint16 window_width; sint16 window_height; uint16 language; + uint8 window_snap_proximity; } general_configuration_t; static const struct { const char *key; int value; } _currencyLookupTable[] = { diff --git a/src/input.c b/src/input.c index 3f430c24b4..c88cb958dc 100644 --- a/src/input.c +++ b/src/input.c @@ -67,6 +67,7 @@ void game_handle_key_scroll(); static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex); void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_window* w, rct_widget* widget); void sub_6ED990(char cursor_id); +static void input_window_drag(rct_window *w, int lastX, int lastY, int newX, int newY); #pragma region Mouse input @@ -249,29 +250,23 @@ static void game_handle_input_mouse(int x, int y, int state) 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) { + input_window_drag( + w, + RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16), + x, + y + ); + + // RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, sint16) = x; + // RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, sint16) = y; + + 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); } @@ -488,6 +483,11 @@ static void game_handle_input_mouse(int x, int y, int state) } } +static void input_window_drag(rct_window *w, int wdx, int wdy, int x, int y) +{ + window_move_and_snap(w, x - wdx, y - wdy, gGeneral_config.window_snap_proximity); +} + /** * * rct2: 0x006ED833 @@ -696,8 +696,8 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex) 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_LAST_X, uint16) = x - w->x; + RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y - w->y; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber; break; diff --git a/src/interface/window.c b/src/interface/window.c index 6fcfe9fbb0..adc022434e 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -1414,6 +1414,11 @@ void window_draw_viewport(rct_drawpixelinfo *dpi, rct_window *w) viewport_render(dpi, w->viewport, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height); } +void window_set_position(rct_window *w, int x, int y) +{ + window_move_position(w, x - w->x, y - w->y); +} + void window_move_position(rct_window *w, int dx, int dy) { if (dx == 0 && dy == 0) @@ -1827,4 +1832,164 @@ void window_update_viewport_ride_music() } break; } +} + +void window_snap_left(rct_window *w, int proximity) +{ + int right, rightMost, wLeftProximity, wRightProximity, wBottom; + rct_window *mainWindow, *w2; + + mainWindow = window_get_main(); + + wBottom = w->y + w->height; + wLeftProximity = w->x - (proximity * 2); + wRightProximity = w->x + (proximity * 2); + rightMost = MININT32; + for (w2 = g_window_list; w2 < RCT2_NEW_WINDOW; w2++) { + if (w2 == w || w2 == mainWindow) + continue; + + right = w2->x + w2->width; + + if (wBottom < w2->y || w->y > w2->y + w2->height) + continue; + + if (right < wLeftProximity || right > wRightProximity) + continue; + + rightMost = max(rightMost, right); + } + + if (0 >= wLeftProximity && 0 <= wRightProximity) + rightMost = max(rightMost, 0); + + if (rightMost != MININT32) + w->x = rightMost; +} + +void window_snap_top(rct_window *w, int proximity) +{ + int bottom, bottomMost, wTopProximity, wBottomProximity, wRight; + rct_window *mainWindow, *w2; + + mainWindow = window_get_main(); + + wRight = w->x + w->width; + wTopProximity = w->y - (proximity * 2); + wBottomProximity = w->y + (proximity * 2); + bottomMost = MININT32; + for (w2 = g_window_list; w2 < RCT2_NEW_WINDOW; w2++) { + if (w2 == w || w2 == mainWindow) + continue; + + bottom = w2->y + w2->height; + + if (wRight < w2->x || w->x > w2->x + w2->width) + continue; + + if (bottom < wTopProximity || bottom > wBottomProximity) + continue; + + bottomMost = max(bottomMost, bottom); + } + + if (0 >= wTopProximity && 0 <= wBottomProximity) + bottomMost = max(bottomMost, 0); + + if (bottomMost != MININT32) + w->y = bottomMost; +} + +void window_snap_right(rct_window *w, int proximity) +{ + int leftMost, wLeftProximity, wRightProximity, wRight, wBottom, screenWidth; + rct_window *mainWindow, *w2; + + mainWindow = window_get_main(); + + wRight = w->x + w->width; + wBottom = w->y + w->height; + wLeftProximity = wRight - (proximity * 2); + wRightProximity = wRight + (proximity * 2); + leftMost = MAXINT32; + for (w2 = g_window_list; w2 < RCT2_NEW_WINDOW; w2++) { + if (w2 == w || w2 == mainWindow) + continue; + + if (wBottom < w2->y || w->y > w2->y + w2->height) + continue; + + if (w2->x < wLeftProximity || w2->x > wRightProximity) + continue; + + leftMost = min(leftMost, w2->x); + } + + screenWidth = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16); + if (screenWidth >= wLeftProximity && screenWidth <= wRightProximity) + leftMost = min(leftMost, screenWidth); + + if (leftMost != MAXINT32) + w->x = leftMost - w->width; +} + +void window_snap_bottom(rct_window *w, int proximity) +{ + int topMost, wTopProximity, wBottomProximity, wRight, wBottom, screenHeight; + rct_window *mainWindow, *w2; + + mainWindow = window_get_main(); + + wRight = w->x + w->width; + wBottom = w->y + w->height; + wTopProximity = wBottom - (proximity * 2); + wBottomProximity = wBottom + (proximity * 2); + topMost = MAXINT32; + for (w2 = g_window_list; w2 < RCT2_NEW_WINDOW; w2++) { + if (w2 == w || w2 == mainWindow) + continue; + + if (wRight < w2->x || w->x > w2->x + w2->width) + continue; + + if (w2->y < wTopProximity || w2->y > wBottomProximity) + continue; + + topMost = min(topMost, w2->y); + } + + screenHeight = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16); + if (screenHeight >= wTopProximity && screenHeight <= wBottomProximity) + topMost = min(topMost, screenHeight); + + if (topMost != MAXINT32) + w->y = topMost - w->height; +} + +void window_move_and_snap(rct_window *w, int newWindowX, int newWindowY, int snapProximity) +{ + int originalX = w->x; + int originalY = w->y; + + newWindowY = clamp(29, newWindowY, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 34); + + if (snapProximity > 0) { + w->x = newWindowX; + w->y = newWindowY; + + window_snap_right(w, snapProximity); + window_snap_bottom(w, snapProximity); + window_snap_left(w, snapProximity); + window_snap_top(w, snapProximity); + + if (w->x == originalX && w->y == originalY) + return; + + newWindowX = w->x; + newWindowY = w->y; + w->x = originalX; + w->y = originalY; + } + + window_set_position(w, newWindowX, newWindowY); } \ No newline at end of file diff --git a/src/interface/window.h b/src/interface/window.h index 69f89bebed..46dac21396 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -455,6 +455,7 @@ void window_draw(rct_window *w, int left, int top, int right, int bottom); void window_draw_widgets(rct_window *w, rct_drawpixelinfo *dpi); void window_draw_viewport(rct_drawpixelinfo *dpi, rct_window *w); +void window_set_position(rct_window *w, int x, int y); void window_move_position(rct_window *w, int dx, int dy); void window_resize(rct_window *w, int dw, int dh); void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth, int maxHeight); @@ -538,6 +539,8 @@ void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct void sub_6EA73F(); +void window_move_and_snap(rct_window *w, int newWindowX, int newWindowY, int snapProximity); + #ifdef _MSC_VER #define window_get_register(w) \ __asm mov w, esi