mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2026-08-15 02:57:49 +04:00
add config file
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
namespace NResUI.Abstractions;
|
||||||
|
|
||||||
|
public interface IConfigProvider
|
||||||
|
{
|
||||||
|
ConfigJson GetConfig();
|
||||||
|
void Set(ConfigJson config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfigProvider : IConfigProvider
|
||||||
|
{
|
||||||
|
private ConfigJson _instance;
|
||||||
|
|
||||||
|
public ConfigProvider(ConfigJson instance)
|
||||||
|
{
|
||||||
|
_instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set(ConfigJson config)
|
||||||
|
{
|
||||||
|
_instance = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigJson GetConfig()
|
||||||
|
{
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace NResUI.Abstractions;
|
||||||
|
|
||||||
|
public interface ILaunchReceiver
|
||||||
|
{
|
||||||
|
void OnLaunch();
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ public class App
|
|||||||
public ImFontPtr OpenSansFont;
|
public ImFontPtr OpenSansFont;
|
||||||
|
|
||||||
private List<IImGuiPanel> _imGuiPanels = [];
|
private List<IImGuiPanel> _imGuiPanels = [];
|
||||||
|
private Later _later = new();
|
||||||
|
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
@@ -40,6 +41,9 @@ public class App
|
|||||||
|
|
||||||
IServiceCollection serviceCollection = new ServiceCollection();
|
IServiceCollection serviceCollection = new ServiceCollection();
|
||||||
|
|
||||||
|
serviceCollection.AddSingleton<ILater>(_later);
|
||||||
|
serviceCollection.AddSingleton<IConfigProvider>(new ConfigProvider(new ConfigJson()));
|
||||||
|
|
||||||
foreach (var type in Utils.GetAssignableTypes<IService>())
|
foreach (var type in Utils.GetAssignableTypes<IService>())
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton(type);
|
serviceCollection.AddSingleton(type);
|
||||||
@@ -50,6 +54,11 @@ public class App
|
|||||||
serviceCollection.AddSingleton(type);
|
serviceCollection.AddSingleton(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var type in Utils.GetAssignableTypes<ILaunchReceiver>())
|
||||||
|
{
|
||||||
|
serviceCollection.AddSingleton(type);
|
||||||
|
}
|
||||||
|
|
||||||
serviceCollection.AddSingleton(openGl);
|
serviceCollection.AddSingleton(openGl);
|
||||||
serviceCollection.AddSingleton(window);
|
serviceCollection.AddSingleton(window);
|
||||||
|
|
||||||
@@ -68,6 +77,12 @@ public class App
|
|||||||
_imGuiPanels = Utils.GetAssignableTypes<IImGuiPanel>()
|
_imGuiPanels = Utils.GetAssignableTypes<IImGuiPanel>()
|
||||||
.Select(t => (serviceProvider.GetService(t) as IImGuiPanel)!)
|
.Select(t => (serviceProvider.GetService(t) as IImGuiPanel)!)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var type in Utils.GetAssignableTypes<ILaunchReceiver>())
|
||||||
|
{
|
||||||
|
var launchReceiver = serviceProvider.GetService(type) as ILaunchReceiver;
|
||||||
|
launchReceiver?.OnLaunch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnImGuiRender()
|
public void OnImGuiRender()
|
||||||
@@ -123,6 +138,11 @@ public class App
|
|||||||
{
|
{
|
||||||
imGuiPanel.OnImGuiRender();
|
imGuiPanel.OnImGuiRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var action in _later.Enumerate())
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
|
||||||
// ImGui.ShowMetricsWindow();
|
// ImGui.ShowMetricsWindow();
|
||||||
// ImGui.ShowDemoWindow();
|
// ImGui.ShowDemoWindow();
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace NResUI;
|
||||||
|
|
||||||
|
public class ConfigJson
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the game itself (the folder that contains DATA, MISSIONS, UNITS etc)
|
||||||
|
/// </summary>
|
||||||
|
public string GameBasePath { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
namespace NResUI;
|
||||||
|
|
||||||
|
public interface ILater
|
||||||
|
{
|
||||||
|
void Execute(Action action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Later : ILater
|
||||||
|
{
|
||||||
|
private Queue<Action> _queue = new();
|
||||||
|
|
||||||
|
public void Execute(Action action)
|
||||||
|
{
|
||||||
|
_queue.Enqueue(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Action> Enumerate()
|
||||||
|
{
|
||||||
|
while (_queue.Count > 0)
|
||||||
|
{
|
||||||
|
var action = _queue.Dequeue();
|
||||||
|
yield return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,12 +16,14 @@ public sealed class ViewportPanel : IImGuiPanel
|
|||||||
private readonly ViewportScene _scene;
|
private readonly ViewportScene _scene;
|
||||||
private readonly ViewportCamera _camera = new();
|
private readonly ViewportCamera _camera = new();
|
||||||
private readonly ViewportInputController _inputController = new();
|
private readonly ViewportInputController _inputController = new();
|
||||||
|
private readonly IConfigProvider _configProvider;
|
||||||
|
|
||||||
private string? _loadedModelPath;
|
private string? _loadedModelPath;
|
||||||
private string? _loadError;
|
private string? _loadError;
|
||||||
|
|
||||||
public ViewportPanel(GL gl, IWindow window)
|
public ViewportPanel(GL gl, IWindow window, IConfigProvider configProvider)
|
||||||
{
|
{
|
||||||
|
_configProvider = configProvider;
|
||||||
var cubeMesh = PrimitiveMeshes.CreateCube(gl);
|
var cubeMesh = PrimitiveMeshes.CreateCube(gl);
|
||||||
var gridMesh = PrimitiveMeshes.CreateWorldGrid(gl);
|
var gridMesh = PrimitiveMeshes.CreateWorldGrid(gl);
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ public sealed class ViewportPanel : IImGuiPanel
|
|||||||
if (ImGui.Button("Reset cube"))
|
if (ImGui.Button("Reset cube"))
|
||||||
{
|
{
|
||||||
var cubeMesh = PrimitiveMeshes.CreateCube(_renderer.Gl);
|
var cubeMesh = PrimitiveMeshes.CreateCube(_renderer.Gl);
|
||||||
_scene.ReplacePieces(new[] { ViewportPiece.CreateUnitCube(0, "Cube", cubeMesh) });
|
_scene.ReplacePieces([ViewportPiece.CreateUnitCube(0, "Cube", cubeMesh)]);
|
||||||
_loadedModelPath = null;
|
_loadedModelPath = null;
|
||||||
_loadError = null;
|
_loadError = null;
|
||||||
_camera.Reset();
|
_camera.Reset();
|
||||||
@@ -109,7 +111,7 @@ public sealed class ViewportPanel : IImGuiPanel
|
|||||||
|
|
||||||
private void LoadMsh(string path)
|
private void LoadMsh(string path)
|
||||||
{
|
{
|
||||||
var loadResult = MshViewportLoader.LoadFromFile(_renderer.Gl, path);
|
var loadResult = MshViewportLoader.LoadFromFile(_renderer.Gl, path, _configProvider);
|
||||||
if (!loadResult.IsSuccess)
|
if (!loadResult.IsSuccess)
|
||||||
{
|
{
|
||||||
_loadError = loadResult.Error ?? "Unknown error.";
|
_loadError = loadResult.Error ?? "Unknown error.";
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using NResUI.Abstractions;
|
||||||
|
using NResUI.ImGuiUI;
|
||||||
|
|
||||||
|
namespace NResUI;
|
||||||
|
|
||||||
|
public class LoadConfigOnLaunch : ILaunchReceiver
|
||||||
|
{
|
||||||
|
private readonly ILater _later;
|
||||||
|
private readonly MessageBoxModalPanel _messageBoxModalPanel;
|
||||||
|
private readonly IConfigProvider _configProvider;
|
||||||
|
|
||||||
|
public LoadConfigOnLaunch(ILater later, MessageBoxModalPanel messageBoxModalPanel, IConfigProvider configProvider)
|
||||||
|
{
|
||||||
|
_later = later;
|
||||||
|
_messageBoxModalPanel = messageBoxModalPanel;
|
||||||
|
_configProvider = configProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnLaunch()
|
||||||
|
{
|
||||||
|
if (!File.Exists("config.json"))
|
||||||
|
{
|
||||||
|
_later.Execute(() =>
|
||||||
|
{
|
||||||
|
_messageBoxModalPanel.Show(
|
||||||
|
"config.json is not present\nViewport may be broken without game files\nPlaceholder file has been created");
|
||||||
|
});
|
||||||
|
var config = new ConfigJson() { GameBasePath = "" };
|
||||||
|
File.WriteAllText("config.json", JsonSerializer.Serialize(config));
|
||||||
|
_configProvider.Set(config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var content = File.ReadAllText("config.json");
|
||||||
|
var config = JsonSerializer.Deserialize<ConfigJson>(content);
|
||||||
|
if (config is null)
|
||||||
|
{
|
||||||
|
_later.Execute(() =>
|
||||||
|
{
|
||||||
|
_messageBoxModalPanel.Show("config.json was corrupted\nReplacement has been created");
|
||||||
|
});
|
||||||
|
config = new ConfigJson() { GameBasePath = "" };
|
||||||
|
File.WriteAllText("config.json", JsonSerializer.Serialize(config));
|
||||||
|
_configProvider.Set(config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_configProvider.Set(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -1,6 +1,7 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using MshLib;
|
using MshLib;
|
||||||
using NResLib;
|
using NResLib;
|
||||||
|
using NResUI.Abstractions;
|
||||||
using NResUI.Rendering.Viewport.Meshes;
|
using NResUI.Rendering.Viewport.Meshes;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ public static class MshViewportLoader
|
|||||||
private const int DefaultModelState = 0;
|
private const int DefaultModelState = 0;
|
||||||
private const int DefaultLod = 0;
|
private const int DefaultLod = 0;
|
||||||
|
|
||||||
public static MshViewportLoadResult LoadFromFile(GL gl, string path)
|
public static MshViewportLoadResult LoadFromFile(GL gl, string path, IConfigProvider configProvider)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -30,7 +31,7 @@ public static class MshViewportLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
fs.Seek(0, SeekOrigin.Begin);
|
fs.Seek(0, SeekOrigin.Begin);
|
||||||
var pieces = LoadModelPieces(gl, fs, archive, path);
|
var pieces = LoadModelPieces(gl, fs, archive, path, configProvider);
|
||||||
if (pieces.Count == 0)
|
if (pieces.Count == 0)
|
||||||
return MshViewportLoadResult.Failure("MSH was parsed, but no renderable geometry pieces were found.", path);
|
return MshViewportLoadResult.Failure("MSH was parsed, but no renderable geometry pieces were found.", path);
|
||||||
|
|
||||||
@@ -42,7 +43,9 @@ public static class MshViewportLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ViewportPiece> LoadModelPieces(GL gl, FileStream fs, NResArchive archive, string path)
|
private static List<ViewportPiece> LoadModelPieces(
|
||||||
|
GL gl, FileStream fs, NResArchive archive, string path, IConfigProvider configProvider
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var nodes = Msh0x01.ReadComponent(fs, archive);
|
var nodes = Msh0x01.ReadComponent(fs, archive);
|
||||||
var geometry = Msh0x02.ReadComponent(fs, archive);
|
var geometry = Msh0x02.ReadComponent(fs, archive);
|
||||||
@@ -54,7 +57,7 @@ public static class MshViewportLoader
|
|||||||
var restPoses = MshRestPoseBuilder.BuildRestPose(nodes, animationDescriptors);
|
var restPoses = MshRestPoseBuilder.BuildRestPose(nodes, animationDescriptors);
|
||||||
var mshToViewportTransform = Matrix4x4.CreateRotationX(-MathF.PI * 0.5f);
|
var mshToViewportTransform = Matrix4x4.CreateRotationX(-MathF.PI * 0.5f);
|
||||||
var names = TryReadNames(fs, archive);
|
var names = TryReadNames(fs, archive);
|
||||||
var materialLibrary = WeaMaterialLibrary.TryLoadForMsh(gl, path);
|
var materialLibrary = WeaMaterialLibrary.TryLoadForMsh(gl, path, configProvider);
|
||||||
|
|
||||||
var pieces = new List<ViewportPiece>();
|
var pieces = new List<ViewportPiece>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using MaterialLib;
|
using MaterialLib;
|
||||||
using NResLib;
|
using NResLib;
|
||||||
|
using NResUI.Abstractions;
|
||||||
using NResUI.Rendering.Viewport.OpenGL;
|
using NResUI.Rendering.Viewport.OpenGL;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
using TexmLib;
|
using TexmLib;
|
||||||
@@ -24,7 +25,7 @@ public sealed class WeaMaterialLibrary
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WeaMaterialLibrary TryLoadForMsh(GL gl, string mshPath)
|
public static WeaMaterialLibrary TryLoadForMsh(GL gl, string mshPath, IConfigProvider configProvider)
|
||||||
{
|
{
|
||||||
var weaPath = FindMatchingWeaPath(mshPath);
|
var weaPath = FindMatchingWeaPath(mshPath);
|
||||||
if (!File.Exists(weaPath))
|
if (!File.Exists(weaPath))
|
||||||
@@ -34,9 +35,13 @@ public sealed class WeaMaterialLibrary
|
|||||||
if (materialRefs.Count == 0)
|
if (materialRefs.Count == 0)
|
||||||
return Empty;
|
return Empty;
|
||||||
|
|
||||||
// TODO: Hardcoded for now
|
var materialLibFs = Path.Combine(configProvider.GetConfig().GameBasePath, "Material.lib");
|
||||||
var materialLibFs = "C:\\IronStrategy\\Material.lib";
|
|
||||||
|
|
||||||
|
if (!File.Exists(materialLibFs))
|
||||||
|
{
|
||||||
|
return new WeaMaterialLibrary([]);
|
||||||
|
}
|
||||||
|
|
||||||
using var materialFs = new FileStream(materialLibFs, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using var materialFs = new FileStream(materialLibFs, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
var parseResult = NResParser.ReadFile(materialFs);
|
var parseResult = NResParser.ReadFile(materialFs);
|
||||||
if (parseResult.Archive == null)
|
if (parseResult.Archive == null)
|
||||||
@@ -46,7 +51,7 @@ public sealed class WeaMaterialLibrary
|
|||||||
|
|
||||||
foreach (var materialRef in materialRefs)
|
foreach (var materialRef in materialRefs)
|
||||||
{
|
{
|
||||||
var texture = TryLoadMaterialTexture(gl, materialFs, parseResult.Archive, materialRef.Name, out var texm);
|
var texture = TryLoadMaterialTexture(gl, materialFs, parseResult.Archive, materialRef.Name, configProvider, out var texm);
|
||||||
result[materialRef.Id] = texture != null
|
result[materialRef.Id] = texture != null
|
||||||
? new ViewportMaterial(materialRef.Name, texture.Value, texm)
|
? new ViewportMaterial(materialRef.Name, texture.Value, texm)
|
||||||
: new ViewportMaterial(materialRef.Name);
|
: new ViewportMaterial(materialRef.Name);
|
||||||
@@ -194,7 +199,8 @@ public sealed class WeaMaterialLibrary
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static uint? TryLoadMaterialTexture(
|
private static uint? TryLoadMaterialTexture(
|
||||||
GL gl, FileStream materialFs, NResArchive materialArchive, string materialName, out TexmFile? texm
|
GL gl, FileStream materialFs, NResArchive materialArchive, string materialName, IConfigProvider configProvider,
|
||||||
|
out TexmFile? texm
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
texm = null;
|
texm = null;
|
||||||
@@ -212,7 +218,12 @@ public sealed class WeaMaterialLibrary
|
|||||||
|
|
||||||
var texture = materialFile.Stages[0].TextureName;
|
var texture = materialFile.Stages[0].TextureName;
|
||||||
|
|
||||||
var textureLibFs = "C:\\IronStrategy\\Textures.lib";
|
var textureLibFs = Path.Combine(configProvider.GetConfig().GameBasePath, "Textures.lib");
|
||||||
|
|
||||||
|
if (!File.Exists(textureLibFs))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
using var textureFs = new FileStream(textureLibFs, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using var textureFs = new FileStream(textureLibFs, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
var textureResult = NResParser.ReadFile(textureFs);
|
var textureResult = NResParser.ReadFile(textureFs);
|
||||||
@@ -269,27 +280,5 @@ public sealed class WeaMaterialLibrary
|
|||||||
Normalize(x.FileName) == normalized);
|
Normalize(x.FileName) == normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string? FindTexturesLib(string? startDirectory)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(startDirectory))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var directory = new DirectoryInfo(startDirectory);
|
|
||||||
while (directory != null)
|
|
||||||
{
|
|
||||||
var candidate = Path.Combine(directory.FullName, "Textures.lib");
|
|
||||||
if (Directory.Exists(candidate))
|
|
||||||
return candidate;
|
|
||||||
|
|
||||||
candidate = Path.Combine(directory.FullName, "textures.lib");
|
|
||||||
if (Directory.Exists(candidate))
|
|
||||||
return candidate;
|
|
||||||
|
|
||||||
directory = directory.Parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly record struct WeaMaterialRef(int Id, string Name);
|
private readonly record struct WeaMaterialRef(int Id, string Name);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user