Skip to content

Commit

Permalink
wzmaplib: Improve map preview generation
Browse files Browse the repository at this point in the history
Better output of structures (based on structure size and direction).
  • Loading branch information
past-due authored and pull[bot] committed Apr 11, 2024
1 parent 790ab4f commit 1077447
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 9 deletions.
3 changes: 2 additions & 1 deletion lib/wzmaplib/include/wzmaplib/map_preview.h
Expand Up @@ -23,6 +23,7 @@
#include <memory>
#include <cinttypes>
#include "map.h"
#include "map_stats.h"

namespace WzMap {

Expand Down Expand Up @@ -78,6 +79,6 @@ struct MapPreviewImage
uint32_t channels; // ex. 3 for RGB
};

std::unique_ptr<MapPreviewImage> generate2DMapPreview(WzMap::Map& wzMap, const MapPreviewColorScheme& colorScheme, WzMap::LoggingProtocol* pCustomLogger = nullptr);
std::unique_ptr<MapPreviewImage> generate2DMapPreview(WzMap::Map& wzMap, const MapPreviewColorScheme& colorScheme, const MapStatsConfiguration& statsConfig = MapStatsConfiguration(), WzMap::LoggingProtocol* pCustomLogger = nullptr);

} // namespace WzMap
3 changes: 3 additions & 0 deletions lib/wzmaplib/include/wzmaplib/map_stats.h
Expand Up @@ -169,6 +169,9 @@ namespace WzMap {
// - "type": "OIL DRUM"
std::unordered_set<std::string> oilDrums;

public:
bool isStructExpansionModule(const std::string& struct_id) const;

private:
// [STRUCT SIZES]:
typedef std::unordered_map<std::string, StructureSize> StructSizesMap;
Expand Down
53 changes: 47 additions & 6 deletions lib/wzmaplib/src/map_preview.cpp
@@ -1,6 +1,6 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2013-2021 Warzone 2100 Project
Copyright (C) 2013-2023 Warzone 2100 Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -119,7 +119,7 @@ static inline T clip(T x, T min, T max)
return x < min ? min : x > max ? max : x;
}

