Merge pull request #15816 from ZehMatt/refactor/15630

Close #15630: Refactor TrackDesign
This commit is contained in:
Michael Steenbeek 2021-11-07 19:53:32 +01:00 committed by GitHub
commit 084b752fb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 588 additions and 531 deletions

View File

@ -81,7 +81,7 @@ static void window_install_track_design(rct_window* w);
*/
rct_window* window_install_track_open(const utf8* path)
{
_trackDesign = track_design_open(path);
_trackDesign = TrackDesignImport(path);
if (_trackDesign == nullptr)
{
context_show_error(STR_UNABLE_TO_LOAD_FILE, STR_NONE, {});
@ -422,7 +422,7 @@ static void window_install_track_text_input(rct_window* w, rct_widgetindex widge
static void window_install_track_update_preview()
{
track_design_draw_preview(_trackDesign.get(), _trackDesignPreviewPixels.data());
TrackDesignDrawPreview(_trackDesign.get(), _trackDesignPreviewPixels.data());
}
static void window_install_track_design(rct_window* w)

View File

@ -5325,7 +5325,8 @@ static void window_ride_measurements_design_save(rct_window* w)
if (gTrackDesignSaveMode)
{
auto errMessage = _trackDesign->CreateTrackDesignScenery();
TrackDesignState tds{};
auto errMessage = _trackDesign->CreateTrackDesignScenery(tds);
if (errMessage != STR_NONE)
{
context_show_error(STR_CANT_SAVE_TRACK_DESIGN, errMessage, {});

View File

@ -133,7 +133,7 @@ static void window_track_place_clear_mini_preview()
*/
rct_window* window_track_place_open(const track_design_file_ref* tdFileRef)
{
_trackDesign = track_design_open(tdFileRef->path);
_trackDesign = TrackDesignImport(tdFileRef->path);
if (_trackDesign == nullptr)
{
return nullptr;
@ -197,7 +197,7 @@ static void window_track_place_mouseup(rct_window* w, rct_widgetindex widgetInde
window_track_place_draw_mini_preview(_trackDesign.get());
break;
case WIDX_MIRROR:
track_design_mirror(_trackDesign.get());
TrackDesignMirror(_trackDesign.get());
_currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3;
w->Invalidate();
_windowTrackPlaceLast.SetNull();
@ -268,8 +268,7 @@ static void window_track_place_toolupdate(rct_window* w, rct_widgetindex widgetI
// Check if tool map position has changed since last update
if (mapCoords == _windowTrackPlaceLast)
{
place_virtual_track(
_trackDesign.get(), PTD_OPERATION_DRAW_OUTLINES, true, GetOrAllocateRide(PreviewRideId), { mapCoords, 0 });
TrackDesignPreviewDrawOutlines(_trackDesign.get(), GetOrAllocateRide(PreviewRideId), { mapCoords, 0 });
return;
}
@ -309,7 +308,7 @@ static void window_track_place_toolupdate(rct_window* w, rct_widgetindex widgetI
widget_invalidate(w, WIDX_PRICE);
}
place_virtual_track(_trackDesign.get(), PTD_OPERATION_DRAW_OUTLINES, true, GetOrAllocateRide(PreviewRideId), trackLoc);
TrackDesignPreviewDrawOutlines(_trackDesign.get(), GetOrAllocateRide(PreviewRideId), trackLoc);
}
/**
@ -413,7 +412,7 @@ static void window_track_place_clear_provisional()
auto ride = get_ride(_window_track_place_ride_index);
if (ride != nullptr)
{
place_virtual_track(_trackDesign.get(), PTD_OPERATION_REMOVE_GHOST, true, ride, _windowTrackPlaceLastValid);
TrackDesignPreviewRemoveGhosts(_trackDesign.get(), ride, _windowTrackPlaceLastValid);
_window_track_place_last_was_valid = false;
}
}
@ -426,7 +425,7 @@ void TrackPlaceClearProvisionalTemporarily()
auto ride = get_ride(_window_track_place_ride_index);
if (ride != nullptr)
{
place_virtual_track(_trackDesign.get(), PTD_OPERATION_REMOVE_GHOST, true, ride, _windowTrackPlaceLastValid);
TrackDesignPreviewRemoveGhosts(_trackDesign.get(), ride, _windowTrackPlaceLastValid);
}
}
}
@ -471,9 +470,7 @@ static int32_t window_track_place_get_base_z(const CoordsXY& loc)
if (surfaceElement->GetWaterHeight() > 0)
z = std::max(z, surfaceElement->GetWaterHeight());
return z
+ place_virtual_track(
_trackDesign.get(), PTD_OPERATION_GET_PLACE_Z, true, GetOrAllocateRide(PreviewRideId), { loc, z });
return z + TrackDesignGetZPlacement(_trackDesign.get(), GetOrAllocateRide(PreviewRideId), { loc, z });
}
/**

View File

@ -186,10 +186,10 @@ private:
bool LoadDesignPreview(utf8* path)
{
_loadedTrackDesign = track_design_open(path);
_loadedTrackDesign = TrackDesignImport(path);
if (_loadedTrackDesign != nullptr)
{
track_design_draw_preview(_loadedTrackDesign.get(), _trackDesignPreviewPixels.data());
TrackDesignDrawPreview(_loadedTrackDesign.get(), _trackDesignPreviewPixels.data());
return true;
}
return false;

View File

@ -21,12 +21,6 @@
#include "RideSetSettingAction.h"
#include "RideSetVehicleAction.h"
static int32_t place_virtual_track(
const TrackDesign& td6, uint8_t ptdOperation, bool placeScenery, Ride* ride, const CoordsXYZ& loc)
{
return place_virtual_track(const_cast<TrackDesign*>(&td6), ptdOperation, placeScenery, ride, loc);
}
TrackDesignAction::TrackDesignAction(const CoordsXYZD& location, const TrackDesign& td)
: _loc(location)
, _td(td)
@ -95,26 +89,36 @@ GameActions::Result::Ptr TrackDesignAction::Query() const
return MakeResult(GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NONE);
}
money32 cost = 0;
bool placeScenery = true;
cost = place_virtual_track(_td, PTD_OPERATION_PLACE_QUERY, placeScenery, ride, _loc);
uint32_t flags = 0;
if (GetFlags() & GAME_COMMAND_FLAG_GHOST)
flags |= GAME_COMMAND_FLAG_GHOST;
if (GetFlags() & GAME_COMMAND_FLAG_REPLAY)
flags |= GAME_COMMAND_FLAG_REPLAY;
auto queryRes = TrackDesignPlace(const_cast<TrackDesign*>(&_td), flags, placeScenery, ride, _loc);
if (_trackDesignPlaceStateSceneryUnavailable)
{
placeScenery = false;
cost = place_virtual_track(_td, PTD_OPERATION_PLACE_QUERY, placeScenery, ride, _loc);
queryRes = TrackDesignPlace(const_cast<TrackDesign*>(&_td), flags, placeScenery, ride, _loc);
}
rct_string_id error_reason = gGameCommandErrorText;
auto gameAction = RideDemolishAction(ride->id, RIDE_MODIFY_DEMOLISH);
gameAction.SetFlags(GetFlags());
GameActions::ExecuteNested(&gameAction);
if (cost == MONEY32_UNDEFINED)
if (queryRes->Error != GameActions::Status::Ok)
{
return MakeResult(GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, error_reason);
res->Error = queryRes->Error;
res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
res->ErrorMessage = queryRes->ErrorMessage;
res->ErrorMessageArgs = queryRes->ErrorMessageArgs;
return res;
}
res->Cost = cost;
res->Cost = queryRes->Cost;
res->SetData(ride_id_t{ RIDE_ID_NULL });
return res;
@ -157,42 +161,52 @@ GameActions::Result::Ptr TrackDesignAction::Execute() const
return MakeResult(GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NONE);
}
money32 cost = 0;
// Query first, this is required again to determine if scenery is available.
bool placeScenery = true;
cost = place_virtual_track(_td, PTD_OPERATION_PLACE_QUERY, placeScenery, ride, _loc);
uint32_t flags = 0;
if (GetFlags() & GAME_COMMAND_FLAG_GHOST)
flags |= GAME_COMMAND_FLAG_GHOST;
if (GetFlags() & GAME_COMMAND_FLAG_REPLAY)
flags |= GAME_COMMAND_FLAG_REPLAY;
auto queryRes = TrackDesignPlace(const_cast<TrackDesign*>(&_td), flags, placeScenery, ride, _loc);
if (_trackDesignPlaceStateSceneryUnavailable)
{
placeScenery = false;
cost = place_virtual_track(_td, PTD_OPERATION_PLACE_QUERY, placeScenery, ride, _loc);
queryRes = TrackDesignPlace(const_cast<TrackDesign*>(&_td), flags, placeScenery, ride, _loc);
}
if (cost != MONEY32_UNDEFINED)
if (queryRes->Error != GameActions::Status::Ok)
{
uint8_t operation;
if (GetFlags() & GAME_COMMAND_FLAG_GHOST)
{
operation = PTD_OPERATION_PLACE_GHOST;
}
else
{
operation = PTD_OPERATION_PLACE;
}
if (GetFlags() & GAME_COMMAND_FLAG_REPLAY)
{
operation |= PTD_OPERATION_FLAG_IS_REPLAY;
}
cost = place_virtual_track(_td, operation, placeScenery, ride, _loc);
}
if (cost == MONEY32_UNDEFINED)
{
rct_string_id error_reason = gGameCommandErrorText;
auto gameAction = RideDemolishAction(ride->id, RIDE_MODIFY_DEMOLISH);
gameAction.SetFlags(GetFlags());
GameActions::ExecuteNested(&gameAction);
return MakeResult(GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, error_reason);
res->Error = queryRes->Error;
res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
res->ErrorMessage = queryRes->ErrorMessage;
res->ErrorMessageArgs = queryRes->ErrorMessageArgs;
return res;
}
// Execute.
flags |= GAME_COMMAND_FLAG_APPLY;
auto execRes = TrackDesignPlace(const_cast<TrackDesign*>(&_td), flags, placeScenery, ride, _loc);
if (execRes->Error != GameActions::Status::Ok)
{
auto gameAction = RideDemolishAction(ride->id, RIDE_MODIFY_DEMOLISH);
gameAction.SetFlags(GetFlags());
GameActions::ExecuteNested(&gameAction);
res->Error = execRes->Error;
res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
res->ErrorMessage = execRes->ErrorMessage;
res->ErrorMessageArgs = execRes->ErrorMessageArgs;
return res;
}
if (entryIndex != OBJECT_ENTRY_INDEX_NULL)
@ -250,7 +264,7 @@ GameActions::Result::Ptr TrackDesignAction::Execute() const
gameAction.SetFlags(GetFlags());
r = GameActions::ExecuteNested(&gameAction);
}
res->Cost = cost;
res->Cost = execRes->Cost;
res->SetData(ride_id_t{ ride->id });
return res;

View File

@ -963,8 +963,9 @@ std::unique_ptr<TrackDesign> Ride::SaveToTrackDesign() const
return nullptr;
}
auto tds = TrackDesignState{};
auto td = std::make_unique<TrackDesign>();
auto errMessage = td->CreateTrackDesign(*this);
auto errMessage = td->CreateTrackDesign(tds, *this);
if (errMessage != STR_NONE)
{
context_show_error(STR_CANT_SAVE_TRACK_DESIGN, errMessage, {});

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
#pragma once
#include "../actions/GameActionResult.h"
#include "../common.h"
#include "../object/Object.h"
#include "../rct12/RCT12.h"
@ -19,6 +20,20 @@ struct Ride;
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
struct TrackDesignState
{
CoordsXYZ PreviewMin;
CoordsXYZ PreviewMax;
CoordsXYZ Origin;
uint8_t PlaceOperation{};
int16_t PlaceZ{};
int16_t PlaceSceneryZ{};
bool EntranceExitPlaced{};
bool HasScenery{};
bool PlaceScenery{};
bool IsReplay{};
};
/* Track Entrance entry */
struct TrackDesignEntranceElement
{
@ -134,14 +149,14 @@ struct TrackDesign
std::string name;
public:
rct_string_id CreateTrackDesign(const Ride& ride);
rct_string_id CreateTrackDesignScenery();
rct_string_id CreateTrackDesign(TrackDesignState& tds, const Ride& ride);
rct_string_id CreateTrackDesignScenery(TrackDesignState& tds);
void Serialise(DataSerialiser& stream);
private:
uint8_t _saveDirection;
rct_string_id CreateTrackDesignTrack(const Ride& ride);
rct_string_id CreateTrackDesignMaze(const Ride& ride);
rct_string_id CreateTrackDesignTrack(TrackDesignState& tds, const Ride& ride);
rct_string_id CreateTrackDesignMaze(TrackDesignState& tds, const Ride& ride);
CoordsXYE MazeGetFirstElement(const Ride& ride);
};
@ -206,16 +221,20 @@ extern bool _trackDesignPlaceStateSceneryUnavailable;
extern bool gTrackDesignSaveMode;
extern ride_id_t gTrackDesignSaveRideIndex;
[[nodiscard]] std::unique_ptr<TrackDesign> track_design_open(const utf8* path);
[[nodiscard]] std::unique_ptr<TrackDesign> TrackDesignImport(const utf8* path);
void track_design_mirror(TrackDesign* td6);
void TrackDesignMirror(TrackDesign* td6);
money32 place_virtual_track(TrackDesign* td6, uint8_t ptdOperation, bool placeScenery, Ride* ride, const CoordsXYZ& coords);
GameActions::Result::Ptr TrackDesignPlace(
TrackDesign* td6, uint32_t flags, bool placeScenery, Ride* ride, const CoordsXYZ& coords);
void TrackDesignPreviewRemoveGhosts(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords);
void TrackDesignPreviewDrawOutlines(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords);
int32_t TrackDesignGetZPlacement(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords);
///////////////////////////////////////////////////////////////////////////////
// Track design preview
///////////////////////////////////////////////////////////////////////////////
void track_design_draw_preview(TrackDesign* td6, uint8_t* pixels);
void TrackDesignDrawPreview(TrackDesign* td6, uint8_t* pixels);
///////////////////////////////////////////////////////////////////////////////
// Track design saving

View File

@ -75,7 +75,7 @@ public:
public:
std::tuple<bool, TrackRepositoryItem> Create(int32_t, const std::string& path) const override
{
auto td6 = track_design_open(path.c_str());
auto td6 = TrackDesignImport(path.c_str());
if (td6 != nullptr)
{
TrackRepositoryItem item;