thief-mission-viewer/project/code/TMV/TextureLoader.cs

129 lines
4.0 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Godot;
namespace KeepersCompound.TMV;
public partial class TextureLoader
{
private readonly string _userTexturesPath;
private readonly string _rootFamPath; // TODO: Load from installation resources
private readonly string _fmPath;
private readonly Dictionary<string, string> _rootTexturePaths = new();
private readonly Dictionary<string, string> _fmTexturePaths = new();
private readonly List<ImageTexture> _textureCache = new();
private readonly Dictionary<int, int> _idMap = new();
private readonly Dictionary<string, int> _pathMap = new();
public TextureLoader(string rootFamPath, string fmPath)
{
_rootFamPath = rootFamPath;
_fmPath = fmPath;
_userTexturesPath = ProjectSettings.GlobalizePath($"user://textures/tmp");
ExtractRootFamFiles();
LoadDefaultTexture();
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()
{
// TODO: This should be a resource loaded from RES
const string path = "user://textures/jorge.png";
var texture = ImageTexture.CreateFromImage(Image.LoadFromFile(path));
_textureCache.Add(texture);
}
private static void RegisterTexturePaths(string rootDir, Dictionary<string, string> map)
{
// TODO: Load DDS BMP GIF CEL
string[] validExtensions = { "png", "tga", "pcx" };
var famOptions = new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive };
var textureOptions = new EnumerationOptions
{
MatchCasing = MatchCasing.CaseInsensitive,
RecurseSubdirectories = true,
};
foreach (var dirPath in Directory.EnumerateDirectories(rootDir, "fam", famOptions))
{
foreach (var path in Directory.EnumerateFiles(dirPath, "*", textureOptions))
{
if (validExtensions.Contains(path.GetExtension().ToLower()))
{
// TODO: This only adds the first one found rather than the highest priority
var key = path.TrimPrefix(rootDir).GetBaseName().ToLower();
map.TryAdd(key, path);
}
}
}
GD.Print($"Registered {map.Count} texture paths at : {rootDir}");
}
public bool Load(int id, string path)
{
var loaded = false;
if (_fmTexturePaths.TryGetValue(path.ToLower(), out var fmTexPath))
{
_textureCache.Add(LoadTexture(fmTexPath));
loaded = true;
}
else if (_rootTexturePaths.TryGetValue(path.ToLower(), out var rootTexPath))
{
_textureCache.Add(LoadTexture(rootTexPath));
loaded = true;
}
var index = loaded ? _textureCache.Count - 1 : 0;
_idMap.TryAdd(id, index);
_pathMap.TryAdd(path, index);
return loaded;
}
private static ImageTexture LoadTexture(string path)
{
var ext = path.GetExtension().ToLower();
var texture = ext switch
{
"pcx" => LoadPcx(path),
_ => ImageTexture.CreateFromImage(Image.LoadFromFile(path)),
};
return texture;
}
public ImageTexture Get(int id)
{
if (!_idMap.ContainsKey(id))
{
return _textureCache[0];
}
return _textureCache[_idMap[id]];
}
public ImageTexture Get(string path)
{
if (!_pathMap.ContainsKey(path))
{
return _textureCache[0];
}
return _textureCache[_pathMap[path]];
}
}