mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-28 09:14:58 +01:00
Draw park graphs with new method.
Also clean up constants and includes.
This commit is contained in:
@@ -13,103 +13,33 @@
|
||||
#include <openrct2/Date.h>
|
||||
#include <openrct2/localisation/Formatter.h>
|
||||
#include <openrct2/localisation/Localisation.Date.h>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
namespace OpenRCT2::Graph
|
||||
{
|
||||
static void DrawMonths(DrawPixelInfo& dpi, const uint8_t* history, int32_t count, const ScreenCoordsXY& origCoords)
|
||||
{
|
||||
auto& date = GetDate();
|
||||
int32_t currentMonth = date.GetMonth();
|
||||
int32_t currentDay = date.GetMonthTicks();
|
||||
int32_t yearOver32 = (currentMonth * 4) + (currentDay >> 14) - 31;
|
||||
auto screenCoords = origCoords;
|
||||
for (int32_t i = count - 1; i >= 0; i--)
|
||||
{
|
||||
if (history[i] != 255 && yearOver32 % 4 == 0)
|
||||
{
|
||||
// Draw month text
|
||||
auto ft = Formatter();
|
||||
ft.Add<uint32_t>(DateGameShortMonthNames[DateGetMonth((yearOver32 / 4) + MONTH_COUNT)]);
|
||||
DrawTextBasic(
|
||||
dpi, screenCoords - ScreenCoordsXY{ 0, 10 }, STR_GRAPH_LABEL, ft,
|
||||
{ FontStyle::Small, TextAlignment::CENTRE });
|
||||
|
||||
// Draw month mark
|
||||
GfxFillRect(dpi, { screenCoords, screenCoords + ScreenCoordsXY{ 0, 3 } }, PALETTE_INDEX_10);
|
||||
}
|
||||
|
||||
yearOver32 = (yearOver32 + 1) % 32;
|
||||
screenCoords.x += 6;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawLineA(DrawPixelInfo& dpi, const uint8_t* history, int32_t count, const ScreenCoordsXY& origCoords)
|
||||
{
|
||||
auto lastCoords = ScreenCoordsXY{ -1, -1 };
|
||||
auto coords = origCoords;
|
||||
for (int32_t i = count - 1; i >= 0; i--)
|
||||
{
|
||||
if (history[i] != 255)
|
||||
{
|
||||
coords.y = origCoords.y + ((255 - history[i]) * 100) / 256;
|
||||
|
||||
if (lastCoords.x != -1)
|
||||
{
|
||||
auto leftTop1 = lastCoords + ScreenCoordsXY{ 1, 1 };
|
||||
auto rightBottom1 = coords + ScreenCoordsXY{ 1, 1 };
|
||||
auto leftTop2 = lastCoords + ScreenCoordsXY{ 0, 1 };
|
||||
auto rightBottom2 = coords + ScreenCoordsXY{ 0, 1 };
|
||||
GfxDrawLine(dpi, { leftTop1, rightBottom1 }, PALETTE_INDEX_10);
|
||||
GfxDrawLine(dpi, { leftTop2, rightBottom2 }, PALETTE_INDEX_10);
|
||||
}
|
||||
if (i == 0)
|
||||
GfxFillRect(dpi, { coords, coords + ScreenCoordsXY{ 2, 2 } }, PALETTE_INDEX_10);
|
||||
|
||||
lastCoords = coords;
|
||||
}
|
||||
coords.x += 6;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawLineB(DrawPixelInfo& dpi, const uint8_t* history, int32_t count, const ScreenCoordsXY& origCoords)
|
||||
{
|
||||
auto lastCoords = ScreenCoordsXY{ -1, -1 };
|
||||
auto coords = origCoords;
|
||||
for (int32_t i = count - 1; i >= 0; i--)
|
||||
{
|
||||
if (history[i] != 255)
|
||||
{
|
||||
coords.y = origCoords.y + ((255 - history[i]) * 100) / 256;
|
||||
|
||||
if (lastCoords.x != -1)
|
||||
{
|
||||
auto leftTop = lastCoords;
|
||||
auto rightBottom = coords;
|
||||
GfxDrawLine(dpi, { leftTop, rightBottom }, PALETTE_INDEX_21);
|
||||
}
|
||||
if (i == 0)
|
||||
GfxFillRect(dpi, { coords - ScreenCoordsXY{ 1, 1 }, coords + ScreenCoordsXY{ 1, 1 } }, PALETTE_INDEX_21);
|
||||
|
||||
lastCoords = coords;
|
||||
}
|
||||
coords.x += 6;
|
||||
}
|
||||
}
|
||||
|
||||
void Draw(DrawPixelInfo& dpi, uint8_t* history, int32_t count, const ScreenCoordsXY& screenPos)
|
||||
{
|
||||
DrawMonths(dpi, history, count, screenPos);
|
||||
DrawLineA(dpi, history, count, screenPos);
|
||||
DrawLineB(dpi, history, count, screenPos);
|
||||
}
|
||||
} // namespace OpenRCT2::Graph
|
||||
#include <openrct2/world/Park.h>
|
||||
|
||||
namespace OpenRCT2::Graph
|
||||
{
|
||||
constexpr int32_t kDashLength = 2;
|
||||
|
||||
template<typename T>
|
||||
static void DrawYLabels(
|
||||
DrawPixelInfo& dpi, const ScreenRect& internalBounds, const T min, const T max, const int32_t numYLabels,
|
||||
const int32_t yLabelStepPx, const StringId fmt, const ColourWithFlags lineCol)
|
||||
{
|
||||
T curLabel = max;
|
||||
int32_t curScreenPos = internalBounds.GetTop() - 5;
|
||||
const T yLabelStep = (max - min) / (numYLabels - 1);
|
||||
for (int32_t i = 0; i < numYLabels; i++)
|
||||
{
|
||||
Formatter ft;
|
||||
ft.Add<T>(curLabel);
|
||||
DrawTextBasic(dpi, { internalBounds.GetLeft(), curScreenPos }, fmt, ft, { FontStyle::Small, TextAlignment::RIGHT });
|
||||
GfxFillRectInset(
|
||||
dpi, { { internalBounds.GetLeft(), curScreenPos + 5 }, { internalBounds.GetRight(), curScreenPos + 5 } },
|
||||
lineCol, INSET_RECT_FLAG_BORDER_INSET);
|
||||
curScreenPos += yLabelStepPx;
|
||||
curLabel -= yLabelStep;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, T TkNoValue>
|
||||
static void DrawMonths(DrawPixelInfo& dpi, const T* series, int32_t count, const ScreenRect& bounds, const int32_t xStep)
|
||||
{
|
||||
@@ -126,11 +56,12 @@ namespace OpenRCT2::Graph
|
||||
auto ft = Formatter();
|
||||
ft.Add<StringId>(DateGameShortMonthNames[DateGetMonth((yearOver32 / 4) + MONTH_COUNT)]);
|
||||
DrawTextBasic(
|
||||
dpi, screenCoords - ScreenCoordsXY{ 0, 13 }, STR_GRAPH_LABEL, ft,
|
||||
dpi, screenCoords - ScreenCoordsXY{ 0, 14 }, STR_GRAPH_LABEL, ft,
|
||||
{ FontStyle::Small, TextAlignment::CENTRE });
|
||||
|
||||
// Draw month mark
|
||||
GfxFillRect(dpi, { screenCoords - ScreenCoordsXY{ 0, 3 }, screenCoords }, PALETTE_INDEX_10);
|
||||
GfxFillRect(
|
||||
dpi, { screenCoords - ScreenCoordsXY{ 0, 4 }, screenCoords - ScreenCoordsXY{ 0, 1 } }, PALETTE_INDEX_10);
|
||||
}
|
||||
|
||||
yearOver32 = (yearOver32 + 1) % 32;
|
||||
@@ -148,12 +79,15 @@ namespace OpenRCT2::Graph
|
||||
|
||||
const int32_t yPosition = bounds.GetBottom() - ((value - minValue) * screenRange) / valueRange;
|
||||
ScreenCoordsXY coords = { bounds.GetRight() - hoverIdx * xStep, yPosition };
|
||||
// Line needs to be shifted over 1 pixel to match with the month ticks.
|
||||
ScreenCoordsXY lineCoords = { coords.x + 1, coords.y };
|
||||
|
||||
GfxDrawDashedLine(
|
||||
dpi, { { lineCoords.x, bounds.GetTop() }, { lineCoords.x, bounds.GetBottom() } }, kDashLength, PALETTE_INDEX_10);
|
||||
GfxDrawDashedLine(dpi, { { bounds.GetLeft(), lineCoords.y }, lineCoords }, kDashLength, PALETTE_INDEX_10);
|
||||
dpi,
|
||||
{
|
||||
{ coords.x, bounds.GetTop() },
|
||||
{ coords.x, bounds.GetBottom() },
|
||||
},
|
||||
kDashLength, PALETTE_INDEX_10);
|
||||
GfxDrawDashedLine(dpi, { { bounds.GetLeft(), coords.y }, coords }, kDashLength, PALETTE_INDEX_10);
|
||||
|
||||
auto ft = Formatter();
|
||||
ft.Add<money64>(value);
|
||||
@@ -222,39 +156,49 @@ namespace OpenRCT2::Graph
|
||||
|
||||
void DrawFinanceGraph(DrawPixelInfo& dpi, const GraphProperties<money64>& p)
|
||||
{
|
||||
money64 curLabel = p.max;
|
||||
int32_t curScreenPos = p.internalBounds.GetTop() - 5;
|
||||
const money64 yLabelStep = (p.max - p.min) / (p.numYLabels - 1);
|
||||
for (int32_t i = 0; i < p.numYLabels; i++)
|
||||
{
|
||||
Formatter ft;
|
||||
ft.Add<money64>(curLabel);
|
||||
DrawTextBasic(
|
||||
dpi, { p.internalBounds.GetLeft(), curScreenPos }, STR_FINANCES_FINANCIAL_GRAPH_CASH_VALUE, ft,
|
||||
{ FontStyle::Small, TextAlignment::RIGHT });
|
||||
GfxFillRectInset(
|
||||
dpi, { { p.internalBounds.GetLeft(), curScreenPos + 5 }, { p.internalBounds.GetRight(), curScreenPos + 5 } },
|
||||
p.lineCol, INSET_RECT_FLAG_BORDER_INSET);
|
||||
curScreenPos += p.yLabelStepPx;
|
||||
curLabel -= yLabelStep;
|
||||
}
|
||||
|
||||
constexpr StringId fmt = STR_FINANCES_FINANCIAL_GRAPH_CASH_VALUE;
|
||||
DrawYLabels<money64>(dpi, p.internalBounds, p.min, p.max, p.numYLabels, p.yLabelStepPx, fmt, p.lineCol);
|
||||
DrawMonths<money64, kMoney64Undefined>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx);
|
||||
DrawLine<money64, kMoney64Undefined, true>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
DrawLine<money64, kMoney64Undefined, false>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
if (p.hoverIdx >= 0 && p.hoverIdx < p.numPoints)
|
||||
{
|
||||
money64 value = p.series[p.hoverIdx];
|
||||
const money64 value = p.series[p.hoverIdx];
|
||||
if (value != kMoney64Undefined)
|
||||
DrawHoveredValue<money64>(dpi, value, p.hoverIdx, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
}
|
||||
}
|
||||
|
||||
// todo debug code.
|
||||
ScreenCoordsXY bottomLeft{ p.internalBounds.Point1.x, p.internalBounds.Point2.y };
|
||||
ScreenCoordsXY topRight{ p.internalBounds.Point2.x, p.internalBounds.Point1.y };
|
||||
GfxDrawLine(dpi, { p.internalBounds.Point1, topRight }, 33);
|
||||
GfxDrawLine(dpi, { p.internalBounds.Point1, bottomLeft }, 33);
|
||||
GfxDrawLine(dpi, { bottomLeft, p.internalBounds.Point2 }, 33);
|
||||
GfxDrawLine(dpi, { topRight, p.internalBounds.Point2 }, 33);
|
||||
void DrawRatingGraph(DrawPixelInfo& dpi, const GraphProperties<uint8_t>& p)
|
||||
{
|
||||
constexpr uint8_t noValue = ParkRatingHistoryUndefined;
|
||||
constexpr StringId fmt = STR_GRAPH_AXIS_LABEL;
|
||||
// Since the park rating rating history is divided by 4, we have to fudge the max number here.
|
||||
DrawYLabels<uint16_t>(dpi, p.internalBounds, p.min, 1000, p.numYLabels, p.yLabelStepPx, fmt, p.lineCol);
|
||||
DrawMonths<uint8_t, noValue>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx);
|
||||
DrawLine<uint8_t, noValue, true>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
DrawLine<uint8_t, noValue, false>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
if (p.hoverIdx >= 0 && p.hoverIdx < p.numPoints)
|
||||
{
|
||||
const uint8_t value = p.series[p.hoverIdx];
|
||||
if (value != noValue)
|
||||
DrawHoveredValue<uint8_t>(dpi, value, p.hoverIdx, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawGuestGraph(DrawPixelInfo& dpi, const GraphProperties<uint32_t>& p)
|
||||
{
|
||||
constexpr uint32_t noValue = GuestsInParkHistoryUndefined;
|
||||
constexpr StringId fmt = STR_GRAPH_AXIS_LABEL;
|
||||
DrawYLabels<uint32_t>(dpi, p.internalBounds, p.min, p.max, p.numYLabels, p.yLabelStepPx, fmt, p.lineCol);
|
||||
DrawMonths<uint32_t, noValue>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx);
|
||||
DrawLine<uint32_t, noValue, true>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
DrawLine<uint32_t, noValue, false>(dpi, p.series, p.numPoints, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
if (p.hoverIdx >= 0 && p.hoverIdx < p.numPoints)
|
||||
{
|
||||
const uint32_t value = p.series[p.hoverIdx];
|
||||
if (value != noValue)
|
||||
DrawHoveredValue<uint32_t>(dpi, value, p.hoverIdx, p.internalBounds, p.xStepPx, p.min, p.max);
|
||||
}
|
||||
}
|
||||
} // namespace OpenRCT2::Graph
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRCT2::Graph
|
||||
template<typename T> struct GraphProperties
|
||||
{
|
||||
ScreenRect internalBounds;
|
||||
T* series;
|
||||
const T* series;
|
||||
T min;
|
||||
T max;
|
||||
int32_t hoverIdx;
|
||||
@@ -41,7 +41,7 @@ namespace OpenRCT2::Graph
|
||||
numYLabels = newNumYLabels;
|
||||
}
|
||||
|
||||
bool UpdateHoverIdx()
|
||||
bool UpdateHoverIndex()
|
||||
{
|
||||
const ScreenCoordsXY cursorPos = ContextGetCursorPositionScaled();
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRCT2::Graph
|
||||
}
|
||||
};
|
||||
|
||||
void Draw(DrawPixelInfo& dpi, uint8_t* history, int32_t count, const ScreenCoordsXY& screenPos);
|
||||
|
||||
void DrawFinanceGraph(DrawPixelInfo& dpi, const GraphProperties<money64>& p);
|
||||
void DrawRatingGraph(DrawPixelInfo& dpi, const GraphProperties<uint8_t>& p);
|
||||
void DrawGuestGraph(DrawPixelInfo& dpi, const GraphProperties<uint32_t>& p);
|
||||
} // namespace OpenRCT2::Graph
|
||||
|
||||
@@ -256,7 +256,7 @@ static Widget _windowFinancesResearchWidgets[] =
|
||||
if (page == WINDOW_FINANCES_PAGE_VALUE_GRAPH || page == WINDOW_FINANCES_PAGE_PROFIT_GRAPH
|
||||
|| page == WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH)
|
||||
{
|
||||
if (_graphProps.UpdateHoverIdx())
|
||||
if (_graphProps.UpdateHoverIndex())
|
||||
{
|
||||
InvalidateWidget(WIDX_BACKGROUND);
|
||||
}
|
||||
@@ -839,19 +839,18 @@ static Widget _windowFinancesResearchWidgets[] =
|
||||
}
|
||||
|
||||
void OnDrawGraph(
|
||||
DrawPixelInfo& dpi, const money64 currentValue, money64 (&series)[kFinanceGraphSize], const StringId fmt, const bool centred)
|
||||
DrawPixelInfo& dpi, const money64 currentValue, money64 (&series)[kFinanceHistorySize], const StringId fmt,
|
||||
const bool centred)
|
||||
{
|
||||
auto ft = Formatter();
|
||||
Formatter ft;
|
||||
ft.Add<money64>(currentValue);
|
||||
DrawTextBasic(dpi, _graphBounds.Point1 - ScreenCoordsXY{ 0, 11 }, fmt, ft);
|
||||
|
||||
// Graph
|
||||
GfxFillRectInset(dpi, _graphBounds, colours[1], INSET_RECT_F_30);
|
||||
|
||||
for (int i = 0; i < 128; i++) // TODO debug
|
||||
series[i] = i % 2 * 96.00_GBP;
|
||||
// series[i] = 0;
|
||||
|
||||
// Calculate Y axis max and min.
|
||||
// This is how the original code does it. Could be improved.
|
||||
money64 max = centred ? 12.00_GBP : 24.00_GBP;
|
||||
for (int32_t i = 0; i < kGraphNumPoints; i++)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <openrct2-ui/interface/Graph.h>
|
||||
#include <openrct2-ui/interface/LandTool.h>
|
||||
#include <openrct2-ui/interface/Objective.h>
|
||||
#include <openrct2-ui/interface/Viewport.h>
|
||||
#include <openrct2-ui/interface/Widget.h>
|
||||
#include <openrct2-ui/windows/Window.h>
|
||||
#include <openrct2/Context.h>
|
||||
@@ -27,13 +26,11 @@
|
||||
#include <openrct2/config/Config.h>
|
||||
#include <openrct2/localisation/Currency.h>
|
||||
#include <openrct2/localisation/Formatting.h>
|
||||
#include <openrct2/localisation/Localisation.Date.h>
|
||||
#include <openrct2/management/Award.h>
|
||||
#include <openrct2/peep/PeepAnimationData.h>
|
||||
#include <openrct2/ride/RideData.h>
|
||||
#include <openrct2/scenario/Scenario.h>
|
||||
#include <openrct2/util/Util.h>
|
||||
#include <openrct2/world/Entrance.h>
|
||||
#include <openrct2/world/Park.h>
|
||||
|
||||
namespace OpenRCT2::Ui::Windows
|
||||
@@ -41,6 +38,10 @@ namespace OpenRCT2::Ui::Windows
|
||||
static constexpr StringId WINDOW_TITLE = STR_STRINGID;
|
||||
static constexpr int32_t WH = 224;
|
||||
|
||||
static constexpr ScreenCoordsXY kGraphTopLeftPadding{ 35, 15 };
|
||||
static constexpr ScreenCoordsXY kGraphBottomRightPadding{ 5, 5 };
|
||||
static constexpr uint8_t kGraphNumYLabels = 6;
|
||||
|
||||
// clang-format off
|
||||
enum WindowParkPage {
|
||||
WINDOW_PARK_PAGE_ENTRANCE,
|
||||
@@ -197,6 +198,12 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
int32_t _numberOfRides = -1;
|
||||
uint8_t _peepAnimationFrame = 0;
|
||||
|
||||
Graph::GraphProperties<uint8_t> _ratingProps{};
|
||||
Graph::GraphProperties<uint32_t> _guestProps{};
|
||||
|
||||
ScreenRect _ratingGraphBounds;
|
||||
ScreenRect _guestGraphBounds;
|
||||
|
||||
public:
|
||||
void OnOpen() override
|
||||
{
|
||||
@@ -206,6 +213,11 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
_numberOfStaff = -1;
|
||||
_peepAnimationFrame = 0;
|
||||
SetPage(0);
|
||||
|
||||
_ratingProps.lineCol = colours[2];
|
||||
_guestProps.lineCol = colours[2];
|
||||
_ratingProps.hoverIdx = -1;
|
||||
_guestProps.hoverIdx = -1;
|
||||
}
|
||||
|
||||
void OnClose() override
|
||||
@@ -692,6 +704,13 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
|
||||
WindowAlignTabs(this, WIDX_TAB_1, WIDX_TAB_7);
|
||||
AnchorBorderWidgets();
|
||||
|
||||
const Widget* background = &widgets[WIDX_PAGE_BACKGROUND];
|
||||
_ratingGraphBounds = { windowPos + ScreenCoordsXY{ background->left + 4, background->top + 15 },
|
||||
windowPos + ScreenCoordsXY{ background->right - 4, background->bottom - 4 } };
|
||||
_ratingProps.RecalculateLayout(
|
||||
{ _ratingGraphBounds.Point1 + kGraphTopLeftPadding, _ratingGraphBounds.Point2 - kGraphBottomRightPadding },
|
||||
kGraphNumYLabels, kParkRatingHistorySize);
|
||||
}
|
||||
|
||||
void OnDrawRating(DrawPixelInfo& dpi)
|
||||
@@ -699,41 +718,21 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
DrawWidgets(dpi);
|
||||
DrawTabImages(dpi);
|
||||
|
||||
auto screenPos = windowPos;
|
||||
Widget* widget = &widgets[WIDX_PAGE_BACKGROUND];
|
||||
const auto& gameState = OpenRCT2::GetGameState();
|
||||
|
||||
// Current value
|
||||
auto ft = Formatter();
|
||||
ft.Add<uint16_t>(GetGameState().Park.Rating);
|
||||
DrawTextBasic(dpi, screenPos + ScreenCoordsXY{ widget->left + 3, widget->top + 2 }, STR_PARK_RATING_LABEL, ft);
|
||||
Formatter ft;
|
||||
ft.Add<uint16_t>(gameState.Park.Rating);
|
||||
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ widget->left + 3, widget->top + 2 }, STR_PARK_RATING_LABEL, ft);
|
||||
|
||||
// Graph border
|
||||
GfxFillRectInset(
|
||||
dpi,
|
||||
{ screenPos + ScreenCoordsXY{ widget->left + 4, widget->top + 15 },
|
||||
screenPos + ScreenCoordsXY{ widget->right - 4, widget->bottom - 4 } },
|
||||
colours[1], INSET_RECT_F_30);
|
||||
GfxFillRectInset(dpi, _ratingGraphBounds, colours[1], INSET_RECT_F_30);
|
||||
|
||||
// Y axis labels
|
||||
screenPos = screenPos + ScreenCoordsXY{ widget->left + 27, widget->top + 23 };
|
||||
for (int i = 5; i >= 0; i--)
|
||||
{
|
||||
uint32_t axisValue = i * 200;
|
||||
ft = Formatter();
|
||||
ft.Add<uint32_t>(axisValue);
|
||||
DrawTextBasic(
|
||||
dpi, screenPos + ScreenCoordsXY{ 10, 0 }, STR_GRAPH_AXIS_LABEL, ft,
|
||||
{ FontStyle::Small, TextAlignment::RIGHT });
|
||||
GfxFillRectInset(
|
||||
dpi, { screenPos + ScreenCoordsXY{ 15, 5 }, screenPos + ScreenCoordsXY{ width - 32, 5 } }, colours[2],
|
||||
INSET_RECT_FLAG_BORDER_INSET);
|
||||
screenPos.y += 20;
|
||||
}
|
||||
|
||||
// Graph
|
||||
screenPos = windowPos + ScreenCoordsXY{ widget->left + 47, widget->top + 26 };
|
||||
|
||||
Graph::Draw(dpi, GetGameState().Park.RatingHistory, kParkRatingHistorySize, screenPos);
|
||||
_ratingProps.min = 0;
|
||||
_ratingProps.max = 250;
|
||||
_ratingProps.series = gameState.Park.RatingHistory;
|
||||
Graph::DrawRatingGraph(dpi, _ratingProps);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -765,6 +764,13 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
|
||||
WindowAlignTabs(this, WIDX_TAB_1, WIDX_TAB_7);
|
||||
AnchorBorderWidgets();
|
||||
|
||||
const Widget* background = &widgets[WIDX_PAGE_BACKGROUND];
|
||||
_guestGraphBounds = { windowPos + ScreenCoordsXY{ background->left + 4, background->top + 15 },
|
||||
windowPos + ScreenCoordsXY{ background->right - 4, background->bottom - 4 } };
|
||||
_guestProps.RecalculateLayout(
|
||||
{ _guestGraphBounds.Point1 + kGraphTopLeftPadding, _guestGraphBounds.Point2 - kGraphBottomRightPadding },
|
||||
kGraphNumYLabels, kGuestsInParkHistorySize);
|
||||
}
|
||||
|
||||
void OnDrawGuests(DrawPixelInfo& dpi)
|
||||
@@ -772,56 +778,30 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
DrawWidgets(dpi);
|
||||
DrawTabImages(dpi);
|
||||
|
||||
auto screenPos = windowPos;
|
||||
Widget* widget = &widgets[WIDX_PAGE_BACKGROUND];
|
||||
|
||||
const auto& gameState = OpenRCT2::GetGameState();
|
||||
|
||||
// Current value
|
||||
auto ft = Formatter();
|
||||
Formatter ft;
|
||||
ft.Add<uint32_t>(gameState.NumGuestsInPark);
|
||||
DrawTextBasic(dpi, screenPos + ScreenCoordsXY{ widget->left + 3, widget->top + 2 }, STR_GUESTS_IN_PARK_LABEL, ft);
|
||||
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ widget->left + 3, widget->top + 2 }, STR_GUESTS_IN_PARK_LABEL, ft);
|
||||
|
||||
// Graph border
|
||||
GfxFillRectInset(
|
||||
dpi,
|
||||
{ screenPos + ScreenCoordsXY{ widget->left + 4, widget->top + 15 },
|
||||
screenPos + ScreenCoordsXY{ widget->right - 4, widget->bottom - 4 } },
|
||||
colours[1], INSET_RECT_F_30);
|
||||
GfxFillRectInset(dpi, _guestGraphBounds, colours[1], INSET_RECT_F_30);
|
||||
|
||||
// Y axis labels
|
||||
screenPos = screenPos + ScreenCoordsXY{ widget->left + 27, widget->top + 23 };
|
||||
for (int i = 5; i >= 0; i--)
|
||||
{
|
||||
uint32_t axisValue = i * 1000;
|
||||
ft = Formatter();
|
||||
ft.Add<uint32_t>(axisValue);
|
||||
DrawTextBasic(
|
||||
dpi, screenPos + ScreenCoordsXY{ 10, 0 }, STR_GRAPH_AXIS_LABEL, ft,
|
||||
{ FontStyle::Small, TextAlignment::RIGHT });
|
||||
GfxFillRectInset(
|
||||
dpi, { screenPos + ScreenCoordsXY{ 15, 5 }, screenPos + ScreenCoordsXY{ width - 32, 5 } }, colours[2],
|
||||
INSET_RECT_FLAG_BORDER_INSET);
|
||||
screenPos.y += 20;
|
||||
}
|
||||
|
||||
// Graph
|
||||
screenPos = windowPos + ScreenCoordsXY{ widget->left + 47, widget->top + 26 };
|
||||
|
||||
uint8_t cappedHistory[32];
|
||||
for (size_t i = 0; i < std::size(cappedHistory); i++)
|
||||
// Calculate Y axis max and min
|
||||
_guestProps.min = 0;
|
||||
_guestProps.max = 5000;
|
||||
for (size_t i = 0; i < std::size(gameState.GuestsInParkHistory); i++)
|
||||
{
|
||||
auto value = gameState.GuestsInParkHistory[i];
|
||||
if (value != std::numeric_limits<uint32_t>::max())
|
||||
{
|
||||
cappedHistory[i] = static_cast<uint8_t>(std::min<uint32_t>(value, 5000) / 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
cappedHistory[i] = std::numeric_limits<uint8_t>::max();
|
||||
}
|
||||
if (value == GuestsInParkHistoryUndefined)
|
||||
continue;
|
||||
while (value > _guestProps.max)
|
||||
_guestProps.max += 5000;
|
||||
}
|
||||
Graph::Draw(dpi, cappedHistory, static_cast<int32_t>(std::size(cappedHistory)), screenPos);
|
||||
_guestProps.series = gameState.GuestsInParkHistory;
|
||||
Graph::DrawGuestGraph(dpi, _guestProps);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -1315,6 +1295,7 @@ static constexpr WindowParkAward _parkAwards[] = {
|
||||
windowPos + ScreenCoordsXY{ widgets[WIDX_TAB_7].left, widgets[WIDX_TAB_7].top });
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
static ParkWindow* ParkWindowOpen(uint8_t page)
|
||||
|
||||
@@ -47,13 +47,13 @@ namespace OpenRCT2
|
||||
money64 ConstructionRightsPrice;
|
||||
money64 CurrentExpenditure;
|
||||
money64 CurrentProfit;
|
||||
uint32_t GuestsInParkHistory[32];
|
||||
uint32_t GuestsInParkHistory[kGuestsInParkHistorySize];
|
||||
ClimateType Climate;
|
||||
ClimateState ClimateCurrent;
|
||||
ClimateState ClimateNext;
|
||||
uint16_t ClimateUpdateTimer;
|
||||
money64 Cash;
|
||||
money64 CashHistory[kFinanceGraphSize];
|
||||
money64 CashHistory[kFinanceHistorySize];
|
||||
money64 InitialCash;
|
||||
money64 GuestInitialCash;
|
||||
uint8_t GuestInitialHappiness;
|
||||
@@ -69,7 +69,7 @@ namespace OpenRCT2
|
||||
money64 TotalIncomeFromAdmissions;
|
||||
money64 TotalRideValueForMoney;
|
||||
uint16_t WeeklyProfitAverageDivisor;
|
||||
money64 WeeklyProfitHistory[kFinanceGraphSize];
|
||||
money64 WeeklyProfitHistory[kFinanceHistorySize];
|
||||
Objective ScenarioObjective;
|
||||
uint16_t ScenarioParkRatingWarningDays;
|
||||
money64 ScenarioCompletedCompanyValue;
|
||||
|
||||
@@ -185,7 +185,7 @@ void FinancePayRideUpkeep()
|
||||
void FinanceResetHistory()
|
||||
{
|
||||
auto& gameState = GetGameState();
|
||||
for (auto i = 0; i < kFinanceGraphSize; i++)
|
||||
for (auto i = 0; i < kFinanceHistorySize; i++)
|
||||
{
|
||||
gameState.CashHistory[i] = kMoney64Undefined;
|
||||
gameState.WeeklyProfitHistory[i] = kMoney64Undefined;
|
||||
|
||||
@@ -32,7 +32,7 @@ enum class ExpenditureType : int32_t
|
||||
};
|
||||
|
||||
constexpr uint8_t kExpenditureTableMonthCount = 16;
|
||||
constexpr uint8_t kFinanceGraphSize = 128;
|
||||
constexpr uint8_t kFinanceHistorySize = 128;
|
||||
|
||||
constexpr uint8_t MaxBankLoanInterestRate = 255;
|
||||
|
||||
|
||||
@@ -769,7 +769,7 @@ namespace OpenRCT2::RCT1
|
||||
uint8_t Unk1990AA[94];
|
||||
uint16_t ParkRating;
|
||||
uint8_t ParkRatingHistory[kParkRatingHistorySize];
|
||||
uint8_t GuestsInParkHistory[32];
|
||||
uint8_t GuestsInParkHistory[kGuestsInParkHistorySize];
|
||||
uint8_t ResearchPriority;
|
||||
uint8_t ResearchProgressStage;
|
||||
uint8_t LastResearchItem;
|
||||
|
||||
@@ -862,7 +862,7 @@ namespace OpenRCT2::RCT2
|
||||
|
||||
// Ignored in scenario
|
||||
uint8_t ParkRatingHistory[kParkRatingHistorySize];
|
||||
uint8_t GuestsInParkHistory[32];
|
||||
uint8_t GuestsInParkHistory[kGuestsInParkHistorySize];
|
||||
|
||||
// SC6[10]
|
||||
uint8_t ActiveResearchTypes;
|
||||
|
||||
@@ -586,8 +586,10 @@ namespace OpenRCT2::Park
|
||||
gameState.NumGuestsInParkLastWeek = gameState.NumGuestsInPark;
|
||||
|
||||
// Update park rating, guests in park and current cash history
|
||||
HistoryPushRecord<uint8_t, 32>(gameState.Park.RatingHistory, gameState.Park.Rating / 4);
|
||||
HistoryPushRecord<uint32_t, 32>(gameState.GuestsInParkHistory, gameState.NumGuestsInPark);
|
||||
constexpr auto ratingHistorySize = std::extent_v<decltype(ParkData::RatingHistory)>;
|
||||
HistoryPushRecord<uint8_t, ratingHistorySize>(gameState.Park.RatingHistory, gameState.Park.Rating / 4);
|
||||
constexpr auto numGuestsHistorySize = std::extent_v<decltype(GameState_t::GuestsInParkHistory)>;
|
||||
HistoryPushRecord<uint32_t, numGuestsHistorySize>(gameState.GuestsInParkHistory, gameState.NumGuestsInPark);
|
||||
|
||||
constexpr auto cashHistorySize = std::extent_v<decltype(GameState_t::CashHistory)>;
|
||||
HistoryPushRecord<money64, cashHistorySize>(gameState.CashHistory, FinanceGetCurrentCash() - gameState.BankLoan);
|
||||
|
||||
@@ -17,6 +17,7 @@ constexpr auto MAX_ENTRANCE_FEE = 999.00_GBP;
|
||||
constexpr uint8_t ParkRatingHistoryUndefined = std::numeric_limits<uint8_t>::max();
|
||||
constexpr uint32_t GuestsInParkHistoryUndefined = std::numeric_limits<uint32_t>::max();
|
||||
constexpr uint8_t kParkRatingHistorySize = 32;
|
||||
constexpr uint8_t kGuestsInParkHistorySize = 32;
|
||||
constexpr uint8_t ParkNameMaxLength = 128;
|
||||
constexpr uint8_t ScenarioNameMaxLength = 128;
|
||||
constexpr uint16_t ScenarioDetailsNameMaxLength = 256;
|
||||
@@ -65,7 +66,7 @@ namespace OpenRCT2
|
||||
std::vector<CoordsXYZD> Entrances;
|
||||
uint32_t Size;
|
||||
money64 Value;
|
||||
money64 ValueHistory[kFinanceGraphSize];
|
||||
money64 ValueHistory[kFinanceHistorySize];
|
||||
|
||||
bool IsOpen() const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user