[Tool] public partial class Grid : Area3D { public const float StepSize = 1.0f / 16; const float Offset = 0.001f; const int ThickLineEvery = 4; const float ThickLineWidth = 0.006f; const float ThinLineWidth = 0.004f; static readonly Color ThickLineColor = new(0.25f, 0.25f, 0.25f); static readonly Color ThinLineColor = new(0.35f, 0.35f, 0.35f); Vector2I _gridSize = new(16, 16); [Export] public Vector2I GridSize { get => _gridSize; set { _gridSize = value; Update(); } } public override void _Ready() => Update(); void Update() { UpdateCollisionShape(); UpdateImmediateMesh(); } static StandardMaterial3D _material; static StandardMaterial3D GetOrCreateMaterial() { if (_material == null) { _material = new StandardMaterial3D(); _material.VertexColorUseAsAlbedo = true; } return _material; } BoxShape3D _shape; void UpdateCollisionShape() { if (Engine.IsEditorHint()) return; if (_shape == null) { _shape = new BoxShape3D(); AddChild(new CollisionShape3D { Shape = _shape }); } _shape.Size = new(GridSize.X * StepSize, 0.001f, GridSize.Y * StepSize); } ImmediateMesh _mesh; void UpdateImmediateMesh() { static bool IsThickLine(int line) => (line % ThickLineEvery) == 0; static (float, Color) GetLineWidthAndColor(int line) => IsThickLine(line) ? (ThickLineWidth, ThickLineColor) : (ThinLineWidth, ThinLineColor); static void FlatQuad(ImmediateMesh mesh, float x1, float x2, float y1, float y2) { mesh.SurfaceAddVertex(new(x1, Offset, y1)); // 1--2 mesh.SurfaceAddVertex(new(x2, Offset, y1)); // | / mesh.SurfaceAddVertex(new(x1, Offset, y2)); // 3' mesh.SurfaceAddVertex(new(x2, Offset, y1)); // .1 mesh.SurfaceAddVertex(new(x2, Offset, y2)); // / | mesh.SurfaceAddVertex(new(x1, Offset, y2)); // 3--2 } if (_mesh == null) { var meshInstance = new MeshInstance3D(); meshInstance.Mesh = _mesh = new(); AddChild(meshInstance); } else { _mesh.ClearSurfaces(); } _mesh.SurfaceBegin(Mesh.PrimitiveType.Triangles); // Horizontal Lines var half_width = GridSize.X * StepSize / 2; for (var line = 0; line <= GridSize.Y; line++) { var (line_width, line_color) = GetLineWidthAndColor(line); var y = StepSize * (line - GridSize.Y / 2.0f); _mesh.SurfaceSetColor(line_color); FlatQuad(_mesh, -half_width, +half_width, y - line_width / 2, y + line_width / 2); } // Vertical Lines var half_depth = GridSize.Y * StepSize / 2; for (var line = 0; line <= GridSize.X; line++) { var (line_width, line_color) = GetLineWidthAndColor(line); var x = StepSize * (line - GridSize.X / 2.0f); _mesh.SurfaceSetColor(line_color); FlatQuad(_mesh, x - line_width / 2, x + line_width / 2, -half_depth, +half_depth); } _mesh.SurfaceEnd(); _mesh.SurfaceSetMaterial(0, GetOrCreateMaterial()); } }