diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 001a33a377..9c89f17604 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -3315,7 +3315,7 @@ static void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) { dropdown_set_checked(11, true); if (mainViewport->flags & VIEWPORT_FLAG_PATH_HEIGHTS) dropdown_set_checked(12, true); - if (mainViewport->flags & VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT) + if (mainViewport->flags & VIEWPORT_FLAG_CLIP_VIEW) dropdown_set_checked(DDIDX_VIEW_CLIPPING, true); if (mainViewport->flags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) dropdown_set_checked(DDIDX_HIGHLIGHT_PATH_ISSUES, true); @@ -3370,7 +3370,7 @@ static void top_toolbar_view_menu_dropdown(sint16 dropdownIndex) context_open_window(WC_VIEW_CLIPPING); } else { // If window is already open, toggle the view clipping on/off - w->viewport->flags ^= VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT; + w->viewport->flags ^= VIEWPORT_FLAG_CLIP_VIEW; } break; case DDIDX_HIGHLIGHT_PATH_ISSUES: diff --git a/src/openrct2-ui/windows/ViewClipping.cpp b/src/openrct2-ui/windows/ViewClipping.cpp index 7b894a21c2..a1e4eaa3f9 100644 --- a/src/openrct2-ui/windows/ViewClipping.cpp +++ b/src/openrct2-ui/windows/ViewClipping.cpp @@ -15,14 +15,15 @@ #pragma endregion #include - -#include -#include - -#include #include +#include +#include +#include +#include +#include #include #include +#include enum WINDOW_VIEW_CLIPPING_WIDGET_IDX { WIDX_BACKGROUND, @@ -32,7 +33,8 @@ enum WINDOW_VIEW_CLIPPING_WIDGET_IDX { WIDX_CLIP_HEIGHT_VALUE, WIDX_CLIP_HEIGHT_INCREASE, WIDX_CLIP_HEIGHT_DECREASE, - WIDX_CLIP_HEIGHT_SLIDER + WIDX_CLIP_HEIGHT_SLIDER, + WIDX_CLIP_SELECTOR, }; enum class DISPLAY_TYPE { @@ -56,16 +58,26 @@ static rct_widget window_view_clipping_widgets[] = { { WWT_BUTTON, 0, 138, 148, 35, 39, STR_NUMERIC_UP, STR_NONE }, // clip height increase { WWT_BUTTON, 0, 138, 148, 40, 44, STR_NUMERIC_DOWN, STR_NONE }, // clip height decrease { WWT_SCROLL, 0, 11, 149, 49, 61, SCROLL_HORIZONTAL, STR_VIEW_CLIPPING_HEIGHT_SCROLL_TIP }, // clip height scrollbar + { WWT_BUTTON, 0, 11, 149, 61, 73, STR_NONE, STR_NONE }, // selector { WIDGETS_END } }; #pragma endregion +#pragma region Members + +static LocationXY16 _selectionStart; + +#pragma endregion + #pragma region Events static void window_view_clipping_close_button(rct_window *w); static void window_view_clipping_mouseup(rct_window *w, rct_widgetindex widgetIndex); static void window_view_clipping_update(rct_window *w); +static void window_view_clipping_tool_down(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); +static void window_view_clipping_tool_drag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); +static void window_view_clipping_tool_up(struct rct_window*, rct_widgetindex, sint32, sint32); static void window_view_clipping_invalidate(rct_window *w); static void window_view_clipping_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_view_clipping_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); @@ -82,9 +94,9 @@ static rct_window_event_list window_view_clipping_events = { nullptr, nullptr, nullptr, - nullptr, - nullptr, - nullptr, + window_view_clipping_tool_down, + window_view_clipping_tool_drag, + window_view_clipping_tool_up, nullptr, nullptr, window_view_clipping_scrollgetsize, @@ -133,7 +145,8 @@ rct_window * window_view_clipping_open() (1ULL << WIDX_CLIP_HEIGHT_VALUE) | (1ULL << WIDX_CLIP_HEIGHT_INCREASE) | (1ULL << WIDX_CLIP_HEIGHT_DECREASE) | - (1ULL << WIDX_CLIP_HEIGHT_SLIDER); + (1ULL << WIDX_CLIP_HEIGHT_SLIDER) | + (1ULL << WIDX_CLIP_SELECTOR); window_init_scroll_widgets(window); @@ -144,7 +157,7 @@ rct_window * window_view_clipping_open() // Turn on view clipping when the window is opened. if (mainWindow != nullptr) { - mainWindow->viewport->flags |= VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT; + mainWindow->viewport->flags |= VIEWPORT_FLAG_CLIP_VIEW; window_invalidate(mainWindow); } @@ -156,7 +169,7 @@ static void window_view_clipping_close() // Turn off view clipping when the window is closed. rct_window *mainWindow = window_get_main(); if (mainWindow != nullptr) { - mainWindow->viewport->flags &= ~VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT; + mainWindow->viewport->flags &= ~VIEWPORT_FLAG_CLIP_VIEW; window_invalidate(mainWindow); } @@ -180,7 +193,7 @@ static void window_view_clipping_mouseup(rct_window *w, rct_widgetindex widgetIn // Toggle height clipping. mainWindow = window_get_main(); if (mainWindow != nullptr) { - mainWindow->viewport->flags ^= VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT; + mainWindow->viewport->flags ^= VIEWPORT_FLAG_CLIP_VIEW; window_invalidate(mainWindow); } window_invalidate(w); @@ -211,9 +224,30 @@ static void window_view_clipping_mouseup(rct_window *w, rct_widgetindex widgetIn } window_invalidate(w); break; + case WIDX_CLIP_SELECTOR: + // Activate the selection tool + tool_set(w, WIDX_BACKGROUND, TOOL_CROSSHAIR); + + // Reset clip selection to show all tiles + gClipXMin = 0; + gClipXMax = MAXIMUM_MAP_SIZE_TECHNICAL - 1; + gClipYMin = 0; + gClipYMax = MAXIMUM_MAP_SIZE_TECHNICAL - 1; + gfx_invalidate_screen(); + break; } } +// Returns true when the tool is active +static bool window_view_clipping_tool_is_active() +{ + if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE))) + return false; + if (gCurrentToolWidget.window_classification != WC_VIEW_CLIPPING) + return false; + return true; +} + static void window_view_clipping_update(rct_window *w) { const rct_widget *const widget = &window_view_clipping_widgets[WIDX_CLIP_HEIGHT_SLIDER]; @@ -229,16 +263,63 @@ static void window_view_clipping_update(rct_window *w) window_invalidate(mainWindow); } } + + if (window_view_clipping_tool_is_active()) + { + // TODO: Deactivate selection tool and restore previous selection + } + widget_invalidate(w, WIDX_CLIP_HEIGHT_SLIDER); } +static void window_view_clipping_tool_down(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y) +{ + sint16 mapX = x; + sint16 mapY = y; + sint32 direction; + screen_pos_to_map_pos(&mapX, &mapY, &direction); + if (mapX != LOCATION_NULL) + { + _selectionStart = { mapX, mapY }; + } +} + +static void window_view_clipping_tool_drag(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y) +{ + sint16 mapX = x; + sint16 mapY = y; + sint32 direction; + screen_pos_to_map_pos(&mapX, &mapY, &direction); + if (mapX != LOCATION_NULL) + { + map_invalidate_selection_rect(); + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; + gMapSelectPositionA.x = std::min(_selectionStart.x, mapX); + gMapSelectPositionB.x = std::max(_selectionStart.x, mapX); + gMapSelectPositionA.y = std::min(_selectionStart.y, mapY); + gMapSelectPositionB.y = std::max(_selectionStart.y, mapY); + gMapSelectType = MAP_SELECT_TYPE_FULL; + map_invalidate_selection_rect(); + } +} + +static void window_view_clipping_tool_up(struct rct_window*, rct_widgetindex, sint32, sint32) +{ + gClipXMin = gMapSelectPositionA.x / 32; + gClipXMax = gMapSelectPositionB.x / 32; + gClipYMin = gMapSelectPositionA.y / 32; + gClipYMax = gMapSelectPositionB.y / 32; + tool_cancel(); + gfx_invalidate_screen(); +} + static void window_view_clipping_invalidate(rct_window *w) { widget_scroll_update_thumbs(w, WIDX_CLIP_HEIGHT_SLIDER); rct_window *mainWindow = window_get_main(); if (mainWindow != nullptr) { - widget_set_checkbox_value(w, WIDX_CLIP_HEIGHT_CHECKBOX, mainWindow->viewport->flags & VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT); + widget_set_checkbox_value(w, WIDX_CLIP_HEIGHT_CHECKBOX, mainWindow->viewport->flags & VIEWPORT_FLAG_CLIP_VIEW); } } diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index a2ba20736e..44888ce7e5 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -879,7 +879,7 @@ static void viewport_paint_column(rct_drawpixelinfo * dpi, uint32 viewFlags) { gCurrentViewportFlags = viewFlags; - if (viewFlags & (VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT)) { + if (viewFlags & (VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_CLIP_VIEW)) { uint8 colour = 10; if (viewFlags & VIEWPORT_FLAG_INVISIBLE_SPRITES) { colour = 0; diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index 167c00f134..3a3958c322 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -48,7 +48,7 @@ enum { VIEWPORT_FLAG_INVISIBLE_SPRITES = (1 << 14), VIEWPORT_FLAG_15 = (1 << 15), VIEWPORT_FLAG_SEETHROUGH_PATHS = (1 << 16), - VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT = (1 << 17), + VIEWPORT_FLAG_CLIP_VIEW = (1 << 17), VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES = (1 << 18), }; diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 3315053eff..74a5451a72 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -24,8 +24,12 @@ #include "sprite/Sprite.h" #include "tile_element/TileElement.h" -// Global for paint clipping height +// Globals for paint clipping uint8 gClipHeight = 128; // Default to middle value +uint8 gClipXMin = 0; +uint8 gClipXMax = MAXIMUM_MAP_SIZE_TECHNICAL - 1; +uint8 gClipYMin = 0; +uint8 gClipYMax = MAXIMUM_MAP_SIZE_TECHNICAL - 1; paint_session gPaintSession; static bool _paintSessionInUse; @@ -1208,4 +1212,4 @@ void paint_draw_money_structs(rct_drawpixelinfo * dpi, paint_string_struct * ps) gfx_draw_string_with_y_offsets(&dpi2, buffer, COLOUR_BLACK, ps->x, ps->y, (sint8 *)ps->y_offsets, forceSpriteFont); } while ((ps = ps->next) != nullptr); -} \ No newline at end of file +} diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index a2ad8bda69..d6a65d9b38 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -170,8 +170,12 @@ struct paint_session extern paint_session gPaintSession; -// Global for paint clipping height. +// Globals for paint clipping extern uint8 gClipHeight; +extern uint8 gClipXMin; +extern uint8 gClipXMax; +extern uint8 gClipYMin; +extern uint8 gClipYMax; /** rct2: 0x00993CC4. The white ghost that indicates not-yet-built elements. */ #define CONSTRUCTION_MARKER (COLOUR_DARK_GREEN << 19 | COLOUR_GREY << 24 | IMAGE_TYPE_REMAP); diff --git a/src/openrct2/paint/sprite/Sprite.cpp b/src/openrct2/paint/sprite/Sprite.cpp index 6cfb4d73fb..1c41fd86ce 100644 --- a/src/openrct2/paint/sprite/Sprite.cpp +++ b/src/openrct2/paint/sprite/Sprite.cpp @@ -69,11 +69,19 @@ void sprite_paint_setup(paint_session * session, const uint16 eax, const uint16 } } - // Only paint sprites that are below the clip height. + // Only paint sprites that are below the clip height and inside the clip selection. // Here converting from land/path/etc height scale to pixel height scale. // Note: peeps/scenery on slopes will be above the base // height of the slope element, and consequently clipped. - if ((gCurrentViewportFlags & VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT) && (spr->unknown.z > (gClipHeight * 8) )) continue; + if ((gCurrentViewportFlags & VIEWPORT_FLAG_CLIP_VIEW)) + { + if (spr->unknown.z > (gClipHeight * 8)) + continue; + if (spr->unknown.x / 32 < gClipXMin || spr->unknown.x / 32 > gClipXMax) + continue; + if (spr->unknown.y / 32 < gClipYMin || spr->unknown.y / 32 > gClipYMax) + continue; + } dpi = session->Unk140E9A8; diff --git a/src/openrct2/paint/tile_element/TileElement.cpp b/src/openrct2/paint/tile_element/TileElement.cpp index 0bc3ecee19..71a326bf1f 100644 --- a/src/openrct2/paint/tile_element/TileElement.cpp +++ b/src/openrct2/paint/tile_element/TileElement.cpp @@ -144,6 +144,14 @@ static void sub_68B3FB(paint_session * session, sint32 x, sint32 y) { rct_drawpixelinfo *dpi = session->Unk140E9A8; + if ((gCurrentViewportFlags & VIEWPORT_FLAG_CLIP_VIEW)) + { + if (x / 32 < gClipXMin || x / 32 > gClipXMax) + return; + if (y / 32 < gClipYMin || y / 32 > gClipYMax) + return; + } + session->LeftTunnelCount = 0; session->RightTunnelCount = 0; session->LeftTunnels[0] = {0xFF, 0xFF}; @@ -247,7 +255,7 @@ static void sub_68B3FB(paint_session * session, sint32 x, sint32 y) sint32 previousHeight = 0; do { // Only paint tile_elements below the clip height. - if ((gCurrentViewportFlags & VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT) && (tile_element->base_height > gClipHeight)) + if ((gCurrentViewportFlags & VIEWPORT_FLAG_CLIP_VIEW) && (tile_element->base_height > gClipHeight)) continue; sint32 direction = tile_element_get_direction_with_offset(tile_element, rotation); @@ -362,7 +370,7 @@ static void sub_68B3FB(paint_session * session, sint32 x, sint32 y) } // Only draw supports below the clipping height. - if ((gCurrentViewportFlags & VIEWPORT_FLAG_PAINT_CLIP_TO_HEIGHT) && (segmentHeight > gClipHeight)) continue; + if ((gCurrentViewportFlags & VIEWPORT_FLAG_CLIP_VIEW) && (segmentHeight > gClipHeight)) continue; sint32 xOffset = sy * 10; sint32 yOffset = -22 + sx * 10;