XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Collections.Concurrent;
using XFEEDToolBox.Core.Rendering;

namespace XFEEDToolBox.Rendering;

internal static class LocalShipModels
{
    private static readonly ConcurrentDictionary<string, WeakReference<ShipMesh>> cache = new();
    private static readonly object sourceLock = new();
    private static EliteLocalModels? gameModels;
    private static string gamePath = "";
    private static readonly ConcurrentDictionary<string,Task<ModuleIconPixels>> icons=new();
    private static readonly ConcurrentDictionary<string,Task<NebulaVolume>> nebulae=new();
    public static Task<NebulaVolume> LoadNebulaAsync(string template)
    {
        var executable=App.ViewModel.PluginGameExecutable;
        return nebulae.GetOrAdd(executable+":"+template,_=>Task.Run(()=>
        {
            lock(sourceLock)
            {
                if(gameModels is null||!executable.Equals(gamePath,StringComparison.OrdinalIgnoreCase)){gameModels=new(executable);gamePath=executable;}
                return EliteNebulae.Read(gameModels,template);
            }
        }));
    }
    public static Task<ModuleIconPixels> LoadIconAsync(string name)
    {
        var executable=App.ViewModel.PluginGameExecutable;
        return icons.GetOrAdd(executable+":"+name,_=>Task.Run(()=>
        {
            lock(sourceLock)
            {
                if(gameModels is null||!executable.Equals(gamePath,StringComparison.OrdinalIgnoreCase)){gameModels=new(executable);gamePath=executable;}
                return EliteModuleIcons.Read(gameModels,name);
            }
        }));
    }
    public static string Key(string type) => new(type.ToLowerInvariant().Where(char.IsAsciiLetterOrDigit).ToArray());
    public static ShipMesh? Load(string type)
    {
        var key = Key(type);
        if (key.Length == 0) return null;
        foreach (var directory in new[] { Path.Combine(App.Runtime.DataDirectory, "models"), Path.Combine(AppContext.BaseDirectory, "Assets", "Ships") })
        foreach (var extension in new[] { ".obj", ".stl" })
        {
            var path = Path.Combine(directory, key + extension);
            if (!File.Exists(path)) continue;
            var stamp = path + ":" + File.GetLastWriteTimeUtc(path).Ticks;
            if (cache.TryGetValue(stamp, out var weak) && weak.TryGetTarget(out var found)) return found;
            var mesh = ShipMeshReader.Read(path);
            cache[stamp] = new(mesh);
            return mesh;
        }
        var executable = App.ViewModel.PluginGameExecutable;
        if (!File.Exists(executable)) return null;
        lock (sourceLock)
        {
            if (gameModels is null || !executable.Equals(gamePath, StringComparison.OrdinalIgnoreCase))
            { gameModels = new(executable); gamePath = executable; }
            var stamp = executable + ":" + key;
            if (cache.TryGetValue(stamp, out var weak) && weak.TryGetTarget(out var found)) return found;
            var mesh = gameModels.Read(type);
            if (mesh is not null) cache[stamp] = new(mesh);
            return mesh;
        }
    }
}