From e3565d5bcbc6dab92df6926a7a9d03fb3e450b68 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 11 Mar 2024 21:09:45 +0100 Subject: [PATCH] feat: Added support for creating views and drawing ImGui elemts from C# --- .../dotnet/AssemblyLoader/Program.cs | 11 ++- plugins/script_loader/dotnet/CMakeLists.txt | 2 +- .../source/script_api/v1/mem.cpp | 1 + .../script_loader/source/script_api/v1/ui.cpp | 39 ++++++++++ .../CSharp/ImHexLibrary/Bookmarks.cs | 8 +-- .../templates/CSharp/ImHexLibrary/Memory.cs | 25 +++---- .../templates/CSharp/ImHexLibrary/UI.cs | 71 ++++++++++++++----- .../CSharp/ImHexScript/ImHexScript.csproj | 8 +-- 8 files changed, 122 insertions(+), 43 deletions(-) diff --git a/plugins/script_loader/dotnet/AssemblyLoader/Program.cs b/plugins/script_loader/dotnet/AssemblyLoader/Program.cs index a317b0e6f..b69550b71 100644 --- a/plugins/script_loader/dotnet/AssemblyLoader/Program.cs +++ b/plugins/script_loader/dotnet/AssemblyLoader/Program.cs @@ -64,8 +64,15 @@ namespace ImHex { continue; } - - context.LoadFromStream(new MemoryStream(File.ReadAllBytes(file))); + + try + { + context.LoadFromStream(new MemoryStream(File.ReadAllBytes(file))); + } + catch (Exception e) + { + Console.WriteLine("[.NET Script] Failed to load assembly: " + file + " - " + e.ToString()); + } } // Load the script assembly diff --git a/plugins/script_loader/dotnet/CMakeLists.txt b/plugins/script_loader/dotnet/CMakeLists.txt index 846bd0b38..47505a747 100644 --- a/plugins/script_loader/dotnet/CMakeLists.txt +++ b/plugins/script_loader/dotnet/CMakeLists.txt @@ -7,7 +7,7 @@ function(add_dotnet_assembly name) file(GLOB_RECURSE sources ${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cs) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../../${name}.dll - COMMAND ${DOTNET_EXECUTABLE} build ${CMAKE_CURRENT_SOURCE_DIR}/${name}/${name}.csproj --nologo -c Release -o ${CMAKE_CURRENT_BINARY_DIR}/../.. && ${CMAKE_COMMAND} -DOUTPUT_RUNTIMECONFIG="\"${OUTPUT_RUNTIMECONFIG}\"" -P ${CMAKE_CURRENT_SOURCE_DIR}/post_process_runtimeconfig.cmake + COMMAND ${DOTNET_EXECUTABLE} build ${CMAKE_CURRENT_SOURCE_DIR}/${name}/${name}.csproj -nologo -consoleLoggerParameters:NoSummary -verbosity:quiet -c Release -o ${CMAKE_CURRENT_BINARY_DIR}/../.. && ${CMAKE_COMMAND} -DOUTPUT_RUNTIMECONFIG="\"${OUTPUT_RUNTIMECONFIG}\"" -P ${CMAKE_CURRENT_SOURCE_DIR}/post_process_runtimeconfig.cmake DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}/${name}.csproj ${sources} COMMENT "Building ${name}.dll" ) diff --git a/plugins/script_loader/source/script_api/v1/mem.cpp b/plugins/script_loader/source/script_api/v1/mem.cpp index b7d1aa414..482c87e67 100644 --- a/plugins/script_loader/source/script_api/v1/mem.cpp +++ b/plugins/script_loader/source/script_api/v1/mem.cpp @@ -94,6 +94,7 @@ private: SCRIPT_API(void registerProvider, const char *typeName, const char *name, ScriptDataProvider::ReadFunction readFunc, ScriptDataProvider::WriteFunction writeFunc, ScriptDataProvider::GetSizeFunction getSizeFunc) { auto typeNameString = std::string(typeName); auto nameString = std::string(name); + hex::ContentRegistry::Provider::impl::add(typeNameString, [typeNameString, nameString, readFunc, writeFunc, getSizeFunc] -> std::unique_ptr { auto provider = std::make_unique(); provider->setTypeName(typeNameString); diff --git a/plugins/script_loader/source/script_api/v1/ui.cpp b/plugins/script_loader/source/script_api/v1/ui.cpp index 5cbfad20e..bc72ba09f 100644 --- a/plugins/script_loader/source/script_api/v1/ui.cpp +++ b/plugins/script_loader/source/script_api/v1/ui.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -7,8 +8,10 @@ #include #include +#include #include +#include using namespace hex; @@ -140,4 +143,40 @@ SCRIPT_API(void showYesNoQuestionBox, const char *title, const char *message, bo *result = s_yesNoQuestionBoxResult.value(); s_yesNoQuestionBoxResult.reset(); +} + +SCRIPT_API(void showToast, const char *message, u32 type) { + switch (type) { + case 0: + ui::ToastInfo::open(message); + break; + case 1: + ui::ToastWarning::open(message); + break; + case 2: + ui::ToastError::open(message); + break; + default: + break; + } +} + +SCRIPT_API(void* getImGuiContext) { + return ImGui::GetCurrentContext(); +} + +class ScriptView : public View::Window { +public: + using DrawFunction = void(*)(); + ScriptView(const char *icon, const char *name, DrawFunction function) : View::Window(UnlocalizedString(name), icon), m_drawFunction(function) { } + void drawContent() override { + m_drawFunction(); + } + +private: + DrawFunction m_drawFunction; +}; + +SCRIPT_API(void registerView, const char *icon, const char *name, void *drawFunction) { + ContentRegistry::Views::add(icon, name, ScriptView::DrawFunction(drawFunction)); } \ No newline at end of file diff --git a/plugins/script_loader/templates/CSharp/ImHexLibrary/Bookmarks.cs b/plugins/script_loader/templates/CSharp/ImHexLibrary/Bookmarks.cs index e936d1758..f857d1a9b 100644 --- a/plugins/script_loader/templates/CSharp/ImHexLibrary/Bookmarks.cs +++ b/plugins/script_loader/templates/CSharp/ImHexLibrary/Bookmarks.cs @@ -2,20 +2,18 @@ using System.Drawing; using System.Runtime.InteropServices; +using System.Text; namespace ImHex { public class Bookmarks { [DllImport(Library.Name)] - private static extern void createBookmarkV1(UInt64 address, UInt64 size, UInt32 color, [MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string description); + private static extern void createBookmarkV1(UInt64 address, UInt64 size, UInt32 color, byte[] name, byte[] description); public static void CreateBookmark(long address, long size, Color color, string name = "", string description = "") { - unsafe - { - createBookmarkV1((UInt64)address, (UInt64)size, (UInt32)(0xA0 << 24 | color.B << 16 | color.G << 8 | color.R), name, description); - } + createBookmarkV1((UInt64)address, (UInt64)size, (UInt32)(0xA0 << 24 | color.B << 16 | color.G << 8 | color.R), Encoding.UTF8.GetBytes(name), Encoding.UTF8.GetBytes(description)); } } diff --git a/plugins/script_loader/templates/CSharp/ImHexLibrary/Memory.cs b/plugins/script_loader/templates/CSharp/ImHexLibrary/Memory.cs index d0460e4bd..6cc49d09d 100644 --- a/plugins/script_loader/templates/CSharp/ImHexLibrary/Memory.cs +++ b/plugins/script_loader/templates/CSharp/ImHexLibrary/Memory.cs @@ -2,6 +2,7 @@ using System.Drawing; using System.Runtime.InteropServices; +using System.Text; namespace ImHex { @@ -36,7 +37,7 @@ namespace ImHex public class Memory { private static List _registeredProviders = new(); - private static List _registeredProviderDelegates = new(); + private static List _registeredDelegates = new(); private delegate void DataAccessDelegate(UInt64 address, IntPtr buffer, UInt64 size); private delegate UInt64 GetSizeDelegate(); @@ -51,7 +52,7 @@ namespace ImHex private static extern bool getSelectionV1(IntPtr start, IntPtr end); [DllImport(Library.Name)] - private static extern int registerProviderV1([MarshalAs(UnmanagedType.LPStr)] string typeName, [MarshalAs(UnmanagedType.LPStr)] string name, IntPtr readFunction, IntPtr writeFunction, IntPtr getSizeFunction); + private static extern void registerProviderV1(byte[] typeName, byte[] name, IntPtr readFunction, IntPtr writeFunction, IntPtr getSizeFunction); public static byte[] Read(ulong address, ulong size) @@ -95,22 +96,22 @@ namespace ImHex } } - public static int RegisterProvider() where T : IProvider, new() + public static void RegisterProvider() where T : IProvider, new() { _registeredProviders.Add(new T()); ref var provider = ref CollectionsMarshal.AsSpan(_registeredProviders)[^1]; - _registeredProviderDelegates.Add(new DataAccessDelegate(provider.readRaw)); - _registeredProviderDelegates.Add(new DataAccessDelegate(provider.writeRaw)); - _registeredProviderDelegates.Add(new GetSizeDelegate(provider.getSize)); + _registeredDelegates.Add(new DataAccessDelegate(provider.readRaw)); + _registeredDelegates.Add(new DataAccessDelegate(provider.writeRaw)); + _registeredDelegates.Add(new GetSizeDelegate(provider.getSize)); - return registerProviderV1( - _registeredProviders[^1].getTypeName(), - _registeredProviders[^1].getName(), - Marshal.GetFunctionPointerForDelegate(_registeredProviderDelegates[^3]), - Marshal.GetFunctionPointerForDelegate(_registeredProviderDelegates[^2]), - Marshal.GetFunctionPointerForDelegate(_registeredProviderDelegates[^1]) + registerProviderV1( + Encoding.UTF8.GetBytes(provider.getTypeName()), + Encoding.UTF8.GetBytes(provider.getName()), + Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^3]), + Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^2]), + Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^1]) ); } diff --git a/plugins/script_loader/templates/CSharp/ImHexLibrary/UI.cs b/plugins/script_loader/templates/CSharp/ImHexLibrary/UI.cs index 3bf5ac887..60aa907d6 100644 --- a/plugins/script_loader/templates/CSharp/ImHexLibrary/UI.cs +++ b/plugins/script_loader/templates/CSharp/ImHexLibrary/UI.cs @@ -1,6 +1,5 @@ #pragma warning disable SYSLIB1054 -using System.Drawing; using System.Runtime.InteropServices; using System.Text; @@ -8,21 +7,31 @@ namespace ImHex { public class UI { - [DllImport(Library.Name)] - private static extern void showMessageBoxV1([MarshalAs(UnmanagedType.LPStr)] string message); + private delegate void DrawContentDelegate(); + + private static List _registeredDelegates = new(); [DllImport(Library.Name)] - private static extern void showInputTextBoxV1([MarshalAs(UnmanagedType.LPStr)] string title, [MarshalAs(UnmanagedType.LPStr)] string message, StringBuilder buffer, int bufferSize); + private static extern void showMessageBoxV1(byte[] message); [DllImport(Library.Name)] - private static extern unsafe void showYesNoQuestionBoxV1([MarshalAs(UnmanagedType.LPStr)] string title, [MarshalAs(UnmanagedType.LPStr)] string message, bool* result); + private static extern void showInputTextBoxV1(byte[] title, byte[] message, StringBuilder buffer, int bufferSize); + + [DllImport(Library.Name)] + private static extern unsafe void showYesNoQuestionBoxV1(byte[] title, byte[] message, bool* result); + + [DllImport(Library.Name)] + private static extern void showToastV1(byte[] message, UInt32 type); + + [DllImport(Library.Name)] + private static extern IntPtr getImGuiContextV1(); + + [DllImport(Library.Name)] + private static extern void registerViewV1(byte[] icon, byte[] name, IntPtr drawFunction); public static void ShowMessageBox(string message) { - unsafe - { - showMessageBoxV1(message); - } + showMessageBoxV1(Encoding.UTF8.GetBytes(message)); } public static bool ShowYesNoQuestionBox(string title, string message) @@ -30,23 +39,47 @@ namespace ImHex unsafe { bool result = false; - showYesNoQuestionBoxV1(title, message, &result); + showYesNoQuestionBoxV1(Encoding.UTF8.GetBytes(title), Encoding.UTF8.GetBytes(message), &result); return result; } } public static string? ShowInputTextBox(string title, string message, int maxSize) { - unsafe - { - StringBuilder buffer = new(maxSize); - showInputTextBoxV1(title, message, buffer, buffer.Capacity); + StringBuilder buffer = new(maxSize); + showInputTextBoxV1(Encoding.UTF8.GetBytes(title), Encoding.UTF8.GetBytes(message), buffer, buffer.Capacity); - if (buffer.Length == 0 || buffer[0] == '\x00') - return null; - else - return buffer.ToString(); - } + if (buffer.Length == 0 || buffer[0] == '\x00') + return null; + else + return buffer.ToString(); + } + + public enum ToastType + { + Info = 0, + Warning = 1, + Error = 2 + } + + public static void ShowToast(string message, ToastType type = ToastType.Info) + { + showToastV1(Encoding.UTF8.GetBytes(message), (UInt32)type); + } + + public static IntPtr GetImGuiContext() + { + return getImGuiContextV1(); + } + + public static void RegisterView(byte[] icon, string name, Action function) + { + _registeredDelegates.Add(new DrawContentDelegate(function)); + registerViewV1( + icon, + Encoding.UTF8.GetBytes(name), + Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^1]) + ); } } diff --git a/plugins/script_loader/templates/CSharp/ImHexScript/ImHexScript.csproj b/plugins/script_loader/templates/CSharp/ImHexScript/ImHexScript.csproj index 7bdc2e6b2..7818bbf8b 100644 --- a/plugins/script_loader/templates/CSharp/ImHexScript/ImHexScript.csproj +++ b/plugins/script_loader/templates/CSharp/ImHexScript/ImHexScript.csproj @@ -14,12 +14,12 @@ true - - - - + + + +