Compare commits
5 Commits
afb6689683
...
e213b3ea26
Author | SHA1 | Date |
---|---|---|
Jarrod Doyle | e213b3ea26 | |
Jarrod Doyle | 6e70ad22c1 | |
Jarrod Doyle | 2f2aab828e | |
Jarrod Doyle | 413e3bf937 | |
Jarrod Doyle | 7ec48abda5 |
|
@ -1,2 +1,3 @@
|
||||||
# Godot 4+ specific ignores
|
# Godot 4+ specific ignores
|
||||||
.godot/
|
.godot/
|
||||||
|
EXPORT/
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
[preset.0]
|
||||||
|
|
||||||
|
name="Linux"
|
||||||
|
platform="Linux"
|
||||||
|
runnable=true
|
||||||
|
advanced_options=false
|
||||||
|
dedicated_server=false
|
||||||
|
custom_features=""
|
||||||
|
export_filter="all_resources"
|
||||||
|
include_filter=""
|
||||||
|
exclude_filter=""
|
||||||
|
export_path="EXPORT/tmv.x86_64"
|
||||||
|
encryption_include_filters=""
|
||||||
|
encryption_exclude_filters=""
|
||||||
|
encrypt_pck=false
|
||||||
|
encrypt_directory=false
|
||||||
|
script_export_mode=2
|
||||||
|
|
||||||
|
[preset.0.options]
|
||||||
|
|
||||||
|
custom_template/debug=""
|
||||||
|
custom_template/release=""
|
||||||
|
debug/export_console_wrapper=1
|
||||||
|
binary_format/embed_pck=false
|
||||||
|
texture_format/s3tc_bptc=true
|
||||||
|
texture_format/etc2_astc=false
|
||||||
|
binary_format/architecture="x86_64"
|
||||||
|
ssh_remote_deploy/enabled=false
|
||||||
|
ssh_remote_deploy/host="user@host_ip"
|
||||||
|
ssh_remote_deploy/port="22"
|
||||||
|
ssh_remote_deploy/extra_args_ssh=""
|
||||||
|
ssh_remote_deploy/extra_args_scp=""
|
||||||
|
ssh_remote_deploy/run_script="#!/usr/bin/env bash
|
||||||
|
export DISPLAY=:0
|
||||||
|
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
|
||||||
|
\"{temp_dir}/{exe_name}\" {cmd_args}"
|
||||||
|
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
|
||||||
|
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
|
||||||
|
rm -rf \"{temp_dir}\""
|
||||||
|
dotnet/include_scripts_content=false
|
||||||
|
dotnet/include_debug_symbols=false
|
||||||
|
dotnet/embed_build_outputs=false
|
|
@ -164,7 +164,7 @@ public class ResourcePathManager
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetObjectPath(string campaignName, string objectName)
|
public string GetObjectPath(ref string campaignName, string objectName)
|
||||||
{
|
{
|
||||||
if (!_initialised) return null;
|
if (!_initialised) return null;
|
||||||
|
|
||||||
|
@ -184,6 +184,7 @@ public class ResourcePathManager
|
||||||
}
|
}
|
||||||
else if (_omResources.objectPathMap.TryGetValue(objectName, out var omPath))
|
else if (_omResources.objectPathMap.TryGetValue(objectName, out var omPath))
|
||||||
{
|
{
|
||||||
|
campaignName = "";
|
||||||
return omPath;
|
return omPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,13 @@ public partial class Mission : Node3D
|
||||||
ResourcePathManager _installPaths;
|
ResourcePathManager _installPaths;
|
||||||
DbFile _file;
|
DbFile _file;
|
||||||
TextureLoader _textureLoader;
|
TextureLoader _textureLoader;
|
||||||
|
ModelLoader _modelLoader;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
var extractPath = ProjectSettings.GlobalizePath($"user://extracted/tmp");
|
var extractPath = ProjectSettings.GlobalizePath($"user://extracted/tmp");
|
||||||
_installPaths = new ResourcePathManager(extractPath);
|
_installPaths = new ResourcePathManager(extractPath);
|
||||||
|
_modelLoader = new ModelLoader(_installPaths);
|
||||||
var missionSelector = GetNode<Control>("%MissionSelector") as MissionSelector;
|
var missionSelector = GetNode<Control>("%MissionSelector") as MissionSelector;
|
||||||
missionSelector.pathManager = _installPaths;
|
missionSelector.pathManager = _installPaths;
|
||||||
missionSelector.MissionSelected += (string campaign, string mission) =>
|
missionSelector.MissionSelected += (string campaign, string mission) =>
|
||||||
|
@ -98,10 +100,11 @@ public partial class Mission : Node3D
|
||||||
ClearMap();
|
ClearMap();
|
||||||
|
|
||||||
_textureLoader = new TextureLoader(_campaignName);
|
_textureLoader = new TextureLoader(_campaignName);
|
||||||
_file = new(FileName);
|
Timing.TimeStage("DbFile Parse", () => _file = new(FileName));
|
||||||
UseChunk<TxList>("TXLIST", LoadTextures);
|
Timing.TimeStage("Load FAM", () => UseChunk<TxList>("TXLIST", LoadTextures));
|
||||||
UseChunk<WorldRep>("WREXT", BuildWrMeshes);
|
Timing.TimeStage("Build WR", () => UseChunk<WorldRep>("WREXT", BuildWrMeshes));
|
||||||
|
|
||||||
|
// TODO: Sort this out so I can time it lol
|
||||||
ObjectHierarchy objHierarchy;
|
ObjectHierarchy objHierarchy;
|
||||||
if (_file.Chunks.TryGetValue("GAM_FILE", out var gamFileChunk))
|
if (_file.Chunks.TryGetValue("GAM_FILE", out var gamFileChunk))
|
||||||
{
|
{
|
||||||
|
@ -123,10 +126,9 @@ public partial class Mission : Node3D
|
||||||
objHierarchy = new ObjectHierarchy(_file);
|
objHierarchy = new ObjectHierarchy(_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (_file.Chunks.TryGetValue("BRLIST", out var brList))
|
||||||
_file.Chunks.TryGetValue("BRLIST", out var brList))
|
|
||||||
{
|
{
|
||||||
PlaceObjects((BrList)brList, objHierarchy);
|
Timing.TimeStage("Object Placement", () => PlaceObjects((BrList)brList, objHierarchy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +170,7 @@ public partial class Mission : Node3D
|
||||||
var rawRot = brush.angle;
|
var rawRot = brush.angle;
|
||||||
var rot = new Vector3(rawRot.Y, rawRot.Z, rawRot.X) * 360 / ushort.MaxValue;
|
var rot = new Vector3(rawRot.Y, rawRot.Z, rawRot.X) * 360 / ushort.MaxValue;
|
||||||
var scale = scaleProp == null ? Vector3.One : scaleProp.scale.ToGodotVec3(false);
|
var scale = scaleProp == null ? Vector3.One : scaleProp.scale.ToGodotVec3(false);
|
||||||
var model = ModelLoader.LoadModel(_installPaths, _campaignName, modelName);
|
var model = _modelLoader.Load(_campaignName, modelName);
|
||||||
if (model != null)
|
if (model != null)
|
||||||
{
|
{
|
||||||
model.Position = pos;
|
model.Position = pos;
|
||||||
|
@ -272,7 +274,7 @@ public partial class Mission : Node3D
|
||||||
private static Texture BuildLightmapTexture(WorldRep.Cell[] cells, PackingRectangle[] packingRects, Dictionary<int, LightmapRectData> rectDataMap, Dictionary<int, MeshSurfaceData> surfaceDataMap)
|
private static Texture BuildLightmapTexture(WorldRep.Cell[] cells, PackingRectangle[] packingRects, Dictionary<int, LightmapRectData> rectDataMap, Dictionary<int, MeshSurfaceData> surfaceDataMap)
|
||||||
{
|
{
|
||||||
RectanglePacker.Pack(packingRects, out var bounds);
|
RectanglePacker.Pack(packingRects, out var bounds);
|
||||||
var image = Image.Create((int)bounds.Width, (int)bounds.Height, false, Image.Format.Rgba8);
|
var image = Image.CreateEmpty((int)bounds.Width, (int)bounds.Height, false, Image.Format.Rgba8);
|
||||||
foreach (var rect in packingRects)
|
foreach (var rect in packingRects)
|
||||||
{
|
{
|
||||||
if (!rectDataMap.ContainsKey(rect.Id)) GD.Print("Invalid rectDataMap key");
|
if (!rectDataMap.ContainsKey(rect.Id)) GD.Print("Invalid rectDataMap key");
|
||||||
|
|
|
@ -1,15 +1,53 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using Godot;
|
using Godot;
|
||||||
using KeepersCompound.LGS;
|
using KeepersCompound.LGS;
|
||||||
|
|
||||||
namespace KeepersCompound.TMV;
|
namespace KeepersCompound.TMV;
|
||||||
|
|
||||||
public static class ModelLoader
|
public class ModelLoader
|
||||||
{
|
{
|
||||||
public static MeshInstance3D LoadModel(ResourcePathManager pathManager, string campaignName, string modelName)
|
private readonly Dictionary<(string, string), MeshInstance3D> _cache;
|
||||||
|
private readonly ResourcePathManager _pathManager;
|
||||||
|
|
||||||
|
public ModelLoader(ResourcePathManager pathManager)
|
||||||
{
|
{
|
||||||
var modelPath = pathManager.GetObjectPath(campaignName, modelName);
|
_pathManager = pathManager;
|
||||||
|
_cache = new Dictionary<(string, string), MeshInstance3D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeshInstance3D Load(string campaignName, string modelName, bool forceLoad = false)
|
||||||
|
{
|
||||||
|
campaignName ??= "";
|
||||||
|
|
||||||
|
if (!forceLoad)
|
||||||
|
{
|
||||||
|
if (_cache.TryGetValue((campaignName, modelName), out var fmModel))
|
||||||
|
{
|
||||||
|
return fmModel == null ? fmModel : fmModel.Duplicate() as MeshInstance3D;
|
||||||
|
}
|
||||||
|
else if (_cache.TryGetValue(("", modelName), out var omModel))
|
||||||
|
{
|
||||||
|
return omModel == null ? omModel : omModel.Duplicate() as MeshInstance3D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't care if this is null actually, we'll still cache that it's null lol
|
||||||
|
var model = LoadModel(_pathManager, ref campaignName, modelName);
|
||||||
|
var key = (campaignName, modelName);
|
||||||
|
if (_cache.ContainsKey(key))
|
||||||
|
{
|
||||||
|
_cache[key] = model;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_cache.TryAdd(key, model);
|
||||||
|
}
|
||||||
|
return model == null ? model : model.Duplicate() as MeshInstance3D;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MeshInstance3D LoadModel(ResourcePathManager pathManager, ref string campaignName, string modelName)
|
||||||
|
{
|
||||||
|
var modelPath = pathManager.GetObjectPath(ref campaignName, modelName);
|
||||||
if (modelPath == null)
|
if (modelPath == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -14,7 +14,7 @@ public partial class TextureLoader
|
||||||
|
|
||||||
var width = gifImage.Width;
|
var width = gifImage.Width;
|
||||||
var height = gifImage.Height;
|
var height = gifImage.Height;
|
||||||
var image = Image.Create(width, height, false, Image.Format.Rgba8);
|
var image = Image.CreateEmpty(width, height, false, Image.Format.Rgba8);
|
||||||
for (var y = 0; y < height; y++)
|
for (var y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < width; x++)
|
for (var x = 0; x < width; x++)
|
||||||
|
|
|
@ -93,7 +93,7 @@ public partial class TextureLoader
|
||||||
// Read run length encoded pixel Data
|
// Read run length encoded pixel Data
|
||||||
var width = (int)(max.X - min.X + 1);
|
var width = (int)(max.X - min.X + 1);
|
||||||
var height = (int)(max.Y - min.Y + 1);
|
var height = (int)(max.Y - min.Y + 1);
|
||||||
var image = Image.Create(width, height, false, Image.Format.Rgba8);
|
var image = Image.CreateEmpty(width, height, false, Image.Format.Rgba8);
|
||||||
for (var y = 0; y < height; y++)
|
for (var y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
var x = 0;
|
var x = 0;
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace KeepersCompound.TMV;
|
||||||
|
|
||||||
|
public static class Timing
|
||||||
|
{
|
||||||
|
public static void TimeStage(string stagename, Action action)
|
||||||
|
{
|
||||||
|
var watch = Stopwatch.StartNew();
|
||||||
|
action();
|
||||||
|
watch.Stop();
|
||||||
|
Godot.GD.Print($"[{stagename}]: {watch.Elapsed:g}");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue