Inventory management focused game written in Godot / C#
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.8 KiB

11 months ago
[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());
}
}