diff --git a/assets/TestHeightmap.png b/assets/TestHeightmap.png new file mode 100644 index 0000000..5ac8119 Binary files /dev/null and b/assets/TestHeightmap.png differ diff --git a/assets/TestHeightmap.png.import b/assets/TestHeightmap.png.import new file mode 100644 index 0000000..3c5ee79 --- /dev/null +++ b/assets/TestHeightmap.png.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="StreamTexture" +path.s3tc="res://.import/TestHeightmap.png-6cbcc94e211273dff5857931034e368e.s3tc.stex" +path.etc2="res://.import/TestHeightmap.png-6cbcc94e211273dff5857931034e368e.etc2.stex" +metadata={ +"imported_formats": [ "s3tc", "etc2" ], +"vram_texture": true +} + +[deps] + +source_file="res://assets/TestHeightmap.png" +dest_files=[ "res://.import/TestHeightmap.png-6cbcc94e211273dff5857931034e368e.s3tc.stex", "res://.import/TestHeightmap.png-6cbcc94e211273dff5857931034e368e.etc2.stex" ] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=true +flags/filter=true +flags/mipmaps=true +flags/anisotropic=false +flags/srgb=1 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/assets/TestHeightmap.tres b/assets/TestHeightmap.tres new file mode 100644 index 0000000..dd38c23 --- /dev/null +++ b/assets/TestHeightmap.tres @@ -0,0 +1,5 @@ +[gd_resource type="StreamTexture" format=2] + +[resource] +flags = 20 +load_path = "res://.import/TestHeightmap.png-6cbcc94e211273dff5857931034e368e.stex" diff --git a/icon.png.import b/icon.png.import index f6a79f2..fb1e23a 100644 --- a/icon.png.import +++ b/icon.png.import @@ -25,7 +25,7 @@ flags/repeat=true flags/filter=true flags/mipmaps=true flags/anisotropic=false -flags/srgb=2 +flags/srgb=1 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false diff --git a/scenes/Game.cs b/scenes/Game.cs index 9dd27e6..5d048c4 100644 --- a/scenes/Game.cs +++ b/scenes/Game.cs @@ -122,6 +122,8 @@ public class Game : Spatial _player.TaskQueueComponent.Connect("StartInteraction", _interactionSystem, nameof(_interactionSystem.OnStartInteraction)); _player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged)); + _worldView.Connect("TileClicked", this, nameof(OnTileClicked)); + _worldView.Connect("TileHovered", this, nameof(OnTileHovered)); // register entity events foreach (Node node in GetNode("Entities").GetChildren()) diff --git a/scenes/Game.tscn b/scenes/Game.tscn index a7eb109..01d5dad 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -329,6 +329,7 @@ flip_v = true visible = false [node name="StreamContainer" parent="." instance=ExtResource( 1 )] +visible = false ShowHexTiles = true [node name="Camera" parent="." instance=ExtResource( 3 )] @@ -339,6 +340,9 @@ script = ExtResource( 15 ) [node name="Player" parent="." instance=ExtResource( 2 )] TileWorldNode = NodePath("../TileWorld") +[node name="Skeleton" parent="Player/Geometry/Armature" index="0"] +bones/4/bound_children = [ ] + [node name="ToolAttachement" parent="Player/Geometry/Armature/Skeleton" index="5"] transform = Transform( 1, 8.68458e-08, -1.04308e-07, 1.74623e-07, -1, -1.30385e-07, 1.41561e-07, 1.50874e-07, -1, -0.72, 0.45, 3.28113e-08 ) diff --git a/scenes/HexTile3D.tscn b/scenes/HexTile3D.tscn index 811fbe8..b05e91a 100644 --- a/scenes/HexTile3D.tscn +++ b/scenes/HexTile3D.tscn @@ -23,7 +23,6 @@ script = ExtResource( 1 ) [node name="Mesh" type="MeshInstance" parent="." groups=["GameGeometry"]] transform = Transform( -4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, -2.5, 0 ) -visible = false mesh = ExtResource( 3 ) material/0 = ExtResource( 2 ) diff --git a/scenes/HexTile3DPatch.tscn b/scenes/HexTile3DPatch.tscn index 57f2235..59766d6 100644 --- a/scenes/HexTile3DPatch.tscn +++ b/scenes/HexTile3DPatch.tscn @@ -5,7 +5,6 @@ [node name="Spatial" type="Spatial"] [node name="HexTile3D1" parent="." instance=ExtResource( 1 )] -transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) [node name="HexTile3D2" parent="." instance=ExtResource( 1 )] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.866 ) diff --git a/scenes/World.cs b/scenes/World.cs index 97a7beb..5e5b32a 100644 --- a/scenes/World.cs +++ b/scenes/World.cs @@ -2,15 +2,27 @@ using Godot; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using Godot.Collections; public class World : Spatial { + public enum GenerationState + { + Undefined, + Heightmap, + TileType, + Objects, + Done + } + public GenerationState State = GenerationState.Done; + // referenced scenes private PackedScene _worldChunkScene = GD.Load("res://scenes/WorldChunk.tscn"); // constants public const int ChunkSize = 16; + public int Seed = 0; public HexGrid HexGrid = new HexGrid(); public Spatial Chunks; public Color DebugColor; @@ -34,13 +46,15 @@ public class World : Spatial private Vector2 _centerPlaneCoord; private int[] _centerChunkCoord = { 0, 0 }; private int[] _previousCenterChunkCoord = { 0, 0 }; - private Rect2 _centerChunkRect2 = new Rect2(); + private Rect2 _centerChunkRect = new Rect2(); private Random _debugColorRandom = new Random(); private Godot.Collections.Dictionary _cachedWorldChunks; private List _activeChunkIndices = new(); private List _addedChunkIndices = new(); private List _removedChunkIndices = new(); + private OpenSimplexNoise noiseGenerator = new(); + public World() { Debug.Assert(ChunkSize % 2 == 0); @@ -53,10 +67,23 @@ public class World : Spatial { Chunks = (Spatial)FindNode("Chunks"); Debug.Assert(Chunks != null); + + InitNoiseGenerator(); SetCenterPlaneCoord(Vector2.Zero); } + public void InitNoiseGenerator() + { + noiseGenerator = new OpenSimplexNoise(); + + noiseGenerator.Seed = Seed; + noiseGenerator.Octaves = 1; + noiseGenerator.Period = 10; + noiseGenerator.Persistence = 0.5f; + noiseGenerator.Lacunarity = 2; + } + public WorldChunk GetOrCreateWorldChunk(int xIndex, int yIndex, Color debugColor) { if (IsTileCached(xIndex, yIndex)) @@ -76,6 +103,7 @@ public class World : Spatial private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor) { WorldChunk result = (WorldChunk)_worldChunkScene.Instance(); + result.SetSize(ChunkSize); Vector2 offsetCoordSouthWest = new Vector2(xIndex, yIndex) * ChunkSize; Vector2 offsetCoordNorthEast = offsetCoordSouthWest + new Vector2(1, 1) * (ChunkSize - 1); @@ -102,6 +130,12 @@ public class World : Spatial public void UpdateCenterChunkFromPlaneCoord(Vector2 planeCoord) { + if (State != GenerationState.Done) + { + GD.PrintErr("Cannot update chunk to new planeCoord " + planeCoord + ": Chunk generation not yet finished!"); + return; + } + // mark all chunks as retired Godot.Collections.Dictionary oldCachedChunks = new(_cachedWorldChunks); @@ -109,7 +143,7 @@ public class World : Spatial var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord); WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2, new Color(GD.Randf(), GD.Randf(), GD.Randf())); - _centerChunkRect2 = currentChunk.PlaneRect; + _centerChunkRect = currentChunk.PlaneRect; // load or create adjacent chunks _activeChunkIndices = new List(); @@ -149,8 +183,11 @@ public class World : Spatial _addedChunkIndices.Add(chunkKey); } } - - EmitSignal("OnTilesChanged", _removedChunkIndices.ToArray(), _addedChunkIndices.ToArray()); + + if (_addedChunkIndices.Count > 0) + { + State = GenerationState.Heightmap; + } } private void RemoveChunk(Vector2 cachedChunkKey) @@ -178,15 +215,72 @@ public class World : Spatial public void SetCenterPlaneCoord(Vector2 centerPlaneCoord) { - if (!_centerChunkRect2.HasPoint(centerPlaneCoord)) + if (!_centerChunkRect.HasPoint(centerPlaneCoord)) { UpdateCenterChunkFromPlaneCoord(centerPlaneCoord); } } -// // Called every frame. 'delta' is the elapsed time since the previous frame. -// public override void _Process(float delta) -// { -// -// } + public override void _Process(float delta) + { + GenerationState oldState = State; + + if (State == GenerationState.Heightmap) + { + // generate heightmap for all new chunks + foreach (Vector2 chunkIndex in _addedChunkIndices) + { + WorldChunk chunk = _cachedWorldChunks[chunkIndex]; + Color debugChunkColor = new Color(Mathf.Abs(chunkIndex.x) / 5, Mathf.Abs(chunkIndex.y) / 5, Mathf.RoundToInt(Mathf.Abs(chunkIndex.x + chunkIndex.y)) % 2); + + GD.Print("Generating for offset " + chunkIndex + " chunk: " + chunk + " debugChunkColor: " + debugChunkColor); + + ImageTexture noiseImageTexture = new ImageTexture(); + noiseImageTexture.CreateFromImage(noiseGenerator.GetImage(ChunkSize, ChunkSize, chunkIndex * ChunkSize), (uint) 0); + + // Debug Texture + Image simpleImage = new Image(); + simpleImage.Create(ChunkSize, ChunkSize, false, Image.Format.Rgb8); + simpleImage.Lock(); + + foreach (int i in Enumerable.Range(0, ChunkSize)) + { + foreach (int j in Enumerable.Range(0, ChunkSize)) + { + if ((i + j) % 2 == 0) + { + simpleImage.SetPixelv(new Vector2(i, j), Colors.Aqua); + } + else + { + simpleImage.SetPixelv(new Vector2(i, j), debugChunkColor); + } + } + } + + simpleImage.Unlock(); + // noiseImageTexture.CreateFromImage(simpleImage, 0); + chunk.SetHeightmap(noiseImageTexture); + } + + // assign height map images + + State = GenerationState.TileType; + } else if (State == GenerationState.TileType) + { + // assign tile type images + + State = GenerationState.Objects; + } else if (State == GenerationState.Objects) + { + // generate objects + + State = GenerationState.Done; + } + + if (oldState != GenerationState.Done && State == GenerationState.Done) + { + EmitSignal("OnTilesChanged", _removedChunkIndices.ToArray(), _addedChunkIndices.ToArray()); + } + } } \ No newline at end of file diff --git a/scenes/WorldChunk.cs b/scenes/WorldChunk.cs index a288694..33e0c96 100644 --- a/scenes/WorldChunk.cs +++ b/scenes/WorldChunk.cs @@ -3,21 +3,22 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; public class WorldChunk : Spatial { // ui elements - + // scene nodes private MeshInstance PlaneRectMesh; // resources - + // exports [Export] public Texture TileTypeMap; [Export] public Texture NavigationMap; [Export] public Texture HeightMap; - [Export] public readonly int size = 32; + [Export] public int Size = 32; [Export] public Vector2 ChunkAddress; // [Export] public Vector2 Size = new Vector2(1, 1); @@ -28,58 +29,127 @@ public class WorldChunk : Spatial // other members public Rect2 PlaneRect; public Color DebugColor = Colors.White; + public Viewport TileTypeOffscreenViewport; + public bool NoiseTextureCheckerboardOverlay = true; + private TextureRect _heightmapRect; + private SpatialMaterial _rectMaterial = new SpatialMaterial(); + public WorldChunk() { - } - + public WorldChunk(int size) { - + SetSize(size); } - + + public void SetSize(int size) + { + Size = size; + + if (TileTypeOffscreenViewport != null) + { + TileTypeOffscreenViewport.Size = Vector2.One * size; + } + } + // other members public void SaveToFile(String chunkName) { Image image = new Image(); - - image.CreateFromData(size, size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData()); + + image.CreateFromData(Size, Size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData()); image.SavePng(chunkName + "_tileType.png"); - - image.CreateFromData(size, size, false, Image.Format.Rgba8, NavigationMap.GetData().GetData()); + + image.CreateFromData(Size, Size, false, Image.Format.Rgba8, NavigationMap.GetData().GetData()); image.SavePng(chunkName + "_navigationMap.png"); - image.CreateFromData(size, size, false, Image.Format.Rgba8, HeightMap.GetData().GetData()); + image.CreateFromData(Size, Size, false, Image.Format.Rgba8, HeightMap.GetData().GetData()); image.SavePng(chunkName + "_heightMap.png"); } public void LoadFromFile(String chunkName) { - } - + // Called when the node enters the scene tree for the first time. public override void _Ready() { - PlaneRectMesh = (MeshInstance) FindNode("PlaneRectMesh"); + PlaneRectMesh = (MeshInstance)FindNode("PlaneRectMesh"); Debug.Assert(PlaneRectMesh != null); - + Transform planeRectTransform = Transform.Identity; - planeRectTransform = planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x * 0.5f, 1, PlaneRect.Size.y * 0.5f)); + planeRectTransform = + planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x, 0.125f, PlaneRect.Size.y)); planeRectTransform.origin.x = PlaneRect.GetCenter().x; - planeRectTransform.origin.z = PlaneRect.GetCenter().y; + planeRectTransform.origin.z = PlaneRect.GetCenter().y; + PlaneRectMesh.Transform = planeRectTransform; - PlaneRectMesh.MaterialOverride = new SpatialMaterial(); - ((SpatialMaterial)PlaneRectMesh.MaterialOverride).AlbedoColor = DebugColor; - ((SpatialMaterial)PlaneRectMesh.MaterialOverride).FlagsTransparent = true; +// PlaneRectMesh.MaterialOverride = new SpatialMaterial(); +// ((SpatialMaterial)PlaneRectMesh.MaterialOverride).AlbedoColor = DebugColor; +// ((SpatialMaterial)PlaneRectMesh.MaterialOverride).FlagsTransparent = true; + + TileTypeOffscreenViewport = (Viewport)FindNode("TileTypeOffscreenViewport"); + TileTypeOffscreenViewport.Size = Vector2.One * Size; + Debug.Assert(TileTypeOffscreenViewport != null); + + _heightmapRect = (TextureRect)FindNode("HeightmapTexture"); + } + + public void SetHeightmap(Texture texture) + { + GD.Print("Setting HeightmapRect Texture: " + _heightmapRect + " with size " + _heightmapRect.GetSize()); + _heightmapRect.Texture = texture; } -// // Called every frame. 'delta' is the elapsed time since the previous frame. -// public override void _Process(float delta) -// { -// -// } -} +// Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(float delta) + { + Texture tileTypeTexture = TileTypeOffscreenViewport.GetTexture(); + + if (NoiseTextureCheckerboardOverlay) + { + Image tileTypeImage = tileTypeTexture.GetData(); + tileTypeImage.Lock(); + + foreach (int i in Enumerable.Range(0, Size)) + { + foreach (int j in Enumerable.Range(0, Size)) + { + Vector2 textureCoord = new Vector2(i, j); + Color baseColor = tileTypeImage.GetPixelv(textureCoord); + + if ((i + j) % 2 == 0) + { + tileTypeImage.SetPixelv(textureCoord, baseColor); + } + else + { + tileTypeImage.SetPixelv(textureCoord, baseColor * 0.6f); + } + } + } + + tileTypeImage.Unlock(); + ImageTexture imageTexture = new ImageTexture(); + imageTexture.CreateFromImage(tileTypeImage, (uint) 0); + tileTypeTexture = imageTexture; + } + + _rectMaterial.AlbedoTexture = tileTypeTexture; + + _rectMaterial.FlagsTransparent = true; +// _rectMaterial.AlbedoTexture = _heightmapRect.Texture; + _rectMaterial.Uv1Scale = new Vector3(-3, -2, 1); + _rectMaterial.Uv1Offset = Vector3.One * 2; + + //RectMaterial.Uv1Triplanar = true; + PlaneRectMesh.SetSurfaceMaterial(0, _rectMaterial); + + TileTypeOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once; + PlaneRectMesh.MaterialOverride = null; + } +} \ No newline at end of file diff --git a/scenes/WorldChunk.tscn b/scenes/WorldChunk.tscn index 79210b3..933054d 100644 --- a/scenes/WorldChunk.tscn +++ b/scenes/WorldChunk.tscn @@ -1,11 +1,29 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=9 format=2] [ext_resource path="res://scenes/WorldChunk.cs" type="Script" id=1] +[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=2] +[ext_resource path="res://assets/TestHeightmap.tres" type="Texture" id=3] +[ext_resource path="res://assets/4x4checkerColor.png" type="Texture" id=4] [sub_resource type="CubeMesh" id=27] -size = Vector3( 2, 0.5, 2 ) +size = Vector3( 1, 1, 1 ) [sub_resource type="SpatialMaterial" id=28] +flags_transparent = true +albedo_color = Color( 1, 1, 1, 0.501961 ) +albedo_texture = ExtResource( 4 ) +uv1_scale = Vector3( -3, -2, 0 ) +uv1_offset = Vector3( 2, 2, 0 ) + +[sub_resource type="OpenSimplexNoise" id=29] +octaves = 1 +period = 9.0 +persistence = 0.0 + +[sub_resource type="NoiseTexture" id=30] +width = 8 +height = 8 +noise = SubResource( 29 ) [node name="WorldChunk" type="Spatial"] script = ExtResource( 1 ) @@ -13,5 +31,37 @@ script = ExtResource( 1 ) [node name="Entities" type="Spatial" parent="."] [node name="PlaneRectMesh" type="MeshInstance" parent="."] +transform = Transform( 2, 0, 0, 0, 0.125, 0, 0, 0, 2, 0, -0.1, 0 ) mesh = SubResource( 27 ) material/0 = SubResource( 28 ) + +[node name="TileTypeOffscreenViewport" type="Viewport" parent="."] +size = Vector2( 8, 8 ) +transparent_bg = true +handle_input_locally = false +hdr = false +disable_3d = true +usage = 0 +render_target_v_flip = true +render_target_update_mode = 3 +shadow_atlas_quad_0 = 0 +shadow_atlas_quad_1 = 0 +shadow_atlas_quad_2 = 0 +shadow_atlas_quad_3 = 0 + +[node name="NoiseTexture" type="TextureRect" parent="TileTypeOffscreenViewport"] +visible = false +margin_right = 40.0 +margin_bottom = 40.0 +texture = SubResource( 30 ) + +[node name="IslandShader" type="TextureRect" parent="TileTypeOffscreenViewport"] +material = ExtResource( 2 ) +margin_right = 100.0 +margin_bottom = 100.0 + +[node name="HeightmapTexture" type="TextureRect" parent="TileTypeOffscreenViewport/IslandShader"] +use_parent_material = true +margin_right = 100.0 +margin_bottom = 100.0 +texture = ExtResource( 3 ) diff --git a/scenes/WorldView.cs b/scenes/WorldView.cs index 1e99237..4902b03 100644 --- a/scenes/WorldView.cs +++ b/scenes/WorldView.cs @@ -1,3 +1,4 @@ +using System.Linq; using Godot; using Godot.Collections; @@ -14,10 +15,62 @@ public class WorldView : Spatial [Export] public Vector2 ViewCenterPlaneCoord; // signals - // delegate void OnCoordClicked(Vector2 world_pos); + [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 TileNodes = new(); + + private PackedScene _hexTile3DScene = GD.Load("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 _sceneTileChunks = new Array(); // Called when the node enters the scene tree for the first time. public override void _Ready() @@ -27,14 +80,88 @@ public class WorldView : Spatial _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 removedChunkIndices, Array addedChunkIndices) { - + Array 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); } } \ No newline at end of file