GodotComponentTest/scenes/WorldView.cs

167 lines
4.8 KiB
C#

using System.Linq;
using Godot;
using Godot.Collections;
public class WorldView : Spatial
{
// ui elements
// scene nodes
// resources
// exports
[Export] public NodePath World;
[Export] public Vector2 ViewCenterPlaneCoord;
// signals
[Signal]
delegate void TileClicked(HexTile3D tile3d);
[Signal]
delegate void TileHovered(HexTile3D tile3d);
// other members
private World _world;
private class SceneTileChunk : Spatial
{
private Vector2 _chunkIndex = Vector2.Inf;
public Vector2 ChunkIndex
{
get
{
return _chunkIndex;
}
set
{
Transform chunkTransform = Transform.Identity;
Vector2 chunkOriginPlaneCoord = HexGrid.GetHexCenterFromOffset(value * global::World.ChunkSize);
chunkTransform.origin = new Vector3(chunkOriginPlaneCoord.x, 0, chunkOriginPlaneCoord.y);
Transform = chunkTransform;
_chunkIndex = value;
}
}
public Array<HexTile3D> TileNodes = new();
private PackedScene _hexTile3DScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
private HexGrid HexGrid = new();
public SceneTileChunk(Vector2 chunkIndex, int size)
{
foreach (int i in Enumerable.Range(0, size))
{
foreach (int j in Enumerable.Range(0, size))
{
HexTile3D tile3D = (HexTile3D)_hexTile3DScene.Instance();
Transform tileTransform = Transform.Identity;
Vector2 centerPlaneCoord = HexGrid.GetHexCenterFromOffset(new Vector2(i, j));
tileTransform.origin = new Vector3(centerPlaneCoord.x, 0, centerPlaneCoord.y);
tile3D.Transform = tileTransform;
TileNodes.Add(tile3D);
AddChild(tile3D);
}
}
ChunkIndex = chunkIndex;
}
}
private Array<SceneTileChunk> _sceneTileChunks = new Array<SceneTileChunk>();
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_world = GetNode<World>(World);
_world.Connect("OnTilesChanged", this, nameof(HandleWorldTileChange));
}
public override void _Process(float delta)
{
}
SceneTileChunk CreateSceneTileChunk(Vector2 chunkIndex)
{
SceneTileChunk sceneTileChunk = new SceneTileChunk(chunkIndex, global::World.ChunkSize);
foreach (HexTile3D hexTile3D in sceneTileChunk.TileNodes)
{
hexTile3D.Connect("TileClicked", this, nameof(OnTileClicked));
hexTile3D.Connect("TileHovered", this, nameof(OnTileHovered));
}
return sceneTileChunk;
}
SceneTileChunk RemoveChunkFromScene(Vector2 chunkIndex)
{
foreach (Spatial child in GetChildren())
{
SceneTileChunk sceneTileChunk = child as SceneTileChunk;
if (sceneTileChunk == null)
{
RemoveChild(child);
continue;
}
if (sceneTileChunk.ChunkIndex == chunkIndex)
{
return sceneTileChunk;
}
}
return null;
}
private void HandleWorldTileChange(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices)
{
Array<SceneTileChunk> removedChunks = new();
foreach (Vector2 chunkIndex in removedChunkIndices)
{
SceneTileChunk chunk = RemoveChunkFromScene(chunkIndex);
if (chunk != null)
{
removedChunks.Add(chunk);
}
}
foreach (Vector2 chunkIndex in addedChunkIndices)
{
SceneTileChunk sceneTileChunk = null;
if (removedChunks.Count > 0)
{
sceneTileChunk = removedChunks[^1];
removedChunks.RemoveAt(removedChunks.Count - 1);
GD.Print("Reused SceneTileChunk");
}
else
{
sceneTileChunk = CreateSceneTileChunk(chunkIndex);
AddChild(sceneTileChunk);
GD.Print("Created SceneTileChunk");
}
sceneTileChunk.ChunkIndex = chunkIndex;
_sceneTileChunks.Add(sceneTileChunk);
}
GD.Print("Removed Chunks " + removedChunkIndices.Count);
GD.Print("Added Chunks " + addedChunkIndices.Count);
GD.Print("Removed chunk count: " + removedChunks.Count);
}
public void OnTileClicked(HexTile3D tile)
{
EmitSignal("TileClicked", tile);
}
public void OnTileHovered(HexTile3D tile)
{
EmitSignal("TileHovered", tile);
}
}