diff --git a/src/openrct2-ui/windows/EditorInventionsList.cpp b/src/openrct2-ui/windows/EditorInventionsList.cpp index 3b55259403..fd20ce035b 100644 --- a/src/openrct2-ui/windows/EditorInventionsList.cpp +++ b/src/openrct2-ui/windows/EditorInventionsList.cpp @@ -66,40 +66,8 @@ static rct_widget _inventionListDragWidgets[] = { #pragma endregion -#pragma region Events - -static void WindowEditorInventionsListClose(rct_window *w); -static void WindowEditorInventionsListMouseup(rct_window *w, rct_widgetindex widgetIndex); -static void WindowEditorInventionsListResize(rct_window *w); -static void WindowEditorInventionsListUpdate(rct_window *w); -static void WindowEditorInventionsListScrollgetheight(rct_window *w, int32_t scrollIndex, int32_t *width, int32_t *height); -static void WindowEditorInventionsListScrollmousedown(rct_window *w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords); -static void WindowEditorInventionsListScrollmouseover(rct_window *w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords); -static void WindowEditorInventionsListCursor(rct_window *w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords, CursorID *cursorId); -static void WindowEditorInventionsListInvalidate(rct_window *w); -static void WindowEditorInventionsListPaint(rct_window *w, rct_drawpixelinfo *dpi); -static void WindowEditorInventionsListScrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int32_t scrollIndex); - static std::pair WindowEditorInventionsListPrepareName(const ResearchItem * researchItem, bool withGap); -// 0x0098177C -static rct_window_event_list window_editor_inventions_list_events([](auto& events) -{ - events.close = &WindowEditorInventionsListClose; - events.mouse_up = &WindowEditorInventionsListMouseup; - events.resize = &WindowEditorInventionsListResize; - events.update = &WindowEditorInventionsListUpdate; - events.get_scroll_size = &WindowEditorInventionsListScrollgetheight; - events.scroll_mousedown = &WindowEditorInventionsListScrollmousedown; - events.scroll_mouseover = &WindowEditorInventionsListScrollmouseover; - events.cursor = &WindowEditorInventionsListCursor; - events.invalidate = &WindowEditorInventionsListInvalidate; - events.paint = &WindowEditorInventionsListPaint; - events.scroll_paint = &WindowEditorInventionsListScrollpaint; -}); - -#pragma endregion - // clang-format on static void WindowEditorInventionsListDragOpen(ResearchItem* researchItem); @@ -161,109 +129,415 @@ static void MoveResearchItem(const ResearchItem& item, ResearchItem* beforeItem, researchList.push_back(item); } -/** - * - * rct2: 0x0068558E - */ -static ResearchItem* WindowEditorInventionsListGetItemFromScrollY(int32_t scrollIndex, int32_t y) -{ - auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented; - for (auto& researchItem : researchList) - { - y -= SCROLLABLE_ROW_HEIGHT; - if (y < 0) - { - return &researchItem; - } - } - - return nullptr; -} - -/** - * - * rct2: 0x006855BB - */ -static ResearchItem* WindowEditorInventionsListGetItemFromScrollYIncludeSeps(int32_t scrollIndex, int32_t y) -{ - auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented; - for (auto& researchItem : researchList) - { - y -= SCROLLABLE_ROW_HEIGHT; - if (y < 0) - { - return &researchItem; - } - } - return nullptr; -} - -static ResearchItem* GetResearchItemAt(const ScreenCoordsXY& screenCoords, int32_t* outScrollId) -{ - rct_window* w = window_find_by_class(WC_EDITOR_INVENTION_LIST); - if (w != nullptr && w->windowPos.x <= screenCoords.x && w->windowPos.y < screenCoords.y - && w->windowPos.x + w->width > screenCoords.x && w->windowPos.y + w->height > screenCoords.y) - { - rct_widgetindex widgetIndex = window_find_widget_from_point(w, screenCoords); - rct_widget* widget = &w->widgets[widgetIndex]; - if (widgetIndex == WIDX_PRE_RESEARCHED_SCROLL || widgetIndex == WIDX_RESEARCH_ORDER_SCROLL) - { - gPressedWidget.widget_index = widgetIndex; - int32_t outScrollArea; - ScreenCoordsXY outScrollCoords; - WidgetScrollGetPart(w, widget, screenCoords, outScrollCoords, &outScrollArea, outScrollId); - if (outScrollArea == SCROLL_PART_VIEW) - { - *outScrollId = *outScrollId == 0 ? 0 : 1; - - int32_t scrollY = outScrollCoords.y + 6; - return WindowEditorInventionsListGetItemFromScrollYIncludeSeps(*outScrollId, scrollY); - } - } - } - - *outScrollId = -1; - return nullptr; -} +#pragma region Invention List Window class InventionListWindow final : public Window { public: void OnOpen() override { + ResearchRidesSetup(); + + widgets = window_editor_inventions_list_widgets; + InitScrollWidgets(); + selected_tab = 0; + research_item = nullptr; + + min_width = WW; + min_height = WH; + max_width = WW * 2; + max_height = WH * 2; } + void OnClose() override { + research_remove_flags(); + + // When used in-game (as a cheat) + if (!(gScreenFlags & SCREEN_FLAGS_EDITOR)) + { + gSilentResearch = true; + research_reset_current_item(); + gSilentResearch = false; + } } + void OnMouseUp(rct_widgetindex widx) override { + switch (widx) + { + case WIDX_CLOSE: + Close(); + break; + case WIDX_RANDOM_SHUFFLE: + research_items_shuffle(); + Invalidate(); + break; + case WIDX_MOVE_ITEMS_TO_TOP: + research_items_make_all_researched(); + InitScrollWidgets(); + Invalidate(); + break; + case WIDX_MOVE_ITEMS_TO_BOTTOM: + research_items_make_all_unresearched(); + InitScrollWidgets(); + Invalidate(); + break; + } } + void OnResize() override { + if (width < min_width) + { + Invalidate(); + width = min_width; + } + if (height < min_height) + { + Invalidate(); + height = min_height; + } } + void OnUpdate() override { + frame_no++; + OnPrepareDraw(); + widget_invalidate(this, WIDX_TAB_1); + + if (WindowEditorInventionsListDragGetItem() != nullptr) + return; + + Invalidate(); } + ScreenSize OnScrollGetSize(int32_t scrollIndex) override { + ScreenSize size{}; + if (scrollIndex == 0) + { + size.height = static_cast(gResearchItemsInvented.size()) * SCROLLABLE_ROW_HEIGHT; + } + else + { + size.height = static_cast(gResearchItemsUninvented.size()) * SCROLLABLE_ROW_HEIGHT; + } + return size; } + void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override { + auto* researchItem = GetItemFromScrollY(scrollIndex, screenCoords.y); + if (researchItem != research_item) + { + research_item = researchItem; + Invalidate(); + + // Prevent always-researched items from being highlighted when hovered over + if (researchItem != nullptr && researchItem->IsAlwaysResearched()) + { + research_item = nullptr; + } + } } + void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override { + auto* researchItem = GetItemFromScrollY(scrollIndex, screenCoords.y); + if (researchItem == nullptr) + return; + + // Disallow picking up always-researched items + if (researchItem->IsAlwaysResearched()) + return; + + Invalidate(); + WindowEditorInventionsListDragOpen(researchItem); } + void OnScrollDraw(int32_t scrollIndex, rct_drawpixelinfo& dpi) override { + // Draw background + uint8_t paletteIndex = ColourMapA[colours[1]].mid_light; + gfx_clear(&dpi, paletteIndex); + + int16_t boxWidth = widgets[WIDX_RESEARCH_ORDER_SCROLL].width(); + int16_t columnSplitOffset = boxWidth / 2; + int32_t itemY = -SCROLLABLE_ROW_HEIGHT; + auto* dragItem = WindowEditorInventionsListDragGetItem(); + + const auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented; + for (const auto& researchItem : researchList) + { + itemY += SCROLLABLE_ROW_HEIGHT; + if (itemY + SCROLLABLE_ROW_HEIGHT < dpi.y || itemY >= dpi.y + dpi.height) + continue; + + if (research_item == &researchItem) + { + int32_t top, bottom; + if (dragItem == nullptr) + { + // Highlight + top = itemY; + bottom = itemY + SCROLLABLE_ROW_HEIGHT - 1; + } + else + { + // Drop horizontal rule + top = itemY - 1; + bottom = itemY; + } + + gfx_filter_rect(&dpi, { 0, top, boxWidth, bottom }, FilterPaletteID::PaletteDarken1); + } + + if (dragItem != nullptr && researchItem == *dragItem) + continue; + + // TODO: this parameter by itself produces very light text. + // It needs a {BLACK} token in the string to work properly. + colour_t colour = COLOUR_BLACK; + FontSpriteBase fontSpriteBase = FontSpriteBase::MEDIUM; + + if (researchItem.IsAlwaysResearched()) + { + if (research_item == &researchItem && dragItem == nullptr) + fontSpriteBase = FontSpriteBase::MEDIUM_EXTRA_DARK; + else + fontSpriteBase = FontSpriteBase::MEDIUM_DARK; + colour = colours[1] | COLOUR_FLAG_INSET; + } + + const rct_string_id itemNameId = researchItem.GetName(); + + if (researchItem.type == Research::EntryType::Ride + && !GetRideTypeDescriptor(researchItem.baseRideType).HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) + { + const auto rideEntry = get_ride_entry(researchItem.entryIndex); + const rct_string_id rideTypeName = get_ride_naming(researchItem.baseRideType, rideEntry).Name; + + // Draw group name + auto ft = Formatter(); + ft.Add(rideTypeName); + DrawTextEllipsised( + &dpi, { 1, itemY }, columnSplitOffset - 11, STR_INVENTIONS_LIST_RIDE_AND_VEHICLE_NAME, ft, + { colour, fontSpriteBase }); + + // Draw vehicle name + ft = Formatter(); + ft.Add(itemNameId); + DrawTextEllipsised( + &dpi, { columnSplitOffset + 1, itemY }, columnSplitOffset - 11, STR_BLACK_STRING, ft, + { colour, fontSpriteBase }); + } + else + { + // Scenery group, flat ride or shop + auto ft = Formatter(); + ft.Add(itemNameId); + DrawTextEllipsised(&dpi, { 1, itemY }, boxWidth, STR_BLACK_STRING, ft, { colour, fontSpriteBase }); + } + } } + CursorID OnCursor(rct_widgetindex widx, const ScreenCoordsXY& screenCoords, CursorID fallback) override { + int32_t scrollIndex = 0; + + switch (widx) + { + case WIDX_PRE_RESEARCHED_SCROLL: + scrollIndex = 0; + break; + case WIDX_RESEARCH_ORDER_SCROLL: + scrollIndex = 1; + break; + default: + return fallback; + } + + // Use the open hand as cursor for items that can be picked up + auto* researchItem = GetItemFromScrollY(scrollIndex, screenCoords.y); + if (researchItem != nullptr && !researchItem->IsAlwaysResearched()) + { + return CursorID::HandOpen; + } + return fallback; } + void OnDraw(rct_drawpixelinfo& dpi) override { + DrawWidgets(dpi); + + // Tab image + auto screenPos = windowPos + ScreenCoordsXY{ widgets[WIDX_TAB_1].left, widgets[WIDX_TAB_1].top }; + gfx_draw_sprite(&dpi, ImageId(SPR_TAB_FINANCES_RESEARCH_0 + (frame_no / 2) % 8), screenPos); + + // Pre-researched items label + screenPos = windowPos + + ScreenCoordsXY{ widgets[WIDX_PRE_RESEARCHED_SCROLL].left, widgets[WIDX_PRE_RESEARCHED_SCROLL].top - 11 }; + DrawTextBasic(&dpi, screenPos - ScreenCoordsXY{ 0, 1 }, STR_INVENTION_PREINVENTED_ITEMS); + + // Research order label + screenPos = windowPos + + ScreenCoordsXY{ widgets[WIDX_RESEARCH_ORDER_SCROLL].left, widgets[WIDX_RESEARCH_ORDER_SCROLL].top - 11 }; + DrawTextBasic(&dpi, screenPos - ScreenCoordsXY{ 0, 1 }, STR_INVENTION_TO_BE_INVENTED_ITEMS); + + // Preview background + auto& bkWidget = widgets[WIDX_PREVIEW]; + gfx_fill_rect( + &dpi, + { windowPos + ScreenCoordsXY{ bkWidget.left + 1, bkWidget.top + 1 }, + windowPos + ScreenCoordsXY{ bkWidget.right - 1, bkWidget.bottom - 1 } }, + ColourMapA[colours[1]].darkest); + + auto* researchItem = WindowEditorInventionsListDragGetItem(); + if (researchItem == nullptr || researchItem->IsNull()) + researchItem = research_item; + // If the research item is null or a list separator. + if (researchItem == nullptr || researchItem->IsNull()) + return; + + // Preview image + ObjectType objectEntryType = ObjectType::SceneryGroup; + if (researchItem->type == Research::EntryType::Ride) + objectEntryType = ObjectType::Ride; + + auto chunk = object_entry_get_chunk(objectEntryType, researchItem->entryIndex); + if (chunk == nullptr) + return; + + // Draw preview + const auto* object = object_entry_get_object(objectEntryType, researchItem->entryIndex); + if (object != nullptr) + { + rct_drawpixelinfo clipDPI; + screenPos = windowPos + ScreenCoordsXY{ bkWidget.left + 1, bkWidget.top + 1 }; + const auto clipWidth = bkWidget.width() - 1; + const auto clipHeight = bkWidget.height() - 1; + if (clip_drawpixelinfo(&clipDPI, &dpi, screenPos, clipWidth, clipHeight)) + { + object->DrawPreview(&clipDPI, clipWidth, height); + } + } + + // Item name + screenPos = windowPos + ScreenCoordsXY{ bkWidget.midX() + 1, bkWidget.bottom + 3 }; + const auto itemWidth = width - widgets[WIDX_RESEARCH_ORDER_SCROLL].right - 6; + + auto [drawString, ft] = WindowEditorInventionsListPrepareName(researchItem, false); + DrawTextEllipsised(&dpi, screenPos, itemWidth, drawString, ft, { TextAlignment::CENTRE }); + screenPos.y += 15; + + // Item category + screenPos.x = windowPos.x + widgets[WIDX_RESEARCH_ORDER_SCROLL].right + 4; + ft = Formatter(); + ft.Add(researchItem->GetCategoryInventionString()); + DrawTextBasic(&dpi, screenPos, STR_INVENTION_RESEARCH_GROUP, ft); } - void OnDrawWidget(rct_widgetindex widgetIndex, rct_drawpixelinfo& dpi) override + + void OnPrepareDraw() override { + pressed_widgets |= 1ULL << WIDX_PREVIEW; + pressed_widgets |= 1ULL << WIDX_TAB_1; + + widgets[WIDX_CLOSE].type = gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR ? WindowWidgetType::Empty + : WindowWidgetType::CloseBox; + + widgets[WIDX_BACKGROUND].right = width - 1; + widgets[WIDX_BACKGROUND].bottom = height - 1; + widgets[WIDX_TITLE].right = width - 2; + widgets[WIDX_CLOSE].left = width - 13; + widgets[WIDX_CLOSE].right = width - 3; + widgets[WIDX_RESIZE].right = width - 1; + widgets[WIDX_RESIZE].bottom = height - 1; + + int16_t scroll_list_height = (height - 88) / 2; + + widgets[WIDX_PRE_RESEARCHED_SCROLL].bottom = 60 + scroll_list_height; + widgets[WIDX_PRE_RESEARCHED_SCROLL].right = width - 229; + + widgets[WIDX_RESEARCH_ORDER_SCROLL].top = widgets[WIDX_PRE_RESEARCHED_SCROLL].bottom + 15; + widgets[WIDX_RESEARCH_ORDER_SCROLL].bottom = widgets[WIDX_RESEARCH_ORDER_SCROLL].top + scroll_list_height; + widgets[WIDX_RESEARCH_ORDER_SCROLL].right = width - 229; + + widgets[WIDX_PREVIEW].left = width - 169; + widgets[WIDX_PREVIEW].right = width - 56; + + widgets[WIDX_MOVE_ITEMS_TO_TOP].top = height - 57; + widgets[WIDX_MOVE_ITEMS_TO_TOP].bottom = height - 44; + widgets[WIDX_MOVE_ITEMS_TO_TOP].left = width - 225; + widgets[WIDX_MOVE_ITEMS_TO_TOP].right = width - 6; + + widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].top = height - 42; + widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].bottom = height - 29; + widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].left = width - 225; + widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].right = width - 6; + + widgets[WIDX_RANDOM_SHUFFLE].top = height - 27; + widgets[WIDX_RANDOM_SHUFFLE].bottom = height - 14; + widgets[WIDX_RANDOM_SHUFFLE].left = width - 225; + widgets[WIDX_RANDOM_SHUFFLE].right = width - 6; + } + + // Get Research Item and Scroll Id (scroll id represents invented(0)/not invented(1)/failure(-1) + std::pair GetResearchItemAt(const ScreenCoordsXY& screenCoords) + { + if (windowPos.x <= screenCoords.x && windowPos.y < screenCoords.y && windowPos.x + width > screenCoords.x + && windowPos.y + height > screenCoords.y) + { + rct_widgetindex widgetIndex = window_find_widget_from_point(this, screenCoords); + auto& widget = widgets[widgetIndex]; + if (widgetIndex == WIDX_PRE_RESEARCHED_SCROLL || widgetIndex == WIDX_RESEARCH_ORDER_SCROLL) + { + gPressedWidget.widget_index = widgetIndex; + int32_t outScrollArea{}; + ScreenCoordsXY outScrollCoords{}; + int32_t outScrollId{}; + WidgetScrollGetPart(this, &widget, screenCoords, outScrollCoords, &outScrollArea, &outScrollId); + if (outScrollArea == SCROLL_PART_VIEW) + { + outScrollId = outScrollId == 0 ? 0 : 1; + + int32_t scrollY = outScrollCoords.y + 6; + return std::make_pair(GetItemFromScrollYIncludeSeps(outScrollId, scrollY), outScrollId); + } + } + } + + return std::make_pair(nullptr, -1); + } + +private: + ResearchItem* GetItemFromScrollY(int32_t scrollIndex, int32_t y) const + { + auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented; + for (auto& researchItem : researchList) + { + y -= SCROLLABLE_ROW_HEIGHT; + if (y < 0) + { + return &researchItem; + } + } + + return nullptr; + } + + ResearchItem* GetItemFromScrollYIncludeSeps(int32_t scrollIndex, int32_t y) const + { + auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented; + for (auto& researchItem : researchList) + { + y -= SCROLLABLE_ROW_HEIGHT; + if (y < 0) + { + return &researchItem; + } + } + return nullptr; } }; @@ -273,411 +547,21 @@ public: */ rct_window* WindowEditorInventionsListOpen() { - rct_window* w; + return WindowFocusOrCreate( + WC_EDITOR_INVENTION_LIST, WW, WH, WF_NO_SCROLLING | WF_RESIZABLE | WF_CENTRE_SCREEN); +} - w = window_bring_to_front_by_class(WC_EDITOR_INVENTION_LIST); +static std::pair GetResearchItemAt(const ScreenCoordsXY& screenCoords) +{ + auto* w = static_cast(window_find_by_class(WC_EDITOR_INVENTION_LIST)); if (w != nullptr) - return w; - - ResearchRidesSetup(); - - w = WindowCreateCentred( - WW, WH, &window_editor_inventions_list_events, WC_EDITOR_INVENTION_LIST, WF_NO_SCROLLING | WF_RESIZABLE); - w->widgets = window_editor_inventions_list_widgets; - WindowInitScrollWidgets(w); - w->selected_tab = 0; - w->research_item = nullptr; - - w->min_width = WW; - w->min_height = WH; - w->max_width = WW * 2; - w->max_height = WH * 2; - - return w; -} - -/** - * - * rct2: 0x006853D2 - */ -static void WindowEditorInventionsListClose(rct_window* w) -{ - research_remove_flags(); - - // When used in-game (as a cheat) - if (!(gScreenFlags & SCREEN_FLAGS_EDITOR)) { - gSilentResearch = true; - research_reset_current_item(); - gSilentResearch = false; - } -} - -/** - * - * rct2: 0x0068521B - */ -static void WindowEditorInventionsListMouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_RANDOM_SHUFFLE: - research_items_shuffle(); - w->Invalidate(); - break; - case WIDX_MOVE_ITEMS_TO_TOP: - research_items_make_all_researched(); - WindowInitScrollWidgets(w); - w->Invalidate(); - break; - case WIDX_MOVE_ITEMS_TO_BOTTOM: - research_items_make_all_unresearched(); - WindowInitScrollWidgets(w); - w->Invalidate(); - break; - } -} - -static void WindowEditorInventionsListResize(rct_window* w) -{ - if (w->width < w->min_width) - { - w->Invalidate(); - w->width = w->min_width; - } - if (w->height < w->min_height) - { - w->Invalidate(); - w->height = w->min_height; - } -} - -/** - * - * rct2: 0x00685392 - */ -static void WindowEditorInventionsListUpdate(rct_window* w) -{ - w->frame_no++; - window_event_invalidate_call(w); - widget_invalidate(w, WIDX_TAB_1); - - if (WindowEditorInventionsListDragGetItem() != nullptr) - return; - - w->Invalidate(); -} - -/** - * - * rct2: 0x00685239 - */ -static void WindowEditorInventionsListScrollgetheight(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height) -{ - *height = 0; - if (scrollIndex == 0) - { - *height += static_cast(gResearchItemsInvented.size()) * SCROLLABLE_ROW_HEIGHT; - } - else - { - *height += static_cast(gResearchItemsUninvented.size()) * SCROLLABLE_ROW_HEIGHT; - } -} - -/** - * - * rct2: 0x006852D4 - */ -static void WindowEditorInventionsListScrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) -{ - ResearchItem* researchItem; - - researchItem = WindowEditorInventionsListGetItemFromScrollY(scrollIndex, screenCoords.y); - if (researchItem == nullptr) - return; - - // Disallow picking up always-researched items - if (researchItem->IsAlwaysResearched()) - return; - - w->Invalidate(); - WindowEditorInventionsListDragOpen(researchItem); -} - -/** - * - * rct2: 0x00685275 - */ -static void WindowEditorInventionsListScrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) -{ - ResearchItem* researchItem; - - researchItem = WindowEditorInventionsListGetItemFromScrollY(scrollIndex, screenCoords.y); - if (researchItem != w->research_item) - { - w->research_item = researchItem; - w->Invalidate(); - - // Prevent always-researched items from being highlighted when hovered over - if (researchItem != nullptr && researchItem->IsAlwaysResearched()) - { - w->research_item = nullptr; - } - } -} - -/** - * - * rct2: 0x00685291 - */ -static void WindowEditorInventionsListCursor( - rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords, CursorID* cursorId) -{ - ResearchItem* researchItem; - int32_t scrollIndex; - - switch (widgetIndex) - { - case WIDX_PRE_RESEARCHED_SCROLL: - scrollIndex = 0; - break; - case WIDX_RESEARCH_ORDER_SCROLL: - scrollIndex = 1; - break; - default: - return; + return w->GetResearchItemAt(screenCoords); } - // Use the open hand as cursor for items that can be picked up - researchItem = WindowEditorInventionsListGetItemFromScrollY(scrollIndex, screenCoords.y); - if (researchItem != nullptr && !researchItem->IsAlwaysResearched()) - { - *cursorId = CursorID::HandOpen; - } -} - -/** - * - * rct2: 0x00685392 - */ -static void WindowEditorInventionsListInvalidate(rct_window* w) -{ - w->pressed_widgets |= 1ULL << WIDX_PREVIEW; - w->pressed_widgets |= 1ULL << WIDX_TAB_1; - - w->widgets[WIDX_CLOSE].type = gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR ? WindowWidgetType::Empty - : WindowWidgetType::CloseBox; - - w->widgets[WIDX_BACKGROUND].right = w->width - 1; - w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; - w->widgets[WIDX_TITLE].right = w->width - 2; - w->widgets[WIDX_CLOSE].left = w->width - 13; - w->widgets[WIDX_CLOSE].right = w->width - 3; - w->widgets[WIDX_RESIZE].right = w->width - 1; - w->widgets[WIDX_RESIZE].bottom = w->height - 1; - - int16_t scroll_list_height = (w->height - 88) / 2; - - w->widgets[WIDX_PRE_RESEARCHED_SCROLL].bottom = 60 + scroll_list_height; - w->widgets[WIDX_PRE_RESEARCHED_SCROLL].right = w->width - 229; - - w->widgets[WIDX_RESEARCH_ORDER_SCROLL].top = w->widgets[WIDX_PRE_RESEARCHED_SCROLL].bottom + 15; - w->widgets[WIDX_RESEARCH_ORDER_SCROLL].bottom = w->widgets[WIDX_RESEARCH_ORDER_SCROLL].top + scroll_list_height; - w->widgets[WIDX_RESEARCH_ORDER_SCROLL].right = w->width - 229; - - w->widgets[WIDX_PREVIEW].left = w->width - 169; - w->widgets[WIDX_PREVIEW].right = w->width - 56; - - w->widgets[WIDX_MOVE_ITEMS_TO_TOP].top = w->height - 57; - w->widgets[WIDX_MOVE_ITEMS_TO_TOP].bottom = w->height - 44; - w->widgets[WIDX_MOVE_ITEMS_TO_TOP].left = w->width - 225; - w->widgets[WIDX_MOVE_ITEMS_TO_TOP].right = w->width - 6; - - w->widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].top = w->height - 42; - w->widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].bottom = w->height - 29; - w->widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].left = w->width - 225; - w->widgets[WIDX_MOVE_ITEMS_TO_BOTTOM].right = w->width - 6; - - w->widgets[WIDX_RANDOM_SHUFFLE].top = w->height - 27; - w->widgets[WIDX_RANDOM_SHUFFLE].bottom = w->height - 14; - w->widgets[WIDX_RANDOM_SHUFFLE].left = w->width - 225; - w->widgets[WIDX_RANDOM_SHUFFLE].right = w->width - 6; -} - -/** - * - * rct2: 0x00684EE0 - */ -static void WindowEditorInventionsListPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - rct_widget* widget; - const ResearchItem* researchItem; - int32_t width; - - WindowDrawWidgets(w, dpi); - - // Tab image - auto screenPos = w->windowPos + ScreenCoordsXY{ w->widgets[WIDX_TAB_1].left, w->widgets[WIDX_TAB_1].top }; - gfx_draw_sprite(dpi, ImageId(SPR_TAB_FINANCES_RESEARCH_0 + (w->frame_no / 2) % 8), screenPos); - - // Pre-researched items label - screenPos = w->windowPos - + ScreenCoordsXY{ w->widgets[WIDX_PRE_RESEARCHED_SCROLL].left, w->widgets[WIDX_PRE_RESEARCHED_SCROLL].top - 11 }; - DrawTextBasic(dpi, screenPos - ScreenCoordsXY{ 0, 1 }, STR_INVENTION_PREINVENTED_ITEMS); - - // Research order label - screenPos = w->windowPos - + ScreenCoordsXY{ w->widgets[WIDX_RESEARCH_ORDER_SCROLL].left, w->widgets[WIDX_RESEARCH_ORDER_SCROLL].top - 11 }; - DrawTextBasic(dpi, screenPos - ScreenCoordsXY{ 0, 1 }, STR_INVENTION_TO_BE_INVENTED_ITEMS); - - // Preview background - widget = &w->widgets[WIDX_PREVIEW]; - gfx_fill_rect( - dpi, - { w->windowPos + ScreenCoordsXY{ widget->left + 1, widget->top + 1 }, - w->windowPos + ScreenCoordsXY{ widget->right - 1, widget->bottom - 1 } }, - ColourMapA[w->colours[1]].darkest); - - researchItem = WindowEditorInventionsListDragGetItem(); - if (researchItem == nullptr || researchItem->IsNull()) - researchItem = w->research_item; - // If the research item is null or a list separator. - if (researchItem == nullptr || researchItem->IsNull()) - return; - - // Preview image - ObjectType objectEntryType = ObjectType::SceneryGroup; - if (researchItem->type == Research::EntryType::Ride) - objectEntryType = ObjectType::Ride; - - auto chunk = object_entry_get_chunk(objectEntryType, researchItem->entryIndex); - if (chunk == nullptr) - return; - - // Draw preview - widget = &w->widgets[WIDX_PREVIEW]; - - const auto* object = object_entry_get_object(objectEntryType, researchItem->entryIndex); - if (object != nullptr) - { - rct_drawpixelinfo clipDPI; - screenPos = w->windowPos + ScreenCoordsXY{ widget->left + 1, widget->top + 1 }; - width = widget->width() - 1; - int32_t height = widget->height() - 1; - if (clip_drawpixelinfo(&clipDPI, dpi, screenPos, width, height)) - { - object->DrawPreview(&clipDPI, width, height); - } - } - - // Item name - screenPos = w->windowPos + ScreenCoordsXY{ widget->midX() + 1, widget->bottom + 3 }; - width = w->width - w->widgets[WIDX_RESEARCH_ORDER_SCROLL].right - 6; - - auto [drawString, ft] = WindowEditorInventionsListPrepareName(researchItem, false); - DrawTextEllipsised(dpi, screenPos, width, drawString, ft, { TextAlignment::CENTRE }); - screenPos.y += 15; - - // Item category - screenPos.x = w->windowPos.x + w->widgets[WIDX_RESEARCH_ORDER_SCROLL].right + 4; - ft = Formatter(); - ft.Add(researchItem->GetCategoryInventionString()); - DrawTextBasic(dpi, screenPos, STR_INVENTION_RESEARCH_GROUP, ft); -} - -/** - * - * rct2: 0x006850BD - */ -static void WindowEditorInventionsListScrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex) -{ - // Draw background - uint8_t paletteIndex = ColourMapA[w->colours[1]].mid_light; - gfx_clear(dpi, paletteIndex); - - int16_t boxWidth = w->widgets[WIDX_RESEARCH_ORDER_SCROLL].width(); - int16_t columnSplitOffset = boxWidth / 2; - int32_t itemY = -SCROLLABLE_ROW_HEIGHT; - auto* dragItem = WindowEditorInventionsListDragGetItem(); - - const auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented; - for (const auto& researchItem : researchList) - { - itemY += SCROLLABLE_ROW_HEIGHT; - if (itemY + SCROLLABLE_ROW_HEIGHT < dpi->y || itemY >= dpi->y + dpi->height) - continue; - - if (w->research_item == &researchItem) - { - int32_t top, bottom; - if (dragItem == nullptr) - { - // Highlight - top = itemY; - bottom = itemY + SCROLLABLE_ROW_HEIGHT - 1; - } - else - { - // Drop horizontal rule - top = itemY - 1; - bottom = itemY; - } - - gfx_filter_rect(dpi, { 0, top, boxWidth, bottom }, FilterPaletteID::PaletteDarken1); - } - - if (dragItem != nullptr && researchItem == *dragItem) - continue; - - // TODO: this parameter by itself produces very light text. - // It needs a {BLACK} token in the string to work properly. - colour_t colour = COLOUR_BLACK; - FontSpriteBase fontSpriteBase = FontSpriteBase::MEDIUM; - - if (researchItem.IsAlwaysResearched()) - { - if (w->research_item == &researchItem && dragItem == nullptr) - fontSpriteBase = FontSpriteBase::MEDIUM_EXTRA_DARK; - else - fontSpriteBase = FontSpriteBase::MEDIUM_DARK; - colour = w->colours[1] | COLOUR_FLAG_INSET; - } - - const rct_string_id itemNameId = researchItem.GetName(); - - if (researchItem.type == Research::EntryType::Ride - && !GetRideTypeDescriptor(researchItem.baseRideType).HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) - { - const auto rideEntry = get_ride_entry(researchItem.entryIndex); - const rct_string_id rideTypeName = get_ride_naming(researchItem.baseRideType, rideEntry).Name; - - // Draw group name - auto ft = Formatter(); - ft.Add(rideTypeName); - DrawTextEllipsised( - dpi, { 1, itemY }, columnSplitOffset - 11, STR_INVENTIONS_LIST_RIDE_AND_VEHICLE_NAME, ft, - { colour, fontSpriteBase }); - - // Draw vehicle name - ft = Formatter(); - ft.Add(itemNameId); - DrawTextEllipsised( - dpi, { columnSplitOffset + 1, itemY }, columnSplitOffset - 11, STR_BLACK_STRING, ft, - { colour, fontSpriteBase }); - } - else - { - // Scenery group, flat ride or shop - auto ft = Formatter(); - ft.Add(itemNameId); - DrawTextEllipsised(dpi, { 1, itemY }, boxWidth, STR_BLACK_STRING, ft, { colour, fontSpriteBase }); - } - } + return std::make_pair(nullptr, -1); } +#pragma endregion #pragma region Drag item @@ -697,9 +581,8 @@ public: auto* inventionListWindow = window_find_by_class(WC_EDITOR_INVENTION_LIST); if (inventionListWindow != nullptr) { - int32_t scrollId; - ResearchItem* researchItem = GetResearchItemAt(screenCoords, &scrollId); - if (researchItem != inventionListWindow->research_item) + auto res = GetResearchItemAt(screenCoords); + if (res.first != inventionListWindow->research_item) { inventionListWindow->Invalidate(); } @@ -710,19 +593,18 @@ public: void OnMoved(const ScreenCoordsXY& screenCoords) override { - ResearchItem* researchItem = nullptr; - int32_t scrollId = -1; + std::pair res = std::make_pair(nullptr, -1); // Skip always researched items, so that the dragged item gets placed underneath them auto newScreenCoords = screenCoords; do { - researchItem = GetResearchItemAt(newScreenCoords, &scrollId); + res = GetResearchItemAt(newScreenCoords); newScreenCoords.y += LIST_ROW_HEIGHT; - } while (researchItem != nullptr && researchItem->IsAlwaysResearched()); + } while (res.first != nullptr && res.first->IsAlwaysResearched()); - if (scrollId != -1) + if (res.second != -1) { - MoveResearchItem(_draggedItem, researchItem, scrollId); + MoveResearchItem(_draggedItem, res.first, res.second); } window_invalidate_by_class(WC_EDITOR_INVENTION_LIST);