Compare commits
4 Commits
27dbc47419
...
a8b9ce8a54
Author | SHA1 | Date |
---|---|---|
Jarrod Doyle | a8b9ce8a54 | |
Jarrod Doyle | 6f62d2ca00 | |
Jarrod Doyle | 9db1bc6681 | |
Jarrod Doyle | e773635677 |
|
@ -134,7 +134,8 @@ public class WorldRep : IChunk
|
||||||
var raw2 = Pixels[layer, y, x, 0] + (Pixels[layer, y, x, 1] << 8);
|
var raw2 = Pixels[layer, y, x, 0] + (Pixels[layer, y, x, 1] << 8);
|
||||||
return new Vector4(raw2 & 31, (raw2 >> 5) & 31, (raw2 >> 10) & 31, 31) / 31.0f;
|
return new Vector4(raw2 & 31, (raw2 >> 5) & 31, (raw2 >> 10) & 31, 31) / 31.0f;
|
||||||
case 4:
|
case 4:
|
||||||
return new Vector4(Pixels[layer, y, x, 0], Pixels[layer, y, x, 1], Pixels[layer, y, x, 2], Pixels[layer, y, x, 3]) / 255.0f;
|
// 4bpp stored as BGRA
|
||||||
|
return new Vector4(Pixels[layer, y, x, 2], Pixels[layer, y, x, 1], Pixels[layer, y, x, 0], Pixels[layer, y, x, 3]) / 255.0f;
|
||||||
default:
|
default:
|
||||||
return Vector4.Zero;
|
return Vector4.Zero;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System.IO;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace KeepersCompound.TMV;
|
||||||
|
|
||||||
|
// TODO: Error handling lol
|
||||||
|
public class InstallPaths
|
||||||
|
{
|
||||||
|
public string rootPath;
|
||||||
|
public string famPath;
|
||||||
|
public string omsPath;
|
||||||
|
public string fmsPath;
|
||||||
|
|
||||||
|
public InstallPaths(string root)
|
||||||
|
{
|
||||||
|
var searchOptions = new EnumerationOptions
|
||||||
|
{
|
||||||
|
MatchCasing = MatchCasing.CaseInsensitive,
|
||||||
|
RecurseSubdirectories = true
|
||||||
|
};
|
||||||
|
|
||||||
|
rootPath = root;
|
||||||
|
famPath = Directory.GetFiles(rootPath, "fam.crf", searchOptions)[0];
|
||||||
|
var paths = Directory.GetFiles(rootPath, "install.cfg", searchOptions);
|
||||||
|
if (paths.Length == 0)
|
||||||
|
{
|
||||||
|
paths = Directory.GetFiles(rootPath, "darkinst.cfg", searchOptions);
|
||||||
|
}
|
||||||
|
var installCfgPath = paths[0];
|
||||||
|
GD.Print($"Install.cfg: {installCfgPath}");
|
||||||
|
foreach (var line in File.ReadLines(installCfgPath))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("load_path"))
|
||||||
|
{
|
||||||
|
var path = line.Split(" ")[1].Replace("\\", "/");
|
||||||
|
omsPath = Path.GetFullPath(rootPath + path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var camModPath = Directory.GetFiles(rootPath, "cam_mod.ini", searchOptions)[0];
|
||||||
|
fmsPath = rootPath + "/FMs";
|
||||||
|
foreach (var line in File.ReadLines(camModPath))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("fm_path"))
|
||||||
|
{
|
||||||
|
var path = line.Split(" ")[1].Replace("\\", "/");
|
||||||
|
fmsPath = Path.GetFullPath(rootPath + path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GD.Print($"OMs Path: {omsPath}");
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,15 +38,18 @@ public partial class Mission : Node3D
|
||||||
[Export]
|
[Export]
|
||||||
public bool Dump = false;
|
public bool Dump = false;
|
||||||
|
|
||||||
|
|
||||||
|
InstallPaths _installPaths;
|
||||||
DbFile _file;
|
DbFile _file;
|
||||||
TextureLoader _textureLoader;
|
TextureLoader _textureLoader;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
var missionSelector = GetNode<Control>("%MissionSelector") as MissionSelector;
|
var missionSelector = GetNode<Control>("%MissionSelector") as MissionSelector;
|
||||||
missionSelector.LoadMission += (string path) =>
|
missionSelector.LoadMission += (string rootPath, string missionPath) =>
|
||||||
{
|
{
|
||||||
FileName = path;
|
_installPaths = new InstallPaths(rootPath);
|
||||||
|
FileName = missionPath;
|
||||||
Build = true;
|
Build = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -88,7 +91,7 @@ public partial class Mission : Node3D
|
||||||
{
|
{
|
||||||
ClearMap();
|
ClearMap();
|
||||||
|
|
||||||
_textureLoader = new TextureLoader("", FileName.GetBaseDir());
|
_textureLoader = new TextureLoader(_installPaths.famPath, FileName.GetBaseDir());
|
||||||
|
|
||||||
_file = new(FileName);
|
_file = new(FileName);
|
||||||
var textureList = (TxList)_file.Chunks["TXLIST"];
|
var textureList = (TxList)_file.Chunks["TXLIST"];
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -7,21 +8,38 @@ namespace KeepersCompound.TMV;
|
||||||
|
|
||||||
public partial class TextureLoader
|
public partial class TextureLoader
|
||||||
{
|
{
|
||||||
private readonly string _rootPath; // TODO: Load from installation resources
|
private readonly string _userTexturesPath;
|
||||||
|
private readonly string _rootFamPath; // TODO: Load from installation resources
|
||||||
private readonly string _fmPath;
|
private readonly string _fmPath;
|
||||||
|
private readonly Dictionary<string, string> _rootTexturePaths = new();
|
||||||
private readonly Dictionary<string, string> _fmTexturePaths = new();
|
private readonly Dictionary<string, string> _fmTexturePaths = new();
|
||||||
|
|
||||||
private readonly List<ImageTexture> _textureCache = new();
|
private readonly List<ImageTexture> _textureCache = new();
|
||||||
private readonly Dictionary<int, int> _idMap = new();
|
private readonly Dictionary<int, int> _idMap = new();
|
||||||
private readonly Dictionary<string, int> _pathMap = new();
|
private readonly Dictionary<string, int> _pathMap = new();
|
||||||
|
|
||||||
public TextureLoader(string rootPath, string fmPath)
|
public TextureLoader(string rootFamPath, string fmPath)
|
||||||
{
|
{
|
||||||
_rootPath = rootPath;
|
_rootFamPath = rootFamPath;
|
||||||
_fmPath = fmPath;
|
_fmPath = fmPath;
|
||||||
|
_userTexturesPath = ProjectSettings.GlobalizePath($"user://textures/tmp");
|
||||||
|
|
||||||
|
ExtractRootFamFiles();
|
||||||
LoadDefaultTexture();
|
LoadDefaultTexture();
|
||||||
RegisterFmTexturePaths();
|
RegisterTexturePaths(_fmPath, _fmTexturePaths);
|
||||||
|
RegisterTexturePaths(_userTexturesPath, _rootTexturePaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtractRootFamFiles()
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(_userTexturesPath);
|
||||||
|
if (dir.Exists)
|
||||||
|
{
|
||||||
|
dir.Delete(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var zip = ZipFile.OpenRead(_rootFamPath);
|
||||||
|
zip.ExtractToDirectory(_userTexturesPath.PathJoin("fam"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadDefaultTexture()
|
private void LoadDefaultTexture()
|
||||||
|
@ -32,7 +50,7 @@ public partial class TextureLoader
|
||||||
_textureCache.Add(texture);
|
_textureCache.Add(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterFmTexturePaths()
|
private static void RegisterTexturePaths(string rootDir, Dictionary<string, string> map)
|
||||||
{
|
{
|
||||||
// TODO: Load DDS BMP GIF CEL
|
// TODO: Load DDS BMP GIF CEL
|
||||||
string[] validExtensions = { "png", "tga", "pcx" };
|
string[] validExtensions = { "png", "tga", "pcx" };
|
||||||
|
@ -44,33 +62,33 @@ public partial class TextureLoader
|
||||||
RecurseSubdirectories = true,
|
RecurseSubdirectories = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var dirPath in Directory.EnumerateDirectories(_fmPath, "fam", famOptions))
|
foreach (var dirPath in Directory.EnumerateDirectories(rootDir, "fam", famOptions))
|
||||||
{
|
{
|
||||||
foreach (var path in Directory.EnumerateFiles(dirPath, "*", textureOptions))
|
foreach (var path in Directory.EnumerateFiles(dirPath, "*", textureOptions))
|
||||||
{
|
{
|
||||||
if (validExtensions.Contains(path.GetExtension().ToLower()))
|
if (validExtensions.Contains(path.GetExtension().ToLower()))
|
||||||
{
|
{
|
||||||
// TODO: This only adds the first one found rather than the highest priority
|
// TODO: This only adds the first one found rather than the highest priority
|
||||||
var key = path.TrimPrefix(_fmPath).GetBaseName().ToLower();
|
var key = path.TrimPrefix(rootDir).GetBaseName().ToLower();
|
||||||
_fmTexturePaths.TryAdd(key, path);
|
map.TryAdd(key, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GD.Print($"Registered {map.Count} texture paths at : {rootDir}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Load(int id, string path)
|
public bool Load(int id, string path)
|
||||||
{
|
{
|
||||||
var userTexturesPath = ProjectSettings.GlobalizePath($"user://textures{path}.PCX");
|
|
||||||
|
|
||||||
var loaded = false;
|
var loaded = false;
|
||||||
if (_fmTexturePaths.TryGetValue(path.ToLower(), out var filePath))
|
if (_fmTexturePaths.TryGetValue(path.ToLower(), out var fmTexPath))
|
||||||
{
|
{
|
||||||
_textureCache.Add(LoadTexture(filePath));
|
_textureCache.Add(LoadTexture(fmTexPath));
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
else if (File.Exists(userTexturesPath))
|
else if (_rootTexturePaths.TryGetValue(path.ToLower(), out var rootTexPath))
|
||||||
{
|
{
|
||||||
_textureCache.Add(LoadTexture(userTexturesPath));
|
_textureCache.Add(LoadTexture(rootTexPath));
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace KeepersCompound.TMV.UI;
|
namespace KeepersCompound.TMV.UI;
|
||||||
|
@ -6,28 +7,35 @@ namespace KeepersCompound.TMV.UI;
|
||||||
public partial class MissionSelector : Control
|
public partial class MissionSelector : Control
|
||||||
{
|
{
|
||||||
[Signal]
|
[Signal]
|
||||||
public delegate void LoadMissionEventHandler(string path);
|
public delegate void LoadMissionEventHandler(string rootPath, string missionPath);
|
||||||
|
|
||||||
|
private InstallPaths _installPaths;
|
||||||
|
|
||||||
private FileDialog _FolderSelect;
|
private FileDialog _FolderSelect;
|
||||||
private LineEdit _FolderPath;
|
private LineEdit _FolderPath;
|
||||||
private Button _BrowseButton;
|
private Button _BrowseButton;
|
||||||
|
private ItemList _Campaigns;
|
||||||
private ItemList _Missions;
|
private ItemList _Missions;
|
||||||
private Button _LoadButton;
|
private Button _LoadButton;
|
||||||
private Button _CancelButton;
|
private Button _CancelButton;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
// TODO: Load initial folderpath from config and prefil everything
|
||||||
|
|
||||||
_FolderSelect = GetNode<FileDialog>("%FolderSelect");
|
_FolderSelect = GetNode<FileDialog>("%FolderSelect");
|
||||||
_FolderPath = GetNode<LineEdit>("%FolderPath");
|
_FolderPath = GetNode<LineEdit>("%FolderPath");
|
||||||
_BrowseButton = GetNode<Button>("%BrowseButton");
|
_BrowseButton = GetNode<Button>("%BrowseButton");
|
||||||
|
_Campaigns = GetNode<ItemList>("%Campaigns");
|
||||||
_Missions = GetNode<ItemList>("%Missions");
|
_Missions = GetNode<ItemList>("%Missions");
|
||||||
_LoadButton = GetNode<Button>("%LoadButton");
|
_LoadButton = GetNode<Button>("%LoadButton");
|
||||||
_CancelButton = GetNode<Button>("%CancelButton");
|
_CancelButton = GetNode<Button>("%CancelButton");
|
||||||
|
|
||||||
_BrowseButton.Pressed += () => _FolderSelect.Visible = true;
|
_BrowseButton.Pressed += () => _FolderSelect.Visible = true;
|
||||||
_FolderSelect.DirSelected += (string dir) => { _FolderPath.Text = dir; BuildMissionList(dir); };
|
_FolderSelect.DirSelected += (string dir) => { _FolderPath.Text = dir; BuildCampaignList(dir); };
|
||||||
_FolderPath.TextSubmitted += BuildMissionList;
|
_FolderPath.TextSubmitted += BuildCampaignList;
|
||||||
_Missions.ItemSelected += (long _) => _LoadButton.Disabled = false;
|
_Missions.ItemSelected += (long _) => _LoadButton.Disabled = false;
|
||||||
|
_Campaigns.ItemSelected += BuildMissionList;
|
||||||
_LoadButton.Pressed += EmitLoadMission;
|
_LoadButton.Pressed += EmitLoadMission;
|
||||||
_CancelButton.Pressed += () => Visible = false;
|
_CancelButton.Pressed += () => Visible = false;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +51,21 @@ public partial class MissionSelector : Control
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BuildCampaignList(string path)
|
||||||
|
{
|
||||||
|
_installPaths = new InstallPaths(path);
|
||||||
|
|
||||||
|
_Campaigns.Clear();
|
||||||
|
_Missions.Clear();
|
||||||
|
_LoadButton.Disabled = true;
|
||||||
|
|
||||||
|
_Campaigns.AddItem("Original Missions");
|
||||||
|
foreach (var c in Directory.GetDirectories(_installPaths.fmsPath))
|
||||||
|
{
|
||||||
|
_Campaigns.AddItem(c.TrimPrefix(_installPaths.fmsPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void BuildMissionList(string path)
|
private void BuildMissionList(string path)
|
||||||
{
|
{
|
||||||
_Missions.Clear();
|
_Missions.Clear();
|
||||||
|
@ -56,18 +79,44 @@ public partial class MissionSelector : Control
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BuildMissionList(long idx)
|
||||||
|
{
|
||||||
|
_Missions.Clear();
|
||||||
|
_LoadButton.Disabled = true;
|
||||||
|
|
||||||
|
var campaignPath = "";
|
||||||
|
if (idx == 0)
|
||||||
|
{
|
||||||
|
campaignPath = _installPaths.omsPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
campaignPath = _installPaths.fmsPath + _Campaigns.GetItemText((int)idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] extensions = { "mis", "cow" };
|
||||||
|
campaignPath = idx == 0 ? _installPaths.omsPath : _installPaths.fmsPath + _Campaigns.GetItemText((int)idx);
|
||||||
|
foreach (var f in Directory.GetFiles(campaignPath))
|
||||||
|
{
|
||||||
|
if (extensions.Contains(f.GetExtension().ToLower()))
|
||||||
|
{
|
||||||
|
_Missions.AddItem(f.TrimPrefix(campaignPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void EmitLoadMission()
|
private void EmitLoadMission()
|
||||||
{
|
{
|
||||||
|
var selectedCampaign = _Campaigns.GetSelectedItems()[0];
|
||||||
var selected = _Missions.GetSelectedItems();
|
var selected = _Missions.GetSelectedItems();
|
||||||
if (selected.IsEmpty())
|
if (selected.IsEmpty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = _Missions.GetItemText(selected[0]);
|
var campaignPath = selectedCampaign == 0 ? _installPaths.omsPath : _installPaths.fmsPath + _Campaigns.GetItemText(selectedCampaign);
|
||||||
var basePath = _FolderPath.Text;
|
var path = campaignPath + _Missions.GetItemText(selected[0]);
|
||||||
var path = basePath + item;
|
EmitSignal(SignalName.LoadMission, _installPaths.rootPath, path);
|
||||||
EmitSignal(SignalName.LoadMission, path);
|
|
||||||
|
|
||||||
Visible = false;
|
Visible = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
font_size = 20
|
font_size = 20
|
||||||
|
|
||||||
[node name="MissionSelector" type="Control"]
|
[node name="MissionSelector" type="Control"]
|
||||||
visible = false
|
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
anchors_preset = 8
|
anchors_preset = 8
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
|
@ -28,7 +27,7 @@ access = 2
|
||||||
use_native_dialog = true
|
use_native_dialog = true
|
||||||
|
|
||||||
[node name="PanelContainer" type="PanelContainer" parent="."]
|
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||||
custom_minimum_size = Vector2(460, 0)
|
custom_minimum_size = Vector2(640, 0)
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 8
|
anchors_preset = 8
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
|
@ -75,10 +74,20 @@ unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Browse"
|
text = "Browse"
|
||||||
|
|
||||||
[node name="Missions" type="ItemList" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Campaigns" type="ItemList" parent="PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 480)
|
custom_minimum_size = Vector2(0, 480)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Missions" type="ItemList" parent="PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(0, 480)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="Buttons" type="HBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
[node name="Buttons" type="HBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
Loading…
Reference in New Issue