Refactored code to be better separated (Rendering, Logic)

This commit is contained in:
=
2026-04-26 11:33:54 +02:00
parent 798fe23bb6
commit c80367dccd
9 changed files with 191 additions and 85 deletions
+48
View File
@@ -0,0 +1,48 @@
using Godot;
using System.Collections.Generic;
public class DecorationHandler
{
public static void Spawn(List<TileRenderData> tiles, Dictionary<string, MeshInstance3D> decorationMeshes)
{
foreach (var data in tiles)
{
Node3D tileNode = data.Tile.DecorationNode;
foreach (var placeholder in data.Placeholders)
{
string key = placeholder.name.ToLower();
var decoration = new MeshInstance3D();
if (decorationMeshes.ContainsKey(key))
{
decoration.Mesh = decorationMeshes[key].Mesh;
}
else
{
continue;
}
decoration.Position = placeholder.pos;
decoration.Rotate(Vector3.Up, Mathf.DegToRad(-90));
if (key == "light")
{
decoration.AddChild(new OmniLight3D()
{
OmniAttenuation = 2f,
LightColor = new Color("#eae7ad"),
ShadowEnabled = true,
LightEnergy = 5f,
LightIndirectEnergy = 1.5f,
Position = new Vector3(0.5f, 0, 0)
});
}
tileNode.AddChild(decoration);
}
}
}
}
+1
View File
@@ -0,0 +1 @@
uid://oe2d2ape41jj
+32 -1
View File
@@ -5,6 +5,7 @@ using System.Linq;
using static WFC;
public partial class Layer : Node3D
{
private Node3D decorationRoot;
public Tile[,] tiles;
int layerSize;
Tile tile;
@@ -14,7 +15,11 @@ public partial class Layer : Node3D
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
decorationRoot = new Node3D
{
Name = "Decorations"
};
AddChild(decorationRoot);
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
@@ -22,6 +27,17 @@ public partial class Layer : Node3D
{
}
public void ClearDecorations()
{
foreach (var tile in tiles)
{
foreach (Node child in tile.DecorationNode.GetChildren())
{
child.QueueFree();
}
}
}
public void SetupLayer(int layerSize, int level, Dictionary<string, MeshInstance3D> tileMeshes)
{
this.layerSize = layerSize;
@@ -44,6 +60,7 @@ public partial class Layer : Node3D
safetyCounter++;
if (safetyCounter > 1000) break;
}
CreateTileNodes();
}
private void GenerateBaseStructure(Dictionary<string, MeshInstance3D> tileMeshes)
@@ -68,6 +85,20 @@ public partial class Layer : Node3D
}
}
private void CreateTileNodes()
{
foreach (var tile in tiles)
{
var node = new Node3D
{
Position = tile.Position
};
decorationRoot.AddChild(node);
tile.DecorationNode = node;
}
}
private void ResetLayer(Dictionary<string, MeshInstance3D> tileMeshes)
{
for (int x = 0; x < layerSize; x++)
+39
View File
@@ -0,0 +1,39 @@
using Godot;
using System.Collections.Generic;
public class MultiMeshHandler
{
private Dictionary<string, MultiMeshInstance3D> multiMeshes;
public MultiMeshHandler(Dictionary<string, MultiMeshInstance3D> multiMeshes)
{
this.multiMeshes = multiMeshes;
}
public void Build(List<TileRenderData> tiles)
{
foreach (var mm in multiMeshes.Values)
mm.Multimesh.InstanceCount = 0;
var batches = new Dictionary<string, List<Transform3D>>();
foreach (var tile in tiles)
{
if (!batches.ContainsKey(tile.MeshKey))
batches[tile.MeshKey] = new List<Transform3D>();
batches[tile.MeshKey].Add(tile.Transform);
}
foreach (var kvp in batches)
{
var mm = multiMeshes[kvp.Key].Multimesh;
var list = kvp.Value;
mm.InstanceCount = list.Count;
for (int i = 0; i < list.Count; i++)
mm.SetInstanceTransform(i, list[i]);
}
}
}
+1
View File
@@ -0,0 +1 @@
uid://dc0v2yndgikkw
+10
View File
@@ -0,0 +1,10 @@
using Godot;
using System.Collections.Generic;
public struct TileRenderData
{
public Tile Tile;
public string MeshKey;
public Transform3D Transform;
public List<Placeholder> Placeholders;
}
+1
View File
@@ -0,0 +1 @@
uid://chwhqyo4abxd4
+1
View File
@@ -10,6 +10,7 @@ public partial class Tile
Random rand = new Random();
public Vector3 Position;
public Vector2I GridPosition;
public Node3D DecorationNode;
public void SetMeshes(Dictionary<string, MeshInstance3D> tileMeshes)
{
+57 -83
View File
@@ -14,40 +14,63 @@ public partial class World : Node3D
private Dictionary<string, Mesh> meshLibrary = new();
Layer[] map;
Layer layerNode;
// Called when the node enters the scene tree for the first time.
private MultiMeshHandler multiMeshHandler;
public override void _Ready()
{
WFC.FillAdjacencies();
tileMeshes = ResourceLoader.LoadTiles();
decorationMeshes = ResourceLoader.LoadDecorations();
tilePlaceholders = new Dictionary<string, List<Placeholder>>();
foreach (var kvp in tileMeshes)
{
tilePlaceholders.Add(kvp.Key, new List<Placeholder>());
tilePlaceholders[kvp.Key] = new List<Placeholder>();
foreach (MeshInstance3D child in kvp.Value.GetChildren())
{
tilePlaceholders[kvp.Key].Add(new Placeholder(child.Name, child.Transform.Origin));
}
var temp = kvp.Value;
meshLibrary[kvp.Key] = temp.Mesh;
temp.QueueFree();
meshLibrary[kvp.Key] = kvp.Value.Mesh;
kvp.Value.QueueFree();
}
foreach (var kvp in meshLibrary)
{
var mm = new MultiMesh();
mm.Mesh = kvp.Value;
mm.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
var instance = new MultiMeshInstance3D();
instance.Multimesh = mm;
multiMeshes = CreateMultiMeshes(meshLibrary);
multiMeshHandler = new MultiMeshHandler(multiMeshes);
AddChild(instance);
multiMeshes[kvp.Key] = instance;
}
map = new Layer[ruinSize];
GenerateWorld();
GD.Print("World generated");
BuildMeshesForLayer(0);
HandleRenderData(BuildRenderData(0));
}
private Dictionary<string, MultiMeshInstance3D> CreateMultiMeshes(Dictionary<string, Mesh> meshLibrary)
{
var result = new Dictionary<string, MultiMeshInstance3D>();
foreach (var kvp in meshLibrary)
{
var mm = new MultiMesh
{
Mesh = kvp.Value,
TransformFormat = MultiMesh.TransformFormatEnum.Transform3D
};
var instance = new MultiMeshInstance3D
{
Multimesh = mm
};
AddChild(instance);
result[kvp.Key] = instance;
}
return result;
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
@@ -57,7 +80,7 @@ public partial class World : Node3D
if (Input.IsActionJustPressed("layer_down") && currentLayer < ruinSize - 1) currentLayer++;
if (currentLayer != visibleLayer)
{
BuildMeshesForLayer(currentLayer);
HandleRenderData(BuildRenderData(currentLayer));
visibleLayer = currentLayer;
}
}
@@ -75,83 +98,34 @@ public partial class World : Node3D
GD.Print("Time for map generation: " + (DateTime.Now - now).Seconds);
}
private void BuildMeshesForLayer(int layerIndex)
private List<TileRenderData> BuildRenderData(int layerIndex)
{
foreach (MultiMeshInstance3D mm in multiMeshes.Values)
{
mm.Multimesh.InstanceCount = 0;
}
var result = new List<TileRenderData>();
Layer layer = map[layerIndex];
Dictionary<string, List<Transform3D>> batches = new();
layer.ClearDecorations();
for (int x = 0; x < layerSize; x++)
{
for (int y = 0; y < layerSize; y++)
{
Tile tile = layer.tiles[x, y];
string key = tile.collapsedMesh;
if (!batches.ContainsKey(key))
batches[key] = new List<Transform3D>();
batches[key].Add(new Transform3D(
Basis.Identity,
tile.Position
));
}
}
foreach (var kvp in batches)
{
MultiMesh mm = multiMeshes[kvp.Key].Multimesh;
List<Placeholder> placeholders = tilePlaceholders[kvp.Key];
List<Transform3D> list = kvp.Value;
mm.InstanceCount = list.Count;
for (int i = 0; i < list.Count; i++)
{
mm.SetInstanceTransform(i, list[i]);
if (placeholders.Count > 0)
result.Add(new TileRenderData
{
Node3D decoration;
Mesh mesh = decorationMeshes.Values.ToList()[0].Mesh;
for(int j = 0; j < placeholders.Count; j++)
{
foreach (MeshInstance3D meshes in decorationMeshes.Values)
{
if (meshes.Name.ToString().ToLower() == placeholders[j].name.ToLower())
{
mesh = meshes.Mesh;
break;
}
}
decoration = new MeshInstance3D();
(decoration as MeshInstance3D).Mesh = mesh;
if (placeholders[j].name.ToLower() == "light")
{
GD.Print("Adding OmniLight");
decoration.AddChild(new OmniLight3D()
{
OmniAttenuation = 2f,
LightColor = new Color("#eae7ad"),
ShadowEnabled = true,
LightEnergy = 5f,
LightIndirectEnergy = 1.5f,
Position = new Vector3(0.5f, 0, 0)
});
}
decoration.Transform = list[i];
decoration.Position += placeholders[j].pos;
decoration.Name = placeholders[j].name + j;
decoration.Rotate(Vector3.Up, Mathf.DegToRad(-90));
layer.AddChild(decoration);
}
}
Tile = tile,
MeshKey = tile.collapsedMesh,
Transform = new Transform3D(Basis.Identity, tile.Position),
Placeholders = tilePlaceholders[tile.collapsedMesh]
});
}
}
return result;
}
private void HandleRenderData(List<TileRenderData> renderData)
{
multiMeshHandler.Build(renderData);
DecorationHandler.Spawn(renderData, decorationMeshes);
}
}