Refactored code to be better separated (Rendering, Logic)
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://oe2d2ape41jj
|
||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using static WFC;
|
using static WFC;
|
||||||
public partial class Layer : Node3D
|
public partial class Layer : Node3D
|
||||||
{
|
{
|
||||||
|
private Node3D decorationRoot;
|
||||||
public Tile[,] tiles;
|
public Tile[,] tiles;
|
||||||
int layerSize;
|
int layerSize;
|
||||||
Tile tile;
|
Tile tile;
|
||||||
@@ -14,7 +15,11 @@ public partial class Layer : Node3D
|
|||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
decorationRoot = new Node3D
|
||||||
|
{
|
||||||
|
Name = "Decorations"
|
||||||
|
};
|
||||||
|
AddChild(decorationRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// 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)
|
public void SetupLayer(int layerSize, int level, Dictionary<string, MeshInstance3D> tileMeshes)
|
||||||
{
|
{
|
||||||
this.layerSize = layerSize;
|
this.layerSize = layerSize;
|
||||||
@@ -44,6 +60,7 @@ public partial class Layer : Node3D
|
|||||||
safetyCounter++;
|
safetyCounter++;
|
||||||
if (safetyCounter > 1000) break;
|
if (safetyCounter > 1000) break;
|
||||||
}
|
}
|
||||||
|
CreateTileNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateBaseStructure(Dictionary<string, MeshInstance3D> tileMeshes)
|
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)
|
private void ResetLayer(Dictionary<string, MeshInstance3D> tileMeshes)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < layerSize; x++)
|
for (int x = 0; x < layerSize; x++)
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dc0v2yndgikkw
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://chwhqyo4abxd4
|
||||||
@@ -10,6 +10,7 @@ public partial class Tile
|
|||||||
Random rand = new Random();
|
Random rand = new Random();
|
||||||
public Vector3 Position;
|
public Vector3 Position;
|
||||||
public Vector2I GridPosition;
|
public Vector2I GridPosition;
|
||||||
|
public Node3D DecorationNode;
|
||||||
|
|
||||||
public void SetMeshes(Dictionary<string, MeshInstance3D> tileMeshes)
|
public void SetMeshes(Dictionary<string, MeshInstance3D> tileMeshes)
|
||||||
{
|
{
|
||||||
|
|||||||
+57
-83
@@ -14,40 +14,63 @@ public partial class World : Node3D
|
|||||||
private Dictionary<string, Mesh> meshLibrary = new();
|
private Dictionary<string, Mesh> meshLibrary = new();
|
||||||
Layer[] map;
|
Layer[] map;
|
||||||
Layer layerNode;
|
Layer layerNode;
|
||||||
// Called when the node enters the scene tree for the first time.
|
|
||||||
|
private MultiMeshHandler multiMeshHandler;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
WFC.FillAdjacencies();
|
WFC.FillAdjacencies();
|
||||||
|
|
||||||
tileMeshes = ResourceLoader.LoadTiles();
|
tileMeshes = ResourceLoader.LoadTiles();
|
||||||
decorationMeshes = ResourceLoader.LoadDecorations();
|
decorationMeshes = ResourceLoader.LoadDecorations();
|
||||||
|
|
||||||
tilePlaceholders = new Dictionary<string, List<Placeholder>>();
|
tilePlaceholders = new Dictionary<string, List<Placeholder>>();
|
||||||
|
|
||||||
foreach (var kvp in tileMeshes)
|
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())
|
foreach (MeshInstance3D child in kvp.Value.GetChildren())
|
||||||
{
|
{
|
||||||
tilePlaceholders[kvp.Key].Add(new Placeholder(child.Name, child.Transform.Origin));
|
tilePlaceholders[kvp.Key].Add(new Placeholder(child.Name, child.Transform.Origin));
|
||||||
}
|
}
|
||||||
var temp = kvp.Value;
|
meshLibrary[kvp.Key] = kvp.Value.Mesh;
|
||||||
meshLibrary[kvp.Key] = temp.Mesh;
|
kvp.Value.QueueFree();
|
||||||
temp.QueueFree();
|
|
||||||
}
|
}
|
||||||
foreach (var kvp in meshLibrary)
|
|
||||||
{
|
|
||||||
var mm = new MultiMesh();
|
|
||||||
mm.Mesh = kvp.Value;
|
|
||||||
mm.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
|
|
||||||
|
|
||||||
var instance = new MultiMeshInstance3D();
|
multiMeshes = CreateMultiMeshes(meshLibrary);
|
||||||
instance.Multimesh = mm;
|
multiMeshHandler = new MultiMeshHandler(multiMeshes);
|
||||||
|
|
||||||
AddChild(instance);
|
|
||||||
multiMeshes[kvp.Key] = instance;
|
|
||||||
}
|
|
||||||
map = new Layer[ruinSize];
|
map = new Layer[ruinSize];
|
||||||
GenerateWorld();
|
GenerateWorld();
|
||||||
|
|
||||||
GD.Print("World generated");
|
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.
|
// 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 (Input.IsActionJustPressed("layer_down") && currentLayer < ruinSize - 1) currentLayer++;
|
||||||
if (currentLayer != visibleLayer)
|
if (currentLayer != visibleLayer)
|
||||||
{
|
{
|
||||||
BuildMeshesForLayer(currentLayer);
|
HandleRenderData(BuildRenderData(currentLayer));
|
||||||
visibleLayer = currentLayer;
|
visibleLayer = currentLayer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,83 +98,34 @@ public partial class World : Node3D
|
|||||||
GD.Print("Time for map generation: " + (DateTime.Now - now).Seconds);
|
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)
|
var result = new List<TileRenderData>();
|
||||||
{
|
|
||||||
mm.Multimesh.InstanceCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Layer layer = map[layerIndex];
|
Layer layer = map[layerIndex];
|
||||||
|
layer.ClearDecorations();
|
||||||
Dictionary<string, List<Transform3D>> batches = new();
|
|
||||||
|
|
||||||
for (int x = 0; x < layerSize; x++)
|
for (int x = 0; x < layerSize; x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < layerSize; y++)
|
for (int y = 0; y < layerSize; y++)
|
||||||
{
|
{
|
||||||
Tile tile = layer.tiles[x, y];
|
Tile tile = layer.tiles[x, y];
|
||||||
string key = tile.collapsedMesh;
|
|
||||||
|
|
||||||
if (!batches.ContainsKey(key))
|
result.Add(new TileRenderData
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
Node3D decoration;
|
Tile = tile,
|
||||||
|
MeshKey = tile.collapsedMesh,
|
||||||
Mesh mesh = decorationMeshes.Values.ToList()[0].Mesh;
|
Transform = new Transform3D(Basis.Identity, tile.Position),
|
||||||
for(int j = 0; j < placeholders.Count; j++)
|
Placeholders = tilePlaceholders[tile.collapsedMesh]
|
||||||
{
|
});
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleRenderData(List<TileRenderData> renderData)
|
||||||
|
{
|
||||||
|
multiMeshHandler.Build(renderData);
|
||||||
|
DecorationHandler.Spawn(renderData, decorationMeshes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user