mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-26 16:24:35 +01:00
Merge pull request #22062 from Gymnasiast/refactor/progress-bar
Close #22043: Create widget for progress bar
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <openrct2/Context.h>
|
||||
#include <openrct2/Game.h>
|
||||
#include <openrct2/Input.h>
|
||||
#include <openrct2/config/Config.h>
|
||||
#include <openrct2/drawing/Text.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<uint16_t>(reliability);
|
||||
DrawTextBasic(dpi, screenCoords, STR_RELIABILITY_LABEL_1757, ft);
|
||||
MaintenanceDrawBar(
|
||||
dpi, screenCoords + ScreenCoordsXY{ 103, 0 }, std::max<int32_t>(10, reliability), COLOUR_BRIGHT_GREEN);
|
||||
WidgetProgressBarSetNewPercentage(widgets[WIDX_RELIABILITY_BAR], std::max<uint8_t>(10, reliability));
|
||||
screenCoords.y += 11;
|
||||
|
||||
uint16_t downTime = ride->downtime;
|
||||
ft = Formatter();
|
||||
ft.Add<uint16_t>(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
|
||||
|
||||
@@ -38,6 +38,7 @@ enum class WindowWidgetType : uint8_t
|
||||
Scroll = 22,
|
||||
Checkbox = 23,
|
||||
Placeholder = 25,
|
||||
ProgressBar = 29,
|
||||
Custom = 28,
|
||||
TextBox = 27,
|
||||
Last = 26,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user