From b89a4d6154b11fbbdd16ca0e4c8d4657ba9fe383 Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Thu, 5 Sep 2024 17:32:29 +0100 Subject: [PATCH] Refactor model viewer to use new Context and support custom models --- project/code/TMV/Model.cs | 98 ++------------------------- project/code/TMV/UI/ModelSelector.cs | 73 ++++++++++++-------- project/scenes/model_viewer.tscn | 10 +-- project/scenes/ui/model_selector.tscn | 6 ++ 4 files changed, 60 insertions(+), 127 deletions(-) diff --git a/project/code/TMV/Model.cs b/project/code/TMV/Model.cs index 1b4894c..7df45e0 100644 --- a/project/code/TMV/Model.cs +++ b/project/code/TMV/Model.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.IO; using Godot; -using KeepersCompound.LGS; using KeepersCompound.TMV.UI; namespace KeepersCompound.TMV; @@ -11,104 +8,17 @@ public partial class Model : Node3D public override void _Ready() { var modelSelector = GetNode("%ModelSelector") as ModelSelector; - modelSelector.LoadModel += BuildModel; + modelSelector.ModelSelected += BuildModel; } - public void BuildModel(string rootPath, string modelPath) + public void BuildModel(string campaignName, string modelPath) { foreach (var node in GetChildren()) { node.QueueFree(); } - var modelFile = new ModelFile(modelPath); - if (modelFile == null) - { - GD.Print($"Failed to load model file: {modelPath}"); - return; - } - - // TODO: Remove this disgusting hack. Not only is it a hack, it doesn't support custom models - var baseDir = Path.GetDirectoryName(modelPath); - var options = new EnumerationOptions - { - MatchCasing = MatchCasing.CaseInsensitive, - RecurseSubdirectories = true, - }; - var materials = new List(); - foreach (var material in modelFile.Materials) - { - if (material.Type == 0) - { - var paths = Directory.GetFiles(baseDir, material.Name, options); - if (paths.IsEmpty()) continue; - - materials.Add(new StandardMaterial3D - { - AlbedoTexture = TextureLoader.LoadTexture(paths[0]) - }); - } - else - { - var b = (material.Handle) & 0xff; - var g = (material.Handle >> 8) & 0xff; - var r = (material.Handle >> 16) & 0xff; - var colour = new Color(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f); - materials.Add(new StandardMaterial3D - { - AlbedoColor = colour - }); - } - } - - var surfaceDataMap = new Dictionary(); - foreach (var poly in modelFile.Polygons) - { - var vertices = new List(); - var normal = modelFile.Normals[poly.Normal].ToGodotVec3(); - var uvs = new List(); - for (var i = 0; i < poly.VertexCount; i++) - { - var vertex = modelFile.Vertices[poly.VertexIndices[i]]; - vertices.Add(vertex.ToGodotVec3()); - if (i < poly.UvIndices.Length) - { - var uv = modelFile.Uvs[poly.UvIndices[i]]; - uvs.Add(new Vector2(uv.X, uv.Y)); - } - else - { - uvs.Add(Vector2.Zero); - } - } - - if (!surfaceDataMap.ContainsKey(poly.Data)) - { - surfaceDataMap.Add(poly.Data, new MeshSurfaceData()); - } - - surfaceDataMap[poly.Data].AddPolygon(vertices, normal, uvs, uvs); - } - - var mesh = new ArrayMesh(); - foreach (var (materialId, surfaceData) in surfaceDataMap) - { - var array = surfaceData.BuildSurfaceArray(); - var surfaceIdx = mesh.GetSurfaceCount(); - mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, array); - for (var i = 0; i < materials.Count; i++) - { - var m = modelFile.Materials[i]; - if (m.Slot == materialId) - { - mesh.SurfaceSetMaterial(surfaceIdx, materials[i]); - break; - } - } - } - - var pos = -modelFile.Header.Center.ToGodotVec3(); - var meshInstance = new MeshInstance3D { Mesh = mesh, Position = pos }; - AddChild(meshInstance); + var model = Context.Instance.ModelLoader.Load(campaignName, modelPath); + AddChild(model); } } diff --git a/project/code/TMV/UI/ModelSelector.cs b/project/code/TMV/UI/ModelSelector.cs index b8bdaba..f713faf 100644 --- a/project/code/TMV/UI/ModelSelector.cs +++ b/project/code/TMV/UI/ModelSelector.cs @@ -6,15 +6,15 @@ using Godot; namespace KeepersCompound.TMV.UI; public partial class ModelSelector : Control -{ - [Signal] - public delegate void LoadModelEventHandler(string rootPath, string modelPath); - private InstallPaths _installPaths; +{ + public event ModelSelectedEventHandler ModelSelected; + public delegate void ModelSelectedEventHandler(string campaign, string mission); private FileDialog _FolderSelect; private LineEdit _FolderPath; private Button _BrowseButton; + private ItemList _Campaigns; private ItemList _Models; private Button _LoadButton; private Button _CancelButton; @@ -28,13 +28,15 @@ public partial class ModelSelector : Control _FolderSelect = GetNode("%FolderSelect"); _FolderPath = GetNode("%FolderPath"); _BrowseButton = GetNode