Hook tile meshing up to Material Item drop and preview
This commit is contained in:
parent
0bb0bd30b0
commit
6e7c0498ef
@ -33,15 +33,15 @@
|
|||||||
"group": "building",
|
"group": "building",
|
||||||
"name": "Cycle Material Collision"
|
"name": "Cycle Material Collision"
|
||||||
},
|
},
|
||||||
"materialRadiusGrow": {
|
"buildingRadiusGrow": {
|
||||||
"default": [],
|
"default": [],
|
||||||
"group": "building",
|
"group": "building",
|
||||||
"name": "Grow Material Radius"
|
"name": "Grow Building Radius"
|
||||||
},
|
},
|
||||||
"materialRadiusShrink": {
|
"buildingRadiusShrink": {
|
||||||
"default": [],
|
"default": [],
|
||||||
"group": "building",
|
"group": "building",
|
||||||
"name": "Shrink Material Radius"
|
"name": "Shrink Building Radius"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,9 +170,9 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
|
|||||||
|
|
||||||
AudioFormat audioFormat = appController->enableAudio();
|
AudioFormat audioFormat = appController->enableAudio();
|
||||||
m_mainMixer = make_shared<MainMixer>(audioFormat.sampleRate, audioFormat.channels);
|
m_mainMixer = make_shared<MainMixer>(audioFormat.sampleRate, audioFormat.channels);
|
||||||
|
|
||||||
m_mainMixer->setVolume(0.5);
|
m_mainMixer->setVolume(0.5);
|
||||||
|
|
||||||
|
m_worldPainter = make_shared<WorldPainter>();
|
||||||
m_guiContext = make_shared<GuiContext>(m_mainMixer->mixer(), appController);
|
m_guiContext = make_shared<GuiContext>(m_mainMixer->mixer(), appController);
|
||||||
m_input = make_shared<Input>();
|
m_input = make_shared<Input>();
|
||||||
m_voice = make_shared<Voice>(appController);
|
m_voice = make_shared<Voice>(appController);
|
||||||
@ -644,7 +644,6 @@ void ClientApplication::changeState(MainAppState newState) {
|
|||||||
|
|
||||||
m_titleScreen->stopMusic();
|
m_titleScreen->stopMusic();
|
||||||
|
|
||||||
m_worldPainter = make_shared<WorldPainter>();
|
|
||||||
m_mainInterface = make_shared<MainInterface>(m_universeClient, m_worldPainter, m_cinematicOverlay);
|
m_mainInterface = make_shared<MainInterface>(m_universeClient, m_worldPainter, m_cinematicOverlay);
|
||||||
m_universeClient->setLuaCallbacks("interface", LuaBindings::makeInterfaceCallbacks(m_mainInterface.get()));
|
m_universeClient->setLuaCallbacks("interface", LuaBindings::makeInterfaceCallbacks(m_mainInterface.get()));
|
||||||
m_universeClient->startLua();
|
m_universeClient->startLua();
|
||||||
|
@ -144,6 +144,7 @@ SET (star_game_HEADERS
|
|||||||
StarTenantDatabase.hpp
|
StarTenantDatabase.hpp
|
||||||
StarTerrainDatabase.hpp
|
StarTerrainDatabase.hpp
|
||||||
StarTileDamage.hpp
|
StarTileDamage.hpp
|
||||||
|
StarTileDrawer.hpp
|
||||||
StarTileModification.hpp
|
StarTileModification.hpp
|
||||||
StarTileSectorArray.hpp
|
StarTileSectorArray.hpp
|
||||||
StarTilesetDatabase.hpp
|
StarTilesetDatabase.hpp
|
||||||
@ -404,6 +405,7 @@ SET (star_game_SOURCES
|
|||||||
StarTenantDatabase.cpp
|
StarTenantDatabase.cpp
|
||||||
StarTerrainDatabase.cpp
|
StarTerrainDatabase.cpp
|
||||||
StarTileDamage.cpp
|
StarTileDamage.cpp
|
||||||
|
StarTileDrawer.cpp
|
||||||
StarTileModification.cpp
|
StarTileModification.cpp
|
||||||
StarTilesetDatabase.cpp
|
StarTilesetDatabase.cpp
|
||||||
StarToolUser.cpp
|
StarToolUser.cpp
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "StarWorld.hpp"
|
#include "StarWorld.hpp"
|
||||||
#include "StarDataStreamExtra.hpp"
|
#include "StarDataStreamExtra.hpp"
|
||||||
#include "StarPlayer.hpp"
|
#include "StarPlayer.hpp"
|
||||||
|
#include "StarMaterialItem.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -231,9 +232,10 @@ void ItemDrop::update(float dt, uint64_t) {
|
|||||||
m_mode.set(Mode::Dead);
|
m_mode.set(Mode::Dead);
|
||||||
|
|
||||||
if (m_mode.get() <= Mode::Available && m_ageItemsTimer.elapsedTime() > m_ageItemsEvery) {
|
if (m_mode.get() <= Mode::Available && m_ageItemsTimer.elapsedTime() > m_ageItemsEvery) {
|
||||||
Root::singleton().itemDatabase()->ageItem(m_item, m_ageItemsTimer.elapsedTime());
|
if (Root::singleton().itemDatabase()->ageItem(m_item, m_ageItemsTimer.elapsedTime())) {
|
||||||
m_itemDescriptor.set(m_item->descriptor());
|
m_itemDescriptor.set(m_item->descriptor());
|
||||||
updateCollisionPoly();
|
updateCollisionPoly();
|
||||||
|
}
|
||||||
m_ageItemsTimer.setElapsedTime(0.0);
|
m_ageItemsTimer.setElapsedTime(0.0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -261,7 +263,7 @@ void ItemDrop::update(float dt, uint64_t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ItemDrop::shouldDestroy() const {
|
bool ItemDrop::shouldDestroy() const {
|
||||||
return m_mode.get() == Mode::Dead;
|
return m_mode.get() == Mode::Dead || m_item->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDrop::render(RenderCallback* renderCallback) {
|
void ItemDrop::render(RenderCallback* renderCallback) {
|
||||||
@ -294,7 +296,13 @@ void ItemDrop::render(RenderCallback* renderCallback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m_drawables) {
|
if (!m_drawables) {
|
||||||
|
if (auto mat = as<MaterialItem>(m_item.get())) {
|
||||||
|
m_drawables = mat->generatedPreview(Vec2I(position().floor()));
|
||||||
|
m_overForeground = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
m_drawables = m_item->dropDrawables();
|
m_drawables = m_item->dropDrawables();
|
||||||
|
|
||||||
if (Directives dropDirectives = m_config.getString("directives", "")) {
|
if (Directives dropDirectives = m_config.getString("directives", "")) {
|
||||||
for (auto& drawable : *m_drawables) {
|
for (auto& drawable : *m_drawables) {
|
||||||
if (drawable.isImage())
|
if (drawable.isImage())
|
||||||
@ -302,7 +310,7 @@ void ItemDrop::render(RenderCallback* renderCallback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EntityRenderLayer renderLayer = m_mode.get() == Mode::Taken ? RenderLayerForegroundTile : RenderLayerItemDrop;
|
EntityRenderLayer renderLayer = m_mode.get() == Mode::Taken || m_overForeground ? RenderLayerForegroundTile : RenderLayerItemDrop;
|
||||||
Vec2F dropPosition = position();
|
Vec2F dropPosition = position();
|
||||||
for (Drawable drawable : *m_drawables) {
|
for (Drawable drawable : *m_drawables) {
|
||||||
drawable.position += dropPosition;
|
drawable.position += dropPosition;
|
||||||
@ -405,11 +413,16 @@ ItemDrop::ItemDrop() {
|
|||||||
m_ageItemsEvery = m_config.getDouble("ageItemsEvery", 10);
|
m_ageItemsEvery = m_config.getDouble("ageItemsEvery", 10);
|
||||||
|
|
||||||
m_eternal = false;
|
m_eternal = false;
|
||||||
|
m_overForeground = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDrop::updateCollisionPoly() {
|
void ItemDrop::updateCollisionPoly() {
|
||||||
|
if (auto mat = as<MaterialItem>(m_item.get()))
|
||||||
|
m_boundBox = RectF{ -0.5, -0.5, 0.5, 0.5 };
|
||||||
|
else {
|
||||||
m_boundBox = Drawable::boundBoxAll(m_item->dropDrawables(), true);
|
m_boundBox = Drawable::boundBoxAll(m_item->dropDrawables(), true);
|
||||||
m_boundBox.rangeSetIfEmpty(RectF{-0.5, -0.5, 0.5, 0.5});
|
m_boundBox.rangeSetIfEmpty(RectF{ -0.5, -0.5, 0.5, 0.5 });
|
||||||
|
}
|
||||||
MovementParameters parameters;
|
MovementParameters parameters;
|
||||||
parameters.collisionPoly = PolyF(collisionArea());
|
parameters.collisionPoly = PolyF(collisionArea());
|
||||||
m_movementController.applyParameters(parameters);
|
m_movementController.applyParameters(parameters);
|
||||||
|
@ -123,6 +123,7 @@ private:
|
|||||||
GameTimer m_intangibleTimer;
|
GameTimer m_intangibleTimer;
|
||||||
EpochTimer m_ageItemsTimer;
|
EpochTimer m_ageItemsTimer;
|
||||||
|
|
||||||
|
bool m_overForeground;
|
||||||
Maybe<List<Drawable>> m_drawables;
|
Maybe<List<Drawable>> m_drawables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
311
source/game/StarTileDrawer.cpp
Normal file
311
source/game/StarTileDrawer.cpp
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
#include "StarTileDrawer.hpp"
|
||||||
|
#include "StarLexicalCast.hpp"
|
||||||
|
#include "StarJsonExtra.hpp"
|
||||||
|
#include "StarXXHash.hpp"
|
||||||
|
#include "StarMaterialDatabase.hpp"
|
||||||
|
#include "StarLiquidsDatabase.hpp"
|
||||||
|
#include "StarAssets.hpp"
|
||||||
|
#include "StarRoot.hpp"
|
||||||
|
|
||||||
|
namespace Star {
|
||||||
|
|
||||||
|
RenderTile TileDrawer::DefaultRenderTile{
|
||||||
|
NullMaterialId,
|
||||||
|
NoModId,
|
||||||
|
NullMaterialId,
|
||||||
|
NoModId,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DefaultMaterialColorVariant,
|
||||||
|
TileDamageType::Protected,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DefaultMaterialColorVariant,
|
||||||
|
TileDamageType::Protected,
|
||||||
|
0,
|
||||||
|
EmptyLiquidId,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
TileDrawer* TileDrawer::s_singleton;
|
||||||
|
|
||||||
|
TileDrawer* TileDrawer::singletonPtr() {
|
||||||
|
return s_singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDrawer& TileDrawer::singleton() {
|
||||||
|
if (!s_singleton)
|
||||||
|
throw StarException("TileDrawer::singleton() called with no TileDrawer instance available");
|
||||||
|
else
|
||||||
|
return *s_singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDrawer::TileDrawer() {
|
||||||
|
auto assets = Root::singleton().assets();
|
||||||
|
|
||||||
|
m_backgroundLayerColor = jsonToColor(assets->json("/rendering.config:backgroundLayerColor")).toRgba();
|
||||||
|
m_foregroundLayerColor = jsonToColor(assets->json("/rendering.config:foregroundLayerColor")).toRgba();
|
||||||
|
m_liquidDrawLevels = jsonToVec2F(assets->json("/rendering.config:liquidDrawLevels"));
|
||||||
|
s_singleton = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDrawer::~TileDrawer() {
|
||||||
|
if (s_singleton == this)
|
||||||
|
s_singleton = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileDrawer::produceTerrainDrawables(Drawables& drawables,
|
||||||
|
TerrainLayer terrainLayer, Vec2I const& pos, WorldRenderData const& renderData, float scale, Vec2I offset, Maybe<TerrainLayer> variantLayer) {
|
||||||
|
auto& root = Root::singleton();
|
||||||
|
auto assets = Root::singleton().assets();
|
||||||
|
auto materialDatabase = root.materialDatabase();
|
||||||
|
|
||||||
|
RenderTile const& tile = getRenderTile(renderData, pos);
|
||||||
|
|
||||||
|
MaterialId material = EmptyMaterialId;
|
||||||
|
MaterialHue materialHue = 0;
|
||||||
|
MaterialColorVariant materialColorVariant = 0;
|
||||||
|
ModId mod = NoModId;
|
||||||
|
MaterialHue modHue = 0;
|
||||||
|
float damageLevel = 0.0f;
|
||||||
|
TileDamageType damageType = TileDamageType::Protected;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
bool occlude = false;
|
||||||
|
|
||||||
|
if (terrainLayer == TerrainLayer::Background) {
|
||||||
|
material = tile.background;
|
||||||
|
materialHue = tile.backgroundHueShift;
|
||||||
|
materialColorVariant = tile.backgroundColorVariant;
|
||||||
|
mod = tile.backgroundMod;
|
||||||
|
modHue = tile.backgroundModHueShift;
|
||||||
|
damageLevel = byteToFloat(tile.backgroundDamageLevel);
|
||||||
|
damageType = tile.backgroundDamageType;
|
||||||
|
color = Color::rgba(m_backgroundLayerColor);
|
||||||
|
} else {
|
||||||
|
material = tile.foreground;
|
||||||
|
materialHue = tile.foregroundHueShift;
|
||||||
|
materialColorVariant = tile.foregroundColorVariant;
|
||||||
|
mod = tile.foregroundMod;
|
||||||
|
modHue = tile.foregroundModHueShift;
|
||||||
|
damageLevel = byteToFloat(tile.foregroundDamageLevel);
|
||||||
|
damageType = tile.foregroundDamageType;
|
||||||
|
color = Color::rgba(m_foregroundLayerColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// render non-block colliding things in the midground
|
||||||
|
bool isBlock = BlockCollisionSet.contains(materialDatabase->materialCollisionKind(material));
|
||||||
|
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
|
||||||
|
? 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));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto materialRenderProfile = materialDatabase->materialRenderProfile(material);
|
||||||
|
|
||||||
|
auto modRenderProfile = materialDatabase->modRenderProfile(mod);
|
||||||
|
|
||||||
|
if (materialRenderProfile) {
|
||||||
|
occlude = materialRenderProfile->occludesBehind;
|
||||||
|
|
||||||
|
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);
|
||||||
|
for (auto const& piecePair : pieces) {
|
||||||
|
auto& variant = piecePair.first->variants.get(materialColorVariant).wrap(variance);
|
||||||
|
auto image = getPieceImage(piecePair.first, variant, materialHue);
|
||||||
|
drawList.emplace_back(Drawable::makeImage(image, scale, false, piecePair.second * scale + Vec2F(pos), color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modRenderProfile) {
|
||||||
|
auto modColorVariant = modRenderProfile->multiColor ? materialColorVariant : 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);
|
||||||
|
for (auto const& piecePair : pieces) {
|
||||||
|
auto& variant = piecePair.first->variants.get(modColorVariant).wrap(variance);
|
||||||
|
auto image = getPieceImage(piecePair.first, variant, modHue);
|
||||||
|
drawList.emplace_back(Drawable::makeImage(image, scale, false, piecePair.second * scale + Vec2F(pos), color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (materialRenderProfile && damageLevel > 0 && isBlock) {
|
||||||
|
auto& drawList = drawables[damageZLevel()];
|
||||||
|
auto const& crackingImage = materialRenderProfile->damageImage(damageLevel, damageType);
|
||||||
|
|
||||||
|
drawList.emplace_back(Drawable::makeImage(crackingImage.first, scale, false, crackingImage.second * scale + Vec2F(pos), color));
|
||||||
|
}
|
||||||
|
|
||||||
|
return occlude;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldRenderData& TileDrawer::renderData() {
|
||||||
|
return m_tempRenderData;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutexLocker TileDrawer::lockRenderData() {
|
||||||
|
return MutexLocker(m_tempRenderDataMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderTile const& TileDrawer::getRenderTile(WorldRenderData const& renderData, Vec2I const& worldPos) {
|
||||||
|
Vec2I arrayPos = renderData.geometry.diff(worldPos, renderData.tileMinPosition);
|
||||||
|
|
||||||
|
Vec2I size = Vec2I(renderData.tiles.size());
|
||||||
|
if (arrayPos[0] >= 0 && arrayPos[1] >= 0 && arrayPos[0] < size[0] && arrayPos[1] < size[1])
|
||||||
|
return renderData.tiles(Vec2S(arrayPos));
|
||||||
|
|
||||||
|
return DefaultRenderTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDrawer::QuadZLevel TileDrawer::materialZLevel(uint32_t zLevel, MaterialId material, MaterialHue hue, MaterialColorVariant colorVariant) {
|
||||||
|
QuadZLevel quadZLevel = 0;
|
||||||
|
quadZLevel |= (uint64_t)colorVariant;
|
||||||
|
quadZLevel |= (uint64_t)hue << 8;
|
||||||
|
quadZLevel |= (uint64_t)material << 16;
|
||||||
|
quadZLevel |= (uint64_t)zLevel << 32;
|
||||||
|
return quadZLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDrawer::QuadZLevel TileDrawer::modZLevel(uint32_t zLevel, ModId mod, MaterialHue hue, MaterialColorVariant colorVariant) {
|
||||||
|
QuadZLevel quadZLevel = 0;
|
||||||
|
quadZLevel |= (uint64_t)colorVariant;
|
||||||
|
quadZLevel |= (uint64_t)hue << 8;
|
||||||
|
quadZLevel |= (uint64_t)mod << 16;
|
||||||
|
quadZLevel |= (uint64_t)zLevel << 32;
|
||||||
|
quadZLevel |= (uint64_t)1 << 63;
|
||||||
|
return quadZLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDrawer::QuadZLevel TileDrawer::damageZLevel() {
|
||||||
|
return (uint64_t)(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileDrawer::determineMatchingPieces(MaterialPieceResultList& resultList, bool* occlude, MaterialDatabaseConstPtr const& materialDb, MaterialRenderMatchList const& matchList,
|
||||||
|
WorldRenderData const& renderData, Vec2I const& basePos, TileLayer layer, bool isMod) {
|
||||||
|
RenderTile const& tile = getRenderTile(renderData, basePos);
|
||||||
|
|
||||||
|
auto matchSetMatches = [&](MaterialRenderMatchConstPtr const& match) -> bool {
|
||||||
|
if (match->requiredLayer && *match->requiredLayer != layer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (match->matchPoints.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool matchValid = match->matchJoin == MaterialJoinType::All;
|
||||||
|
for (auto const& matchPoint : match->matchPoints) {
|
||||||
|
auto const& neighborTile = getRenderTile(renderData, basePos + matchPoint.position);
|
||||||
|
|
||||||
|
bool neighborShadowing = false;
|
||||||
|
if (layer == TileLayer::Background) {
|
||||||
|
if (auto profile = materialDb->materialRenderProfile(neighborTile.foreground))
|
||||||
|
neighborShadowing = !profile->foregroundLightTransparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialHue baseHue = layer == TileLayer::Foreground ? tile.foregroundHueShift : tile.backgroundHueShift;
|
||||||
|
MaterialHue neighborHue = layer == TileLayer::Foreground ? neighborTile.foregroundHueShift : neighborTile.backgroundHueShift;
|
||||||
|
MaterialHue baseModHue = layer == TileLayer::Foreground ? tile.foregroundModHueShift : tile.backgroundModHueShift;
|
||||||
|
MaterialHue neighborModHue = layer == TileLayer::Foreground ? neighborTile.foregroundModHueShift : neighborTile.backgroundModHueShift;
|
||||||
|
MaterialId baseMaterial = layer == TileLayer::Foreground ? tile.foreground : tile.background;
|
||||||
|
MaterialId neighborMaterial = layer == TileLayer::Foreground ? neighborTile.foreground : neighborTile.background;
|
||||||
|
ModId baseMod = layer == TileLayer::Foreground ? tile.foregroundMod : tile.backgroundMod;
|
||||||
|
ModId neighborMod = layer == TileLayer::Foreground ? neighborTile.foregroundMod : neighborTile.backgroundMod;
|
||||||
|
|
||||||
|
bool rulesValid = matchPoint.rule->join == MaterialJoinType::All;
|
||||||
|
for (auto const& ruleEntry : matchPoint.rule->entries) {
|
||||||
|
bool valid = true;
|
||||||
|
if (isMod) {
|
||||||
|
if (ruleEntry.rule.is<MaterialRule::RuleEmpty>()) {
|
||||||
|
valid = neighborMod == NoModId;
|
||||||
|
} else if (ruleEntry.rule.is<MaterialRule::RuleConnects>()) {
|
||||||
|
valid = isConnectableMaterial(neighborMaterial);
|
||||||
|
} else if (ruleEntry.rule.is<MaterialRule::RuleShadows>()) {
|
||||||
|
valid = neighborShadowing;
|
||||||
|
} else if (auto equalsSelf = ruleEntry.rule.ptr<MaterialRule::RuleEqualsSelf>()) {
|
||||||
|
valid = neighborMod == baseMod;
|
||||||
|
if (equalsSelf->matchHue)
|
||||||
|
valid = valid && baseModHue == neighborModHue;
|
||||||
|
} else if (auto equalsId = ruleEntry.rule.ptr<MaterialRule::RuleEqualsId>()) {
|
||||||
|
valid = neighborMod == equalsId->id;
|
||||||
|
} else if (auto propertyEquals = ruleEntry.rule.ptr<MaterialRule::RulePropertyEquals>()) {
|
||||||
|
if (auto profile = materialDb->modRenderProfile(neighborMod))
|
||||||
|
valid = profile->ruleProperties.get(propertyEquals->propertyName, Json()) == propertyEquals->compare;
|
||||||
|
else
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ruleEntry.rule.is<MaterialRule::RuleEmpty>()) {
|
||||||
|
valid = neighborMaterial == EmptyMaterialId;
|
||||||
|
} else if (ruleEntry.rule.is<MaterialRule::RuleConnects>()) {
|
||||||
|
valid = isConnectableMaterial(neighborMaterial);
|
||||||
|
} else if (ruleEntry.rule.is<MaterialRule::RuleShadows>()) {
|
||||||
|
valid = neighborShadowing;
|
||||||
|
} else if (auto equalsSelf = ruleEntry.rule.ptr<MaterialRule::RuleEqualsSelf>()) {
|
||||||
|
valid = neighborMaterial == baseMaterial;
|
||||||
|
if (equalsSelf->matchHue)
|
||||||
|
valid = valid && baseHue == neighborHue;
|
||||||
|
} else if (auto equalsId = ruleEntry.rule.ptr<MaterialRule::RuleEqualsId>()) {
|
||||||
|
valid = neighborMaterial == equalsId->id;
|
||||||
|
} else if (auto propertyEquals = ruleEntry.rule.ptr<MaterialRule::RulePropertyEquals>()) {
|
||||||
|
if (auto profile = materialDb->materialRenderProfile(neighborMaterial))
|
||||||
|
valid = profile->ruleProperties.get(propertyEquals->propertyName) == propertyEquals->compare;
|
||||||
|
else
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ruleEntry.inverse)
|
||||||
|
valid = !valid;
|
||||||
|
|
||||||
|
if (matchPoint.rule->join == MaterialJoinType::All) {
|
||||||
|
rulesValid = valid && rulesValid;
|
||||||
|
if (!rulesValid)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
rulesValid = valid || rulesValid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match->matchJoin == MaterialJoinType::All) {
|
||||||
|
matchValid = matchValid && rulesValid;
|
||||||
|
if (!matchValid)
|
||||||
|
return matchValid;
|
||||||
|
} else {
|
||||||
|
matchValid = matchValid || rulesValid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matchValid;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool subMatchResult = false;
|
||||||
|
for (auto const& match : matchList) {
|
||||||
|
if (matchSetMatches(match)) {
|
||||||
|
if (match->occlude)
|
||||||
|
*occlude = match->occlude.get();
|
||||||
|
|
||||||
|
subMatchResult = true;
|
||||||
|
|
||||||
|
for (auto const& piecePair : match->resultingPieces)
|
||||||
|
resultList.append({piecePair.first, piecePair.second});
|
||||||
|
|
||||||
|
if (determineMatchingPieces(resultList, occlude, materialDb, match->subMatches, renderData, basePos, layer, isMod) && match->haltOnSubMatch)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (match->haltOnMatch)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return subMatchResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
77
source/game/StarTileDrawer.hpp
Normal file
77
source/game/StarTileDrawer.hpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#ifndef STAR_TILE_DRAWER_HPP
|
||||||
|
#define STAR_TILE_DRAWER_HPP
|
||||||
|
|
||||||
|
#include "StarTtlCache.hpp"
|
||||||
|
#include "StarWorldRenderData.hpp"
|
||||||
|
#include "StarMaterialRenderProfile.hpp"
|
||||||
|
#include "StarDrawable.hpp"
|
||||||
|
|
||||||
|
namespace Star {
|
||||||
|
|
||||||
|
STAR_CLASS(Assets);
|
||||||
|
STAR_CLASS(MaterialDatabase);
|
||||||
|
STAR_CLASS(TileDrawer);
|
||||||
|
|
||||||
|
class TileDrawer {
|
||||||
|
public:
|
||||||
|
typedef uint64_t QuadZLevel;
|
||||||
|
typedef HashMap<QuadZLevel, List<Drawable>> Drawables;
|
||||||
|
|
||||||
|
typedef size_t MaterialRenderPieceIndex;
|
||||||
|
typedef List<pair<MaterialRenderPieceConstPtr, Vec2F>> MaterialPieceResultList;
|
||||||
|
|
||||||
|
enum class TerrainLayer { Background, Midground, Foreground };
|
||||||
|
|
||||||
|
static RenderTile DefaultRenderTile;
|
||||||
|
|
||||||
|
static TileDrawer* singletonPtr();
|
||||||
|
static TileDrawer& singleton();
|
||||||
|
|
||||||
|
TileDrawer();
|
||||||
|
~TileDrawer();
|
||||||
|
|
||||||
|
bool produceTerrainDrawables(Drawables& drawables, TerrainLayer terrainLayer, Vec2I const& pos,
|
||||||
|
WorldRenderData const& renderData, float scale = 1.0f, Vec2I variantOffset = {}, Maybe<TerrainLayer> variantLayer = {});
|
||||||
|
|
||||||
|
WorldRenderData& renderData();
|
||||||
|
MutexLocker lockRenderData();
|
||||||
|
|
||||||
|
template <typename Function>
|
||||||
|
static void forEachRenderTile(WorldRenderData const& renderData, RectI const& worldCoordRange, Function&& function);
|
||||||
|
private:
|
||||||
|
friend class TilePainter;
|
||||||
|
|
||||||
|
static TileDrawer* s_singleton;
|
||||||
|
|
||||||
|
static RenderTile const& getRenderTile(WorldRenderData const& renderData, Vec2I const& worldPos);
|
||||||
|
|
||||||
|
static QuadZLevel materialZLevel(uint32_t zLevel, MaterialId material, MaterialHue hue, MaterialColorVariant colorVariant);
|
||||||
|
static QuadZLevel modZLevel(uint32_t zLevel, ModId mod, MaterialHue hue, MaterialColorVariant colorVariant);
|
||||||
|
static QuadZLevel damageZLevel();
|
||||||
|
|
||||||
|
static bool determineMatchingPieces(MaterialPieceResultList& resultList, bool* occlude, MaterialDatabaseConstPtr const& materialDb, MaterialRenderMatchList const& matchList,
|
||||||
|
WorldRenderData const& renderData, Vec2I const& basePos, TileLayer layer, bool isMod);
|
||||||
|
|
||||||
|
Vec4B m_backgroundLayerColor;
|
||||||
|
Vec4B m_foregroundLayerColor;
|
||||||
|
Vec2F m_liquidDrawLevels;
|
||||||
|
|
||||||
|
WorldRenderData m_tempRenderData;
|
||||||
|
Mutex m_tempRenderDataMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Function>
|
||||||
|
void TileDrawer::forEachRenderTile(WorldRenderData const& renderData, RectI const& worldCoordRange, Function&& function) {
|
||||||
|
RectI indexRect = RectI::withSize(renderData.geometry.diff(worldCoordRange.min(), renderData.tileMinPosition), worldCoordRange.size());
|
||||||
|
indexRect.limit(RectI::withSize(Vec2I(0, 0), Vec2I(renderData.tiles.size())));
|
||||||
|
|
||||||
|
if (!indexRect.isEmpty()) {
|
||||||
|
renderData.tiles.forEach(Array2S(indexRect.min()), Array2S(indexRect.size()), [&](Array2S const& index, RenderTile const& tile) {
|
||||||
|
return function(worldCoordRange.min() + (Vec2I(index) - indexRect.min()), tile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -536,9 +536,9 @@ void ToolUser::render(RenderCallback* renderCallback, bool inToolRange, bool shi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auto pri = as<PreviewTileTool>(m_primaryHandItem.get()))
|
if (auto pri = as<PreviewTileTool>(m_primaryHandItem.get()))
|
||||||
renderCallback->addTilePreviews(pri->preview(shifting));
|
renderCallback->addTilePreviews(pri->previewTiles(shifting));
|
||||||
else if (auto alt = as<PreviewTileTool>(m_altHandItem.get()))
|
else if (auto alt = as<PreviewTileTool>(m_altHandItem.get()))
|
||||||
renderCallback->addTilePreviews(alt->preview(shifting));
|
renderCallback->addTilePreviews(alt->previewTiles(shifting));
|
||||||
|
|
||||||
if (auto ren = as<RenderableItem>(m_primaryHandItem.get()))
|
if (auto ren = as<RenderableItem>(m_primaryHandItem.get()))
|
||||||
ren->render(renderCallback, renderLayer);
|
ren->render(renderCallback, renderLayer);
|
||||||
|
@ -12,7 +12,7 @@ namespace Star {
|
|||||||
class PreviewTileTool {
|
class PreviewTileTool {
|
||||||
public:
|
public:
|
||||||
virtual ~PreviewTileTool() {}
|
virtual ~PreviewTileTool() {}
|
||||||
virtual List<PreviewTile> preview(bool shifting) const = 0;
|
virtual List<PreviewTile> previewTiles(bool shifting) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ float LiquidItem::liquidQuantity() const {
|
|||||||
return m_quantity;
|
return m_quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PreviewTile> LiquidItem::preview(bool shifting) const {
|
List<PreviewTile> LiquidItem::previewTiles(bool shifting) const {
|
||||||
List<PreviewTile> result;
|
List<PreviewTile> result;
|
||||||
if (initialized()) {
|
if (initialized()) {
|
||||||
auto liquid = liquidId();
|
auto liquid = liquidId();
|
||||||
|
@ -28,7 +28,7 @@ public:
|
|||||||
LiquidId liquidId() const;
|
LiquidId liquidId() const;
|
||||||
float liquidQuantity() const;
|
float liquidQuantity() const;
|
||||||
|
|
||||||
List<PreviewTile> preview(bool shifting) const override;
|
List<PreviewTile> previewTiles(bool shifting) const override;
|
||||||
|
|
||||||
bool canPlace(bool shifting) const;
|
bool canPlace(bool shifting) const;
|
||||||
bool canPlaceAtTile(Vec2I pos) const;
|
bool canPlaceAtTile(Vec2I pos) const;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "StarWorldClient.hpp"
|
#include "StarWorldClient.hpp"
|
||||||
#include "StarWorldTemplate.hpp"
|
#include "StarWorldTemplate.hpp"
|
||||||
#include "StarInput.hpp"
|
#include "StarInput.hpp"
|
||||||
|
#include "StarTileDrawer.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ MaterialItem::MaterialItem(Json const& config, String const& directory, Json con
|
|||||||
: Item(config, directory, settings), FireableItem(config), BeamItem(config) {
|
: Item(config, directory, settings), FireableItem(config), BeamItem(config) {
|
||||||
m_material = config.getInt("materialId");
|
m_material = config.getInt("materialId");
|
||||||
m_materialHueShift = materialHueFromDegrees(instanceValue("materialHueShift", 0).toFloat());
|
m_materialHueShift = materialHueFromDegrees(instanceValue("materialHueShift", 0).toFloat());
|
||||||
|
auto materialDatabase = Root::singleton().materialDatabase();
|
||||||
|
|
||||||
if (materialHueShift() != MaterialHue()) {
|
if (materialHueShift() != MaterialHue()) {
|
||||||
auto drawables = iconDrawables();
|
auto drawables = iconDrawables();
|
||||||
@ -36,7 +38,6 @@ MaterialItem::MaterialItem(Json const& config, String const& directory, Json con
|
|||||||
m_blockRadius = instanceValue("blockRadius", defaultParameters.getFloat("blockRadius")).toFloat();
|
m_blockRadius = instanceValue("blockRadius", defaultParameters.getFloat("blockRadius")).toFloat();
|
||||||
m_altBlockRadius = instanceValue("altBlockRadius", defaultParameters.getFloat("altBlockRadius")).toFloat();
|
m_altBlockRadius = instanceValue("altBlockRadius", defaultParameters.getFloat("altBlockRadius")).toFloat();
|
||||||
|
|
||||||
auto materialDatabase = Root::singleton().materialDatabase();
|
|
||||||
auto multiplace = instanceValue("allowMultiplace", BlockCollisionSet.contains(materialDatabase->materialCollisionKind(m_material)));
|
auto multiplace = instanceValue("allowMultiplace", BlockCollisionSet.contains(materialDatabase->materialCollisionKind(m_material)));
|
||||||
if (multiplace.isType(Json::Type::Bool))
|
if (multiplace.isType(Json::Type::Bool))
|
||||||
m_multiplace = multiplace.toBool();
|
m_multiplace = multiplace.toBool();
|
||||||
@ -96,16 +97,16 @@ void MaterialItem::update(float dt, FireMode fireMode, bool shifting, HashSet<Mo
|
|||||||
owner()->addSound("/sfx/tools/cyclematcollision.ogg", 1.0f, Random::randf(0.9f, 1.1f));
|
owner()->addSound("/sfx/tools/cyclematcollision.ogg", 1.0f, Random::randf(0.9f, 1.1f));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto presses = input.bindDown("opensb", "materialRadiusGrow")) {
|
if (auto presses = input.bindDown("opensb", "buildingRadiusGrow")) {
|
||||||
m_blockRadius = min(BlockRadiusLimit, int(m_blockRadius + *presses));
|
m_blockRadius = min(BlockRadiusLimit, int(m_blockRadius + *presses));
|
||||||
setInstanceValue("blockRadius", m_blockRadius);
|
setInstanceValue("blockRadius", m_blockRadius);
|
||||||
owner()->addSound("/sfx/tools/matradiusgrow.wav", 1.0f, 1.0f + m_blockRadius / BlockRadiusLimit);
|
owner()->addSound("/sfx/tools/buildradiusgrow.wav", 1.0f, 1.0f + m_blockRadius / BlockRadiusLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto presses = input.bindDown("opensb", "materialRadiusShrink")) {
|
if (auto presses = input.bindDown("opensb", "buildingRadiusShrink")) {
|
||||||
m_blockRadius = max(1, int(m_blockRadius - *presses));
|
m_blockRadius = max(1, int(m_blockRadius - *presses));
|
||||||
setInstanceValue("blockRadius", m_blockRadius);
|
setInstanceValue("blockRadius", m_blockRadius);
|
||||||
owner()->addSound("/sfx/tools/matradiusshrink.wav", 1.0f, 1.0f + m_blockRadius / BlockRadiusLimit);
|
owner()->addSound("/sfx/tools/buildradiusshrink.wav", 1.0f, 1.0f + m_blockRadius / BlockRadiusLimit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -148,6 +149,14 @@ void MaterialItem::render(RenderCallback* renderCallback, EntityRenderLayer rend
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Drawable> MaterialItem::preview(PlayerPtr const&) const {
|
||||||
|
return generatedPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Drawable> MaterialItem::dropDrawables() const {
|
||||||
|
return generatedPreview();
|
||||||
|
}
|
||||||
|
|
||||||
List<Drawable> MaterialItem::nonRotatedDrawables() const {
|
List<Drawable> MaterialItem::nonRotatedDrawables() const {
|
||||||
return beamDrawables(canPlace(m_shifting));
|
return beamDrawables(canPlace(m_shifting));
|
||||||
}
|
}
|
||||||
@ -218,6 +227,47 @@ MaterialId MaterialItem::materialId() const {
|
|||||||
return m_material;
|
return m_material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Drawable> const& MaterialItem::generatedPreview(Vec2I position) const {
|
||||||
|
if (!m_generatedPreviewCache) {
|
||||||
|
if (TileDrawer* tileDrawer = TileDrawer::singletonPtr()) {
|
||||||
|
auto locker = tileDrawer->lockRenderData();
|
||||||
|
WorldRenderData& renderData = tileDrawer->renderData();
|
||||||
|
renderData.geometry = WorldGeometry(3, 3);
|
||||||
|
renderData.tiles.resize({ 3, 3 });
|
||||||
|
renderData.tiles.fill(TileDrawer::DefaultRenderTile);
|
||||||
|
renderData.tileMinPosition = { 0, 0 };
|
||||||
|
RenderTile& tile = renderData.tiles.at({ 1, 1 });
|
||||||
|
tile.foreground = m_material;
|
||||||
|
tile.foregroundHueShift = m_materialHueShift;
|
||||||
|
tile.foregroundColorVariant = 0;
|
||||||
|
|
||||||
|
List<Drawable> drawables;
|
||||||
|
TileDrawer::Drawables tileDrawables;
|
||||||
|
bool isBlock = BlockCollisionSet.contains(Root::singleton().materialDatabase()->materialCollisionKind(m_material));
|
||||||
|
TileDrawer::TerrainLayer layer = isBlock ? TileDrawer::TerrainLayer::Foreground : TileDrawer::TerrainLayer::Midground;
|
||||||
|
for (int x = 0; x != 3; ++x) {
|
||||||
|
for (int y = 0; y != 3; ++y)
|
||||||
|
tileDrawer->produceTerrainDrawables(tileDrawables, layer, { x, y }, renderData, 1.0f / TilePixels, position - Vec2I(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
locker.unlock();
|
||||||
|
for (auto& index : tileDrawables.keys())
|
||||||
|
drawables.appendAll(tileDrawables.take(index));
|
||||||
|
|
||||||
|
auto boundBox = Drawable::boundBoxAll(drawables, true);
|
||||||
|
if (!boundBox.isEmpty()) {
|
||||||
|
for (auto& drawable : drawables)
|
||||||
|
drawable.translate(-boundBox.center());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_generatedPreviewCache.emplace(move(drawables));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_generatedPreviewCache.emplace(iconDrawables());
|
||||||
|
}
|
||||||
|
return *m_generatedPreviewCache;
|
||||||
|
}
|
||||||
|
|
||||||
float MaterialItem::calcRadius(bool shifting) const {
|
float MaterialItem::calcRadius(bool shifting) const {
|
||||||
if (!multiplaceEnabled())
|
if (!multiplaceEnabled())
|
||||||
return 1;
|
return 1;
|
||||||
@ -270,7 +320,7 @@ TileCollisionOverride& MaterialItem::collisionOverride() {
|
|||||||
return m_collisionOverride;
|
return m_collisionOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PreviewTile> MaterialItem::preview(bool shifting) const {
|
List<PreviewTile> MaterialItem::previewTiles(bool shifting) const {
|
||||||
List<PreviewTile> result;
|
List<PreviewTile> result;
|
||||||
if (initialized()) {
|
if (initialized()) {
|
||||||
Color lightColor = Color::rgba(owner()->favoriteColor());
|
Color lightColor = Color::rgba(owner()->favoriteColor());
|
||||||
|
@ -7,13 +7,15 @@
|
|||||||
#include "StarEntityRendering.hpp"
|
#include "StarEntityRendering.hpp"
|
||||||
#include "StarPreviewTileTool.hpp"
|
#include "StarPreviewTileTool.hpp"
|
||||||
#include "StarRenderableItem.hpp"
|
#include "StarRenderableItem.hpp"
|
||||||
|
#include "StarPreviewableItem.hpp"
|
||||||
#include "StarCollisionBlock.hpp"
|
#include "StarCollisionBlock.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
STAR_CLASS(MaterialItem);
|
STAR_CLASS(MaterialItem);
|
||||||
|
STAR_CLASS(Player);
|
||||||
|
|
||||||
class MaterialItem : public Item, public FireableItem, public PreviewTileTool, public RenderableItem, public BeamItem {
|
class MaterialItem : public Item, public FireableItem, public PreviewTileTool, public RenderableItem, public PreviewableItem, public BeamItem {
|
||||||
public:
|
public:
|
||||||
MaterialItem(Json const& config, String const& directory, Json const& settings);
|
MaterialItem(Json const& config, String const& directory, Json const& settings);
|
||||||
virtual ~MaterialItem() {}
|
virtual ~MaterialItem() {}
|
||||||
@ -25,6 +27,8 @@ public:
|
|||||||
void update(float dt, FireMode fireMode, bool shifting, HashSet<MoveControlType> const& moves) override;
|
void update(float dt, FireMode fireMode, bool shifting, HashSet<MoveControlType> const& moves) override;
|
||||||
void render(RenderCallback* renderCallback, EntityRenderLayer renderLayer) override;
|
void render(RenderCallback* renderCallback, EntityRenderLayer renderLayer) override;
|
||||||
|
|
||||||
|
virtual List<Drawable> preview(PlayerPtr const& viewer = {}) const override;
|
||||||
|
virtual List<Drawable> dropDrawables() const override;
|
||||||
List<Drawable> nonRotatedDrawables() const override;
|
List<Drawable> nonRotatedDrawables() const override;
|
||||||
|
|
||||||
void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
|
void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
|
||||||
@ -40,7 +44,8 @@ public:
|
|||||||
float& altBlockRadius();
|
float& altBlockRadius();
|
||||||
TileCollisionOverride& collisionOverride();
|
TileCollisionOverride& collisionOverride();
|
||||||
|
|
||||||
List<PreviewTile> preview(bool shifting) const override;
|
List<PreviewTile> previewTiles(bool shifting) const override;
|
||||||
|
List<Drawable> const& generatedPreview(Vec2I position = {}) const;
|
||||||
private:
|
private:
|
||||||
float calcRadius(bool shifting) const;
|
float calcRadius(bool shifting) const;
|
||||||
List<Vec2I>& tileArea(float radius, Vec2F const& position) const;
|
List<Vec2I>& tileArea(float radius, Vec2F const& position) const;
|
||||||
@ -60,6 +65,8 @@ private:
|
|||||||
mutable Vec2F m_lastTileAreaOriginCache;
|
mutable Vec2F m_lastTileAreaOriginCache;
|
||||||
mutable float m_lastTileAreaRadiusCache;
|
mutable float m_lastTileAreaRadiusCache;
|
||||||
mutable List<Vec2I> m_tileAreasCache;
|
mutable List<Vec2I> m_tileAreasCache;
|
||||||
|
|
||||||
|
mutable Maybe<List<Drawable>> m_generatedPreviewCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -360,7 +360,7 @@ void BeamMiningTool::setEnd(EndType) {
|
|||||||
m_endType = EndType::Object;
|
m_endType = EndType::Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PreviewTile> BeamMiningTool::preview(bool shifting) const {
|
List<PreviewTile> BeamMiningTool::previewTiles(bool shifting) const {
|
||||||
List<PreviewTile> result;
|
List<PreviewTile> result;
|
||||||
auto ownerp = owner();
|
auto ownerp = owner();
|
||||||
auto worldp = world();
|
auto worldp = world();
|
||||||
@ -636,7 +636,7 @@ void PaintingBeamTool::update(float dt, FireMode fireMode, bool shifting, HashSe
|
|||||||
FireableItem::update(dt, fireMode, shifting, moves);
|
FireableItem::update(dt, fireMode, shifting, moves);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PreviewTile> PaintingBeamTool::preview(bool shifting) const {
|
List<PreviewTile> PaintingBeamTool::previewTiles(bool shifting) const {
|
||||||
List<PreviewTile> result;
|
List<PreviewTile> result;
|
||||||
auto ownerp = owner();
|
auto ownerp = owner();
|
||||||
auto worldp = world();
|
auto worldp = world();
|
||||||
|
@ -150,7 +150,7 @@ public:
|
|||||||
List<Drawable> drawables() const override;
|
List<Drawable> drawables() const override;
|
||||||
|
|
||||||
virtual void setEnd(EndType type) override;
|
virtual void setEnd(EndType type) override;
|
||||||
virtual List<PreviewTile> preview(bool shifting) const override;
|
virtual List<PreviewTile> previewTiles(bool shifting) const override;
|
||||||
virtual List<Drawable> nonRotatedDrawables() const override;
|
virtual List<Drawable> nonRotatedDrawables() const override;
|
||||||
virtual void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
|
virtual void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ public:
|
|||||||
|
|
||||||
void setEnd(EndType type) override;
|
void setEnd(EndType type) override;
|
||||||
void update(float dt, FireMode fireMode, bool shifting, HashSet<MoveControlType> const& moves) override;
|
void update(float dt, FireMode fireMode, bool shifting, HashSet<MoveControlType> const& moves) override;
|
||||||
List<PreviewTile> preview(bool shifting) const override;
|
List<PreviewTile> previewTiles(bool shifting) const override;
|
||||||
void init(ToolUserEntity* owner, ToolHand hand) override;
|
void init(ToolUserEntity* owner, ToolHand hand) override;
|
||||||
List<Drawable> nonRotatedDrawables() const override;
|
List<Drawable> nonRotatedDrawables() const override;
|
||||||
void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
|
void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
#include "StarLiquidsDatabase.hpp"
|
#include "StarLiquidsDatabase.hpp"
|
||||||
#include "StarAssets.hpp"
|
#include "StarAssets.hpp"
|
||||||
#include "StarRoot.hpp"
|
#include "StarRoot.hpp"
|
||||||
|
#include "StarTileDrawer.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
TilePainter::TilePainter(RendererPtr renderer) {
|
TilePainter::TilePainter(RendererPtr renderer) : TileDrawer() {
|
||||||
m_renderer = move(renderer);
|
m_renderer = move(renderer);
|
||||||
m_textureGroup = m_renderer->createTextureGroup(TextureGroupSize::Large);
|
m_textureGroup = m_renderer->createTextureGroup(TextureGroupSize::Large);
|
||||||
|
|
||||||
@ -24,10 +25,6 @@ TilePainter::TilePainter(RendererPtr renderer) {
|
|||||||
|
|
||||||
m_textureCache.setTimeToLive(assets->json("/rendering.config:textureTimeout").toInt());
|
m_textureCache.setTimeToLive(assets->json("/rendering.config:textureTimeout").toInt());
|
||||||
|
|
||||||
m_backgroundLayerColor = jsonToColor(assets->json("/rendering.config:backgroundLayerColor")).toRgba();
|
|
||||||
m_foregroundLayerColor = jsonToColor(assets->json("/rendering.config:foregroundLayerColor")).toRgba();
|
|
||||||
m_liquidDrawLevels = jsonToVec2F(assets->json("/rendering.config:liquidDrawLevels"));
|
|
||||||
|
|
||||||
for (auto const& liquid : root.liquidsDatabase()->allLiquidSettings()) {
|
for (auto const& liquid : root.liquidsDatabase()->allLiquidSettings()) {
|
||||||
m_liquids.set(liquid->id, LiquidInfo{
|
m_liquids.set(liquid->id, LiquidInfo{
|
||||||
m_renderer->createTexture(*assets->image(liquid->config.getString("texture")), TextureAddressing::Wrap),
|
m_renderer->createTexture(*assets->image(liquid->config.getString("texture")), TextureAddressing::Wrap),
|
||||||
@ -152,57 +149,6 @@ TilePainter::ChunkHash TilePainter::liquidChunkHash(WorldRenderData& renderData,
|
|||||||
return XXH3_64bits(buffer.ptr(), buffer.size());
|
return XXH3_64bits(buffer.ptr(), buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TilePainter::QuadZLevel TilePainter::materialZLevel(uint32_t zLevel, MaterialId material, MaterialHue hue, MaterialColorVariant colorVariant) {
|
|
||||||
QuadZLevel quadZLevel = 0;
|
|
||||||
quadZLevel |= (uint64_t)colorVariant;
|
|
||||||
quadZLevel |= (uint64_t)hue << 8;
|
|
||||||
quadZLevel |= (uint64_t)material << 16;
|
|
||||||
quadZLevel |= (uint64_t)zLevel << 32;
|
|
||||||
return quadZLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
TilePainter::QuadZLevel TilePainter::modZLevel(uint32_t zLevel, ModId mod, MaterialHue hue, MaterialColorVariant colorVariant) {
|
|
||||||
QuadZLevel quadZLevel = 0;
|
|
||||||
quadZLevel |= (uint64_t)colorVariant;
|
|
||||||
quadZLevel |= (uint64_t)hue << 8;
|
|
||||||
quadZLevel |= (uint64_t)mod << 16;
|
|
||||||
quadZLevel |= (uint64_t)zLevel << 32;
|
|
||||||
quadZLevel |= (uint64_t)1 << 63;
|
|
||||||
return quadZLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
TilePainter::QuadZLevel TilePainter::damageZLevel() {
|
|
||||||
return (uint64_t)(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderTile const& TilePainter::getRenderTile(WorldRenderData const& renderData, Vec2I const& worldPos) {
|
|
||||||
Vec2I arrayPos = renderData.geometry.diff(worldPos, renderData.tileMinPosition);
|
|
||||||
|
|
||||||
Vec2I size = Vec2I(renderData.tiles.size());
|
|
||||||
if (arrayPos[0] >= 0 && arrayPos[1] >= 0 && arrayPos[0] < size[0] && arrayPos[1] < size[1])
|
|
||||||
return renderData.tiles(Vec2S(arrayPos));
|
|
||||||
|
|
||||||
static RenderTile defaultRenderTile = {
|
|
||||||
NullMaterialId,
|
|
||||||
NoModId,
|
|
||||||
NullMaterialId,
|
|
||||||
NoModId,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
DefaultMaterialColorVariant,
|
|
||||||
TileDamageType::Protected,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
DefaultMaterialColorVariant,
|
|
||||||
TileDamageType::Protected,
|
|
||||||
0,
|
|
||||||
EmptyLiquidId,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
return defaultRenderTile;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TilePainter::renderTerrainChunks(WorldCamera const& camera, TerrainLayer terrainLayer) {
|
void TilePainter::renderTerrainChunks(WorldCamera const& camera, TerrainLayer terrainLayer) {
|
||||||
Map<QuadZLevel, List<RenderBufferPtr>> zOrderBuffers;
|
Map<QuadZLevel, List<RenderBufferPtr>> zOrderBuffers;
|
||||||
for (auto const& chunk : m_pendingTerrainChunks) {
|
for (auto const& chunk : m_pendingTerrainChunks) {
|
||||||
@ -285,7 +231,7 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
|
|||||||
|
|
||||||
MaterialId material = EmptyMaterialId;
|
MaterialId material = EmptyMaterialId;
|
||||||
MaterialHue materialHue = 0;
|
MaterialHue materialHue = 0;
|
||||||
MaterialHue materialColorVariant = 0;
|
MaterialColorVariant materialColorVariant = 0;
|
||||||
ModId mod = NoModId;
|
ModId mod = NoModId;
|
||||||
MaterialHue modHue = 0;
|
MaterialHue modHue = 0;
|
||||||
float damageLevel = 0.0f;
|
float damageLevel = 0.0f;
|
||||||
@ -316,7 +262,7 @@ bool TilePainter::produceTerrainPrimitives(HashMap<QuadZLevel, List<RenderPrimit
|
|||||||
|
|
||||||
// render non-block colliding things in the midground
|
// render non-block colliding things in the midground
|
||||||
bool isBlock = BlockCollisionSet.contains(materialDatabase->materialCollisionKind(material));
|
bool isBlock = BlockCollisionSet.contains(materialDatabase->materialCollisionKind(material));
|
||||||
if ((isBlock && terrainLayer == TerrainLayer::Midground) || (!isBlock && terrainLayer == TerrainLayer::Foreground))
|
if (terrainLayer == (isBlock ? TerrainLayer::Midground : TerrainLayer::Foreground))
|
||||||
return false;
|
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, bool mod) {
|
||||||
@ -423,7 +369,7 @@ void TilePainter::produceLiquidPrimitives(HashMap<LiquidId, List<RenderPrimitive
|
|||||||
auto texRect = worldRect.scaled(TilePixels);
|
auto texRect = worldRect.scaled(TilePixels);
|
||||||
|
|
||||||
auto const& liquid = m_liquids[tile.liquidId];
|
auto const& liquid = m_liquids[tile.liquidId];
|
||||||
primitives[tile.liquidId].emplace_back(std::in_place_type_t<RenderQuad>(), move(liquid.texture),
|
primitives[tile.liquidId].emplace_back(std::in_place_type_t<RenderQuad>(), liquid.texture,
|
||||||
worldRect.min(), texRect.min(),
|
worldRect.min(), texRect.min(),
|
||||||
Vec2F(worldRect.xMax(), worldRect.yMin()), Vec2F(texRect.xMax(), texRect.yMin()),
|
Vec2F(worldRect.xMax(), worldRect.yMin()), Vec2F(texRect.xMax(), texRect.yMin()),
|
||||||
worldRect.max(), texRect.max(),
|
worldRect.max(), texRect.max(),
|
||||||
@ -431,123 +377,6 @@ void TilePainter::produceLiquidPrimitives(HashMap<LiquidId, List<RenderPrimitive
|
|||||||
liquid.color, 1.0f);
|
liquid.color, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TilePainter::determineMatchingPieces(MaterialPieceResultList& resultList, bool* occlude, MaterialDatabaseConstPtr const& materialDb, MaterialRenderMatchList const& matchList,
|
|
||||||
WorldRenderData const& renderData, Vec2I const& basePos, TileLayer layer, bool isMod) {
|
|
||||||
RenderTile const& tile = getRenderTile(renderData, basePos);
|
|
||||||
|
|
||||||
auto matchSetMatches = [&](MaterialRenderMatchConstPtr const& match) -> bool {
|
|
||||||
if (match->requiredLayer && *match->requiredLayer != layer)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (match->matchPoints.empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
bool matchValid = match->matchJoin == MaterialJoinType::All;
|
|
||||||
for (auto const& matchPoint : match->matchPoints) {
|
|
||||||
auto const& neighborTile = getRenderTile(renderData, basePos + matchPoint.position);
|
|
||||||
|
|
||||||
bool neighborShadowing = false;
|
|
||||||
if (layer == TileLayer::Background) {
|
|
||||||
if (auto profile = materialDb->materialRenderProfile(neighborTile.foreground))
|
|
||||||
neighborShadowing = !profile->foregroundLightTransparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialHue baseHue = layer == TileLayer::Foreground ? tile.foregroundHueShift : tile.backgroundHueShift;
|
|
||||||
MaterialHue neighborHue = layer == TileLayer::Foreground ? neighborTile.foregroundHueShift : neighborTile.backgroundHueShift;
|
|
||||||
MaterialHue baseModHue = layer == TileLayer::Foreground ? tile.foregroundModHueShift : tile.backgroundModHueShift;
|
|
||||||
MaterialHue neighborModHue = layer == TileLayer::Foreground ? neighborTile.foregroundModHueShift : neighborTile.backgroundModHueShift;
|
|
||||||
MaterialId baseMaterial = layer == TileLayer::Foreground ? tile.foreground : tile.background;
|
|
||||||
MaterialId neighborMaterial = layer == TileLayer::Foreground ? neighborTile.foreground : neighborTile.background;
|
|
||||||
ModId baseMod = layer == TileLayer::Foreground ? tile.foregroundMod : tile.backgroundMod;
|
|
||||||
ModId neighborMod = layer == TileLayer::Foreground ? neighborTile.foregroundMod : neighborTile.backgroundMod;
|
|
||||||
|
|
||||||
bool rulesValid = matchPoint.rule->join == MaterialJoinType::All;
|
|
||||||
for (auto const& ruleEntry : matchPoint.rule->entries) {
|
|
||||||
bool valid = true;
|
|
||||||
if (isMod) {
|
|
||||||
if (ruleEntry.rule.is<MaterialRule::RuleEmpty>()) {
|
|
||||||
valid = neighborMod == NoModId;
|
|
||||||
} else if (ruleEntry.rule.is<MaterialRule::RuleConnects>()) {
|
|
||||||
valid = isConnectableMaterial(neighborMaterial);
|
|
||||||
} else if (ruleEntry.rule.is<MaterialRule::RuleShadows>()) {
|
|
||||||
valid = neighborShadowing;
|
|
||||||
} else if (auto equalsSelf = ruleEntry.rule.ptr<MaterialRule::RuleEqualsSelf>()) {
|
|
||||||
valid = neighborMod == baseMod;
|
|
||||||
if (equalsSelf->matchHue)
|
|
||||||
valid = valid && baseModHue == neighborModHue;
|
|
||||||
} else if (auto equalsId = ruleEntry.rule.ptr<MaterialRule::RuleEqualsId>()) {
|
|
||||||
valid = neighborMod == equalsId->id;
|
|
||||||
} else if (auto propertyEquals = ruleEntry.rule.ptr<MaterialRule::RulePropertyEquals>()) {
|
|
||||||
if (auto profile = materialDb->modRenderProfile(neighborMod))
|
|
||||||
valid = profile->ruleProperties.get(propertyEquals->propertyName, Json()) == propertyEquals->compare;
|
|
||||||
else
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ruleEntry.rule.is<MaterialRule::RuleEmpty>()) {
|
|
||||||
valid = neighborMaterial == EmptyMaterialId;
|
|
||||||
} else if (ruleEntry.rule.is<MaterialRule::RuleConnects>()) {
|
|
||||||
valid = isConnectableMaterial(neighborMaterial);
|
|
||||||
} else if (ruleEntry.rule.is<MaterialRule::RuleShadows>()) {
|
|
||||||
valid = neighborShadowing;
|
|
||||||
} else if (auto equalsSelf = ruleEntry.rule.ptr<MaterialRule::RuleEqualsSelf>()) {
|
|
||||||
valid = neighborMaterial == baseMaterial;
|
|
||||||
if (equalsSelf->matchHue)
|
|
||||||
valid = valid && baseHue == neighborHue;
|
|
||||||
} else if (auto equalsId = ruleEntry.rule.ptr<MaterialRule::RuleEqualsId>()) {
|
|
||||||
valid = neighborMaterial == equalsId->id;
|
|
||||||
} else if (auto propertyEquals = ruleEntry.rule.ptr<MaterialRule::RulePropertyEquals>()) {
|
|
||||||
if (auto profile = materialDb->materialRenderProfile(neighborMaterial))
|
|
||||||
valid = profile->ruleProperties.get(propertyEquals->propertyName) == propertyEquals->compare;
|
|
||||||
else
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ruleEntry.inverse)
|
|
||||||
valid = !valid;
|
|
||||||
|
|
||||||
if (matchPoint.rule->join == MaterialJoinType::All) {
|
|
||||||
rulesValid = valid && rulesValid;
|
|
||||||
if (!rulesValid)
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
rulesValid = valid || rulesValid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match->matchJoin == MaterialJoinType::All) {
|
|
||||||
matchValid = matchValid && rulesValid;
|
|
||||||
if (!matchValid)
|
|
||||||
return matchValid;
|
|
||||||
} else {
|
|
||||||
matchValid = matchValid || rulesValid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matchValid;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool subMatchResult = false;
|
|
||||||
for (auto const& match : matchList) {
|
|
||||||
if (matchSetMatches(match)) {
|
|
||||||
if (match->occlude)
|
|
||||||
*occlude = match->occlude.get();
|
|
||||||
|
|
||||||
subMatchResult = true;
|
|
||||||
|
|
||||||
for (auto const& piecePair : match->resultingPieces)
|
|
||||||
resultList.append({piecePair.first, piecePair.second});
|
|
||||||
|
|
||||||
if (determineMatchingPieces(resultList, occlude, materialDb, match->subMatches, renderData, basePos, layer, isMod) && match->haltOnSubMatch)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (match->haltOnMatch)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return subMatchResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
float TilePainter::liquidDrawLevel(float liquidLevel) const {
|
float TilePainter::liquidDrawLevel(float liquidLevel) const {
|
||||||
return clamp((liquidLevel - m_liquidDrawLevels[0]) / (m_liquidDrawLevels[1] - m_liquidDrawLevels[0]), 0.0f, 1.0f);
|
return clamp((liquidLevel - m_liquidDrawLevels[0]) / (m_liquidDrawLevels[1] - m_liquidDrawLevels[0]), 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "StarMaterialRenderProfile.hpp"
|
#include "StarMaterialRenderProfile.hpp"
|
||||||
#include "StarRenderer.hpp"
|
#include "StarRenderer.hpp"
|
||||||
#include "StarWorldCamera.hpp"
|
#include "StarWorldCamera.hpp"
|
||||||
|
#include "StarTileDrawer.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ STAR_CLASS(Assets);
|
|||||||
STAR_CLASS(MaterialDatabase);
|
STAR_CLASS(MaterialDatabase);
|
||||||
STAR_CLASS(TilePainter);
|
STAR_CLASS(TilePainter);
|
||||||
|
|
||||||
class TilePainter {
|
class TilePainter : public TileDrawer {
|
||||||
public:
|
public:
|
||||||
// The rendered tiles are split and cached in chunks of RenderChunkSize x
|
// The rendered tiles are split and cached in chunks of RenderChunkSize x
|
||||||
// RenderChunkSize. This means that, around the border, there may be as many
|
// RenderChunkSize. This means that, around the border, there may be as many
|
||||||
@ -62,13 +63,10 @@ private:
|
|||||||
typedef HashMap<TerrainLayer, HashMap<QuadZLevel, RenderBufferPtr>> TerrainChunk;
|
typedef HashMap<TerrainLayer, HashMap<QuadZLevel, RenderBufferPtr>> TerrainChunk;
|
||||||
typedef HashMap<LiquidId, RenderBufferPtr> LiquidChunk;
|
typedef HashMap<LiquidId, RenderBufferPtr> LiquidChunk;
|
||||||
|
|
||||||
typedef size_t MaterialRenderPieceIndex;
|
|
||||||
typedef tuple<MaterialId, MaterialRenderPieceIndex, MaterialHue, bool> MaterialPieceTextureKey;
|
typedef tuple<MaterialId, MaterialRenderPieceIndex, MaterialHue, bool> MaterialPieceTextureKey;
|
||||||
typedef String AssetTextureKey;
|
typedef String AssetTextureKey;
|
||||||
typedef Variant<MaterialPieceTextureKey, AssetTextureKey> TextureKey;
|
typedef Variant<MaterialPieceTextureKey, AssetTextureKey> TextureKey;
|
||||||
|
|
||||||
typedef List<pair<MaterialRenderPieceConstPtr, Vec2F>> MaterialPieceResultList;
|
|
||||||
|
|
||||||
struct TextureKeyHash {
|
struct TextureKeyHash {
|
||||||
size_t operator()(TextureKey const& key) const;
|
size_t operator()(TextureKey const& key) const;
|
||||||
};
|
};
|
||||||
@ -80,15 +78,6 @@ private:
|
|||||||
static ChunkHash terrainChunkHash(WorldRenderData& renderData, Vec2I chunkIndex);
|
static ChunkHash terrainChunkHash(WorldRenderData& renderData, Vec2I chunkIndex);
|
||||||
static ChunkHash liquidChunkHash(WorldRenderData& renderData, Vec2I chunkIndex);
|
static ChunkHash liquidChunkHash(WorldRenderData& renderData, Vec2I chunkIndex);
|
||||||
|
|
||||||
static QuadZLevel materialZLevel(uint32_t zLevel, MaterialId material, MaterialHue hue, MaterialColorVariant colorVariant);
|
|
||||||
static QuadZLevel modZLevel(uint32_t zLevel, ModId mod, MaterialHue hue, MaterialColorVariant colorVariant);
|
|
||||||
static QuadZLevel damageZLevel();
|
|
||||||
|
|
||||||
static RenderTile const& getRenderTile(WorldRenderData const& renderData, Vec2I const& worldPos);
|
|
||||||
|
|
||||||
template <typename Function>
|
|
||||||
static void forEachRenderTile(WorldRenderData const& renderData, RectI const& worldCoordRange, Function&& function);
|
|
||||||
|
|
||||||
void renderTerrainChunks(WorldCamera const& camera, TerrainLayer terrainLayer);
|
void renderTerrainChunks(WorldCamera const& camera, TerrainLayer terrainLayer);
|
||||||
|
|
||||||
shared_ptr<TerrainChunk const> getTerrainChunk(WorldRenderData& renderData, Vec2I chunkIndex);
|
shared_ptr<TerrainChunk const> getTerrainChunk(WorldRenderData& renderData, Vec2I chunkIndex);
|
||||||
@ -98,17 +87,10 @@ private:
|
|||||||
TerrainLayer terrainLayer, Vec2I const& pos, WorldRenderData const& renderData);
|
TerrainLayer terrainLayer, Vec2I const& pos, WorldRenderData const& renderData);
|
||||||
void produceLiquidPrimitives(HashMap<LiquidId, List<RenderPrimitive>>& primitives, Vec2I const& pos, WorldRenderData const& renderData);
|
void produceLiquidPrimitives(HashMap<LiquidId, List<RenderPrimitive>>& primitives, Vec2I const& pos, WorldRenderData const& renderData);
|
||||||
|
|
||||||
bool determineMatchingPieces(MaterialPieceResultList& resultList, bool* occlude, MaterialDatabaseConstPtr const& materialDb, MaterialRenderMatchList const& matchList,
|
|
||||||
WorldRenderData const& renderData, Vec2I const& basePos, TileLayer layer, bool isMod);
|
|
||||||
|
|
||||||
float liquidDrawLevel(float liquidLevel) const;
|
float liquidDrawLevel(float liquidLevel) const;
|
||||||
|
|
||||||
List<LiquidInfo> m_liquids;
|
List<LiquidInfo> m_liquids;
|
||||||
|
|
||||||
Vec4B m_backgroundLayerColor;
|
|
||||||
Vec4B m_foregroundLayerColor;
|
|
||||||
Vec2F m_liquidDrawLevels;
|
|
||||||
|
|
||||||
RendererPtr m_renderer;
|
RendererPtr m_renderer;
|
||||||
TextureGroupPtr m_textureGroup;
|
TextureGroupPtr m_textureGroup;
|
||||||
|
|
||||||
@ -123,18 +105,6 @@ private:
|
|||||||
Vec2F m_cameraPan;
|
Vec2F m_cameraPan;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Function>
|
|
||||||
void TilePainter::forEachRenderTile(WorldRenderData const& renderData, RectI const& worldCoordRange, Function&& function) {
|
|
||||||
RectI indexRect = RectI::withSize(renderData.geometry.diff(worldCoordRange.min(), renderData.tileMinPosition), worldCoordRange.size());
|
|
||||||
indexRect.limit(RectI::withSize(Vec2I(0, 0), Vec2I(renderData.tiles.size())));
|
|
||||||
|
|
||||||
if (!indexRect.isEmpty()) {
|
|
||||||
renderData.tiles.forEach(Array2S(indexRect.min()), Array2S(indexRect.size()), [&](Array2S const& index, RenderTile const& tile) {
|
|
||||||
return function(worldCoordRange.min() + (Vec2I(index) - indexRect.min()), tile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user