mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #16127 from Gymnasiast/feature/rct1-image-fallback
Create fallback system for csg1 images
This commit is contained in:
commit
4caeb797f8
|
@ -61,9 +61,9 @@ set(TITLE_SEQUENCE_VERSION "0.1.2c")
|
||||||
set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v${TITLE_SEQUENCE_VERSION}/title-sequences.zip")
|
set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v${TITLE_SEQUENCE_VERSION}/title-sequences.zip")
|
||||||
set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d")
|
set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d")
|
||||||
|
|
||||||
set(OBJECTS_VERSION "1.2.2")
|
set(OBJECTS_VERSION "1.2.4")
|
||||||
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip")
|
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip")
|
||||||
set(OBJECTS_SHA1 "a808fd47e9bc35d105dc371428a55888e6a86860")
|
set(OBJECTS_SHA1 "c82605035f120188b7334a781a786ced9588e9af")
|
||||||
|
|
||||||
set(REPLAYS_VERSION "0.0.60")
|
set(REPLAYS_VERSION "0.0.60")
|
||||||
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip")
|
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip")
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
<GtestSha1>058b9df80244c03f1633cb06e9f70471a29ebb8e</GtestSha1>
|
<GtestSha1>058b9df80244c03f1633cb06e9f70471a29ebb8e</GtestSha1>
|
||||||
<TitleSequencesUrl>https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2c/title-sequences.zip</TitleSequencesUrl>
|
<TitleSequencesUrl>https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2c/title-sequences.zip</TitleSequencesUrl>
|
||||||
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
|
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
|
||||||
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.2.2/objects.zip</ObjectsUrl>
|
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.2.4/objects.zip</ObjectsUrl>
|
||||||
<ObjectsSha1>a808fd47e9bc35d105dc371428a55888e6a86860</ObjectsSha1>
|
<ObjectsSha1>c82605035f120188b7334a781a786ced9588e9af</ObjectsSha1>
|
||||||
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.60/replays.zip</ReplaysUrl>
|
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.60/replays.zip</ReplaysUrl>
|
||||||
<ReplaysSha1>1EB460BB3C71BD21CCBE778BEF1E8CD593241A18</ReplaysSha1>
|
<ReplaysSha1>1EB460BB3C71BD21CCBE778BEF1E8CD593241A18</ReplaysSha1>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -15,8 +15,8 @@ let
|
||||||
objects-src = pkgs.fetchFromGitHub {
|
objects-src = pkgs.fetchFromGitHub {
|
||||||
owner = "OpenRCT2";
|
owner = "OpenRCT2";
|
||||||
repo = "objects";
|
repo = "objects";
|
||||||
rev = "v1.2.2";
|
rev = "v1.2.4";
|
||||||
sha256 = "2c77023068831c68423eb51f96251d1a06f58253414e4563ca17407d654ed96b";
|
sha256 = "d01e5f1d2c95ba8ee295c457ae6215c048728ab07adc3db58a08f3cf2b1fa179";
|
||||||
};
|
};
|
||||||
|
|
||||||
title-sequences-src = pkgs.fetchFromGitHub {
|
title-sequences-src = pkgs.fetchFromGitHub {
|
||||||
|
|
|
@ -64,8 +64,8 @@ void LandTool::ShowSurfaceStyleDropdown(rct_window* w, rct_widget* widget, Objec
|
||||||
for (size_t i = 0; i < MAX_TERRAIN_SURFACE_OBJECTS; i++)
|
for (size_t i = 0; i < MAX_TERRAIN_SURFACE_OBJECTS; i++)
|
||||||
{
|
{
|
||||||
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(objManager.GetLoadedObject(ObjectType::TerrainSurface, i));
|
const auto surfaceObj = static_cast<TerrainSurfaceObject*>(objManager.GetLoadedObject(ObjectType::TerrainSurface, i));
|
||||||
// NumImagesLoaded can be 1 for RCT1 surfaces if the user does not have RCT1 linked.
|
// If fallback images are loaded, the RCT1 styles will just look like copies of already existing styles, so hide them.
|
||||||
if (surfaceObj != nullptr && surfaceObj->NumImagesLoaded > 1)
|
if (surfaceObj != nullptr && !surfaceObj->UsesFallbackImages())
|
||||||
{
|
{
|
||||||
gDropdownItemsFormat[itemIndex] = Dropdown::FormatLandPicker;
|
gDropdownItemsFormat[itemIndex] = Dropdown::FormatLandPicker;
|
||||||
gDropdownItemsArgs[itemIndex] = surfaceObj->IconImageId;
|
gDropdownItemsArgs[itemIndex] = surfaceObj->IconImageId;
|
||||||
|
@ -98,7 +98,8 @@ void LandTool::ShowEdgeStyleDropdown(rct_window* w, rct_widget* widget, ObjectEn
|
||||||
for (size_t i = 0; i < MAX_TERRAIN_EDGE_OBJECTS; i++)
|
for (size_t i = 0; i < MAX_TERRAIN_EDGE_OBJECTS; i++)
|
||||||
{
|
{
|
||||||
const auto edgeObj = static_cast<TerrainEdgeObject*>(objManager.GetLoadedObject(ObjectType::TerrainEdge, i));
|
const auto edgeObj = static_cast<TerrainEdgeObject*>(objManager.GetLoadedObject(ObjectType::TerrainEdge, i));
|
||||||
if (edgeObj != nullptr && edgeObj->NumImagesLoaded > 1)
|
// If fallback images are loaded, the RCT1 styles will just look like copies of already existing styles, so hide them.
|
||||||
|
if (edgeObj != nullptr && !edgeObj->UsesFallbackImages())
|
||||||
{
|
{
|
||||||
gDropdownItemsFormat[itemIndex] = Dropdown::FormatLandPicker;
|
gDropdownItemsFormat[itemIndex] = Dropdown::FormatLandPicker;
|
||||||
gDropdownItemsArgs[itemIndex] = edgeObj->IconImageId;
|
gDropdownItemsArgs[itemIndex] = edgeObj->IconImageId;
|
||||||
|
|
|
@ -443,15 +443,23 @@ std::vector<std::pair<std::string, Image>> ImageTable::GetImageSources(IReadObje
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageTable::ReadJson(IReadObjectContext* context, json_t& root)
|
bool ImageTable::ReadJson(IReadObjectContext* context, json_t& root)
|
||||||
{
|
{
|
||||||
Guard::Assert(root.is_object(), "ImageTable::ReadJson expects parameter root to be object");
|
Guard::Assert(root.is_object(), "ImageTable::ReadJson expects parameter root to be object");
|
||||||
|
|
||||||
|
bool usesFallbackSprites = false;
|
||||||
|
|
||||||
if (context->ShouldLoadImages())
|
if (context->ShouldLoadImages())
|
||||||
{
|
{
|
||||||
// First gather all the required images from inspecting the JSON
|
// First gather all the required images from inspecting the JSON
|
||||||
std::vector<std::unique_ptr<RequiredImage>> allImages;
|
std::vector<std::unique_ptr<RequiredImage>> allImages;
|
||||||
auto jsonImages = root["images"];
|
auto jsonImages = root["images"];
|
||||||
|
if (!is_csg_loaded() && root.contains("noCsgImages"))
|
||||||
|
{
|
||||||
|
jsonImages = root["noCsgImages"];
|
||||||
|
usesFallbackSprites = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto imageSources = GetImageSources(context, jsonImages);
|
auto imageSources = GetImageSources(context, jsonImages);
|
||||||
|
|
||||||
for (auto& jsonImage : jsonImages)
|
for (auto& jsonImage : jsonImages)
|
||||||
|
@ -506,6 +514,8 @@ void ImageTable::ReadJson(IReadObjectContext* context, json_t& root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return usesFallbackSprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageTable::AddImage(const rct_g1_element* g1)
|
void ImageTable::AddImage(const rct_g1_element* g1)
|
||||||
|
|
|
@ -56,7 +56,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @note root is deliberately left non-const: json_t behaviour changes when const
|
* @note root is deliberately left non-const: json_t behaviour changes when const
|
||||||
*/
|
*/
|
||||||
void ReadJson(IReadObjectContext* context, json_t& root);
|
bool ReadJson(IReadObjectContext* context, json_t& root);
|
||||||
const rct_g1_element* GetImages() const
|
const rct_g1_element* GetImages() const
|
||||||
{
|
{
|
||||||
return _entries.data();
|
return _entries.data();
|
||||||
|
|
|
@ -116,7 +116,7 @@ void Object::ReadLegacy(IReadObjectContext* context, OpenRCT2::IStream* stream)
|
||||||
void Object::PopulateTablesFromJson(IReadObjectContext* context, json_t& root)
|
void Object::PopulateTablesFromJson(IReadObjectContext* context, json_t& root)
|
||||||
{
|
{
|
||||||
_stringTable.ReadJson(root);
|
_stringTable.ReadJson(root);
|
||||||
_imageTable.ReadJson(context, root);
|
_usesFallbackImages = _imageTable.ReadJson(context, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
rct_object_entry Object::ParseObjectEntry(const std::string& s)
|
rct_object_entry Object::ParseObjectEntry(const std::string& s)
|
||||||
|
|
|
@ -259,6 +259,7 @@ private:
|
||||||
std::vector<ObjectSourceGame> _sourceGames;
|
std::vector<ObjectSourceGame> _sourceGames;
|
||||||
std::vector<std::string> _authors;
|
std::vector<std::string> _authors;
|
||||||
ObjectGeneration _generation{};
|
ObjectGeneration _generation{};
|
||||||
|
bool _usesFallbackImages{};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StringTable& GetStringTable()
|
StringTable& GetStringTable()
|
||||||
|
@ -324,6 +325,11 @@ public:
|
||||||
_descriptor = value;
|
_descriptor = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr bool UsesFallbackImages() const
|
||||||
|
{
|
||||||
|
return _usesFallbackImages;
|
||||||
|
}
|
||||||
|
|
||||||
// Legacy data structures
|
// Legacy data structures
|
||||||
std::string_view GetLegacyIdentifier() const
|
std::string_view GetLegacyIdentifier() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,7 +59,6 @@ void TerrainEdgeObject::ReadJson(IReadObjectContext* context, json_t& root)
|
||||||
}
|
}
|
||||||
|
|
||||||
PopulateTablesFromJson(context, root);
|
PopulateTablesFromJson(context, root);
|
||||||
NumImagesLoaded = GetImageTable().GetCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainEdgeObject* TerrainEdgeObject::GetById(ObjectEntryIndex entryIndex)
|
TerrainEdgeObject* TerrainEdgeObject::GetById(ObjectEntryIndex entryIndex)
|
||||||
|
|
|
@ -18,7 +18,6 @@ public:
|
||||||
rct_string_id NameStringId{};
|
rct_string_id NameStringId{};
|
||||||
uint32_t IconImageId{};
|
uint32_t IconImageId{};
|
||||||
uint32_t BaseImageId{};
|
uint32_t BaseImageId{};
|
||||||
uint32_t NumImagesLoaded{};
|
|
||||||
bool HasDoors{};
|
bool HasDoors{};
|
||||||
|
|
||||||
void ReadJson(IReadObjectContext* context, json_t& root) override;
|
void ReadJson(IReadObjectContext* context, json_t& root) override;
|
||||||
|
|
|
@ -125,8 +125,6 @@ void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, json_t& root)
|
||||||
}
|
}
|
||||||
|
|
||||||
PopulateTablesFromJson(context, root);
|
PopulateTablesFromJson(context, root);
|
||||||
|
|
||||||
NumImagesLoaded = GetImageTable().GetCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TerrainSurfaceObject::GetImageId(
|
uint32_t TerrainSurfaceObject::GetImageId(
|
||||||
|
|
|
@ -54,8 +54,6 @@ public:
|
||||||
money32 Price{};
|
money32 Price{};
|
||||||
TERRAIN_SURFACE_FLAGS Flags{};
|
TERRAIN_SURFACE_FLAGS Flags{};
|
||||||
|
|
||||||
uint32_t NumImagesLoaded{};
|
|
||||||
|
|
||||||
void ReadJson(IReadObjectContext* context, json_t& root) override;
|
void ReadJson(IReadObjectContext* context, json_t& root) override;
|
||||||
void Load() override;
|
void Load() override;
|
||||||
void Unload() override;
|
void Unload() override;
|
||||||
|
|
|
@ -317,15 +317,6 @@ static uint32_t get_surface_image(
|
||||||
const paint_session* session, ObjectEntryIndex index, int32_t offset, uint8_t rotation, int32_t grassLength, bool grid,
|
const paint_session* session, ObjectEntryIndex index, int32_t offset, uint8_t rotation, int32_t grassLength, bool grid,
|
||||||
bool underground)
|
bool underground)
|
||||||
{
|
{
|
||||||
// Provide fallback for RCT1 surfaces if the user does have RCT1 linked.
|
|
||||||
if (!is_csg_loaded() && index >= TERRAIN_RCT2_COUNT)
|
|
||||||
{
|
|
||||||
if (index == TERRAIN_ROOF_GREY)
|
|
||||||
index = TERRAIN_ROCK;
|
|
||||||
else
|
|
||||||
index = TERRAIN_DIRT;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto image = static_cast<uint32_t>(SPR_NONE);
|
auto image = static_cast<uint32_t>(SPR_NONE);
|
||||||
auto obj = get_surface_object(index);
|
auto obj = get_surface_object(index);
|
||||||
if (obj != nullptr)
|
if (obj != nullptr)
|
||||||
|
@ -416,7 +407,7 @@ static uint32_t get_tunnel_image(ObjectEntryIndex index, uint8_t type)
|
||||||
if (obj != nullptr)
|
if (obj != nullptr)
|
||||||
{
|
{
|
||||||
auto tobj = static_cast<TerrainEdgeObject*>(obj);
|
auto tobj = static_cast<TerrainEdgeObject*>(obj);
|
||||||
hasDoors = tobj->HasDoors;
|
hasDoors = tobj->HasDoors && !tobj->UsesFallbackImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasDoors && type >= REGULAR_TUNNEL_TYPE_COUNT && type < std::size(offsets))
|
if (!hasDoors && type >= REGULAR_TUNNEL_TYPE_COUNT && type < std::size(offsets))
|
||||||
|
@ -638,9 +629,6 @@ static void viewport_surface_draw_tile_side_bottom(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_csg_loaded() && edgeStyle >= TERRAIN_EDGE_RCT2_COUNT)
|
|
||||||
edgeStyle = TERRAIN_EDGE_ROCK;
|
|
||||||
|
|
||||||
uint32_t base_image_id = get_edge_image(edgeStyle, 0);
|
uint32_t base_image_id = get_edge_image(edgeStyle, 0);
|
||||||
if (session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
|
if (session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
|
||||||
{
|
{
|
||||||
|
@ -784,9 +772,6 @@ static void viewport_surface_draw_tile_side_top(
|
||||||
// From big Z to tiny Z
|
// From big Z to tiny Z
|
||||||
height /= COORDS_Z_PER_TINY_Z;
|
height /= COORDS_Z_PER_TINY_Z;
|
||||||
|
|
||||||
if (!is_csg_loaded() && terrain >= TERRAIN_EDGE_RCT2_COUNT)
|
|
||||||
terrain = TERRAIN_EDGE_ROCK;
|
|
||||||
|
|
||||||
int16_t cornerHeight1, neighbourCornerHeight1, cornerHeight2, neighbourCornerHeight2;
|
int16_t cornerHeight1, neighbourCornerHeight1, cornerHeight2, neighbourCornerHeight2;
|
||||||
|
|
||||||
CoordsXY offset = { 0, 0 };
|
CoordsXY offset = { 0, 0 };
|
||||||
|
|
Loading…
Reference in New Issue