diff --git a/SharpPluginLoader.Core/IO/Key.cs b/SharpPluginLoader.Core/IO/Key.cs
index f491182..a235922 100644
--- a/SharpPluginLoader.Core/IO/Key.cs
+++ b/SharpPluginLoader.Core/IO/Key.cs
@@ -9,8 +9,10 @@ namespace SharpPluginLoader.Core.IO
///
/// The buttons on a keyboard.
///
- public enum Key
+ public enum Key : int
{
+ MaxNameLength = 12, // For parsing purposes.
+ // -------
Escape = 1,
D1 = 2,
D2 = 3,
diff --git a/SharpPluginLoader.Core/Rendering/Renderer.cs b/SharpPluginLoader.Core/Rendering/Renderer.cs
index 39c66fc..f77a915 100644
--- a/SharpPluginLoader.Core/Rendering/Renderer.cs
+++ b/SharpPluginLoader.Core/Rendering/Renderer.cs
@@ -199,21 +199,18 @@ internal static unsafe void ResolveCustomFonts()
}
[UnmanagedCallersOnly]
- internal static nint Initialize(Size viewportSize, Size windowSize, byte d3d12, nint menuKey)
+ internal static unsafe nint Initialize(Size viewportSize, Size windowSize, byte d3d12, LoaderGuiConfig* config)
{
IsDirectX12 = d3d12 != 0;
- if (menuKey != 0)
+ string keyStr = new string(config->MenuKey);
+ if (Enum.TryParse(keyStr, out var key))
{
- var keyStr = MemoryUtil.ReadString(menuKey);
- if (Enum.TryParse(keyStr, out var key))
- {
- _menuKey = key;
- }
- else
- {
- Log.Warn($"Invalid menu key: {keyStr}, falling back to {DefaultMenuKey}");
- }
+ _menuKey = key;
+ }
+ else
+ {
+ Log.Warn($"Invalid menu key: {keyStr}, falling back to {DefaultMenuKey}");
}
_viewportSize = new Vector2(viewportSize.Width, viewportSize.Height);
@@ -241,6 +238,13 @@ Initializing Renderer with
// Currently causes a freeze when dragging a window outside of the main window.
// Most likely the WndProc doesn't process events anymore which causes windows to think it's frozen.
// io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;
+ if (config->KeyboardNavigation)
+ {
+ io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard;
+ }
+
+ io.FontGlobalScale = config->FontScale;
+ _baseAlpha = config->WindowTransparency;
SetupImGuiStyle();
@@ -387,7 +391,7 @@ internal static unsafe nint ImGuiRender()
io.DisplaySize = _viewportSize;
if (_showMenu)
- ImGui.GetStyle().Alpha = anyFocused ? 1.0f : 0.5f;
+ ImGui.GetStyle().Alpha = anyFocused ? _baseAlpha : Math.Max(_baseAlpha - 0.5f, 0.25f);
ImGui.NewFrame();
if (_showMenu)
@@ -398,6 +402,13 @@ internal static unsafe nint ImGuiRender()
{
if (ImGui.BeginMenu("Options"))
{
+ ImGui.Checkbox("Draw Primitives as Wireframe",
+ ref MemoryUtil.AsRef(_renderingOptionPointers.DrawPrimitivesAsWireframe));
+
+ ImGui.SliderFloat("Line Thickness",
+ ref MemoryUtil.AsRef(_renderingOptionPointers.LineThickness),
+ 1.0f, 10.0f);
+
bool keyboardNav = (io.ConfigFlags & ImGuiConfigFlags.NavEnableKeyboard) != 0;
if (ImGui.Checkbox("Keyboard Navigation", ref keyboardNav))
{
@@ -411,14 +422,16 @@ internal static unsafe nint ImGuiRender()
}
}
- ImGui.Checkbox("Draw Primitives as Wireframe",
- ref MemoryUtil.AsRef(_renderingOptionPointers.DrawPrimitivesAsWireframe));
-
- ImGui.SliderFloat("Line Thickness",
- ref MemoryUtil.AsRef(_renderingOptionPointers.LineThickness),
- 1.0f, 10.0f);
+ ImGui.SliderFloat("Font Scale",
+ ref io.FontGlobalScale,
+ 0.5f, 2.0f, null, ImGuiSliderFlags.NoRoundToFormat);
- ImGui.SliderFloat("Font Scale", ref io.FontGlobalScale, 0.5f, 2.0f);
+ if (ImGui.SliderFloat("Window Transparency",
+ ref _baseAlpha,
+ 0.25f, 1.0f, null, ImGuiSliderFlags.NoRoundToFormat))
+ {
+ ImGui.GetStyle().DisabledAlpha = _baseAlpha;
+ }
ImGui.EndMenu();
}
@@ -485,8 +498,8 @@ private static void SetupImGuiStyle()
{
var style = ImGui.GetStyle();
- style.Alpha = 1.0f;
- style.DisabledAlpha = 1.0f;
+ style.Alpha = _baseAlpha;
+ style.DisabledAlpha = _baseAlpha;
style.WindowPadding = new Vector2(12.0f, 12.0f);
style.WindowRounding = 2.0f;
style.WindowBorderSize = 1.0f;
@@ -607,6 +620,7 @@ private static nint GetCursorPositionHook(nint app, out Point pos)
private static Vector2 _windowSize;
private static Vector2 _mousePos;
private static Vector2 _mousePosScalingFactor;
+ private static float _baseAlpha = 1.0f;
private static bool _fontsSubmitted = false;
private static NativeArray CustomFonts;
@@ -646,4 +660,13 @@ internal unsafe struct CustomFontNative
public ushort* GlyphRanges;
public ImFont* Font;
}
+
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct LoaderGuiConfig
+ {
+ public fixed sbyte MenuKey[(int)Key.MaxNameLength + 1];
+ public bool KeyboardNavigation;
+ public float FontScale;
+ public float WindowTransparency;
+ }
}
diff --git a/mhw-cs-plugin-loader/Config.h b/mhw-cs-plugin-loader/Config.h
index 897f4fb..d63254b 100644
--- a/mhw-cs-plugin-loader/Config.h
+++ b/mhw-cs-plugin-loader/Config.h
@@ -95,4 +95,4 @@ static constexpr const char* SPL_DEFAULT_CHUNK_PATH = "nativePC/plugins/CSharp/L
// The path of the address repository cache file
static constexpr const char* SPL_ADDRESS_REPOSITORY_CACHE_PATH = "nativePC/plugins/CSharp/Loader/NativeAddressCache.json";
-}
\ No newline at end of file
+}
diff --git a/mhw-cs-plugin-loader/D3DModule.cpp b/mhw-cs-plugin-loader/D3DModule.cpp
index 4f78de1..8c96465 100644
--- a/mhw-cs-plugin-loader/D3DModule.cpp
+++ b/mhw-cs-plugin-loader/D3DModule.cpp
@@ -44,7 +44,7 @@ void D3DModule::initialize(CoreClr* coreclr) {
L"SharpPluginLoader.Core.Rendering.Renderer",
L"ImGuiRender"
);
- m_core_initialize_imgui = coreclr->get_method(
+ m_core_initialize_imgui = coreclr->get_method(
config::SPL_CORE_ASSEMBLY_NAME,
L"SharpPluginLoader.Core.Rendering.Renderer",
L"Initialize"
@@ -493,7 +493,7 @@ void D3DModule::d3d12_initialize_imgui(IDXGISwapChain* swap_chain) {
};
const auto& config = preloader::LoaderConfig::get();
- const auto context = m_core_initialize_imgui(viewport_size, window_size, true, config.get_menu_key().c_str());
+ const auto context = m_core_initialize_imgui(viewport_size, window_size, true, config.get_gui_config());
igSetCurrentContext(context);
@@ -626,7 +626,7 @@ void D3DModule::d3d11_initialize_imgui(IDXGISwapChain* swap_chain) {
};
const auto& config = preloader::LoaderConfig::get();
- const auto context = m_core_initialize_imgui(viewport_size, window_size, false, config.get_menu_key().c_str());
+ const auto context = m_core_initialize_imgui(viewport_size, window_size, false, config.get_gui_config());
igSetCurrentContext(context);
imgui_load_fonts();
diff --git a/mhw-cs-plugin-loader/D3DModule.h b/mhw-cs-plugin-loader/D3DModule.h
index 5e89755..1fdc41d 100644
--- a/mhw-cs-plugin-loader/D3DModule.h
+++ b/mhw-cs-plugin-loader/D3DModule.h
@@ -2,6 +2,7 @@
#include "NativeModule.h"
#include "TextureManager.h"
#include "PrimitiveRenderingModule.h"
+#include "LoaderConfig.h"
#include
#include
@@ -121,7 +122,7 @@ class D3DModule final : public NativeModule {
HWND m_temp_window = nullptr;
WNDCLASSEX* m_temp_window_class = nullptr;
- ImGuiContext*(*m_core_initialize_imgui)(MtSize viewport_size, MtSize window_size, bool d3d12, const char* menu_key) = nullptr;
+ ImGuiContext*(*m_core_initialize_imgui)(MtSize viewport_size, MtSize window_size, bool d3d12, const preloader::LoaderGuiConfig* config) = nullptr;
ImDrawData*(*m_core_imgui_render)() = nullptr;
void(*m_core_render)() = nullptr;
int(*m_core_get_custom_fonts)(CustomFont** out_fonts) = nullptr;
diff --git a/mhw-cs-plugin-loader/LoaderConfig.cpp b/mhw-cs-plugin-loader/LoaderConfig.cpp
index a1ff4c9..97c4883 100644
--- a/mhw-cs-plugin-loader/LoaderConfig.cpp
+++ b/mhw-cs-plugin-loader/LoaderConfig.cpp
@@ -10,16 +10,20 @@ namespace preloader
using json = nlohmann::ordered_json;
void to_json(json& j, const ConfigFile& c) {
- j = json{
+ j = json {
{"logfile", c.LogFile},
{"logcmd", c.LogCmd},
{"logLevel", c.LogLevel},
{"outputEveryPath", c.OutputEveryPath},
{"enablePluginLoader", c.EnablePluginLoader},
{"SPL", {
+ {"PreloadDlls", c.PreloadDlls},
{"ImGuiRenderingEnabled", c.ImGuiRenderingEnabled},
{"PrimitiveRenderingEnabled", c.PrimitiveRenderingEnabled},
- {"MenuKey", c.MenuKey},
+ {"MenuKey", c.Gui.MenuKey},
+ {"KeyboardNavigation", c.Gui.KeyboardNavigation},
+ {"FontScale", c.Gui.FontScale},
+ {"WindowTransparency", c.Gui.WindowTransparency},
}}
};
}
@@ -30,49 +34,39 @@ namespace preloader
j.at("logLevel").get_to(c.LogLevel);
j.at("outputEveryPath").get_to(c.OutputEveryPath);
j.at("enablePluginLoader").get_to(c.EnablePluginLoader);
-
if (j.contains("SPL")) {
const json& spl = j.at("SPL");
- spl.at("ImGuiRenderingEnabled").get_to(c.ImGuiRenderingEnabled);
- spl.at("PrimitiveRenderingEnabled").get_to(c.PrimitiveRenderingEnabled);
- c.MenuKey = spl.value("MenuKey", "F9");
- }
- else {
- c.ImGuiRenderingEnabled = true;
- c.PrimitiveRenderingEnabled = true;
+ if (spl.contains("PreloadDlls"))
+ {
+ spl.at("PreloadDlls").get_to(c.PreloadDlls);
+ }
+ c.ImGuiRenderingEnabled = spl.value("ImGuiRenderingEnabled", true);
+ c.PrimitiveRenderingEnabled = spl.value("PrimitiveRenderingEnabled", true);
+ std::string keyStr = spl.value("MenuKey", "F9");
+ if (keyStr.length() <= sizeof(c.Gui.MenuKey) - 1) {
+ std::memcpy(c.Gui.MenuKey, keyStr.c_str(), keyStr.length() + 1);
+ }
+ c.Gui.KeyboardNavigation = spl.value("KeyboardNavigation", false);
+ c.Gui.FontScale = spl.value("FontScale", 1.0f);
+ c.Gui.WindowTransparency = spl.value("WindowTransparency", 1.0f);
}
}
- LoaderConfig& LoaderConfig::get()
- {
+ LoaderConfig& LoaderConfig::get() {
static LoaderConfig instance;
return instance;
}
- LoaderConfig::LoaderConfig()
- {
- // Attempt to load file from disk
- if (std::filesystem::exists(config::SPL_LOADER_CONFIG_FILE))
- {
+ LoaderConfig::LoaderConfig() {
+ // Attempt to load file from disk.
+ if (std::filesystem::exists(config::SPL_LOADER_CONFIG_FILE)) {
std::ifstream file(config::SPL_LOADER_CONFIG_FILE);
json data = json::parse(file);
this->config = data.get();
file.close();
}
- else
- {
- // No existing config, create a default and save to disk.
- this->config = ConfigFile
- {
- .LogFile = true,
- .LogCmd = true,
- .LogLevel = "INFO",
- .OutputEveryPath = false,
- .EnablePluginLoader = true,
- };
- }
- // Make sure any new options are added to the config file
+ // Make sure any new options are added to the config file.
std::ofstream outfile(config::SPL_LOADER_CONFIG_FILE);
if (outfile.is_open()) {
json data = this->config;
@@ -80,4 +74,4 @@ namespace preloader
outfile.close();
}
}
-} // namespace preloader
\ No newline at end of file
+} // namespace preloader
diff --git a/mhw-cs-plugin-loader/LoaderConfig.h b/mhw-cs-plugin-loader/LoaderConfig.h
index b020475..49015fc 100644
--- a/mhw-cs-plugin-loader/LoaderConfig.h
+++ b/mhw-cs-plugin-loader/LoaderConfig.h
@@ -3,16 +3,24 @@
namespace preloader
{
+ struct LoaderGuiConfig {
+ char MenuKey[13] = { "F9" };
+ bool KeyboardNavigation = false;
+ float FontScale = 1.0f;
+ float WindowTransparency = 1.0f;
+ };
+
struct ConfigFile {
- bool LogFile = true;
- bool LogCmd = false;
- std::string LogLevel = "ERROR";
+ bool LogFile = false;
+ bool LogCmd = true;
+ std::string LogLevel = "INFO";
bool OutputEveryPath = false;
bool EnablePluginLoader = true;
struct {
+ std::vector PreloadDlls = { "dinput8.dll", "dxgi.dll" };
bool ImGuiRenderingEnabled = true;
bool PrimitiveRenderingEnabled = true;
- std::string MenuKey = "F9";
+ LoaderGuiConfig Gui;
};
};
void to_json(nlohmann::json& j, const ConfigFile& c);
@@ -35,9 +43,10 @@ namespace preloader
inline bool get_log_cmd() const { return this->config.LogCmd; }
inline std::string get_log_level() const { return this->config.LogLevel; }
inline bool get_output_every_path() const { return this->config.OutputEveryPath; }
+ inline std::vector& get_preload_dlls() { return this->config.PreloadDlls; }
inline bool get_enable_plugin_loader() const { return this->config.EnablePluginLoader; }
inline bool get_imgui_rendering_enabled() const { return this->config.ImGuiRenderingEnabled; }
inline bool get_primitive_rendering_enabled() const { return this->config.PrimitiveRenderingEnabled; }
- inline std::string get_menu_key() const { return this->config.MenuKey; }
+ inline const LoaderGuiConfig* get_gui_config() const { return &this->config.Gui; }
};
-} // namespace preloader
\ No newline at end of file
+} // namespace preloader
diff --git a/mhw-cs-plugin-loader/NativePluginFramework.cpp b/mhw-cs-plugin-loader/NativePluginFramework.cpp
index 066a078..df7e8f6 100644
--- a/mhw-cs-plugin-loader/NativePluginFramework.cpp
+++ b/mhw-cs-plugin-loader/NativePluginFramework.cpp
@@ -46,13 +46,13 @@ void NativePluginFramework::trigger_on_mh_main_ctor() {
m_managed_functions.TriggerOnMhMainCtor();
}
-void NativePluginFramework::run_compatibility_checks() {
- // We intentionally force Stracker's Loader to be loaded early so any (native) plugins that
- // rely on injecting code via relative calls will be able to find available memory for their hooks.
- constexpr auto DINPUT8_PATH = "dinput8.dll";
-
- if (std::filesystem::exists(DINPUT8_PATH)) {
- (void)LoadLibraryA(DINPUT8_PATH);
+// We intentionally force Stracker's Loader to be loaded early so any (native) plugins that
+// rely on injecting code via relative calls will be able to find available memory for their hooks.
+void NativePluginFramework::preload_dlls(std::vector& dlls) {
+ for (const auto& dll : dlls) {
+ if (std::filesystem::exists(dll)) {
+ (void)LoadLibraryA(dll.c_str());
+ }
}
}
diff --git a/mhw-cs-plugin-loader/NativePluginFramework.h b/mhw-cs-plugin-loader/NativePluginFramework.h
index 4b12762..5152b61 100644
--- a/mhw-cs-plugin-loader/NativePluginFramework.h
+++ b/mhw-cs-plugin-loader/NativePluginFramework.h
@@ -33,7 +33,7 @@ class NativePluginFramework {
void trigger_on_win_main();
void trigger_on_mh_main_ctor();
- static void run_compatibility_checks();
+ static void preload_dlls(std::vector& dlls);
static uintptr_t get_repository_address(const char* name);
static const char* get_game_revision();
diff --git a/mhw-cs-plugin-loader/Preloader.cpp b/mhw-cs-plugin-loader/Preloader.cpp
index c53e474..86d68b0 100644
--- a/mhw-cs-plugin-loader/Preloader.cpp
+++ b/mhw-cs-plugin-loader/Preloader.cpp
@@ -163,7 +163,8 @@ void hooked_get_system_time_as_file_time(LPFILETIME lpSystemTimeAsFileTime) {
}
dlog::debug("[Preloader] Resolved address for sMhMain::ctor: 0x{:X}", mhmain_ctor_address);
- NativePluginFramework::run_compatibility_checks();
+ auto& loader_config = preloader::LoaderConfig::get();
+ NativePluginFramework::preload_dlls(loader_config.get_preload_dlls());
// Hook the functions.
g_scrt_common_main_hook = safetyhook::create_inline(
diff --git a/mhw-cs-plugin-loader/dllmain.cpp b/mhw-cs-plugin-loader/dllmain.cpp
index 55aabd9..c291863 100644
--- a/mhw-cs-plugin-loader/dllmain.cpp
+++ b/mhw-cs-plugin-loader/dllmain.cpp
@@ -11,8 +11,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
// Only load the the mod loader DLL if winmm.dll/ucrtbase.dll has been loaded into the correct process.
if (wil::GetModuleFileNameW().contains(L"MonsterHunterWorld.exe")) {
auto& loader_config = preloader::LoaderConfig::get();
- if (loader_config.get_enable_plugin_loader())
- {
+ if (loader_config.get_enable_plugin_loader()) {
initialize_preloader();
}
}