From c80367dccdce688bef9992b5525cf32d2ff28407 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 26 Apr 2026 11:33:54 +0200 Subject: [PATCH] Refactored code to be better separated (Rendering, Logic) --- Scripts/Helpers/DecorationHandler.cs | 48 ++++++++ Scripts/Helpers/DecorationHandler.cs.uid | 1 + Scripts/Helpers/Layer.cs | 33 +++++- Scripts/Helpers/MultimeshHandler.cs | 39 +++++++ Scripts/Helpers/MultimeshHandler.cs.uid | 1 + Scripts/Structs/TileRenderData.cs | 10 ++ Scripts/Structs/TileRenderData.cs.uid | 1 + Scripts/Tile.cs | 1 + Scripts/World.cs | 142 +++++++++-------------- 9 files changed, 191 insertions(+), 85 deletions(-) create mode 100644 Scripts/Helpers/DecorationHandler.cs create mode 100644 Scripts/Helpers/DecorationHandler.cs.uid create mode 100644 Scripts/Helpers/MultimeshHandler.cs create mode 100644 Scripts/Helpers/MultimeshHandler.cs.uid create mode 100644 Scripts/Structs/TileRenderData.cs create mode 100644 Scripts/Structs/TileRenderData.cs.uid diff --git a/Scripts/Helpers/DecorationHandler.cs b/Scripts/Helpers/DecorationHandler.cs new file mode 100644 index 0000000..b5f4f38 --- /dev/null +++ b/Scripts/Helpers/DecorationHandler.cs @@ -0,0 +1,48 @@ +using Godot; +using System.Collections.Generic; + +public class DecorationHandler +{ + public static void Spawn(List tiles, Dictionary 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); + } + } + } +} \ No newline at end of file diff --git a/Scripts/Helpers/DecorationHandler.cs.uid b/Scripts/Helpers/DecorationHandler.cs.uid new file mode 100644 index 0000000..dd2fb96 --- /dev/null +++ b/Scripts/Helpers/DecorationHandler.cs.uid @@ -0,0 +1 @@ +uid://oe2d2ape41jj diff --git a/Scripts/Helpers/Layer.cs b/Scripts/Helpers/Layer.cs index e7aa9a9..418ebc1 100644 --- a/Scripts/Helpers/Layer.cs +++ b/Scripts/Helpers/Layer.cs @@ -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 tileMeshes) { this.layerSize = layerSize; @@ -44,6 +60,7 @@ public partial class Layer : Node3D safetyCounter++; if (safetyCounter > 1000) break; } + CreateTileNodes(); } private void GenerateBaseStructure(Dictionary 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 tileMeshes) { for (int x = 0; x < layerSize; x++) diff --git a/Scripts/Helpers/MultimeshHandler.cs b/Scripts/Helpers/MultimeshHandler.cs new file mode 100644 index 0000000..3cb40e9 --- /dev/null +++ b/Scripts/Helpers/MultimeshHandler.cs @@ -0,0 +1,39 @@ +using Godot; +using System.Collections.Generic; + +public class MultiMeshHandler +{ + private Dictionary multiMeshes; + + public MultiMeshHandler(Dictionary multiMeshes) + { + this.multiMeshes = multiMeshes; + } + + public void Build(List tiles) + { + foreach (var mm in multiMeshes.Values) + mm.Multimesh.InstanceCount = 0; + + var batches = new Dictionary>(); + + foreach (var tile in tiles) + { + if (!batches.ContainsKey(tile.MeshKey)) + batches[tile.MeshKey] = new List(); + + 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]); + } + } +} \ No newline at end of file diff --git a/Scripts/Helpers/MultimeshHandler.cs.uid b/Scripts/Helpers/MultimeshHandler.cs.uid new file mode 100644 index 0000000..2ffd8c2 --- /dev/null +++ b/Scripts/Helpers/MultimeshHandler.cs.uid @@ -0,0 +1 @@ +uid://dc0v2yndgikkw diff --git a/Scripts/Structs/TileRenderData.cs b/Scripts/Structs/TileRenderData.cs new file mode 100644 index 0000000..ebc4c02 --- /dev/null +++ b/Scripts/Structs/TileRenderData.cs @@ -0,0 +1,10 @@ +using Godot; +using System.Collections.Generic; + +public struct TileRenderData +{ + public Tile Tile; + public string MeshKey; + public Transform3D Transform; + public List Placeholders; +} \ No newline at end of file diff --git a/Scripts/Structs/TileRenderData.cs.uid b/Scripts/Structs/TileRenderData.cs.uid new file mode 100644 index 0000000..fd9d505 --- /dev/null +++ b/Scripts/Structs/TileRenderData.cs.uid @@ -0,0 +1 @@ +uid://chwhqyo4abxd4 diff --git a/Scripts/Tile.cs b/Scripts/Tile.cs index 9c2a245..5f2df8f 100644 --- a/Scripts/Tile.cs +++ b/Scripts/Tile.cs @@ -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 tileMeshes) { diff --git a/Scripts/World.cs b/Scripts/World.cs index da95072..b878a70 100644 --- a/Scripts/World.cs +++ b/Scripts/World.cs @@ -14,40 +14,63 @@ public partial class World : Node3D private Dictionary 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>(); + foreach (var kvp in tileMeshes) { - tilePlaceholders.Add(kvp.Key, new List()); + tilePlaceholders[kvp.Key] = new List(); 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; - - AddChild(instance); - multiMeshes[kvp.Key] = instance; - } + multiMeshes = CreateMultiMeshes(meshLibrary); + multiMeshHandler = new MultiMeshHandler(multiMeshes); + map = new Layer[ruinSize]; GenerateWorld(); + GD.Print("World generated"); - BuildMeshesForLayer(0); + + HandleRenderData(BuildRenderData(0)); + } + + private Dictionary CreateMultiMeshes(Dictionary meshLibrary) + { + var result = new Dictionary(); + + 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 BuildRenderData(int layerIndex) { - foreach (MultiMeshInstance3D mm in multiMeshes.Values) - { - mm.Multimesh.InstanceCount = 0; - } - + var result = new List(); Layer layer = map[layerIndex]; - - Dictionary> 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(); - - batches[key].Add(new Transform3D( - Basis.Identity, - tile.Position - )); - } - } - - foreach (var kvp in batches) - { - MultiMesh mm = multiMeshes[kvp.Key].Multimesh; - List placeholders = tilePlaceholders[kvp.Key]; - List 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 renderData) + { + multiMeshHandler.Build(renderData); + DecorationHandler.Spawn(renderData, decorationMeshes); } }