Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-06-02 22:37:52 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2024-06-02 22:37:52 +1000
commitadd17da988f4518c451abc4d0bacf536071e1c0b (patch)
tree86e1db5f276269e41f93d9f6e198186d2d95fa26
parent68bd850fe73819c75841c5b6147255caf16c6ed9 (diff)
directive-based color variants for materials
-rw-r--r--source/core/StarDirectives.hpp2
-rw-r--r--source/game/StarMaterialDatabase.cpp24
-rw-r--r--source/game/StarMaterialDatabase.hpp2
-rw-r--r--source/game/StarMaterialRenderProfile.cpp8
-rw-r--r--source/game/StarMaterialRenderProfile.hpp4
-rw-r--r--source/game/StarTileDrawer.cpp38
-rw-r--r--source/rendering/StarTilePainter.cpp33
7 files changed, 80 insertions, 31 deletions
diff --git a/source/core/StarDirectives.hpp b/source/core/StarDirectives.hpp
index e6b0a6e..9290649 100644
--- a/source/core/StarDirectives.hpp
+++ b/source/core/StarDirectives.hpp
@@ -121,7 +121,7 @@ private:
void buildString(String& string, const DirectivesGroup& directives) const;
List<Directives> m_directives;
- size_t m_count;
+ size_t m_count = 0;
};
template <>
diff --git a/source/game/StarMaterialDatabase.cpp b/source/game/StarMaterialDatabase.cpp
index 6363c5d..99ce32e 100644
--- a/source/game/StarMaterialDatabase.cpp
+++ b/source/game/StarMaterialDatabase.cpp
@@ -402,11 +402,31 @@ ItemDescriptor MaterialDatabase::modItemDrop(ModId modId) const {
return {};
}
+MaterialColorVariant MaterialDatabase::materialColorVariants(MaterialId materialId) const {
+ if (isRealMaterial(materialId)) {
+ auto const& matInfo = getMaterialInfo(materialId);
+ if (matInfo->materialRenderProfile)
+ return matInfo->materialRenderProfile->colorVariants;
+ }
+
+ return 0;
+}
+
+MaterialColorVariant MaterialDatabase::modColorVariants(ModId modId) const {
+ if (isRealMod(modId)) {
+ auto const& modInfo = getModInfo(modId);
+ if (modInfo->modRenderProfile)
+ return modInfo->modRenderProfile->colorVariants;
+ }
+
+ return 0;
+}
+
bool MaterialDatabase::isMultiColor(MaterialId materialId) const {
if (isRealMaterial(materialId)) {
auto const& matInfo = getMaterialInfo(materialId);
if (matInfo->materialRenderProfile)
- return matInfo->materialRenderProfile->multiColor;
+ return matInfo->materialRenderProfile->colorVariants > 0;
}
return false;
@@ -568,7 +588,7 @@ shared_ptr<MaterialDatabase::MaterialInfo const> const& MaterialDatabase::getMat
shared_ptr<MaterialDatabase::ModInfo const> const& MaterialDatabase::getModInfo(ModId modId) const {
if (modId >= m_mods.size() || !m_mods[modId])
- throw MaterialException(strf("No such modId id: {}\n", modId));
+ throw MaterialException(strf("No such mod id: {}\n", modId));
else
return m_mods[modId];
}
diff --git a/source/game/StarMaterialDatabase.hpp b/source/game/StarMaterialDatabase.hpp
index f20a3e2..1d7d709 100644
--- a/source/game/StarMaterialDatabase.hpp
+++ b/source/game/StarMaterialDatabase.hpp
@@ -69,6 +69,8 @@ public:
ItemDescriptor materialItemDrop(MaterialId materialId) const;
ItemDescriptor modItemDrop(ModId modId) const;
+ MaterialColorVariant materialColorVariants(MaterialId materialId) const;
+ MaterialColorVariant modColorVariants(ModId modId) const;
bool isMultiColor(MaterialId materialId) const;
bool foregroundLightTransparent(MaterialId materialId) const;
bool backgroundLightTransparent(MaterialId materialId) const;
diff --git a/source/game/StarMaterialRenderProfile.cpp b/source/game/StarMaterialRenderProfile.cpp
index 975e7fa..1272e83 100644
--- a/source/game/StarMaterialRenderProfile.cpp
+++ b/source/game/StarMaterialRenderProfile.cpp
@@ -80,7 +80,9 @@ MaterialRenderProfile parseMaterialRenderProfile(Json const& spec, String const&
bool lightTransparent = spec.getBool("lightTransparent", false);
profile.foregroundLightTransparent = spec.getBool("foregroundLightTransparent", lightTransparent);
profile.backgroundLightTransparent = spec.getBool("backgroundLightTransparent", lightTransparent);
- profile.multiColor = spec.getBool("multiColored", false);
+ profile.colorVariants = spec.getBool("multiColored", false) ? spec.getUInt("colorVariants", MaxMaterialColorVariant) : 0;
+ for (auto& entry : spec.getArray("colorDirectives", JsonArray()))
+ profile.colorDirectives.append(entry.toString());
profile.occludesBehind = spec.getBool("occludesBelow", true);
profile.zLevel = spec.getUInt("zLevel", 0);
profile.radiantLight = Color::rgb(jsonToVec3B(spec.get("radiantLight", JsonArray{0, 0, 0}))).toRgbF();
@@ -126,8 +128,8 @@ MaterialRenderProfile parseMaterialRenderProfile(Json const& spec, String const&
auto flipTextureCoordinates = [imageHeight](
RectF const& rect) { return RectF::withSize(Vec2F(rect.xMin(), imageHeight - rect.yMax()), rect.size()); };
for (unsigned v = 0; v < variants; ++v) {
- if (profile.multiColor) {
- for (MaterialColorVariant c = 0; c <= MaxMaterialColorVariant; ++c) {
+ if (profile.colorVariants > 0) {
+ for (MaterialColorVariant c = 0; c <= profile.colorVariants; ++c) {
RectF textureRect = RectF::withSize(texturePosition + variantStride * v + colorStride * c, textureSize);
renderPiece->variants[c].append(flipTextureCoordinates(textureRect));
}
diff --git a/source/game/StarMaterialRenderProfile.hpp b/source/game/StarMaterialRenderProfile.hpp
index 658cd89..f721cdb 100644
--- a/source/game/StarMaterialRenderProfile.hpp
+++ b/source/game/StarMaterialRenderProfile.hpp
@@ -6,6 +6,7 @@
#include "StarMultiArray.hpp"
#include "StarGameTypes.hpp"
#include "StarTileDamage.hpp"
+#include "StarDirectives.hpp"
namespace Star {
@@ -96,11 +97,12 @@ struct MaterialRenderProfile {
MaterialRenderMatchList mainMatchList;
List<pair<String, Vec2F>> crackingFrames;
List<pair<String, Vec2F>> protectedFrames;
+ List<Directives> colorDirectives;
Json ruleProperties;
bool foregroundLightTransparent;
bool backgroundLightTransparent;
- bool multiColor;
+ uint8_t colorVariants;
bool occludesBehind;
uint32_t zLevel;
Vec3F radiantLight;
diff --git a/source/game/StarTileDrawer.cpp b/source/game/StarTileDrawer.cpp
index 70cd7d0..2fa5051 100644
--- a/source/game/StarTileDrawer.cpp
+++ b/source/game/StarTileDrawer.cpp
@@ -65,7 +65,7 @@ bool TileDrawer::produceTerrainDrawables(Drawables& drawables,
MaterialId material = EmptyMaterialId;
MaterialHue materialHue = 0;
- MaterialColorVariant materialColorVariant = 0;
+ MaterialColorVariant colorVariant = 0;
ModId mod = NoModId;
MaterialHue modHue = 0;
float damageLevel = 0.0f;
@@ -77,7 +77,7 @@ bool TileDrawer::produceTerrainDrawables(Drawables& drawables,
if (terrainLayer == TerrainLayer::Background) {
material = tile.background;
materialHue = tile.backgroundHueShift;
- materialColorVariant = tile.backgroundColorVariant;
+ colorVariant = tile.backgroundColorVariant;
mod = tile.backgroundMod;
modHue = tile.backgroundModHueShift;
damageLevel = byteToFloat(tile.backgroundDamageLevel);
@@ -86,7 +86,7 @@ bool TileDrawer::produceTerrainDrawables(Drawables& drawables,
} else {
material = tile.foreground;
materialHue = tile.foregroundHueShift;
- materialColorVariant = tile.foregroundColorVariant;
+ colorVariant = tile.foregroundColorVariant;
mod = tile.foregroundMod;
modHue = tile.foregroundModHueShift;
damageLevel = byteToFloat(tile.foregroundDamageLevel);
@@ -99,10 +99,14 @@ bool TileDrawer::produceTerrainDrawables(Drawables& drawables,
if ((isBlock && terrainLayer == TerrainLayer::Midground) || (!isBlock && terrainLayer == TerrainLayer::Foreground))
return false;
- auto getPieceImage = [](MaterialRenderPieceConstPtr const& piece, Box<float, 2> const& box, MaterialHue hue) -> String {
- return hue == 0
+ auto getPieceImage = [](MaterialRenderPieceConstPtr const& piece, Box<float, 2> const& box, MaterialHue hue, Directives const* directives) -> AssetPath {
+ AssetPath image = hue == 0
? strf("{}?crop={};{};{};{}", piece->texture, box.xMin(), box.yMin(), box.xMax(), box.yMax())
: strf("{}?crop={};{};{};{}?hueshift={}", piece->texture, box.xMin(), box.yMin(), box.xMax(), box.yMax(), materialHueToDegrees(hue));
+ if (directives)
+ image.directives += *directives;
+
+ return image;
};
auto materialRenderProfile = materialDatabase->materialRenderProfile(material);
@@ -110,31 +114,43 @@ bool TileDrawer::produceTerrainDrawables(Drawables& drawables,
if (materialRenderProfile) {
occlude = materialRenderProfile->occludesBehind;
-
+ auto materialColorVariant = materialRenderProfile->colorVariants > 0 ? colorVariant % materialRenderProfile->colorVariants : 0;
uint32_t variance = staticRandomU32(renderData.geometry.xwrap(pos[0]) + offset[0], pos[1] + offset[1], (int)variantLayer.value(terrainLayer), "main");
auto& drawList = drawables[materialZLevel(materialRenderProfile->zLevel, material, materialHue, materialColorVariant)];
MaterialPieceResultList pieces;
determineMatchingPieces(pieces, &occlude, materialDatabase, materialRenderProfile->mainMatchList, renderData, pos,
terrainLayer == TerrainLayer::Background ? TileLayer::Background : TileLayer::Foreground, false);
+ Directives const* directives = materialRenderProfile->colorDirectives.empty()
+ ? nullptr
+ : &materialRenderProfile->colorDirectives.wrap(materialColorVariant);
for (auto const& piecePair : pieces) {
- auto& variant = piecePair.first->variants.get(materialColorVariant).wrap(variance);
- auto image = getPieceImage(piecePair.first, variant, materialHue);
+ auto variant = piecePair.first->variants.ptr(materialColorVariant);
+ if (!variant) variant = piecePair.first->variants.ptr(0);
+ if (!variant) continue;
+ auto& textureCoords = variant->wrap(variance);
+ auto image = getPieceImage(piecePair.first, textureCoords, materialHue, directives);
drawList.emplace_back(Drawable::makeImage(image, scale, false, piecePair.second * scale + Vec2F(pos), color));
}
}
if (modRenderProfile) {
- auto modColorVariant = modRenderProfile->multiColor ? materialColorVariant : 0;
+ auto modColorVariant = modRenderProfile->colorVariants > 0 ? colorVariant % modRenderProfile->colorVariants : 0;
uint32_t variance = staticRandomU32(renderData.geometry.xwrap(pos[0]), pos[1], (int)variantLayer.value(terrainLayer), "mod");
auto& drawList = drawables[modZLevel(modRenderProfile->zLevel, mod, modHue, modColorVariant)];
MaterialPieceResultList pieces;
determineMatchingPieces(pieces, &occlude, materialDatabase, modRenderProfile->mainMatchList, renderData, pos,
terrainLayer == TerrainLayer::Background ? TileLayer::Background : TileLayer::Foreground, true);
+ Directives const* directives = modRenderProfile->colorDirectives.empty()
+ ? nullptr
+ : &modRenderProfile->colorDirectives.wrap(modColorVariant);
for (auto const& piecePair : pieces) {
- auto& variant = piecePair.first->variants.get(modColorVariant).wrap(variance);
- auto image = getPieceImage(piecePair.first, variant, modHue);
+ auto variant = piecePair.first->variants.ptr(modColorVariant);
+ if (!variant) variant = piecePair.first->variants.ptr(0);
+ if (!variant) continue;
+ auto& textureCoords = variant->wrap(variance);
+ auto image = getPieceImage(piecePair.first, textureCoords, modHue, directives);
drawList.emplace_back(Drawable::makeImage(image, scale, false, piecePair.second * scale + Vec2F(pos), color));
}
}
diff --git a/source/rendering/StarTilePainter.cpp b/source/rendering/StarTilePainter.cpp
index f9cff34..eef54b6 100644
--- a/source/rendering/StarTilePainter.cpp
+++ b/source/rendering/StarTilePainter.cpp
@@ -230,7 +230,7 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
MaterialId material = EmptyMaterialId;
MaterialHue materialHue = 0;
- MaterialColorVariant materialColorVariant = 0;
+ MaterialColorVariant colorVariant = 0;
ModId mod = NoModId;
MaterialHue modHue = 0;
float damageLevel = 0.0f;
@@ -242,7 +242,7 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
if (terrainLayer == TerrainLayer::Background) {
material = tile.background;
materialHue = tile.backgroundHueShift;
- materialColorVariant = tile.backgroundColorVariant;
+ colorVariant = tile.backgroundColorVariant;
mod = tile.backgroundMod;
modHue = tile.backgroundModHueShift;
damageLevel = byteToFloat(tile.backgroundDamageLevel);
@@ -251,7 +251,7 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
} else {
material = tile.foreground;
materialHue = tile.foregroundHueShift;
- materialColorVariant = tile.foregroundColorVariant;
+ colorVariant = tile.foregroundColorVariant;
mod = tile.foregroundMod;
modHue = tile.foregroundModHueShift;
damageLevel = byteToFloat(tile.foregroundDamageLevel);
@@ -264,13 +264,12 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
if (terrainLayer == (isBlock ? TerrainLayer::Midground : TerrainLayer::Foreground))
return false;
- auto getPieceTexture = [this, assets](MaterialId material, MaterialRenderPieceConstPtr const& piece, MaterialHue hue, bool mod) {
+ auto getPieceTexture = [this, assets](MaterialId material, MaterialRenderPieceConstPtr const& piece, MaterialHue hue, Directives const* directives, bool mod) {
return m_textureCache.get(MaterialPieceTextureKey(material, piece->pieceId, hue, mod), [&](auto const&) {
- String texture;
- if (hue == 0)
- texture = piece->texture;
- else
- texture = strf("{}?hueshift={}", piece->texture, materialHueToDegrees(hue));
+ AssetPath texture = (hue == 0) ? piece->texture : strf("{}?hueshift={}", piece->texture, materialHueToDegrees(hue));
+
+ if (directives)
+ texture.directives += *directives;
return m_textureGroup->create(*assets->image(texture));
});
@@ -281,16 +280,20 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
if (materialRenderProfile) {
occlude = materialRenderProfile->occludesBehind;
-
+ auto materialColorVariant = materialRenderProfile->colorVariants > 0 ? colorVariant % materialRenderProfile->colorVariants : 0;
uint32_t variance = staticRandomU32(renderData.geometry.xwrap(pos[0]), pos[1], (int)terrainLayer, "main");
auto& quadList = primitives[materialZLevel(materialRenderProfile->zLevel, material, materialHue, materialColorVariant)];
MaterialPieceResultList pieces;
determineMatchingPieces(pieces, &occlude, materialDatabase, materialRenderProfile->mainMatchList, renderData, pos,
terrainLayer == TerrainLayer::Background ? TileLayer::Background : TileLayer::Foreground, false);
+ Directives const* directives = materialRenderProfile->colorDirectives.empty()
+ ? nullptr
+ : &materialRenderProfile->colorDirectives.wrap(materialColorVariant);
for (auto const& piecePair : pieces) {
- TexturePtr texture = getPieceTexture(material, piecePair.first, materialHue, false);
+ TexturePtr texture = getPieceTexture(material, piecePair.first, materialHue, directives, false);
auto variant = piecePair.first->variants.ptr(materialColorVariant);
+ if (!variant) variant = piecePair.first->variants.ptr(0);
if (!variant) continue;
RectF textureCoords = variant->wrap(variance);
RectF worldCoords = RectF::withSize(piecePair.second / TilePixels + Vec2F(pos), textureCoords.size() / TilePixels);
@@ -308,16 +311,20 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
}
if (modRenderProfile) {
- auto modColorVariant = modRenderProfile->multiColor ? materialColorVariant : 0;
+ auto modColorVariant = modRenderProfile->colorVariants > 0 ? colorVariant % modRenderProfile->colorVariants : 0;
uint32_t variance = staticRandomU32(renderData.geometry.xwrap(pos[0]), pos[1], (int)terrainLayer, "mod");
auto& quadList = primitives[modZLevel(modRenderProfile->zLevel, mod, modHue, modColorVariant)];
MaterialPieceResultList pieces;
determineMatchingPieces(pieces, &occlude, materialDatabase, modRenderProfile->mainMatchList, renderData, pos,
terrainLayer == TerrainLayer::Background ? TileLayer::Background : TileLayer::Foreground, true);
+ Directives const* directives = modRenderProfile->colorDirectives.empty()
+ ? nullptr
+ : &modRenderProfile->colorDirectives.wrap(modColorVariant);
for (auto const& piecePair : pieces) {
- auto texture = getPieceTexture(mod, piecePair.first, modHue, true);
+ auto texture = getPieceTexture(mod, piecePair.first, modHue, directives, true);
auto variant = piecePair.first->variants.ptr(modColorVariant);
+ if (!variant) variant = piecePair.first->variants.ptr(0);
if (!variant) continue;
auto& textureCoords = variant->wrap(variance);
RectF worldCoords = RectF::withSize(piecePair.second / TilePixels + Vec2F(pos), textureCoords.size() / TilePixels);