diff --git a/.gitignore b/.gitignore
index b6d8c97..d9927ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,9 @@
.import/*
.mono/*
+.idea/*
+
*.swp
*.apk
*.idsig
+
+mono_crash.*
diff --git a/GodotComponentTest.csproj b/GodotComponentTest.csproj
new file mode 100644
index 0000000..2fd8e7d
--- /dev/null
+++ b/GodotComponentTest.csproj
@@ -0,0 +1,14 @@
+
+
+ netstandard2.1
+ 10.0
+
+
+
+ true
+
+
+
+
+
+
diff --git a/GodotComponentTest.sln b/GodotComponentTest.sln
new file mode 100644
index 0000000..68263ee
--- /dev/null
+++ b/GodotComponentTest.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotComponentTest", "GodotComponentTest.csproj", "{4DD477E5-5F2E-4AB0-A863-E006389DD60E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ ExportDebug|Any CPU = ExportDebug|Any CPU
+ ExportRelease|Any CPU = ExportRelease|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4DD477E5-5F2E-4AB0-A863-E006389DD60E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4DD477E5-5F2E-4AB0-A863-E006389DD60E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
+ {4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
+ {4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
+ {4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/HexCell.cs b/HexCell.cs
new file mode 100644
index 0000000..c043917
--- /dev/null
+++ b/HexCell.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Diagnostics;
+using Godot;
+using Array = Godot.Collections.Array;
+
+public class HexCell : Resource
+{
+ public static readonly Vector2 size = new Vector2(1, Mathf.Sqrt(3) / 2);
+ public static readonly Vector3 DIR_N = new Vector3(0, 1, -1);
+ public static readonly Vector3 DIR_NE = new Vector3(1, 0, -1);
+ public static readonly Vector3 DIR_SE = new Vector3(1, -1, 0);
+ public static readonly Vector3 DIR_S = new Vector3(0, -1, 1);
+ public static readonly Vector3 DIR_SW = new Vector3(-1, 0, 1);
+ public static readonly Vector3 DIR_NW = new Vector3(-1, 1, 0);
+
+ public static readonly Array DIR_ALL = new Array()
+ { DIR_N, DIR_NE, DIR_SE, DIR_S, DIR_SW, DIR_NW };
+
+ public HexCell() { }
+ public HexCell(float cubeX, float cubeY, float cubeZ)
+ {
+ CubeCoords = RoundCoords(new Vector3(cubeX, cubeY, cubeZ));
+ }
+
+ public HexCell(Vector3 cubeCoords)
+ {
+ CubeCoords = cubeCoords;
+ }
+
+ public HexCell(float axialX, float axialY)
+ {
+ AxialCoords = new Vector2(axialX, axialY);
+ }
+
+ public HexCell(Vector2 axialCoords)
+ {
+ AxialCoords = axialCoords;
+ }
+
+ public HexCell(HexCell other)
+ {
+ CubeCoords = other.CubeCoords;
+ }
+
+ private Vector3 _cubeCoords;
+ public Vector3 CubeCoords
+ {
+ get
+ {
+ return _cubeCoords;
+ }
+ set
+ {
+ if (Mathf.Abs(value.x + value.y + value.z) > 0.0001)
+ {
+ GD.Print("Warning: Invalid cube coordinates for hex (x + y + z != 0): ", value.ToString());
+ }
+ _cubeCoords = RoundCoords(value);
+ }
+ }
+
+ public Vector2 AxialCoords
+ {
+ get => new Vector2(CubeCoords.x, CubeCoords.y);
+
+ set
+ {
+ CubeCoords = AxialToCubeCoords(value);
+ }
+ }
+
+ public Vector2 OffsetCoords
+ {
+ get
+ {
+ int x = (int)CubeCoords.x;
+ int y = (int)CubeCoords.y;
+ int off_y = y + (x - (x & 1)) / 2;
+ return new Vector2(x, off_y);
+ }
+
+ set
+ {
+ int x = (int)value.x;
+ int y = (int)value.y;
+ int cube_y = y - (x - (x & 1)) / 2;
+ AxialCoords = new Vector2(x, cube_y);
+ }
+ }
+
+ public Vector3 AxialToCubeCoords(Vector2 axialCoords)
+ {
+ return new Vector3(axialCoords.x, axialCoords.y, -axialCoords.x - axialCoords.y);
+ }
+
+ public Vector3 RoundCoords(Vector2 coords)
+ {
+ Vector3 cubeCoords = AxialToCubeCoords(coords);
+
+ return RoundCoords(cubeCoords);
+ }
+
+ public Vector3 RoundCoords(Vector3 cubeCoords)
+ {
+ Vector3 rounded = new Vector3(
+ Mathf.Round(cubeCoords.x),
+ Mathf.Round(cubeCoords.y),
+ Mathf.Round(cubeCoords.z));
+
+ Vector3 diffs = (rounded - cubeCoords).Abs();
+ if (diffs.x > diffs.y && diffs.x > diffs.z)
+ {
+ rounded.x = -rounded.y - rounded.z;
+ }
+ else if (diffs.y > diffs.z)
+ {
+ rounded.y = -rounded.x - rounded.z;
+ }
+ else
+ {
+ rounded.z = -rounded.x - rounded.y;
+ }
+
+ return rounded;
+ }
+
+ public HexCell getAdjacent(Vector3 dir)
+ {
+ return new HexCell(this.CubeCoords + dir);
+ }
+}
\ No newline at end of file
diff --git a/HexGrid.cs b/HexGrid.cs
new file mode 100644
index 0000000..eadbf76
--- /dev/null
+++ b/HexGrid.cs
@@ -0,0 +1,66 @@
+using System;
+using Godot;
+
+public class HexGrid : Resource
+{
+ private Vector2 _baseHexSize = new Vector2(1, Mathf.Sqrt(3) / 2);
+ private Vector2 _hexSize = new Vector2(1, Mathf.Sqrt(3) / 2);
+ private Vector2 _hexScale = new Vector2(1, 1);
+ private Godot.Transform2D _hexTransform;
+ private Godot.Transform2D _hexTransformInv;
+
+ public Vector2 HexSize
+ {
+ get { return _hexSize; }
+ }
+ public Vector2 HexScale
+ {
+ get
+ {
+ return _hexScale;
+ }
+ set
+ {
+ _hexScale = value;
+ _hexSize = _baseHexSize * _hexScale;
+ _hexTransform = new Transform2D(
+ new Vector2(_hexSize.x * 3/4, -_hexSize.y / 2),
+ new Vector2(0, -_hexSize.y),
+ new Vector2(0, 0)
+ );
+
+ _hexTransformInv = _hexTransform.AffineInverse();
+ }
+ }
+
+ public HexGrid()
+ {
+ HexScale = new Vector2(1, 1);
+ }
+
+ public Vector2 GetHexCenter(HexCell cell)
+ {
+ return _hexTransform * cell.AxialCoords;
+ }
+
+ public Vector2 GetHexCenterFromOffset(Vector2 offsetCoord)
+ {
+ HexCell cell = new HexCell();
+ cell.OffsetCoords = offsetCoord;
+ return GetHexCenter(cell);
+ }
+
+ public HexCell GetHexAtOffset(Vector2 offsetCoord)
+ {
+ HexCell cell = new HexCell();
+ cell.OffsetCoords = offsetCoord;
+ return cell;
+ }
+
+ public HexCell GetHexAt(Vector2 planeCoord)
+ {
+ HexCell result = new HexCell(_hexTransformInv * planeCoord);
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/entities/Player.cs b/entities/Player.cs
new file mode 100644
index 0000000..bdc3195
--- /dev/null
+++ b/entities/Player.cs
@@ -0,0 +1,21 @@
+using Godot;
+using System;
+
+public class Player : KinematicBody
+{
+ // Declare member variables here. Examples:
+ // private int a = 2;
+ // private string b = "text";
+
+ // Called when the node enters the scene tree for the first time.
+ public override void _Ready()
+ {
+
+ }
+
+// // Called every frame. 'delta' is the elapsed time since the previous frame.
+// public override void _Process(float delta)
+// {
+//
+// }
+}
diff --git a/scenes/AdaptiveWorldStream.cs b/scenes/AdaptiveWorldStream.cs
new file mode 100644
index 0000000..8e3d253
--- /dev/null
+++ b/scenes/AdaptiveWorldStream.cs
@@ -0,0 +1,117 @@
+using Godot;
+using System;
+using System.Linq;
+using Dictionary = Godot.Collections.Dictionary;
+using Array = Godot.Collections.Array;
+
+public class AdaptiveWorldStream : Spatial
+{
+ // ui elements
+ private Label _tileLabel;
+ private Label _tileOffsetLabel;
+ private Label _numTilesLabel;
+ private Label _mouseWorldLabel;
+ private Label _mouseTileLabel;
+
+ // scene nodes
+ private Spatial _tileHighlight;
+ private Spatial _mouseTileHighlight;
+ private Area _streamContainerArea;
+ private Player _player;
+
+ // Resources
+ private PackedScene _tileHighlightScene;
+
+ // other members
+ private HexGrid _hexGrid;
+ private HexCell _lastTile;
+ private HexCell _currentTile;
+ private Vector2 _currentTileOffset;
+
+ // Called when the node enters the scene tree for the first time.
+ public override void _Ready()
+ {
+ // UI elements
+ _tileLabel = GetNode