From 1091605e2de180fd8846f25d603cb9cec1369484 Mon Sep 17 00:00:00 2001 From: bird_egop Date: Fri, 15 Nov 2024 19:06:44 +0300 Subject: [PATCH] create NResUI --- NResLib/NResArchive.cs | 45 ++++++++ NResLib/NResLib.csproj | 9 ++ NResLib/NResParseResult.cs | 3 + NResLib/NResParser.cs | 78 +++++++++++++ NResUI/Abstractions/IExitReceiver.cs | 7 ++ NResUI/Abstractions/IImGuiPanel.cs | 7 ++ NResUI/Abstractions/IKeyPressReceiver.cs | 17 +++ NResUI/Abstractions/IService.cs | 6 + NResUI/Abstractions/IUpdateReceiver.cs | 10 ++ NResUI/App.cs | 140 +++++++++++++++++++++++ NResUI/ImGuiUI/ExplorerPanel.cs | 127 ++++++++++++++++++++ NResUI/ImGuiUI/ImGuiModalPanel.cs | 39 +++++++ NResUI/ImGuiUI/MainMenuBar.cs | 108 +++++++++++++++++ NResUI/Models/ExplorerViewModel.cs | 26 +++++ NResUI/NResUI.csproj | 25 ++++ NResUI/Program.cs | 109 ++++++++++++++++++ NResUI/Utils.cs | 64 +++++++++++ NResUI/assets/Font/OpenSans-Regular.ttf | Bin 0 -> 129796 bytes ParkanPlayground.sln | 12 ++ ParkanPlayground/ListMetadataItem.cs | 3 - ParkanPlayground/ParkanPlayground.csproj | 4 + ParkanPlayground/Program.cs | 130 ++++++--------------- 22 files changed, 869 insertions(+), 100 deletions(-) create mode 100644 NResLib/NResArchive.cs create mode 100644 NResLib/NResLib.csproj create mode 100644 NResLib/NResParseResult.cs create mode 100644 NResLib/NResParser.cs create mode 100644 NResUI/Abstractions/IExitReceiver.cs create mode 100644 NResUI/Abstractions/IImGuiPanel.cs create mode 100644 NResUI/Abstractions/IKeyPressReceiver.cs create mode 100644 NResUI/Abstractions/IService.cs create mode 100644 NResUI/Abstractions/IUpdateReceiver.cs create mode 100644 NResUI/App.cs create mode 100644 NResUI/ImGuiUI/ExplorerPanel.cs create mode 100644 NResUI/ImGuiUI/ImGuiModalPanel.cs create mode 100644 NResUI/ImGuiUI/MainMenuBar.cs create mode 100644 NResUI/Models/ExplorerViewModel.cs create mode 100644 NResUI/NResUI.csproj create mode 100644 NResUI/Program.cs create mode 100644 NResUI/Utils.cs create mode 100644 NResUI/assets/Font/OpenSans-Regular.ttf delete mode 100644 ParkanPlayground/ListMetadataItem.cs diff --git a/NResLib/NResArchive.cs b/NResLib/NResArchive.cs new file mode 100644 index 0000000..92202ab --- /dev/null +++ b/NResLib/NResArchive.cs @@ -0,0 +1,45 @@ +namespace NResLib; + +/// +/// Архив NRes (файл NRes) +/// +public record NResArchive(NResArchiveHeader Header, List Files); + +/// +/// Заголовок файла +/// +/// [0..4] ASCII NRes +/// [4..8] Версия кодировщика (должно быть всегда 0x100) +/// [8..12] Количество файлов +/// [12..16] Длина всего архива +public record NResArchiveHeader(string NRes, int Version, int FileCount, int TotalFileLengthBytes); + +/// +/// В конце файла есть список метаданных, +/// каждый элемент это 64 байта, +/// найти начало можно как (Header.TotalFileLengthBytes - Header.FileCount * 64) +/// +/// [0..8] ASCII описание типа файла, например TEXM или MAT0 +/// [8..12] Неизвестное число +/// [12..16] Длина файла в байтах +/// [16..20] Неизвестное число +/// [20..40] ASCII имя файла +/// [40..44] Неизвестное число +/// [44..48] Неизвестное число +/// [48..52] Неизвестное число +/// [52..56] Неизвестное число +/// [56..60] Смещение подфайла от начала NRes (именно самого NRes) в байтах +/// [60..64] Индекс в файле (от 0, не больше чем кол-во файлов) +public record ListMetadataItem( + string FileType, + int Magic1, + int FileLength, + int Magic2, + string FileName, + int Magic3, + int Magic4, + int Magic5, + int Magic6, + int OffsetInFile, + int Index +); \ No newline at end of file diff --git a/NResLib/NResLib.csproj b/NResLib/NResLib.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/NResLib/NResLib.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/NResLib/NResParseResult.cs b/NResLib/NResParseResult.cs new file mode 100644 index 0000000..1f2b671 --- /dev/null +++ b/NResLib/NResParseResult.cs @@ -0,0 +1,3 @@ +namespace NResLib; + +public record NResParseResult(NResArchive? Archive = null, string? Error = null); \ No newline at end of file diff --git a/NResLib/NResParser.cs b/NResLib/NResParser.cs new file mode 100644 index 0000000..7054565 --- /dev/null +++ b/NResLib/NResParser.cs @@ -0,0 +1,78 @@ +using System.Buffers.Binary; +using System.Text; + +namespace NResLib; + +public static class NResParser +{ + public static NResParseResult ReadFile(string path) + { + using FileStream nResFs = new FileStream(path, FileMode.Open); + + if (nResFs.Length < 16) + { + return new NResParseResult(null, "Файл не может быть NRes, менее 16 байт"); + } + + Span buffer = stackalloc byte[16]; + + nResFs.ReadExactly(buffer); + + if (buffer[0] != 'N' || buffer[1] != 'R' || buffer[2] != 'e' || buffer[3] != 's') + { + return new NResParseResult(null, "Файл не начинается с NRes"); + } + + var header = new NResArchiveHeader( + NRes: Encoding.ASCII.GetString(buffer[0..4]), + Version: BinaryPrimitives.ReadInt32LittleEndian(buffer[4..8]), + FileCount: BinaryPrimitives.ReadInt32LittleEndian(buffer[8..12]), + TotalFileLengthBytes: BinaryPrimitives.ReadInt32LittleEndian(buffer[12..16]) + ); + + if (header.TotalFileLengthBytes != nResFs.Length) + { + return new NResParseResult( + null, + $"Длина файла не совпадает с заявленным в заголовке.\n" + + $"Заявлено: {header.TotalFileLengthBytes}\n" + + $"Фактически: {nResFs.Length}" + ); + } + + nResFs.Seek(-header.FileCount * 64, SeekOrigin.End); + + var elements = new List(header.FileCount); + + Span metaDataBuffer = stackalloc byte[64]; + for (int i = 0; i < header.FileCount; i++) + { + nResFs.ReadExactly(metaDataBuffer); + + elements.Add( + new ListMetadataItem( + FileType: Encoding.ASCII.GetString(metaDataBuffer[..8]), + Magic1: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[8..12]), + FileLength: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[12..16]), + Magic2: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[16..20]), + FileName: Encoding.ASCII.GetString(metaDataBuffer[20..40]), + Magic3: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[40..44]), + Magic4: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[44..48]), + Magic5: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[48..52]), + Magic6: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[52..56]), + OffsetInFile: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[56..60]), + Index: BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer[60..64]) + ) + ); + + metaDataBuffer.Clear(); + } + + return new NResParseResult( + new NResArchive( + Header: header, + Files: elements + ) + ); + } +} \ No newline at end of file diff --git a/NResUI/Abstractions/IExitReceiver.cs b/NResUI/Abstractions/IExitReceiver.cs new file mode 100644 index 0000000..2c3d093 --- /dev/null +++ b/NResUI/Abstractions/IExitReceiver.cs @@ -0,0 +1,7 @@ +namespace NResUI.Abstractions +{ + public interface IExitReceiver + { + void OnExit(); + } +} \ No newline at end of file diff --git a/NResUI/Abstractions/IImGuiPanel.cs b/NResUI/Abstractions/IImGuiPanel.cs new file mode 100644 index 0000000..94390b2 --- /dev/null +++ b/NResUI/Abstractions/IImGuiPanel.cs @@ -0,0 +1,7 @@ +namespace NResUI.Abstractions +{ + public interface IImGuiPanel + { + void OnImGuiRender(); + } +} \ No newline at end of file diff --git a/NResUI/Abstractions/IKeyPressReceiver.cs b/NResUI/Abstractions/IKeyPressReceiver.cs new file mode 100644 index 0000000..23aa7d8 --- /dev/null +++ b/NResUI/Abstractions/IKeyPressReceiver.cs @@ -0,0 +1,17 @@ +using Silk.NET.Input; + +namespace NResUI.Abstractions +{ + public interface IKeyPressReceiver + { + void OnKeyPressed(Key key); + } + public interface IKeyReleaseReceiver + { + void OnKeyReleased(Key key); + } + public interface IKeyDownReceiver + { + void OnKeyDown(Key key); + } +} \ No newline at end of file diff --git a/NResUI/Abstractions/IService.cs b/NResUI/Abstractions/IService.cs new file mode 100644 index 0000000..f668d31 --- /dev/null +++ b/NResUI/Abstractions/IService.cs @@ -0,0 +1,6 @@ +namespace NResUI.Abstractions +{ + public interface IService + { + } +} \ No newline at end of file diff --git a/NResUI/Abstractions/IUpdateReceiver.cs b/NResUI/Abstractions/IUpdateReceiver.cs new file mode 100644 index 0000000..d338a52 --- /dev/null +++ b/NResUI/Abstractions/IUpdateReceiver.cs @@ -0,0 +1,10 @@ +namespace NResUI.Abstractions +{ + public interface IUpdateReceiver + { + /// + /// Called before every UI render + /// + void OnUpdate(float delta); + } +} \ No newline at end of file diff --git a/NResUI/App.cs b/NResUI/App.cs new file mode 100644 index 0000000..e5b6516 --- /dev/null +++ b/NResUI/App.cs @@ -0,0 +1,140 @@ +using System.Numerics; +using ImGuiNET; +using Microsoft.Extensions.DependencyInjection; +using NResUI.Abstractions; +using NResUI.Models; +using Silk.NET.Input; +using Silk.NET.OpenGL; +using Silk.NET.Windowing; + +namespace NResUI; + +public class App + { + public GL GL { get; set; } + public IInputContext Input { get; set; } + + public static App Instance; + + private static bool _dockspaceOpen = true; + private static bool _optFullscreenPersistant = true; + private static bool _optFullscreen = _optFullscreenPersistant; + + private static ImGuiDockNodeFlags _dockspaceFlags = ImGuiDockNodeFlags.None; + + public ImFontPtr OpenSansFont; + + private List _imGuiPanels; + + public App() + { + Instance = this; + } + + public void Init(IWindow window, GL openGl, ImFontPtr openSansFont) + { + ImGui.StyleColorsLight(); + + IServiceCollection serviceCollection = new ServiceCollection(); + + foreach (var type in Utils.GetAssignableTypes()) + { + serviceCollection.AddSingleton(type); + } + + foreach (var type in Utils.GetAssignableTypes()) + { + serviceCollection.AddSingleton(type); + } + + serviceCollection.AddSingleton(new ExplorerViewModel()); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + _imGuiPanels = Utils.GetAssignableTypes() + .Select(t => (serviceProvider.GetService(t) as IImGuiPanel)!) + .ToList(); + } + + public void OnImGuiRender() + { + ImGui.PushFont(OpenSansFont); + + // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into, + // because it would be confusing to have two docking targets within each others. + var windowFlags = ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.NoDocking; + if (_optFullscreen) + { + var viewport = ImGui.GetMainViewport(); + ImGui.SetNextWindowPos(viewport.Pos); + ImGui.SetNextWindowSize(viewport.Size); + ImGui.SetNextWindowViewport(viewport.ID); + ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0.0f); + ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 0.0f); + windowFlags |= ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | + ImGuiWindowFlags.NoMove; + windowFlags |= ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus; + } + + // When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background and handle the pass-thru hole, so we ask Begin() to not render a background. + if ((_dockspaceFlags & ImGuiDockNodeFlags.PassthruCentralNode) != 0) + windowFlags |= ImGuiWindowFlags.NoBackground; + + // Important: note that we proceed even if Begin() returns false (aka window is collapsed). + // This is because we want to keep our DockSpace() active. If a DockSpace() is inactive, + // all active windows docked into it will lose their parent and become undocked. + // We cannot preserve the docking relationship between an active window and an inactive docking, otherwise + // any change of dockspace/settings would lead to windows being stuck in limbo and never being visible. + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0.0f, 0.0f)); + ImGui.Begin("DockSpace Demo", ref _dockspaceOpen, windowFlags); + ImGui.PopStyleVar(); + + if (_optFullscreen) + ImGui.PopStyleVar(2); + + // DockSpace + var io = ImGui.GetIO(); + var style = ImGui.GetStyle(); + var minWinSizeX = style.WindowMinSize.X; + style.WindowMinSize.X = 370.0f; + if ((io.ConfigFlags & ImGuiConfigFlags.DockingEnable) != 0) + { + var dockspaceId = ImGui.GetID("MyDockSpace"); + ImGui.DockSpace(dockspaceId, new Vector2(0.0f, 0.0f), _dockspaceFlags); + } + + style.WindowMinSize.X = minWinSizeX; + + foreach (var imGuiPanel in _imGuiPanels) + { + imGuiPanel.OnImGuiRender(); + } + + ImGui.ShowMetricsWindow(); + ImGui.ShowDemoWindow(); + + ImGui.PopFont(); + + ImGui.End(); + } + + public void Exit() + { + } + + public void Update(double delta) + { + } + + public void OnKeyPressed(Key key) + { + } + + public void OnKeyDown(Key key) + { + } + + public void OnKeyReleased(Key key) + { + } + } \ No newline at end of file diff --git a/NResUI/ImGuiUI/ExplorerPanel.cs b/NResUI/ImGuiUI/ExplorerPanel.cs new file mode 100644 index 0000000..82b4189 --- /dev/null +++ b/NResUI/ImGuiUI/ExplorerPanel.cs @@ -0,0 +1,127 @@ +using ImGuiNET; +using NResUI.Abstractions; +using NResUI.Models; + +namespace NResUI.ImGuiUI; + +public class ExplorerPanel : IImGuiPanel +{ + private readonly ExplorerViewModel _viewModel; + + public ExplorerPanel(ExplorerViewModel viewModel) + { + _viewModel = viewModel; + } + + public void OnImGuiRender() + { + if (ImGui.Begin("Explorer")) + { + if (!_viewModel.HasFile) + { + ImGui.Text("No NRes is opened"); + } + else + { + if (_viewModel.Error != null) + { + ImGui.Text(_viewModel.Error); + } + + if (_viewModel.Archive is not null) + { + ImGui.Text(_viewModel.Path); + + ImGui.Text("Header: "); + ImGui.SameLine(); + ImGui.Text(_viewModel.Archive.Header.NRes); + ImGui.Text("Version: "); + ImGui.SameLine(); + ImGui.Text(_viewModel.Archive.Header.Version.ToString()); + ImGui.Text("File Count: "); + ImGui.SameLine(); + ImGui.Text(_viewModel.Archive.Header.FileCount.ToString()); + ImGui.Text("Total File Length: "); + ImGui.SameLine(); + ImGui.Text(_viewModel.Archive.Header.TotalFileLengthBytes.ToString()); + + + if (ImGui.BeginTable("content", 11)) + { + ImGui.TableSetupColumn("Тип файла"); + ImGui.TableSetupColumn("Magic1"); + ImGui.TableSetupColumn("Длина файла в байтах"); + ImGui.TableSetupColumn("Magic2"); + ImGui.TableSetupColumn("Имя файла"); + ImGui.TableSetupColumn("Magic3"); + ImGui.TableSetupColumn("Magic4"); + ImGui.TableSetupColumn("Magic5"); + ImGui.TableSetupColumn("Magic6"); + ImGui.TableSetupColumn("Смещение в байтах"); + ImGui.TableSetupColumn("Индекс в файле"); + + ImGui.TableHeadersRow(); + + for (int i = 0; i < _viewModel.Archive.Files.Count; i++) + { + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.Text(_viewModel.Archive.Files[i].FileType); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Magic1.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .FileLength.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Magic2.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text(_viewModel.Archive.Files[i].FileName); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Magic3.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Magic4.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Magic5.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Magic6.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .OffsetInFile.ToString() + ); + ImGui.TableNextColumn(); + ImGui.Text( + _viewModel.Archive.Files[i] + .Index.ToString() + ); + } + + ImGui.EndTable(); + } + } + } + + ImGui.End(); + } + } +} \ No newline at end of file diff --git a/NResUI/ImGuiUI/ImGuiModalPanel.cs b/NResUI/ImGuiUI/ImGuiModalPanel.cs new file mode 100644 index 0000000..a772b04 --- /dev/null +++ b/NResUI/ImGuiUI/ImGuiModalPanel.cs @@ -0,0 +1,39 @@ +using System.Numerics; +using ImGuiNET; +using NResUI.Abstractions; + +namespace NResUI.ImGuiUI; + +public abstract class ImGuiModalPanel : IImGuiPanel +{ + protected abstract string ImGuiId { get; } + + private bool _shouldOpen = false; + + public virtual void Open() + { + _shouldOpen = true; + } + + protected abstract void OnImGuiRenderContent(); + + public void OnImGuiRender() + { + // this is a ImGui stack fix. Because menubars and some other controls use their separate stack context, + // The panel gets rendered on it's own, at the root of the stack, and with _shouldOpen we control, if the panel should open this frame. + if (_shouldOpen) + { + ImGui.OpenPopup(ImGuiId, ImGuiPopupFlags.AnyPopupLevel); + _shouldOpen = false; + } + + ImGui.SetNextWindowSize(new Vector2(600, 400)); + + if (ImGui.BeginPopup(ImGuiId, ImGuiWindowFlags.NoResize)) + { + OnImGuiRenderContent(); + + ImGui.EndPopup(); + } + } +} \ No newline at end of file diff --git a/NResUI/ImGuiUI/MainMenuBar.cs b/NResUI/ImGuiUI/MainMenuBar.cs new file mode 100644 index 0000000..462a9e2 --- /dev/null +++ b/NResUI/ImGuiUI/MainMenuBar.cs @@ -0,0 +1,108 @@ +using System.Numerics; +using ImGuiNET; +using NativeFileDialogSharp; +using NResLib; +using NResUI.Abstractions; +using NResUI.Models; + +namespace NResUI.ImGuiUI +{ + public class MainMenuBar : IImGuiPanel + { + private readonly ExplorerViewModel _explorerViewModel; + + public MainMenuBar(ExplorerViewModel explorerViewModel) + { + _explorerViewModel = explorerViewModel; + } + + public void OnImGuiRender() + { + if (ImGui.BeginMenuBar()) + { + if (ImGui.BeginMenu("File")) + { + if (ImGui.MenuItem("Open NRes")) + { + var result = Dialog.FileOpen(); + + if (result.IsOk) + { + var path = result.Path; + + var parseResult = NResParser.ReadFile(path); + + _explorerViewModel.SetParseResult(parseResult, path); + } + } + + if (_explorerViewModel.HasFile) + { + if (ImGui.MenuItem("Экспортировать")) + { + var result = Dialog.FolderPicker(); + + if (result.IsOk) + { + var path = result.Path; + + Console.WriteLine(path); + } + } + } + + if (ImGui.BeginMenu("Open Recent")) + { + ImGui.EndMenu(); + } + + if (ImGui.MenuItem("Exit")) + { + App.Instance.Exit(); + } + + ImGui.EndMenu(); + } + + if (ImGui.BeginMenu("Windows")) + { + if (ImGui.MenuItem("Settings")) + { + } + + ImGui.EndMenu(); + } + + ImGui.EndMenuBar(); + } + } + + // This is a direct port of imgui_demo.cpp HelpMarker function + + // https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L190 + + private void ShowHint(string message) + { + // ImGui.TextDisabled("(?)"); + if (ImGui.IsItemHovered()) + { + // Change background transparency + ImGui.PushStyleColor( + ImGuiCol.PopupBg, + new Vector4( + 1, + 1, + 1, + 0.8f + ) + ); + ImGui.BeginTooltip(); + ImGui.PushTextWrapPos(ImGui.GetFontSize() * 35.0f); + ImGui.TextUnformatted(message); + ImGui.PopTextWrapPos(); + ImGui.EndTooltip(); + ImGui.PopStyleColor(); + } + } + } +} \ No newline at end of file diff --git a/NResUI/Models/ExplorerViewModel.cs b/NResUI/Models/ExplorerViewModel.cs new file mode 100644 index 0000000..bb83211 --- /dev/null +++ b/NResUI/Models/ExplorerViewModel.cs @@ -0,0 +1,26 @@ +using NResLib; + +namespace NResUI.Models; + +public class ExplorerViewModel +{ + public bool HasFile { get; set; } + public string? Error { get; set; } + + public NResArchive? Archive { get; set; } + + public string? Path { get; set; } + + public void SetParseResult(NResParseResult result, string path) + { + Error = result.Error; + + if (result.Archive != null) + { + HasFile = true; + } + + Archive = result.Archive; + Path = path; + } +} \ No newline at end of file diff --git a/NResUI/NResUI.csproj b/NResUI/NResUI.csproj new file mode 100644 index 0000000..16483bf --- /dev/null +++ b/NResUI/NResUI.csproj @@ -0,0 +1,25 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + diff --git a/NResUI/Program.cs b/NResUI/Program.cs new file mode 100644 index 0000000..55d1c9f --- /dev/null +++ b/NResUI/Program.cs @@ -0,0 +1,109 @@ +// See https://aka.ms/new-console-template for more information + +using System.Drawing; +using ImGuiNET; +using NResUI; +using Silk.NET.Input; +using Silk.NET.OpenGL; +using Silk.NET.OpenGL.Extensions.ImGui; +using Silk.NET.Windowing; + +var window = Window.Create(WindowOptions.Default); + +// Declare some variables +ImGuiController controller = null!; +GL gl = null!; +IInputContext inputContext = null!; + +var app = new App(); + +// Our loading function +window.Load += () => +{ + var openGl = window.CreateOpenGL(); + + ImFontPtr mainFont = null; + + controller = new ImGuiController( + gl = openGl, // load OpenGL + window, // pass in our window + inputContext = window.CreateInput(), // create an input context + () => + { + var io = ImGui.GetIO(); + io.ConfigFlags |= ImGuiConfigFlags.DockingEnable; + mainFont = io.Fonts.AddFontFromFileTTF( + filename: "assets/Font/OpenSans-Regular.ttf", + size_pixels: 18, + font_cfg: null, + glyph_ranges: io.Fonts.GetGlyphRangesCyrillic() + ); + } + ); + app.Init(window, openGl, mainFont); + + inputContext.Keyboards[0] + .KeyDown += (keyboard, key, scancode) => { app.OnKeyDown(key); }; + inputContext.Keyboards[0] + .KeyUp += (keyboard, key, scancode) => { app.OnKeyPressed(key); }; + inputContext.Keyboards[0] + .KeyUp += (keyboard, key, scancode) => { app.OnKeyReleased(key); }; +}; + +// Handle resizes +window.FramebufferResize += s => +{ + // Adjust the viewport to the new window size + gl.Viewport(s); +}; + +// Handles the dile drop and receives the array of paths to the files. +window.FileDrop += paths => { }; + +window.Update += delta => +{ + // Make sure ImGui is up-to-date + controller.Update((float) delta); + + app.Update(delta); +}; + +// The render function +window.Render += delta => +{ + // This is where you'll do any rendering beneath the ImGui context + // Here, we just have a blank screen. + gl.ClearColor( + Color.FromArgb( + 255, + (int) (.45f * 255), + (int) (.55f * 255), + (int) (.60f * 255) + ) + ); + gl.Clear((uint) ClearBufferMask.ColorBufferBit); + + app.OnImGuiRender(); + + // Make sure ImGui renders too! + controller.Render(); +}; + +// The closing function +window.Closing += () => +{ + app.Exit(); + + ImGui.SaveIniSettingsToDisk("imgui.ini"); + // Dispose our controller first + controller?.Dispose(); + + // Dispose the input context + inputContext?.Dispose(); + + // Unload OpenGL + gl?.Dispose(); +}; + +// Now that everything's defined, let's run this bad boy! +window.Run(); \ No newline at end of file diff --git a/NResUI/Utils.cs b/NResUI/Utils.cs new file mode 100644 index 0000000..aff87cb --- /dev/null +++ b/NResUI/Utils.cs @@ -0,0 +1,64 @@ +using System.Reflection; + +namespace NResUI +{ + public static class Utils + { + public static bool IsDirectory(this FileSystemInfo info) + { + // get the file attributes for file or directory + FileAttributes attr = info.Attributes; + + //detect whether its a directory or file + if ((attr & FileAttributes.Directory) == FileAttributes.Directory) + return true; + else + return false; + } + + public static bool IsDirectoryPath(this string path) + { + return Directory.Exists(path); + } + + public static void ClearContent(this DirectoryInfo directoryInfo) + { + foreach (var directory in directoryInfo.EnumerateDirectories()) + { + directory.Delete(true); + } + + foreach (var file in directoryInfo.EnumerateFiles()) + { + file.Delete(); + } + } + + public static IEnumerable GetAssignableTypesFromAssembly(Assembly assembly) + { + return assembly.ExportedTypes + .Where(t => t.IsAssignableTo(typeof(T)) && t is {IsAbstract: false, IsInterface: false}); + } + + public static IList GetAssignableTypes() + { + var executingAssembly = Assembly.GetExecutingAssembly(); + var referencedAssemblyNames = executingAssembly.GetReferencedAssemblies(); + var types = referencedAssemblyNames.SelectMany( + name => + GetAssignableTypesFromAssembly(Assembly.Load(name)) + ) + .Concat( + GetAssignableTypesFromAssembly(executingAssembly) + ) + .ToList(); + + return types; + } + + public static bool IsNullOrEmpty(this string? str) + { + return string.IsNullOrEmpty(str); + } + } +} \ No newline at end of file diff --git a/NResUI/assets/Font/OpenSans-Regular.ttf b/NResUI/assets/Font/OpenSans-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3a29f26497950810af1f58a52625552a2fa07a4a GIT binary patch literal 129796 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 G#`%ArKbQCb literal 0 HcmV?d00001 diff --git a/ParkanPlayground.sln b/ParkanPlayground.sln index d0ae5da..73783f3 100644 --- a/ParkanPlayground.sln +++ b/ParkanPlayground.sln @@ -6,6 +6,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TextureDecoder", "TextureDe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NLUnpacker", "NLUnpacker\NLUnpacker.csproj", "{50C83E6C-23ED-4A8E-B948-89686A742CF0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NResUI", "NResUI\NResUI.csproj", "{7456A089-0701-416C-8668-1F740BF4B72C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NResLib", "NResLib\NResLib.csproj", "{9429AEAE-80A6-4EE7-AB66-9161CC4C3A3D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +28,13 @@ Global {50C83E6C-23ED-4A8E-B948-89686A742CF0}.Debug|Any CPU.Build.0 = Debug|Any CPU {50C83E6C-23ED-4A8E-B948-89686A742CF0}.Release|Any CPU.ActiveCfg = Release|Any CPU {50C83E6C-23ED-4A8E-B948-89686A742CF0}.Release|Any CPU.Build.0 = Release|Any CPU + {7456A089-0701-416C-8668-1F740BF4B72C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7456A089-0701-416C-8668-1F740BF4B72C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7456A089-0701-416C-8668-1F740BF4B72C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7456A089-0701-416C-8668-1F740BF4B72C}.Release|Any CPU.Build.0 = Release|Any CPU + {9429AEAE-80A6-4EE7-AB66-9161CC4C3A3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9429AEAE-80A6-4EE7-AB66-9161CC4C3A3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9429AEAE-80A6-4EE7-AB66-9161CC4C3A3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9429AEAE-80A6-4EE7-AB66-9161CC4C3A3D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/ParkanPlayground/ListMetadataItem.cs b/ParkanPlayground/ListMetadataItem.cs deleted file mode 100644 index 4f87002..0000000 --- a/ParkanPlayground/ListMetadataItem.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace ParkanPlayground; - -public record ListMetadataItem(string ItemType, int ItemLength, string FileName, int OffsetInFile); \ No newline at end of file diff --git a/ParkanPlayground/ParkanPlayground.csproj b/ParkanPlayground/ParkanPlayground.csproj index 2f4fc77..d8e0c53 100644 --- a/ParkanPlayground/ParkanPlayground.csproj +++ b/ParkanPlayground/ParkanPlayground.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/ParkanPlayground/Program.cs b/ParkanPlayground/Program.cs index 61bfb86..e7e12c8 100644 --- a/ParkanPlayground/Program.cs +++ b/ParkanPlayground/Program.cs @@ -1,105 +1,41 @@ using System.Buffers.Binary; -using System.Text;using ParkanPlayground; +using System.Text; +using NResLib; var libFile = "C:\\Program Files (x86)\\Nikita\\Iron Strategy\\ui\\ui_back.lib"; -using FileStream nResFs = new FileStream(libFile, FileMode.Open); +var parseResult = NResParser.ReadFile(libFile); -Span buffer = stackalloc byte[4]; - -nResFs.ReadExactly(buffer); - -var nResHeader = BinaryPrimitives.ReadInt32LittleEndian(buffer); - -var str = Encoding.ASCII.GetString(buffer); - -Console.WriteLine($"NRES Header: {nResHeader:X} - {str}"); - -// ---- -nResFs.ReadExactly(buffer); - -var version = BinaryPrimitives.ReadInt32LittleEndian(buffer); - -Console.WriteLine($"VERSION: {version:X}"); - -// ---- -nResFs.ReadExactly(buffer); - -var elementCount = BinaryPrimitives.ReadInt32LittleEndian(buffer); - -Console.WriteLine($"ElementCount: {elementCount}"); - -// ---- -nResFs.ReadExactly(buffer); - -var totalLength = BinaryPrimitives.ReadInt32LittleEndian(buffer); - -Console.WriteLine($"TOTAL_LENGTH: {totalLength}"); - -// ---- - -nResFs.Seek(-elementCount * 64, SeekOrigin.End); - -_ = 5; - -var elements = new List(elementCount); - -Span metaDataBuffer = stackalloc byte[64]; -for (int i = 0; i < elementCount; i++) +if (parseResult.Error != null) { - nResFs.ReadExactly(metaDataBuffer); - - var itemType = Encoding.ASCII.GetString(metaDataBuffer.Slice(0, 8)); - - var itemLength = BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer.Slice(12, 4)); - - var fileNameBlock = metaDataBuffer.Slice(20, 20); - var len = fileNameBlock.IndexOf((byte)'\0'); - if (len == -1) len = 20; // whole 20 bytes is a filename - var fileName = Encoding.ASCII.GetString(fileNameBlock.Slice(0, len)); - - var offsetInFile = BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer.Slice(56, 4)); - - var lastMagicNumber = BinaryPrimitives.ReadInt32LittleEndian(metaDataBuffer.Slice(60, 4)); - - Console.WriteLine( - $"File {i+1}: \n" + - $"\tType: {itemType}\n" + - $"\tItemLength: {itemLength}\n" + - $"\tFileName: {fileName}\n" + - $"\tOffsetInFile: {offsetInFile}\n" + - $"\tLastMagicNumber: {lastMagicNumber}" - ); - - elements.Add(new ListMetadataItem(itemType, itemLength, fileName, offsetInFile)); - - metaDataBuffer.Clear(); + Console.WriteLine(parseResult.Error); + return; } -var libFileName = new FileInfo(libFile).Name; - -if (Directory.Exists(libFileName)) -{ - Directory.Delete(libFileName, true); -} - -var dir = Directory.CreateDirectory(libFileName); - -byte[] copyBuffer = new byte[8192]; - -foreach (var element in elements) -{ - nResFs.Seek(element.OffsetInFile, SeekOrigin.Begin); - using var destFs = new FileStream(Path.Combine(libFileName, element.FileName), FileMode.CreateNew); - - var totalCopiedBytes = 0; - while (totalCopiedBytes < element.ItemLength) - { - var needReadBytes = Math.Min(element.ItemLength - totalCopiedBytes, copyBuffer.Length); - var readBytes = nResFs.Read(copyBuffer, 0, needReadBytes); - - destFs.Write(copyBuffer, 0, readBytes); - - totalCopiedBytes += readBytes; - } -} \ No newline at end of file +// var libFileName = new FileInfo(libFile).Name; +// +// if (Directory.Exists(libFileName)) +// { +// Directory.Delete(libFileName, true); +// } +// +// var dir = Directory.CreateDirectory(libFileName); +// +// byte[] copyBuffer = new byte[8192]; +// +// foreach (var element in elements) +// { +// nResFs.Seek(element.OffsetInFile, SeekOrigin.Begin); +// using var destFs = new FileStream(Path.Combine(libFileName, element.FileName), FileMode.CreateNew); +// +// var totalCopiedBytes = 0; +// while (totalCopiedBytes < element.ItemLength) +// { +// var needReadBytes = Math.Min(element.ItemLength - totalCopiedBytes, copyBuffer.Length); +// var readBytes = nResFs.Read(copyBuffer, 0, needReadBytes); +// +// destFs.Write(copyBuffer, 0, readBytes); +// +// totalCopiedBytes += readBytes; +// } +// } \ No newline at end of file