Files
RuinAdventurer/Scripts/World.cs
T

128 lines
3.3 KiB
C#

using Godot;
using System;
using System.Collections.Generic;
using static GameData;
public partial class World : Node3D
{
public Dictionary<string, MeshInstance3D> tileMeshes;
public Dictionary<string, List<Placeholder>> tilePlaceholders;
PackedScene layerPrefab = ResourceLoader.LoadLayerPrefab();
private Dictionary<string, MultiMeshInstance3D> multiMeshes = new();
private Dictionary<string, Mesh> meshLibrary = new();
Layer[] map;
Layer layerNode;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
WFC.FillAdjacencies();
tileMeshes = ResourceLoader.LoadTiles();
tilePlaceholders = new Dictionary<string, List<Placeholder>>();
foreach (var kvp in tileMeshes)
{
tilePlaceholders.Add(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();
}
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;
}
map = new Layer[ruinSize];
GenerateWorld();
GD.Print("World generated");
BuildMeshesForLayer(0);
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
if (Input.IsActionJustPressed("layer_up") && currentLayer > 0) currentLayer--;
if (Input.IsActionJustPressed("layer_down") && currentLayer < ruinSize - 1) currentLayer++;
if (currentLayer != visibleLayer)
{
BuildMeshesForLayer(currentLayer);
visibleLayer = currentLayer;
}
}
private void GenerateWorld()
{
DateTime now = DateTime.Now;
for (int layer = 0; layer < ruinSize; layer++)
{
layerNode = layerPrefab.Instantiate<Layer>();
AddChild(layerNode);
layerNode.SetupLayer(layerSize, layer, tileMeshes);
map[layer] = layerNode;
}
GD.Print("Time for map generation: " + (DateTime.Now - now).Seconds);
}
private void BuildMeshesForLayer(int layerIndex)
{
foreach (MultiMeshInstance3D mm in multiMeshes.Values)
{
mm.Multimesh.InstanceCount = 0;
}
Layer layer = map[layerIndex];
Dictionary<string, List<Transform3D>> batches = new();
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)
{
Node3D robot;
foreach (Placeholder placeholder in placeholders)
{
robot = ResourceLoader.LoadRobotPrefab().Instantiate<Node3D>();
robot.Position = placeholder.pos + list[i].Origin;
AddChild(robot);
}
}
}
}
}
}