using Godot; using KeepersCompound.LGS; using KeepersCompound.LGS.Database; using KeepersCompound.LGS.Database.Chunks; using Microsoft.VisualBasic; using System; using System.Collections.Generic; namespace KeepersCompound; [Tool] public partial class Mission : Node3D { [Export(PropertyHint.GlobalFile, "*.mis")] public string FileName { get; set; } [Export] public bool Build = false; [Export] public bool Clear = false; DbFile _file; public override void _Ready() { RebuildMap(); } public override void _Process(double delta) { if (Build) { RebuildMap(); Build = false; } if (Clear) { ClearMap(); Clear = false; } } public override void _Input(InputEvent @event) { if (@event is InputEventKey keyEvent && keyEvent.Pressed) { if (keyEvent.Keycode == Key.R) { Build = true; } } } public void ClearMap() { foreach (var node in GetChildren()) { node.QueueFree(); } } public void RebuildMap() { ClearMap(); _file = new(FileName); var wr = (WorldRep)_file.Chunks["WREXT"]; foreach (var cell in wr.Cells) { BuildCellMesh(cell); } } private void BuildCellMesh(WorldRep.Cell cell) { var numPolys = cell.PolyCount; var numRenderPolys = cell.RenderPolyCount; var numPortalPolys = cell.PortalPolyCount; if (numRenderPolys == 0 || numPortalPolys >= numPolys) { return; } var vertices = new List(); var normals = new List(); var indices = new List(); var idxOffset = 0; for (int i = 0; i < numPolys; i++) { var poly = cell.Polys[i]; // TODO: Make this break lol if (i >= numRenderPolys || i >= numPolys - numPortalPolys) { idxOffset += poly.VertexCount; continue; } var plane = cell.Planes[poly.PlaneId]; var normal = plane.Normal; var numPolyVertices = poly.VertexCount; var baseIdx = vertices.Count; for (var j = 0; j < numPolyVertices; j++) { var vertex = cell.Vertices[cell.Indices[idxOffset + j]]; vertices.Add(vertex.ToGodotVec3(4.0f)); normals.Add(normal.ToGodotVec3(4.0f)); } for (int j = 1; j < numPolyVertices - 1; j++) { foreach (var offset in new int[] { 0, j, j + 1 }) { indices.Add(baseIdx + offset); } } idxOffset += poly.VertexCount; } var cellNode = new Node3D(); var arrMesh = new ArrayMesh(); var arrays = new Godot.Collections.Array(); arrays.Resize((int)Mesh.ArrayType.Max); arrays[(int)Mesh.ArrayType.Vertex] = vertices.ToArray(); arrays[(int)Mesh.ArrayType.Normal] = normals.ToArray(); arrays[(int)Mesh.ArrayType.Index] = indices.ToArray(); arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); var meshInstance = new MeshInstance3D { Mesh = arrMesh, CastShadow = GeometryInstance3D.ShadowCastingSetting.On }; cellNode.AddChild(meshInstance); var occluderInstance = new OccluderInstance3D(); var occluder = new ArrayOccluder3D(); occluder.SetArrays(vertices.ToArray(), indices.ToArray()); occluderInstance.Occluder = occluder; occluderInstance.BakeSimplificationDistance = 0.0f; cellNode.AddChild(occluderInstance); var r = new Random(); if (r.NextSingle() > 0.9 && cell.SphereRadius > 5.0) { var light = new OmniLight3D { Position = cell.SphereCenter.ToGodotVec3(4.0f), OmniRange = cell.SphereRadius * (r.NextSingle() + 1.0f) * 0.5f, }; cellNode.AddChild(light); } AddChild(cellNode); } }