diff --git a/src/openrct2-ui/input/MouseInput.cpp b/src/openrct2-ui/input/MouseInput.cpp index dc139be5b1..83c13be951 100644 --- a/src/openrct2-ui/input/MouseInput.cpp +++ b/src/openrct2-ui/input/MouseInput.cpp @@ -1067,6 +1067,7 @@ static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, W case WindowWidgetType::LabelCentred: case WindowWidgetType::Label: case WindowWidgetType::Groupbox: + case WindowWidgetType::ProgressBar: case WindowWidgetType::Placeholder: case WindowWidgetType::Last: // Non-interactive widget type diff --git a/src/openrct2-ui/interface/Widget.cpp b/src/openrct2-ui/interface/Widget.cpp index ab24c843ac..f66b2e629a 100644 --- a/src/openrct2-ui/interface/Widget.cpp +++ b/src/openrct2-ui/interface/Widget.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,7 @@ static void WidgetTextCentred(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex wid static void WidgetText(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); static void WidgetTextInset(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); static void WidgetTextBoxDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); +static void WidgetProgressBarDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); static void WidgetGroupboxDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); static void WidgetCaptionDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); static void WidgetCheckboxDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex); @@ -108,6 +110,9 @@ void WidgetDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex) case WindowWidgetType::TextBox: WidgetTextBoxDraw(dpi, w, widgetIndex); break; + case WindowWidgetType::ProgressBar: + WidgetProgressBarDraw(dpi, w, widgetIndex); + break; default: break; } @@ -1189,6 +1194,37 @@ static void WidgetTextBoxDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex wid } } +static void WidgetProgressBarDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex widgetIndex) +{ + const auto& widget = w.widgets[widgetIndex]; + + ScreenCoordsXY topLeft{ w.windowPos + ScreenCoordsXY{ widget.left, widget.top } }; + ScreenCoordsXY bottomRight{ w.windowPos + ScreenCoordsXY{ widget.right, widget.bottom } }; + + auto percentage = widget.content & 0xFF; + auto lowerBlinkBounds = (widget.content >> 8) & 0xFF; + auto upperBlinkBounds = (widget.content >> 16) & 0xFF; + + auto isBlinking = (lowerBlinkBounds != upperBlinkBounds) && (percentage >= lowerBlinkBounds) + && (percentage <= upperBlinkBounds); + + GfxFillRectInset(dpi, { topLeft, bottomRight }, w.colours[1], INSET_RECT_F_30); + if (isBlinking) + { + if (GameIsNotPaused() && (gCurrentRealTimeTicks & 8)) + return; + } + + const auto barWidth = widget.width() - 2; + const int32_t fillSize = (barWidth * percentage) / 100; + if (fillSize > 0) + { + GfxFillRectInset( + dpi, { topLeft + ScreenCoordsXY{ 1, 1 }, topLeft + ScreenCoordsXY{ fillSize + 1, widget.height() - 1 } }, + widget.colour, 0); + } +} + ImageId GetColourButtonImage(colour_t colour) { if (colour == COLOUR_INVISIBLE) @@ -1200,3 +1236,9 @@ ImageId GetColourButtonImage(colour_t colour) return ImageId(SPR_PALETTE_BTN, colour).WithBlended(true); } } + +void WidgetProgressBarSetNewPercentage(Widget& widget, uint8_t newPercentage) +{ + widget.content &= ~0xFF; + widget.content |= newPercentage; +} diff --git a/src/openrct2-ui/interface/Widget.h b/src/openrct2-ui/interface/Widget.h index 5b8a3fe2ac..dafa430e49 100644 --- a/src/openrct2-ui/interface/Widget.h +++ b/src/openrct2-ui/interface/Widget.h @@ -85,6 +85,23 @@ constexpr Widget MakeTab(const ScreenCoordsXY& origin, StringId tooltip = STR_NO return MakeWidget(origin, size, type, colour, content, tooltip); } +constexpr Widget MakeProgressBar( + const ScreenCoordsXY& origin, const ScreenSize& size, colour_t colour, uint8_t lowerBlinkBound = 0, + uint8_t upperBlinkBound = 0) +{ + Widget out = {}; + out.left = origin.x; + out.right = origin.x + size.width - 1; + out.top = origin.y; + out.bottom = origin.y + size.height - 1; + out.type = WindowWidgetType::ProgressBar; + out.colour = colour; + out.content = 0 | (lowerBlinkBound << 8) | (upperBlinkBound << 16); + out.tooltip = STR_NONE; + + return out; +} + // NOLINTBEGIN #define MakeSpinnerWidgets(...) \ MakeWidget(__VA_ARGS__), MakeSpinnerIncreaseWidget(__VA_ARGS__), MakeSpinnerDecreaseWidget(__VA_ARGS__) @@ -154,3 +171,5 @@ void WidgetSetHoldable(WindowBase& w, WidgetIndex widgetIndex, bool value); void WidgetSetVisible(WindowBase& w, WidgetIndex widgetIndex, bool value); void WidgetSetPressed(WindowBase& w, WidgetIndex widgetIndex, bool value); void WidgetSetCheckboxValue(WindowBase& w, WidgetIndex widgetIndex, bool value); + +void WidgetProgressBarSetNewPercentage(Widget& widget, uint8_t newPercentage); diff --git a/src/openrct2-ui/scripting/ScWidget.hpp b/src/openrct2-ui/scripting/ScWidget.hpp index 5ffa194999..a7082df10e 100644 --- a/src/openrct2-ui/scripting/ScWidget.hpp +++ b/src/openrct2-ui/scripting/ScWidget.hpp @@ -112,6 +112,8 @@ namespace OpenRCT2::Scripting return "empty"; case WindowWidgetType::Placeholder: return "placeholder"; + case WindowWidgetType::ProgressBar: + return "progress_bar"; case WindowWidgetType::Custom: return "custom"; case WindowWidgetType::Last: diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index 66fd20e284..d1cc1937c0 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -70,7 +70,9 @@ namespace OpenRCT2::Ui::Windows WIDX_TAB_6, WIDX_TAB_7, - WIDX_MARQUEE = 11, + WIDX_TAB_CONTENT_START, + + WIDX_MARQUEE = WIDX_TAB_CONTENT_START, WIDX_VIEWPORT, WIDX_ACTION_LBL, WIDX_PICKUP, @@ -78,7 +80,14 @@ namespace OpenRCT2::Ui::Windows WIDX_LOCATE, WIDX_TRACK, - WIDX_RIDE_SCROLL = 11 + WIDX_HAPPINESS_BAR = WIDX_TAB_CONTENT_START, + WIDX_ENERGY_BAR, + WIDX_HUNGER_BAR, + WIDX_THIRST_BAR, + WIDX_NAUSEA_BAR, + WIDX_TOILET_BAR, + + WIDX_RIDE_SCROLL = WIDX_TAB_CONTENT_START, }; validate_global_widx(WC_PEEP, WIDX_PICKUP); @@ -112,6 +121,12 @@ static Widget _guestWindowWidgetsOverview[] = { static Widget _guestWindowWidgetsStats[] = { MAIN_GUEST_WIDGETS, + MakeProgressBar({ 65, (kListRowHeight * 0) + 4 + 43 }, { 119, 10 }, COLOUR_BRIGHT_GREEN, 0, 19), // Happiness + MakeProgressBar({ 65, (kListRowHeight * 1) + 4 + 43 }, { 119, 10 }, COLOUR_BRIGHT_GREEN, 0, 19), // Energy + MakeProgressBar({ 65, (kListRowHeight * 2) + 4 + 43 }, { 119, 10 }, COLOUR_BRIGHT_RED, 67, 100), // Hunger + MakeProgressBar({ 65, (kListRowHeight * 3) + 4 + 43 }, { 119, 10 }, COLOUR_BRIGHT_RED, 67, 100), // Thirst + MakeProgressBar({ 65, (kListRowHeight * 4) + 4 + 43 }, { 119, 10 }, COLOUR_BRIGHT_RED, 47, 100), // Nausea + MakeProgressBar({ 65, (kListRowHeight * 5) + 4 + 43 }, { 119, 10 }, COLOUR_BRIGHT_RED, 62, 100), // Toilet kWidgetsEnd, }; @@ -1036,38 +1051,14 @@ static_assert(_guestWindowPageWidgets.size() == WINDOW_GUEST_PAGE_COUNT); Invalidate(); } - void StatsBarsDraw(int32_t value, const ScreenCoordsXY& origCoords, DrawPixelInfo& dpi, int32_t colour, bool blinkFlag) - { - auto coords = origCoords; - if (FontGetLineHeight(FontStyle::Medium) > 10) - { - coords.y += 1; - } - - GfxFillRectInset( - dpi, { coords + ScreenCoordsXY{ 61, 1 }, coords + ScreenCoordsXY{ 61 + 121, 9 } }, colours[1], INSET_RECT_F_30); - - if (!blinkFlag || GameIsPaused() || (gCurrentRealTimeTicks & 8) == 0) - { - value *= 118; - value >>= 8; - - if (value <= 2) - return; - - GfxFillRectInset( - dpi, { coords + ScreenCoordsXY{ 63, 2 }, coords + ScreenCoordsXY{ 63 + value - 1, 8 } }, colour, 0); - } - } - /** - * Takes a guest stat value (scaled to currMax) and adjusts it to be scaled out of 255. - * Then clamp the value to between newMin and 255. + * Takes a guest stat value (scaled to currMax) and adjusts it to be scaled out of 100. + * Then clamp the value to between newMin and 100. */ int32_t NormalizeGuestStatValue(int32_t value, int32_t currMax, int32_t newMin) const { - int32_t newValue = (value * 255) / currMax; - return std::clamp(newValue, newMin, 255); + int32_t newValue = (value * 100) / currMax; + return std::clamp(newValue, newMin, 100); } void OnDrawStats(DrawPixelInfo& dpi) @@ -1096,57 +1087,46 @@ static_assert(_guestWindowPageWidgets.size() == WINDOW_GUEST_PAGE_COUNT); // Happiness DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_HAPPINESS_LABEL); - int32_t happiness = NormalizeGuestStatValue(peep->Happiness, kPeepMaxHappiness, 10); - int32_t barColour = COLOUR_BRIGHT_GREEN; - bool barBlink = happiness < 50; - StatsBarsDraw(happiness, screenCoords, dpi, barColour, barBlink); + int32_t happinessPercentage = NormalizeGuestStatValue(peep->Happiness, kPeepMaxHappiness, 10); + WidgetProgressBarSetNewPercentage(widgets[WIDX_HAPPINESS_BAR], happinessPercentage); // Energy screenCoords.y += kListRowHeight; DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_ENERGY_LABEL); - int32_t energy = NormalizeGuestStatValue(peep->Energy - kPeepMinEnergy, kPeepMaxEnergy - kPeepMinEnergy, 10); - barColour = COLOUR_BRIGHT_GREEN; - barBlink = energy < 50; - StatsBarsDraw(energy, screenCoords, dpi, barColour, barBlink); + int32_t energyPercentage = NormalizeGuestStatValue( + peep->Energy - kPeepMinEnergy, kPeepMaxEnergy - kPeepMinEnergy, 10); + WidgetProgressBarSetNewPercentage(widgets[WIDX_ENERGY_BAR], energyPercentage); // Hunger screenCoords.y += kListRowHeight; DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_HUNGER_LABEL); - int32_t hunger = NormalizeGuestStatValue(peep->Hunger - 32, 158, 0); - hunger = 255 - hunger; // the bar should be longer when peep->Hunger is low - barColour = COLOUR_BRIGHT_RED; - barBlink = hunger > 170; - StatsBarsDraw(hunger, screenCoords, dpi, barColour, barBlink); + int32_t hungerPercentage = NormalizeGuestStatValue(peep->Hunger - 32, 158, 0); + hungerPercentage = 100 - hungerPercentage; // the bar should be longer when peep->Hunger is low + WidgetProgressBarSetNewPercentage(widgets[WIDX_HUNGER_BAR], hungerPercentage); // Thirst screenCoords.y += kListRowHeight; DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_THIRST_LABEL); - int32_t thirst = NormalizeGuestStatValue(peep->Thirst - 32, 158, 0); - thirst = 255 - thirst; // the bar should be longer when peep->Thirst is low - barColour = COLOUR_BRIGHT_RED; - barBlink = thirst > 170; - StatsBarsDraw(thirst, screenCoords, dpi, barColour, barBlink); + int32_t thirstPercentage = NormalizeGuestStatValue(peep->Thirst - 32, 158, 0); + thirstPercentage = 100 - thirstPercentage; // the bar should be longer when peep->Thirst is low + WidgetProgressBarSetNewPercentage(widgets[WIDX_THIRST_BAR], thirstPercentage); // Nausea screenCoords.y += kListRowHeight; DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_NAUSEA_LABEL); - int32_t nausea = NormalizeGuestStatValue(peep->Nausea - 32, 223, 0); - barColour = COLOUR_BRIGHT_RED; - barBlink = nausea > 120; - StatsBarsDraw(nausea, screenCoords, dpi, barColour, barBlink); + int32_t nauseaPercentage = NormalizeGuestStatValue(peep->Nausea - 32, 223, 0); + WidgetProgressBarSetNewPercentage(widgets[WIDX_NAUSEA_BAR], nauseaPercentage); // Toilet screenCoords.y += kListRowHeight; DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_TOILET_LABEL); - int32_t toilet = NormalizeGuestStatValue(peep->Toilet - 64, 178, 0); - barColour = COLOUR_BRIGHT_RED; - barBlink = toilet > 160; - StatsBarsDraw(toilet, screenCoords, dpi, barColour, barBlink); + int32_t toiletPercentage = NormalizeGuestStatValue(peep->Toilet - 64, 178, 0); + WidgetProgressBarSetNewPercentage(widgets[WIDX_TOILET_BAR], toiletPercentage); // Time in park screenCoords.y += kListRowHeight + 1; diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index ba6c0c89be..5b8a1ce0e5 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -168,6 +168,8 @@ enum { WIDX_LOCATE_MECHANIC, WIDX_REFURBISH_RIDE, WIDX_FORCE_BREAKDOWN, + WIDX_RELIABILITY_BAR, + WIDX_DOWN_TIME_BAR, WIDX_TRACK_PREVIEW = 14, WIDX_TRACK_COLOUR_SCHEME, @@ -303,6 +305,8 @@ static Widget _maintenanceWidgets[] = { MakeWidget({289, 108}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_LOCATE_NEAREST_AVAILABLE_MECHANIC_TIP ), MakeWidget({265, 108}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_CONSTRUCTION), STR_REFURBISH_RIDE_TIP ), MakeWidget({241, 108}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_NO_ENTRY), STR_DEBUG_FORCE_BREAKDOWN_TIP ), + MakeProgressBar({107, 47}, { 147, 10}, COLOUR_BRIGHT_GREEN), + MakeProgressBar({107, 58}, { 147, 10}, COLOUR_BRIGHT_RED), kWidgetsEnd, }; @@ -3656,23 +3660,6 @@ static_assert(std::size(RatingNames) == 6); } } - void MaintenanceDrawBar(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t value, int32_t colour) const - { - GfxFillRectInset(dpi, { coords, coords + ScreenCoordsXY{ 149, 8 } }, colours[1], INSET_RECT_F_30); - if (colour & kBarBlink) - { - colour &= ~kBarBlink; - if (GameIsNotPaused() && (gCurrentRealTimeTicks & 8)) - return; - } - - value = ((186 * ((value * 2) & 0xFF)) >> 8) & 0xFF; - if (value > 2) - { - GfxFillRectInset(dpi, { coords + ScreenCoordsXY{ 2, 1 }, coords + ScreenCoordsXY{ value + 1, 7 } }, colour, 0); - } - } - void MaintenanceOnMouseUp(WidgetIndex widgetIndex) { switch (widgetIndex) @@ -3993,15 +3980,14 @@ static_assert(std::size(RatingNames) == 6); auto ft = Formatter(); ft.Add(reliability); DrawTextBasic(dpi, screenCoords, STR_RELIABILITY_LABEL_1757, ft); - MaintenanceDrawBar( - dpi, screenCoords + ScreenCoordsXY{ 103, 0 }, std::max(10, reliability), COLOUR_BRIGHT_GREEN); + WidgetProgressBarSetNewPercentage(widgets[WIDX_RELIABILITY_BAR], std::max(10, reliability)); screenCoords.y += 11; uint16_t downTime = ride->downtime; ft = Formatter(); ft.Add(downTime); DrawTextBasic(dpi, screenCoords, STR_DOWN_TIME_LABEL_1889, ft); - MaintenanceDrawBar(dpi, screenCoords + ScreenCoordsXY{ 103, 0 }, downTime, COLOUR_BRIGHT_RED); + WidgetProgressBarSetNewPercentage(widgets[WIDX_DOWN_TIME_BAR], downTime); screenCoords.y += 26; // Last inspection diff --git a/src/openrct2/interface/Widget.h b/src/openrct2/interface/Widget.h index 2f395de441..11d15c87c0 100644 --- a/src/openrct2/interface/Widget.h +++ b/src/openrct2/interface/Widget.h @@ -38,6 +38,7 @@ enum class WindowWidgetType : uint8_t Scroll = 22, Checkbox = 23, Placeholder = 25, + ProgressBar = 29, Custom = 28, TextBox = 27, Last = 26, diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index e1b64c8d62..7a18b7fb2f 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -130,6 +130,12 @@ struct Widget bottom += amount; } + void moveTo(ScreenCoordsXY coords) + { + moveRight(coords.x - left); + moveDown(coords.y - top); + } + bool IsVisible() const { return !(flags & WIDGET_FLAGS::IS_HIDDEN);