static void plotBackdropPixel(MapPreviewImage& output, int32_t xx, int32_t yy, MapPreviewColor const &colour)
static void plotBackdropPixel(MapPreviewImage& output, int32_t xx, int32_t yy, const MapPreviewColor &colour)
{
xx = clip(xx, 0, static_cast<int32_t>(output.width - 1));
yy = clip(yy, 0, static_cast<int32_t>(output.height - 1));
Expand All @@ -129,6 +129,47 @@ static void plotBackdropPixel(MapPreviewImage& output, int32_t xx, int32_t yy, M
pixel[2] = colour.b;
}

// Round direction to nearest axis-aligned direction.
static inline uint16_t snapDirection(uint16_t direction)
{
return (direction + 0x2000) & 0xC000;
}

static void plotBackdropStructurePixels(MapPreviewImage& output, const Structure &structure, const MapStatsConfiguration& statsConfig, const MapPreviewColor &colour)
{
if (statsConfig.isStructExpansionModule(structure.name))
{
// Skip drawing expansion modules on the map preview
return;
}

MapStatsConfiguration::StructureSize structStatSize = statsConfig.getStructureSize(structure.name).value_or(MapStatsConfiguration::StructureSize(1,1));

std::pair<int32_t, int32_t> size = {structStatSize.baseWidth, structStatSize.baseBreadth};
if ((snapDirection(structure.direction) & 0x4000) != 0)
{
// If building is rotated left or right by 90°, swap width and height
std::swap(size.first, size.second);
}

// Snap the WorldPos to a tile
int32_t x = (structure.position.x & ~TILE_MASK) + size.first % 2 * TILE_UNITS / 2;
int32_t y = (structure.position.y & ~TILE_MASK) + size.second % 2 * TILE_UNITS / 2;

// Calculate starting MapTilePos for output
std::pair<int32_t, int32_t> map = { map_coord(x), map_coord(y) };
map.first -= size.first / 2;
map.second -= size.second / 2;

for (int32_t tileX = map.first; tileX < map.first + size.first; ++tileX)
{
for (int32_t tileY = map.second; tileY < map.second + size.second; ++tileY)
{
plotBackdropPixel(output, tileX, tileY, colour);
}
}
}

static inline bool isOilResource(const Feature& feature)
{
return feature.name.rfind("OilResource", 0) == 0;
Expand Down Expand Up @@ -184,7 +225,7 @@ static void plotWzMapFeature(Map &wzMap, const MapPreviewColorScheme& colorSchem
* present. Additionally we load the player's HQ location into playeridpos so
* we know the player's starting location.
*/
bool plotStructurePreviewWzMap(Map &wzMap, const MapPreviewColorScheme& colorScheme, MapPreviewImage& output, LoggingProtocol* pCustomLogger)
bool plotStructurePreviewWzMap(Map &wzMap, const MapPreviewColorScheme& colorScheme, const MapStatsConfiguration& statsConfig, MapPreviewImage& output, LoggingProtocol* pCustomLogger)
{
auto pStructures = wzMap.mapStructures();
if (pStructures == nullptr)
Expand Down Expand Up @@ -219,7 +260,7 @@ bool plotStructurePreviewWzMap(Map &wzMap, const MapPreviewColorScheme& colorSch
color = colorScheme.hqColor;
}
// and now we blit the color to the texture
plotBackdropPixel(output, pos.first, pos.second, color);
plotBackdropStructurePixels(output, structure, statsConfig, color);
}

plotWzMapFeature(wzMap, colorScheme, output, pCustomLogger);
Expand All @@ -237,7 +278,7 @@ static inline TYPE_OF_TERRAIN terrainTypeWzMap(const MapData::MapTile& tile, con
return data.terrainTypes[tileType];
}

std::unique_ptr<MapPreviewImage> generate2DMapPreview(Map& wzMap, const MapPreviewColorScheme& colorScheme, LoggingProtocol* pCustomLogger /*= nullptr*/)
std::unique_ptr<MapPreviewImage> generate2DMapPreview(Map& wzMap, const MapPreviewColorScheme& colorScheme, const MapStatsConfiguration& statsConfig /*= MapStatsConfiguration()*/, LoggingProtocol* pCustomLogger /*= nullptr*/)
{
auto mapData = wzMap.mapData();
if (!mapData)
Expand Down Expand Up @@ -303,7 +344,7 @@ std::unique_ptr<MapPreviewImage> generate2DMapPreview(Map& wzMap, const MapPrevi
}

// color our texture with clancolors @ correct position
plotStructurePreviewWzMap(wzMap, colorScheme, *(result.get()), pCustomLogger);
plotStructurePreviewWzMap(wzMap, colorScheme, statsConfig, *(result.get()), pCustomLogger);

return result;
}
Expand Down
9 changes: 8 additions & 1 deletion lib/wzmaplib/src/map_stats.cpp
@@ -1,6 +1,6 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2022 Warzone 2100 Project
Copyright (C) 2022-2023 Warzone 2100 Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -662,4 +662,11 @@ optional<MapStatsConfiguration::StructureSize> MapStatsConfiguration::getStructu
return it->second;
}

bool MapStatsConfiguration::isStructExpansionModule(const std::string& struct_id) const
{
return powerModules.count(struct_id)
|| factoryModules.count(struct_id)
|| researchModules.count(struct_id);
}

} // namespace WzMap
2 changes: 1 addition & 1 deletion src/multiint.cpp
Expand Up @@ -698,7 +698,7 @@ void loadMapPreview(bool hideInterface)
}

std::unique_ptr<WzMap::LoggingProtocol> generatePreviewLogger(new WzMapDebugLogger());
auto mapPreviewResult = WzMap::generate2DMapPreview(*data, previewColorScheme, generatePreviewLogger.get());
auto mapPreviewResult = WzMap::generate2DMapPreview(*data, previewColorScheme, WzMap::MapStatsConfiguration(WzMap::MapType::SKIRMISH), generatePreviewLogger.get());
if (!mapPreviewResult)
{
// Failed to generate map preview
Expand Down

0 comments on commit 1077447

Please sign in to comment.