Move formatter to separate file. Rework GetMeasurement (#13131)

* Move formatter to seperate file. Rework GetMeasurement

* Add Formatter source files to Xcode project

Co-authored-by: Aaron van Geffen <aaron@aaronweb.net>
This commit is contained in:
Duncan 2020-10-09 12:02:07 +01:00 committed by GitHub
parent 32c2b7d449
commit 84c9ff833a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 181 additions and 134 deletions

View File

@ -108,6 +108,8 @@
939A359F20C12FDE00630B3F /* Paint.Surface.h in Headers */ = {isa = PBXBuildFile; fileRef = 939A359D20C12FDD00630B3F /* Paint.Surface.h */; };
939A35A020C12FDE00630B3F /* Paint.TileElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 939A359E20C12FDE00630B3F /* Paint.TileElement.h */; };
939A35A220C12FFD00630B3F /* InteractiveConsole.h in Headers */ = {isa = PBXBuildFile; fileRef = 939A35A120C12FFD00630B3F /* InteractiveConsole.h */; };
93AE2389252F948A00CD03C3 /* Formatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 93AE2387252F948A00CD03C3 /* Formatter.h */; };
93AE238A252F948A00CD03C3 /* Formatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AE2388252F948A00CD03C3 /* Formatter.cpp */; };
93CBA4C020A74FF200867D56 /* BitmapReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93CBA4BF20A74FF200867D56 /* BitmapReader.cpp */; };
93CBA4C320A7502E00867D56 /* Imaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 93CBA4C120A7502D00867D56 /* Imaging.h */; };
93CBA4C420A7502E00867D56 /* Imaging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93CBA4C220A7502E00867D56 /* Imaging.cpp */; };
@ -1322,6 +1324,8 @@
939A359D20C12FDD00630B3F /* Paint.Surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Paint.Surface.h; sourceTree = "<group>"; };
939A359E20C12FDE00630B3F /* Paint.TileElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Paint.TileElement.h; sourceTree = "<group>"; };
939A35A120C12FFD00630B3F /* InteractiveConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractiveConsole.h; sourceTree = "<group>"; };
93AE2387252F948A00CD03C3 /* Formatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Formatter.h; sourceTree = "<group>"; };
93AE2388252F948A00CD03C3 /* Formatter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Formatter.cpp; sourceTree = "<group>"; };
93CBA4BE20A74FF200867D56 /* BitmapReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitmapReader.h; sourceTree = "<group>"; };
93CBA4BF20A74FF200867D56 /* BitmapReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitmapReader.cpp; sourceTree = "<group>"; };
93CBA4C120A7502D00867D56 /* Imaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Imaging.h; sourceTree = "<group>"; };
@ -2938,6 +2942,8 @@
4C7B53AE1FFF935B00A52E21 /* Date.h */,
4C7B53AF1FFF935B00A52E21 /* FormatCodes.cpp */,
4C7B53B01FFF935B00A52E21 /* FormatCodes.h */,
93AE2388252F948A00CD03C3 /* Formatter.cpp */,
93AE2387252F948A00CD03C3 /* Formatter.h */,
4C7B53B11FFF935B00A52E21 /* Language.cpp */,
4C7B53C91FFF991000A52E21 /* Language.h */,
4C7B53B31FFF935B00A52E21 /* LanguagePack.cpp */,
@ -3708,6 +3714,7 @@
2ADE2F2B224418B2002598AF /* JobPool.hpp in Headers */,
2ADE2F3622441960002598AF /* RideTypes.h in Headers */,
93DFD05324521C1A001FCBAF /* ScRide.hpp in Headers */,
93AE2389252F948A00CD03C3 /* Formatter.h in Headers */,
93DFD05424521C1A001FCBAF /* ScDate.hpp in Headers */,
93FC08FF2418F3ED00CA3054 /* duktape.h in Headers */,
93DFD04F24521C1A001FCBAF /* ScConsole.hpp in Headers */,
@ -4182,6 +4189,7 @@
C688786820289A4A0084B384 /* Util.cpp in Sources */,
C688792720289B9B0084B384 /* TopSpin.cpp in Sources */,
C688787E20289ADE0084B384 /* Drawing.cpp in Sources */,
93AE238A252F948A00CD03C3 /* Formatter.cpp in Sources */,
C68878A120289B200084B384 /* Localisation.cpp in Sources */,
C68878ED20289B9B0084B384 /* BobsleighCoaster.cpp in Sources */,
C688785E20289A0A0084B384 /* Fountain.cpp in Sources */,

View File

@ -5787,7 +5787,7 @@ static void window_ride_graphs_update(rct_window* w)
if (ride != nullptr)
{
RideMeasurement* measurement{};
std::tie(measurement, std::ignore) = ride_get_measurement(ride);
std::tie(measurement, std::ignore) = ride->GetMeasurement();
x = measurement == nullptr ? 0 : measurement->current_item - ((widget->width() / 4) * 3);
}
}
@ -5812,7 +5812,7 @@ static void window_ride_graphs_scrollgetheight(rct_window* w, int32_t scrollInde
if (ride != nullptr)
{
RideMeasurement* measurement{};
std::tie(measurement, std::ignore) = ride_get_measurement(ride);
std::tie(measurement, std::ignore) = ride->GetMeasurement();
if (measurement != nullptr)
{
*width = std::max<int32_t>(*width, measurement->num_items);
@ -5840,7 +5840,7 @@ static void window_ride_graphs_tooltip(rct_window* w, rct_widgetindex widgetInde
auto ride = get_ride(w->number);
if (ride != nullptr)
{
auto [measurement, message] = ride_get_measurement(ride);
auto [measurement, message] = ride->GetMeasurement();
if (measurement != nullptr && (measurement->flags & RIDE_MEASUREMENT_FLAG_RUNNING))
{
auto ft = Formatter::Common();
@ -5850,7 +5850,7 @@ static void window_ride_graphs_tooltip(rct_window* w, rct_widgetindex widgetInde
}
else
{
*stringId = message;
*stringId = message.str;
}
}
}
@ -5941,19 +5941,20 @@ static void window_ride_graphs_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi
gfx_clear(dpi, ColourMapA[COLOUR_SATURATED_GREEN].darker);
auto widget = &window_ride_graphs_widgets[WIDX_GRAPH];
auto stringId = STR_NONE;
RideMeasurement* measurement{};
auto ride = get_ride(w->number);
if (ride != nullptr)
if (ride == nullptr)
{
std::tie(measurement, stringId) = ride_get_measurement(ride);
return;
}
auto [measurement, message] = ride->GetMeasurement();
if (measurement == nullptr)
{
// No measurement message
ScreenCoordsXY stringCoords(widget->width() / 2, widget->height() / 2 - 5);
int32_t width = widget->width() - 2;
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, stringCoords, width, stringId, COLOUR_BLACK);
gfx_draw_string_centred_wrapped(dpi, message.args.Data(), stringCoords, width, message.str, COLOUR_BLACK);
return;
}

View File

@ -184,7 +184,7 @@ public:
ride->race_winner = SPRITE_INDEX_NULL;
ride->current_issues = 0;
ride->last_issue_time = 0;
ride_get_measurement(ride);
ride->GetMeasurement();
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
window_invalidate_by_number(WC_RIDE, _rideIndex);
break;
@ -231,7 +231,7 @@ public:
ride->status = _status;
ride->current_issues = 0;
ride->last_issue_time = 0;
ride_get_measurement(ride);
ride->GetMeasurement();
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
window_invalidate_by_number(WC_RIDE, _rideIndex);
break;

View File

@ -219,6 +219,7 @@
<ClInclude Include="localisation\Currency.h" />
<ClInclude Include="localisation\Date.h" />
<ClInclude Include="localisation\FormatCodes.h" />
<ClInclude Include="localisation\Formatter.h" />
<ClInclude Include="localisation\Language.h" />
<ClInclude Include="localisation\LanguagePack.h" />
<ClInclude Include="localisation\Localisation.h" />
@ -546,6 +547,7 @@
<ClCompile Include="localisation\Convert.cpp" />
<ClCompile Include="localisation\Currency.cpp" />
<ClCompile Include="localisation\FormatCodes.cpp" />
<ClCompile Include="localisation\Formatter.cpp" />
<ClCompile Include="localisation\Language.cpp" />
<ClCompile Include="localisation\LanguagePack.cpp" />
<ClCompile Include="localisation\Localisation.cpp" />
@ -775,4 +777,4 @@
<ClCompile Include="world\Wall.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -0,0 +1,33 @@
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "Formatter.h"
thread_local uint8_t gCommonFormatArgs[80];
Formatter& Formatter::operator=(const Formatter& other)
{
// If using global or not
if (other.StartBuf == other.Buffer.data())
{
std::copy(std::begin(other.Buffer), std::end(other.Buffer), std::begin(Buffer));
StartBuf = Buffer.data();
}
else
{
StartBuf = other.StartBuf;
}
CurrentBuf = StartBuf + other.NumBytes();
return *this;
}
Formatter Formatter::Common()
{
return Formatter{ gCommonFormatArgs };
}

View File

@ -0,0 +1,112 @@
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include "../common.h"
#include <array>
#include <cstring>
extern thread_local uint8_t gCommonFormatArgs[80];
class Formatter
{
std::array<uint8_t, 80> Buffer{};
uint8_t* StartBuf{};
uint8_t* CurrentBuf{};
public:
explicit Formatter(uint8_t* buf)
: StartBuf(buf)
, CurrentBuf(buf)
{
}
Formatter()
: Buffer{}
, StartBuf(Buffer.data())
, CurrentBuf(StartBuf)
{
}
Formatter(const Formatter& other)
{
*this = other;
}
Formatter& operator=(const Formatter& other);
static Formatter Common();
auto Buf()
{
return CurrentBuf;
}
auto Data() const
{
return StartBuf;
}
void Increment(size_t count)
{
CurrentBuf += count;
}
void Rewind()
{
CurrentBuf -= NumBytes();
}
std::size_t NumBytes() const
{
return CurrentBuf - StartBuf;
}
template<typename TSpecified, typename TDeduced> Formatter& Add(TDeduced value)
{
static_assert(sizeof(TSpecified) <= sizeof(uintptr_t), "Type too large");
static_assert(sizeof(TDeduced) <= sizeof(uintptr_t), "Type too large");
// clang-format off
static_assert(
std::is_same_v<TSpecified, char*> ||
std::is_same_v<TSpecified, const char*> ||
std::is_same_v<TSpecified, int16_t> ||
std::is_same_v<TSpecified, int32_t> ||
std::is_same_v<TSpecified, money32> ||
std::is_same_v<TSpecified, rct_string_id> ||
std::is_same_v<TSpecified, uint16_t> ||
std::is_same_v<TSpecified, uint32_t> ||
std::is_same_v<TSpecified, utf8*> ||
std::is_same_v<TSpecified, const utf8*>
);
// clang-format on
uintptr_t convertedValue;
if constexpr (std::is_integral_v<TSpecified>)
{
convertedValue = static_cast<uintptr_t>(value);
}
else
{
convertedValue = reinterpret_cast<uintptr_t>(value);
}
std::memcpy(CurrentBuf, &convertedValue, sizeof(TSpecified));
Increment(sizeof(TSpecified));
return *this;
}
};
struct OpenRCT2String
{
rct_string_id str;
Formatter args;
};

View File

@ -37,7 +37,6 @@
#include <limits.h>
thread_local char gCommonStringFormatBuffer[512];
thread_local uint8_t gCommonFormatArgs[80];
#ifdef DEBUG
// Set to true before a string format call to see details of the formatting.

View File

@ -17,8 +17,6 @@
#include "Language.h"
#include "StringIds.h"
#include <array>
#include <cstring>
#include <string>
bool utf8_is_format_code(char32_t codepoint);
@ -67,7 +65,6 @@ extern const char real_name_initials[16];
extern const char* real_names[1024];
extern thread_local char gCommonStringFormatBuffer[512];
extern thread_local uint8_t gCommonFormatArgs[80];
extern bool gDebugStringFormatting;
extern const rct_string_id SpeedNames[5];
@ -80,110 +77,4 @@ extern const rct_string_id DateDayNames[31];
extern const rct_string_id DateGameMonthNames[MONTH_COUNT];
extern const rct_string_id DateGameShortMonthNames[MONTH_COUNT];
class Formatter
{
std::array<uint8_t, 80> Buffer{};
uint8_t* StartBuf{};
uint8_t* CurrentBuf{};
public:
explicit Formatter(uint8_t* buf)
: StartBuf(buf)
, CurrentBuf(buf)
{
}
Formatter()
: Buffer{}
, StartBuf(Buffer.data())
, CurrentBuf(StartBuf)
{
}
Formatter(const Formatter& other)
{
*this = other;
}
Formatter& operator=(const Formatter& other)
{
// If using global or not
if (other.StartBuf == other.Buffer.data())
{
std::copy(std::begin(other.Buffer), std::end(other.Buffer), std::begin(Buffer));
StartBuf = Buffer.data();
}
else
{
StartBuf = other.StartBuf;
}
CurrentBuf = StartBuf + other.NumBytes();
return *this;
}
static Formatter Common()
{
return Formatter{ gCommonFormatArgs };
}
auto Buf()
{
return CurrentBuf;
}
auto Data() const
{
return StartBuf;
}
void Increment(size_t count)
{
CurrentBuf += count;
}
void Rewind()
{
CurrentBuf -= NumBytes();
}
std::size_t NumBytes() const
{
return CurrentBuf - StartBuf;
}
template<typename TSpecified, typename TDeduced> Formatter& Add(TDeduced value)
{
static_assert(sizeof(TSpecified) <= sizeof(uintptr_t), "Type too large");
static_assert(sizeof(TDeduced) <= sizeof(uintptr_t), "Type too large");
// clang-format off
static_assert(
std::is_same_v<TSpecified, char*> ||
std::is_same_v<TSpecified, const char*> ||
std::is_same_v<TSpecified, int16_t> ||
std::is_same_v<TSpecified, int32_t> ||
std::is_same_v<TSpecified, money32> ||
std::is_same_v<TSpecified, rct_string_id> ||
std::is_same_v<TSpecified, uint16_t> ||
std::is_same_v<TSpecified, uint32_t> ||
std::is_same_v<TSpecified, utf8*> ||
std::is_same_v<TSpecified, const utf8*>
);
// clang-format on
uintptr_t convertedValue;
if constexpr (std::is_integral_v<TSpecified>)
{
convertedValue = static_cast<uintptr_t>(value);
}
else
{
convertedValue = reinterpret_cast<uintptr_t>(value);
}
std::memcpy(CurrentBuf, &convertedValue, sizeof(TSpecified));
Increment(sizeof(TSpecified));
return *this;
}
};
#endif

View File

@ -3008,38 +3008,37 @@ static void ride_free_old_measurements()
} while (numRideMeasurements > MAX_RIDE_MEASUREMENTS);
}
std::pair<RideMeasurement*, rct_string_id> ride_get_measurement(Ride* ride)
std::pair<RideMeasurement*, OpenRCT2String> Ride::GetMeasurement()
{
// Check if ride type supports data logging
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING))
if (!ride_type_has_flag(type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING))
{
return { nullptr, STR_DATA_LOGGING_NOT_AVAILABLE_FOR_THIS_TYPE_OF_RIDE };
return { nullptr, { STR_DATA_LOGGING_NOT_AVAILABLE_FOR_THIS_TYPE_OF_RIDE, {} } };
}
// Check if a measurement already exists for this ride
auto& measurement = ride->measurement;
if (measurement == nullptr)
{
measurement = std::make_unique<RideMeasurement>();
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES))
if (ride_type_has_flag(type, RIDE_TYPE_FLAG_HAS_G_FORCES))
{
measurement->flags |= RIDE_MEASUREMENT_FLAG_G_FORCES;
}
ride_free_old_measurements();
assert(ride->measurement != nullptr);
assert(measurement != nullptr);
}
measurement->last_use_tick = gScenarioTicks;
if (measurement->flags & 1)
{
return { measurement.get(), STR_EMPTY };
return { measurement.get(), { STR_EMPTY, {} } };
}
else
{
auto ft = Formatter::Common();
ft.Add<rct_string_id>(RideComponentNames[RideTypeDescriptors[ride->type].NameConvention.vehicle].singular);
ft.Add<rct_string_id>(RideComponentNames[RideTypeDescriptors[ride->type].NameConvention.station].singular);
return { nullptr, STR_DATA_LOGGING_WILL_START_WHEN_NEXT_LEAVES };
auto ft = Formatter();
ft.Add<rct_string_id>(RideComponentNames[RideTypeDescriptors[type].NameConvention.vehicle].singular);
ft.Add<rct_string_id>(RideComponentNames[RideTypeDescriptors[type].NameConvention.station].singular);
return { nullptr, { STR_DATA_LOGGING_WILL_START_WHEN_NEXT_LEAVES, ft } };
}
}

