2023-11-04 19:15:26 +01:00
|
|
|
using System.Diagnostics;
|
2023-10-23 21:22:53 +02:00
|
|
|
using System.Linq;
|
2023-10-05 18:17:48 +02:00
|
|
|
using Godot;
|
2023-10-14 21:54:06 +02:00
|
|
|
using Godot.Collections;
|
2023-10-05 18:17:48 +02:00
|
|
|
|
2023-11-01 16:02:39 +01:00
|
|
|
public class TileInstanceManager : Spatial
|
2023-10-05 18:17:48 +02:00
|
|
|
{
|
2023-11-04 19:15:26 +01:00
|
|
|
private readonly Array<SceneTileChunk> _sceneTileChunks = new();
|
|
|
|
private MultiMeshInstance _tileMultiMeshInstance;
|
|
|
|
private ImageTexture _viewTileTypeTexture;
|
|
|
|
|
|
|
|
private World _world;
|
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
// other members
|
|
|
|
[Export] public bool ShowHexTiles;
|
|
|
|
[Export] public Vector2 ViewCenterPlaneCoord;
|
2023-11-04 19:15:26 +01:00
|
|
|
|
2023-10-05 18:17:48 +02:00
|
|
|
// ui elements
|
|
|
|
|
|
|
|
// scene nodes
|
|
|
|
|
|
|
|
// resources
|
|
|
|
|
|
|
|
// exports
|
|
|
|
[Export] public NodePath World;
|
|
|
|
|
|
|
|
// Called when the node enters the scene tree for the first time.
|
|
|
|
public override void _Ready()
|
|
|
|
{
|
|
|
|
_world = GetNode<World>(World);
|
2023-10-14 21:54:06 +02:00
|
|
|
|
|
|
|
_world.Connect("OnTilesChanged", this, nameof(HandleWorldTileChange));
|
2023-11-04 19:15:26 +01:00
|
|
|
|
|
|
|
_tileMultiMeshInstance = (MultiMeshInstance)FindNode("TileMultiMeshInstance");
|
|
|
|
Debug.Assert(_tileMultiMeshInstance != null);
|
2023-10-05 18:17:48 +02:00
|
|
|
}
|
|
|
|
|
2023-10-23 21:22:53 +02:00
|
|
|
|
2023-10-05 18:17:48 +02:00
|
|
|
public override void _Process(float delta)
|
|
|
|
{
|
|
|
|
}
|
2023-10-14 21:54:06 +02:00
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
private SceneTileChunk CreateSceneTileChunk(Vector2 chunkIndex)
|
2023-10-23 21:22:53 +02:00
|
|
|
{
|
2023-11-04 19:15:26 +01:00
|
|
|
var sceneTileChunk = new SceneTileChunk(chunkIndex, _tileMultiMeshInstance);
|
2023-10-23 21:22:53 +02:00
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
foreach (var hexTile3D in sceneTileChunk.TileNodes)
|
2023-10-23 21:22:53 +02:00
|
|
|
{
|
|
|
|
hexTile3D.Connect("TileClicked", this, nameof(OnTileClicked));
|
|
|
|
hexTile3D.Connect("TileHovered", this, nameof(OnTileHovered));
|
|
|
|
}
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-10-23 21:22:53 +02:00
|
|
|
return sceneTileChunk;
|
|
|
|
}
|
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
private SceneTileChunk FindSceneTileChunkAtIndex(Vector2 chunkIndex)
|
2023-10-23 21:22:53 +02:00
|
|
|
{
|
|
|
|
foreach (Spatial child in GetChildren())
|
|
|
|
{
|
2023-11-01 17:59:43 +01:00
|
|
|
var sceneTileChunk = child as SceneTileChunk;
|
|
|
|
if (sceneTileChunk == null) continue;
|
2023-10-23 21:22:53 +02:00
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
if (sceneTileChunk.ChunkIndex == chunkIndex) return sceneTileChunk;
|
2023-10-23 21:22:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-10-14 21:54:06 +02:00
|
|
|
private void HandleWorldTileChange(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices)
|
|
|
|
{
|
2023-10-23 21:22:53 +02:00
|
|
|
Array<SceneTileChunk> removedChunks = new();
|
2023-11-01 17:59:43 +01:00
|
|
|
foreach (var chunkIndex in removedChunkIndices)
|
2023-10-23 21:22:53 +02:00
|
|
|
{
|
2023-11-01 17:59:43 +01:00
|
|
|
var chunk = FindSceneTileChunkAtIndex(chunkIndex);
|
|
|
|
if (chunk != null) removedChunks.Add(chunk);
|
2023-10-23 21:22:53 +02:00
|
|
|
}
|
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
foreach (var chunkIndex in addedChunkIndices)
|
2023-10-23 21:22:53 +02:00
|
|
|
{
|
|
|
|
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;
|
2023-10-27 22:58:37 +02:00
|
|
|
|
2023-11-04 19:15:26 +01:00
|
|
|
// if (ShowHexTiles)
|
|
|
|
// foreach (var tile3D in sceneTileChunk.TileNodes)
|
|
|
|
// tile3D.Transform = new Transform(Basis.Identity.Scaled(Vector3.One * 0.95f),
|
|
|
|
// tile3D.Transform.origin);
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-10-23 21:22:53 +02:00
|
|
|
_sceneTileChunks.Add(sceneTileChunk);
|
|
|
|
}
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-10-14 21:54:06 +02:00
|
|
|
GD.Print("Removed Chunks " + removedChunkIndices.Count);
|
|
|
|
GD.Print("Added Chunks " + addedChunkIndices.Count);
|
2023-10-23 21:22:53 +02:00
|
|
|
GD.Print("Removed chunk count: " + removedChunks.Count);
|
|
|
|
}
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-10-23 21:22:53 +02:00
|
|
|
public void OnTileClicked(HexTile3D tile)
|
|
|
|
{
|
|
|
|
EmitSignal("TileClicked", tile);
|
|
|
|
}
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-10-23 21:22:53 +02:00
|
|
|
public void OnTileHovered(HexTile3D tile)
|
|
|
|
{
|
|
|
|
EmitSignal("TileHovered", tile);
|
2023-10-14 21:54:06 +02:00
|
|
|
}
|
2023-11-01 17:59:43 +01:00
|
|
|
|
|
|
|
// signals
|
|
|
|
[Signal]
|
|
|
|
private delegate void TileClicked(HexTile3D tile3d);
|
|
|
|
|
|
|
|
[Signal]
|
|
|
|
private delegate void TileHovered(HexTile3D tile3d);
|
|
|
|
|
|
|
|
private class SceneTileChunk : Spatial
|
|
|
|
{
|
|
|
|
private readonly PackedScene _hexTile3DScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
|
2023-11-04 19:15:26 +01:00
|
|
|
private readonly MultiMeshInstance _multiMeshInstance;
|
2023-11-01 17:59:43 +01:00
|
|
|
private readonly HexGrid HexGrid = new();
|
2023-11-04 19:15:26 +01:00
|
|
|
private readonly Array<int> TileInstanceIndices = new();
|
2023-11-01 17:59:43 +01:00
|
|
|
|
|
|
|
public readonly Array<HexTile3D> TileNodes = new();
|
2023-11-04 19:15:26 +01:00
|
|
|
private Vector2 _chunkIndex = Vector2.Inf;
|
2023-11-01 17:59:43 +01:00
|
|
|
|
2023-11-04 19:15:26 +01:00
|
|
|
public SceneTileChunk(Vector2 chunkIndex, MultiMeshInstance multiMeshInstance)
|
2023-11-01 17:59:43 +01:00
|
|
|
{
|
|
|
|
var chunkSize = global::World.ChunkSize;
|
|
|
|
|
|
|
|
foreach (var i in Enumerable.Range(0, chunkSize))
|
|
|
|
foreach (var j in Enumerable.Range(0, chunkSize))
|
|
|
|
{
|
|
|
|
var tile3D = (HexTile3D)_hexTile3DScene.Instance();
|
2023-11-05 21:46:28 +01:00
|
|
|
tile3D.Cell.OffsetCoords = new Vector2(chunkIndex * global::World.ChunkSize + new Vector2(i, j));
|
2023-11-01 17:59:43 +01:00
|
|
|
|
|
|
|
var tileTransform = Transform.Identity;
|
|
|
|
var centerPlaneCoord = HexGrid.GetHexCenterFromOffset(new Vector2(i, j));
|
|
|
|
tileTransform.origin = new Vector3(centerPlaneCoord.x, 0, centerPlaneCoord.y);
|
|
|
|
tile3D.Transform = tileTransform;
|
|
|
|
|
|
|
|
TileNodes.Add(tile3D);
|
|
|
|
AddChild(tile3D);
|
|
|
|
}
|
|
|
|
|
2023-11-04 19:15:26 +01:00
|
|
|
_multiMeshInstance = multiMeshInstance;
|
|
|
|
|
|
|
|
var chunkTileCount = global::World.ChunkSize * global::World.ChunkSize;
|
|
|
|
|
|
|
|
foreach (var i in Enumerable.Range(0, chunkTileCount))
|
|
|
|
TileInstanceIndices.Add(_multiMeshInstance.Multimesh.InstanceCount + i);
|
|
|
|
|
|
|
|
_multiMeshInstance.Multimesh.InstanceCount += chunkTileCount;
|
|
|
|
_multiMeshInstance.Multimesh.VisibleInstanceCount = _multiMeshInstance.Multimesh.InstanceCount;
|
|
|
|
|
|
|
|
GD.Print("VisibleInstanceCount = " + _multiMeshInstance.Multimesh.VisibleInstanceCount);
|
2023-11-05 21:46:28 +01:00
|
|
|
|
2023-11-01 17:59:43 +01:00
|
|
|
ChunkIndex = chunkIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vector2 ChunkIndex
|
|
|
|
{
|
|
|
|
get => _chunkIndex;
|
|
|
|
|
|
|
|
set
|
|
|
|
{
|
|
|
|
var chunkTransform = Transform.Identity;
|
|
|
|
var chunkOriginPlaneCoord = HexGrid.GetHexCenterFromOffset(value * global::World.ChunkSize);
|
|
|
|
chunkTransform.origin = new Vector3(chunkOriginPlaneCoord.x, 0, chunkOriginPlaneCoord.y);
|
|
|
|
Transform = chunkTransform;
|
|
|
|
_chunkIndex = value;
|
2023-11-04 19:15:26 +01:00
|
|
|
|
|
|
|
var tileOrientation = new Basis(Vector3.Up, 90f * Mathf.Pi / 180f);
|
|
|
|
|
2023-11-05 21:46:28 +01:00
|
|
|
GD.Print("Updating transforms for instances of chunk " + value + " origin: " + chunkTransform.origin);
|
|
|
|
|
2023-11-04 19:15:26 +01:00
|
|
|
foreach (var i in Enumerable.Range(0, TileInstanceIndices.Count))
|
|
|
|
{
|
|
|
|
var column = i % global::World.ChunkSize;
|
|
|
|
var row = i / global::World.ChunkSize;
|
|
|
|
|
|
|
|
var tilePlaneCoord =
|
|
|
|
HexGrid.GetHexCenterFromOffset(new Vector2(column, row));
|
2023-11-05 21:46:28 +01:00
|
|
|
|
2023-11-04 19:15:26 +01:00
|
|
|
_multiMeshInstance.Multimesh.SetInstanceTransform(TileInstanceIndices[i],
|
|
|
|
new Transform(tileOrientation,
|
|
|
|
chunkTransform.origin + new Vector3(tilePlaneCoord.x, 0, tilePlaneCoord.y)));
|
|
|
|
}
|
2023-11-01 17:59:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-05 18:17:48 +02:00
|
|
|
}
|