mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-04 13:42:55 +01:00
Fix #19822: Banners can now be copy-pasted from the tile inspector
This commit is contained in:
committed by
Michael Bernardi
parent
62914a39fb
commit
055a532571
@@ -8,6 +8,7 @@
|
||||
- Fix: [#6152] Camera and UI are no longer locked at 40 Hz, providing a smoother experience.
|
||||
- Fix: [#9534] Screams no longer cut-off on steep diagonal drops.
|
||||
- Fix: [#19450] The correct element is now auto-suggested when building a Medium Half Loop backwards.
|
||||
- Fix: [#19822] Tile inspector does not deep copy banners.
|
||||
- Fix: [#19823] Parkobj: disallow overriding objects of different object types.
|
||||
- Fix: [#19878] Unresearched scenery can be placed via prebuilt rides.
|
||||
- Fix: [#20083] Cannot use terrain surfaces with ID > 32 and terrain edges with ID > 16.
|
||||
|
||||
@@ -483,6 +483,7 @@ private:
|
||||
bool _applyToAll = false;
|
||||
bool _elementCopied = false;
|
||||
TileElement _copiedElement;
|
||||
Banner _copiedBanner;
|
||||
|
||||
public:
|
||||
void OnOpen() override
|
||||
@@ -1835,13 +1836,21 @@ private:
|
||||
{
|
||||
// Copy value, in case the element gets moved
|
||||
_copiedElement = *GetSelectedElement();
|
||||
_copiedBanner = {};
|
||||
auto bannerIndex = _copiedElement.GetBannerIndex();
|
||||
if (bannerIndex != BannerIndex::GetNull())
|
||||
{
|
||||
auto banner = GetBanner(bannerIndex);
|
||||
if (banner != nullptr)
|
||||
_copiedBanner = *banner;
|
||||
}
|
||||
_elementCopied = true;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void PasteElement()
|
||||
{
|
||||
auto modifyTile = TileModifyAction(_toolMap, TileModifyType::AnyPaste, 0, 0, _copiedElement);
|
||||
auto modifyTile = TileModifyAction(_toolMap, TileModifyType::AnyPaste, 0, 0, _copiedElement, _copiedBanner);
|
||||
GameActions::Execute(&modifyTile);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
using namespace OpenRCT2;
|
||||
|
||||
TileModifyAction::TileModifyAction(
|
||||
CoordsXY loc, TileModifyType setting, uint32_t value1, uint32_t value2, TileElement pasteElement)
|
||||
CoordsXY loc, TileModifyType setting, uint32_t value1, uint32_t value2, TileElement pasteElement, Banner pasteBanner)
|
||||
: _loc(loc)
|
||||
, _setting(setting)
|
||||
, _value1(value1)
|
||||
, _value2(value2)
|
||||
, _pasteElement(pasteElement)
|
||||
, _pasteBanner(pasteBanner)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,7 +41,8 @@ void TileModifyAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
|
||||
stream << DS_TAG(_loc) << DS_TAG(_setting) << DS_TAG(_value1) << DS_TAG(_value2) << DS_TAG(_pasteElement);
|
||||
stream << DS_TAG(_loc) << DS_TAG(_setting) << DS_TAG(_value1) << DS_TAG(_value2) << DS_TAG(_pasteElement)
|
||||
<< DS_TAG(_pasteBanner);
|
||||
}
|
||||
|
||||
GameActions::Result TileModifyAction::Query() const
|
||||
@@ -89,7 +91,7 @@ GameActions::Result TileModifyAction::QueryExecute(bool isExecuting) const
|
||||
}
|
||||
case TileModifyType::AnyPaste:
|
||||
{
|
||||
res = TileInspector::PasteElementAt(_loc, _pasteElement, isExecuting);
|
||||
res = TileInspector::PasteElementAt(_loc, _pasteElement, _pasteBanner, isExecuting);
|
||||
break;
|
||||
}
|
||||
case TileModifyType::AnySort:
|
||||
|
||||
@@ -49,11 +49,13 @@ private:
|
||||
uint32_t _value1{};
|
||||
uint32_t _value2{};
|
||||
TileElement _pasteElement{};
|
||||
Banner _pasteBanner{};
|
||||
|
||||
public:
|
||||
TileModifyAction() = default;
|
||||
TileModifyAction(
|
||||
CoordsXY loc, TileModifyType setting, uint32_t value1 = 0, uint32_t value2 = 0, TileElement pasteElement = {});
|
||||
CoordsXY loc, TileModifyType setting, uint32_t value1 = 0, uint32_t value2 = 0, TileElement pasteElement = {},
|
||||
Banner _pasteBanner = {});
|
||||
|
||||
void AcceptParameters(GameActionParameterVisitor& visitor) override;
|
||||
|
||||
|
||||
@@ -890,3 +890,38 @@ template<typename T, T TNull, typename TTag> struct DataSerializerTraitsT<TIdent
|
||||
stream->Write(msg, strlen(msg));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct DataSerializerTraitsT<Banner>
|
||||
{
|
||||
static void encode(OpenRCT2::IStream* stream, const Banner& banner)
|
||||
{
|
||||
DataSerializerTraits<BannerIndex>().encode(stream, banner.id);
|
||||
DataSerializerTraits<ObjectEntryIndex>().encode(stream, banner.type);
|
||||
stream->WriteValue(banner.flags);
|
||||
stream->WriteString(banner.text);
|
||||
stream->WriteValue(banner.colour);
|
||||
DataSerializerTraits<RideId>().encode(stream, banner.ride_index);
|
||||
stream->WriteValue(banner.text_colour);
|
||||
DataSerializerTraits<TileCoordsXY>().encode(stream, banner.position);
|
||||
}
|
||||
|
||||
static void decode(OpenRCT2::IStream* stream, Banner& banner)
|
||||
{
|
||||
DataSerializerTraits<BannerIndex>().decode(stream, banner.id);
|
||||
DataSerializerTraits<ObjectEntryIndex>().decode(stream, banner.type);
|
||||
stream->Read(&banner.flags);
|
||||
banner.text = stream->ReadStdString();
|
||||
stream->Read(&banner.colour);
|
||||
DataSerializerTraits<RideId>().decode(stream, banner.ride_index);
|
||||
stream->Read(&banner.text_colour);
|
||||
DataSerializerTraits<TileCoordsXY>().decode(stream, banner.position);
|
||||
}
|
||||
|
||||
static void log(OpenRCT2::IStream* stream, const Banner& banner)
|
||||
{
|
||||
char msg[128] = {};
|
||||
snprintf(
|
||||
msg, sizeof(msg), "Banner(x = %d, y = %d, text = %s)", banner.position.x, banner.position.y, banner.text.c_str());
|
||||
stream->Write(msg, strlen(msg));
|
||||
}
|
||||
};
|
||||
@@ -320,7 +320,7 @@ namespace OpenRCT2::TileInspector
|
||||
return GameActions::Result();
|
||||
}
|
||||
|
||||
GameActions::Result PasteElementAt(const CoordsXY& loc, TileElement element, bool isExecuting)
|
||||
GameActions::Result PasteElementAt(const CoordsXY& loc, TileElement element, Banner banner, bool isExecuting)
|
||||
{
|
||||
// Make sure there is enough space for the new element
|
||||
if (!MapCheckCapacityAndReorganise(loc))
|
||||
@@ -330,28 +330,31 @@ namespace OpenRCT2::TileInspector
|
||||
|
||||
auto tileLoc = TileCoordsXY(loc);
|
||||
|
||||
auto bannerIndex = element.GetBannerIndex();
|
||||
if (bannerIndex != BannerIndex::GetNull() && GetBanner(bannerIndex) == nullptr)
|
||||
{
|
||||
return GameActions::Result(GameActions::Status::Unknown, STR_NONE, STR_NONE);
|
||||
}
|
||||
|
||||
if (isExecuting)
|
||||
{
|
||||
// Check if the element to be pasted refers to a banner index
|
||||
if (bannerIndex != BannerIndex::GetNull())
|
||||
// Check if the element to be pasted has a banner
|
||||
if (element.GetBannerIndex() != BannerIndex::GetNull())
|
||||
{
|
||||
// The element to be pasted refers to a banner index - make a copy of it
|
||||
// The element to be pasted has a banner - make a copy of it from the banner provided
|
||||
auto newBanner = CreateBanner();
|
||||
if (newBanner == nullptr)
|
||||
{
|
||||
LOG_ERROR("No free banners available");
|
||||
return GameActions::Result(GameActions::Status::Unknown, STR_TOO_MANY_BANNERS_IN_GAME, STR_NONE);
|
||||
}
|
||||
auto newId = newBanner->id;
|
||||
// Copy the banners style
|
||||
*newBanner = *GetBanner(bannerIndex);
|
||||
*newBanner = banner;
|
||||
// Reset the location to the paste location
|
||||
newBanner->position = tileLoc;
|
||||
newBanner->id = newId;
|
||||
|
||||
// If the linked ride has been destroyed since copying, unlink the pasted banner
|
||||
if (newBanner->flags & BANNER_FLAG_LINKED_TO_RIDE && GetRide(newBanner->ride_index) == nullptr)
|
||||
{
|
||||
newBanner->flags &= ~BANNER_FLAG_LINKED_TO_RIDE;
|
||||
newBanner->ride_index = RideId::GetNull();
|
||||
}
|
||||
|
||||
// Use the new banner index
|
||||
element.SetBannerIndex(newBanner->id);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRCT2::TileInspector
|
||||
GameActions::Result SwapElementsAt(const CoordsXY& loc, int16_t first, int16_t second, bool isExecuting);
|
||||
GameActions::Result RotateElementAt(const CoordsXY& loc, int32_t elementIndex, bool isExecuting);
|
||||
GameActions::Result ToggleInvisibilityOfElementAt(const CoordsXY& loc, int32_t elementIndex, bool isExecuting);
|
||||
GameActions::Result PasteElementAt(const CoordsXY& loc, TileElement element, bool isExecuting);
|
||||
GameActions::Result PasteElementAt(const CoordsXY& loc, TileElement element, Banner banner, bool isExecuting);
|
||||
GameActions::Result SortElementsAt(const CoordsXY& loc, bool isExecuting);
|
||||
GameActions::Result AnyBaseHeightOffset(const CoordsXY& loc, int16_t elementIndex, int8_t heightOffset, bool isExecuting);
|
||||
GameActions::Result SurfaceShowParkFences(const CoordsXY& loc, bool showFences, bool isExecuting);
|
||||
|
||||
Reference in New Issue
Block a user