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;
}
}
}
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;
}
}
}