View File

@ -11,6 +11,7 @@
#define _RIDE_H_
#include "../common.h"
#include "../localisation/Formatter.h"
#include "../rct12/RCT12.h"
#include "../rct2/RCT2.h"
#include "../world/Map.h"
@ -433,6 +434,8 @@ public:
uint64_t GetAvailableModes() const;
const RideTypeDescriptor& GetRideTypeDescriptor() const;
TrackElement* GetOriginElement(StationIndex stationIndex) const;
std::pair<RideMeasurement*, OpenRCT2String> GetMeasurement();
};
#pragma pack(push, 1)
@ -1108,7 +1111,6 @@ vehicle_colour ride_get_vehicle_colour(Ride* ride, int32_t vehicleIndex);
int32_t ride_get_unused_preset_vehicle_colour(uint8_t ride_sub_type);
void ride_set_vehicle_colours_to_random_preset(Ride* ride, uint8_t preset_index);
void ride_measurements_update();
std::pair<RideMeasurement*, rct_string_id> ride_get_measurement(Ride* ride);
void ride_breakdown_add_news_item(Ride* ride);
Peep* ride_find_closest_mechanic(Ride* ride, int32_t forInspection);
int32_t ride_is_valid_for_open(Ride* ride, int32_t goingToBeOpen, bool isApplying);