diff --git a/Dependencies/GWCA b/Dependencies/GWCA
index 9588909a3..6b5d1010c 160000
--- a/Dependencies/GWCA
+++ b/Dependencies/GWCA
@@ -1 +1 @@
-Subproject commit 9588909a3f75fe2b165e7c09d1d1690b1131eaef
+Subproject commit 6b5d1010cf0bea7e95ffadf6fd6041cf6ba9b868
diff --git a/Dependencies/imgui b/Dependencies/imgui
index e916310b2..78b28d545 160000
--- a/Dependencies/imgui
+++ b/Dependencies/imgui
@@ -1 +1 @@
-Subproject commit e916310b2e1f9cacbb2b9ce192a3dfb359e4b509
+Subproject commit 78b28d545f79c5c5ed3e0ebae4099e44bdc6c5a6
diff --git a/GWToolbox/GWToolbox.vcxproj b/GWToolbox/GWToolbox.vcxproj
index f4e8048b1..ebe185863 100644
--- a/GWToolbox/GWToolbox.vcxproj
+++ b/GWToolbox/GWToolbox.vcxproj
@@ -56,7 +56,7 @@
Level3
Disabled
- WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;_USRDLL;API_EXPORTS;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;IMGUI_USE_BGRA_PACKED_COLOR;%(PreprocessorDefinitions)
+ ENABLE_BORDERLESS;WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_WINDOWS;_USRDLL;API_EXPORTS;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;IMGUI_USE_BGRA_PACKED_COLOR;%(PreprocessorDefinitions)
true
GWCA\Utilities\Export.h
false
@@ -81,7 +81,7 @@
Full
true
true
- WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;_USRDLL;API_EXPORTS;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;IMGUI_USE_BGRA_PACKED_COLOR;%(PreprocessorDefinitions)
+ ENABLE_BORDERLESS;WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_WINDOWS;_USRDLL;API_EXPORTS;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;IMGUI_USE_BGRA_PACKED_COLOR;%(PreprocessorDefinitions)
true
Speed
diff --git a/GWToolbox/GWToolbox/GWToolbox.cpp b/GWToolbox/GWToolbox/GWToolbox.cpp
index c8aaa1b50..81e048ec7 100644
--- a/GWToolbox/GWToolbox/GWToolbox.cpp
+++ b/GWToolbox/GWToolbox/GWToolbox.cpp
@@ -1,462 +1,503 @@
-#include "GWToolbox.h"
-
-#include "Defines.h"
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "logger.h"
-#include "CursorFix.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#ifdef ENABLE_LUA
-# include
-#endif
-#include
-
-#include
-
-#include "GuiUtils.h"
-
-namespace {
- HMODULE dllmodule = 0;
-
- long OldWndProc = 0;
- bool tb_initialized = false;
- bool tb_destroyed = false;
-
- bool drawing_world = 0;
- int drawing_passes = 0;
- int last_drawing_passes = 0;
-}
-
-HMODULE GWToolbox::GetDLLModule() {
- return dllmodule;
-}
-
-DWORD __stdcall SafeThreadEntry(LPVOID module) {
- dllmodule = (HMODULE)module;
- __try {
- return ThreadEntry(nullptr);
- } __except ( EXCEPT_EXPRESSION_ENTRY ) {
- Log::Log("SafeThreadEntry __except body\n");
- return EXIT_SUCCESS;
- }
-}
-
-DWORD __stdcall ThreadEntry(LPVOID) {
- Log::Log("Initializing API\n");
-
- GW::HookBase::Initialize();
- if (!GW::Initialize()){
- MessageBoxA(0, "Initialize Failed at finding all addresses, contact Developers about this.", "GWToolbox++ API Error", 0);
- FreeLibraryAndExitThread(dllmodule, EXIT_SUCCESS);
- return EXIT_SUCCESS;
- }
-
- Log::Log("Installing Cursor Fix\n");
-
- InstallCursorFix();
-
- Log::Log("Installing dx hooks\n");
- GW::Render::SetRenderCallback([](IDirect3DDevice9* device) {
- GWToolbox::Instance().Draw(device);
- });
- GW::Render::SetResetCallback([](IDirect3DDevice9* device) {
- ImGui_ImplDX9_InvalidateDeviceObjects();
- });
-
- Log::Log("Installed dx hooks\n");
-
- Log::InitializeChat();
-
- Log::Log("Installed chat hooks\n");
-
- GW::HookBase::EnableHooks();
-
- Log::Log("Hooks Enabled!\n");
-
- while (!tb_destroyed) { // wait until destruction
- Sleep(100);
-
-#ifdef _DEBUG
- if (GetAsyncKeyState(VK_END) & 1) {
- GWToolbox::Instance().StartSelfDestruct();
- break;
- }
-#endif
- }
-
- Sleep(100);
- Log::Log("Removing Cursor Fix\n");
- UninstallCursorFix();
- Sleep(100);
- Log::Log("Closing log/console, bye!\n");
- Log::Terminate();
- Sleep(100);
-
- GW::HookBase::Deinitialize(); // At this point every hook should be disable, so we only need to free the memory
- FreeLibraryAndExitThread(dllmodule, EXIT_SUCCESS);
-}
-
-LRESULT CALLBACK SafeWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {
- __try {
- return WndProc(hWnd, Message, wParam, lParam);
- } __except (EXCEPTION_EXECUTE_HANDLER) {
- return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
- }
-}
-
-LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {
- static bool right_mouse_down = false;
-
- if (!tb_initialized || tb_destroyed) {
- return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
- }
-
- if (Message == WM_QUIT || Message == WM_CLOSE) {
- GWToolbox::Instance().SaveSettings();
- return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
- }
-
- if (Message == WM_RBUTTONDOWN) right_mouse_down = true;
- if (Message == WM_RBUTTONDBLCLK) right_mouse_down = true;
- if (Message == WM_RBUTTONUP) right_mouse_down = false;
-
- GWToolbox::Instance().right_mouse_down = right_mouse_down;
-
- // === Send events to ImGui ===
- ImGuiIO& io = ImGui::GetIO();
-
- switch (Message) {
- case WM_LBUTTONDOWN:
- case WM_LBUTTONDBLCLK:
- if (!right_mouse_down) io.MouseDown[0] = true;
- break;
- case WM_LBUTTONUP:
- io.MouseDown[0] = false;
- break;
- case WM_MBUTTONDOWN:
- case WM_MBUTTONDBLCLK:
- if (!right_mouse_down) {
- io.KeysDown[VK_MBUTTON] = true;
- io.MouseDown[2] = true;
- }
- break;
- case WM_MBUTTONUP:
- io.KeysDown[VK_MBUTTON] = false;
- io.MouseDown[2] = false;
- break;
- case WM_MOUSEWHEEL:
- if (!right_mouse_down) io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
- break;
- case WM_MOUSEMOVE:
- if (!right_mouse_down) {
- io.MousePos.x = (float)GET_X_LPARAM(lParam);
- io.MousePos.y = (float)GET_Y_LPARAM(lParam);
- }
- break;
- case WM_XBUTTONDOWN:
- if (!right_mouse_down) {
- if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) io.KeysDown[VK_XBUTTON1] = true;
- if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2) io.KeysDown[VK_XBUTTON2] = true;
- }
- break;
- case WM_XBUTTONUP:
- if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) io.KeysDown[VK_XBUTTON1] = false;
- if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2) io.KeysDown[VK_XBUTTON2] = false;
- break;
- case WM_KEYDOWN:
- if (wParam < 256)
- io.KeysDown[wParam] = true;
- break;
- case WM_KEYUP:
- if (wParam < 256)
- io.KeysDown[wParam] = false;
- break;
- case WM_CHAR: // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
- if (wParam > 0 && wParam < 0x10000)
- io.AddInputCharacter((unsigned short)wParam);
- break;
- default:
- break;
- }
-
- // === Send events to toolbox ===
- GWToolbox& tb = GWToolbox::Instance();
- switch (Message) {
- // Send button up mouse events to everything, to avoid being stuck on mouse-down
- case WM_LBUTTONUP:
- for (ToolboxModule* m : tb.GetModules()) {
- m->WndProc(Message, wParam, lParam);
- }
- break;
-
- // Other mouse events:
- // - If right mouse down, leave it to gw
- // - ImGui first (above), if WantCaptureMouse that's it
- // - Toolbox module second (e.g.: minimap), if captured, that's it
- // - otherwise pass to gw
- case WM_LBUTTONDOWN:
- case WM_LBUTTONDBLCLK:
- case WM_MOUSEMOVE:
- case WM_MOUSEWHEEL:
- if (!right_mouse_down) {
- if (io.WantCaptureMouse) return true;
- bool captured = false;
- for (ToolboxModule* m : tb.GetModules()) {
- if (m->WndProc(Message, wParam, lParam)) captured = true;
- }
- if (captured) return true;
- }
- break;
-
- // keyboard messages
- case WM_KEYUP:
- case WM_SYSKEYUP:
- if (io.WantTextInput) break; // if imgui wants them, send to imgui (above) and to gw
- // else fallthrough
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- case WM_CHAR:
- case WM_SYSCHAR:
- case WM_IME_CHAR:
- case WM_XBUTTONDOWN:
- case WM_XBUTTONDBLCLK:
- case WM_XBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONDBLCLK:
- case WM_MBUTTONUP:
- if (io.WantTextInput) return true; // if imgui wants them, send just to imgui (above)
-
- // send input to chat commands for camera movement
- if (ChatCommands::Instance().WndProc(Message, wParam, lParam)) {
- return true;
- }
-
- // send to toolbox modules
- for (ToolboxModule* m : tb.GetModules()) {
- m->WndProc(Message, wParam, lParam);
- }
- // note: capturing those events would prevent typing if you have a hotkey assigned to normal letters.
- // We may want to not send events to toolbox if the player is typing in-game
- // Otherwise, we may want to capture events.
- // For that, we may want to only capture *successfull* hotkey activations.
-
- // block alt-enter if in borderless to avoid graphic glitches (no reason to go fullscreen anyway)
- if (GameSettings::Instance().borderlesswindow
- && (GetAsyncKeyState(VK_MENU) < 0)
- && (GetAsyncKeyState(VK_RETURN) < 0)) {
- return true;
- }
- break;
-
- case WM_SIZE:
- // ImGui doesn't need this, it reads the viewport size directly
- break;
-
- default:
- break;
- }
-
- return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
-}
-
-void GWToolbox::Initialize() {
- Log::Log("Creating Toolbox\n");
- Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img"));
- Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\bonds"));
- Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\icons"));
- Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\materials"));
- Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\pcons"));
- Resources::Instance().EnsureFolderExists(Resources::GetPath(L"location logs"));
- Resources::Instance().EnsureFileExists(Resources::GetPath(L"GWToolbox.ini"),
- L"https://raw.githubusercontent.com/HasKha/GWToolboxpp/master/resources/GWToolbox.ini",
- [](bool success) {
- if (success) {
- GWToolbox::Instance().OpenSettingsFile();
- GWToolbox::Instance().LoadModuleSettings();
- }
- });
- // if the file does not exist we'll load module settings once downloaded, but we need the file open
- // in order to read defaults
- OpenSettingsFile();
- Resources::Instance().EnsureFileExists(Resources::GetPath(L"Markers.ini"),
- L"https://raw.githubusercontent.com/HasKha/GWToolboxpp/master/resources/Markers.ini",
- [](bool success) {
- Minimap::Instance().custom_renderer.LoadMarkers();
- });
-
- Log::Log("Creating Modules\n");
- std::vector core_modules;
- core_modules.push_back(&Resources::Instance());
- core_modules.push_back(&Updater::Instance());
-#ifdef ENABLE_LUA
- core_modules.push_back(&LUAInterface::Instance());
-#endif
- core_modules.push_back(&GameSettings::Instance());
- core_modules.push_back(&ToolboxSettings::Instance());
- core_modules.push_back(&ChatFilter::Instance());
- core_modules.push_back(&ChatCommands::Instance());
- core_modules.push_back(&ToolboxTheme::Instance());
-
- for (ToolboxModule* core : core_modules) {
- core->Initialize();
- }
- LoadModuleSettings(); // This will only read settings of the core modules (specified above)
-
- ToolboxSettings::Instance().InitializeModules(); // initialize all other modules as specified by the user
-
- // Only read settings of non-core modules
- for (ToolboxModule* module : modules) {
- bool is_core = false;
- for (ToolboxModule* core : core_modules) {
- if (module == core) is_core = true;
- }
- if (!is_core) module->LoadSettings(inifile);
- }
-
- Updater::Instance().CheckForUpdate();
-
- if (GW::Map::GetInstanceType() != GW::Constants::InstanceType::Loading
- && GW::Agents::GetAgentArray().valid()
- && GW::Agents::GetPlayer() != nullptr) {
-
- DWORD playerNumber = GW::Agents::GetPlayer()->PlayerNumber;
- Log::Info("Hello %ls!", GW::Agents::GetPlayerNameByLoginNumber(playerNumber));
- }
-}
-
-void GWToolbox::OpenSettingsFile() {
- Log::Log("Opening ini file\n");
- if (inifile == nullptr) inifile = new CSimpleIni(false, false, false);
- inifile->LoadFile(Resources::GetPath(L"GWToolbox.ini").c_str());
-}
-void GWToolbox::LoadModuleSettings() {
- for (ToolboxModule* module : modules) {
- module->LoadSettings(inifile);
- }
-}
-
-void GWToolbox::SaveSettings() {
- for (ToolboxModule* module : modules) {
- module->SaveSettings(inifile);
- }
- if (inifile) inifile->SaveFile(Resources::GetPath(L"GWToolbox.ini").c_str());
-}
-
-void GWToolbox::Terminate() {
- SaveSettings();
- inifile->Reset();
- delete inifile;
-
- for (ToolboxModule* module : modules) {
- module->Terminate();
- }
-
- if (GW::Map::GetInstanceType() != GW::Constants::InstanceType::Loading) {
- Log::Info("Bye!");
- }
-}
-
-void GWToolbox::Draw(IDirect3DDevice9* device) {
-
- static HWND gw_window_handle = 0;
- static DWORD last_tick_count;
-
- // === initialization ===
- if (!tb_initialized && !GWToolbox::Instance().must_self_destruct) {
-
- Log::Log("installing event handler\n");
- gw_window_handle = GW::MemoryMgr::GetGWWindowHandle();
- OldWndProc = SetWindowLongPtr(gw_window_handle, GWL_WNDPROC, (long)SafeWndProc);
- Log::Log("Installed input event handler, oldwndproc = 0x%X\n", OldWndProc);
-
- ImGui_ImplDX9_Init(GW::MemoryMgr().GetGWWindowHandle(), device);
- ImGuiIO& io = ImGui::GetIO();
- io.MouseDrawCursor = false;
- static Utf8 imgui_inifile = Resources::GetPathUtf8(L"interface.ini");
- io.IniFilename = imgui_inifile.c_str();
-
- Resources::Instance().EnsureFileExists(Resources::GetPath(L"Font.ttf"),
- L"https://raw.githubusercontent.com/HasKha/GWToolboxpp/master/resources/Font.ttf",
- [](bool success) {
- if (success) {
- GuiUtils::LoadFonts();
- } else {
- Log::Error("Cannot load font!");
- }
- });
-
- GWToolbox::Instance().Initialize();
-
- // Maybe temporary...
- GW::HookBase::EnableHooks();
-
- last_tick_count = GetTickCount();
- tb_initialized = true;
- }
-
- // === runtime ===
- if (tb_initialized
- && !GWToolbox::Instance().must_self_destruct
- && GW::Render::GetViewportWidth() > 0
- && GW::Render::GetViewportHeight() > 0) {
-
- ImGui_ImplDX9_NewFrame(GW::Render::GetViewportWidth(), GW::Render::GetViewportHeight());
-
- // Improve precision with QueryPerformanceCounter
- DWORD tick = GetTickCount();
- DWORD delta = tick - last_tick_count;
- float delta_f = delta / 1000.f;
-
- for (ToolboxModule* module : GWToolbox::Instance().modules) {
- module->Update(delta_f);
- }
- last_tick_count = tick;
-
- Resources::Instance().DxUpdate(device);
-
- for (ToolboxUIElement* uielement : GWToolbox::Instance().uielements) {
- uielement->Draw(device);
- }
-
-#ifdef _DEBUG
- // Feel free to uncomment to play with ImGui's features
- //ImGui::ShowDemoWindow();
- //ImGui::ShowStyleEditor(); // Warning, this WILL change your theme. Back up theme.ini first!
-#endif
-
- ImGui::Render();
- }
-
- // === destruction ===
- if (tb_initialized && GWToolbox::Instance().must_self_destruct) {
- GWToolbox::Instance().Terminate();
-
- ImGui_ImplDX9_Shutdown();
-
- Log::Log("Restoring input hook\n");
- SetWindowLongPtr(gw_window_handle, GWL_WNDPROC, (long)OldWndProc);
- Log::Log("Destroying directX hook\n");
- GW::Render::RestoreHooks();
- Log::Log("Destroying API\n");
- GW::Terminate();
- tb_destroyed = true;
- }
-}
+#include "GWToolbox.h"
+
+#include "Defines.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "logger.h"
+#include "CursorFix.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef ENABLE_LUA
+# include
+#endif
+#include
+
+#include
+
+#include "GuiUtils.h"
+
+namespace {
+ HMODULE dllmodule = 0;
+
+ long OldWndProc = 0;
+ bool tb_initialized = false;
+ bool tb_destroyed = false;
+
+ bool drawing_world = 0;
+ int drawing_passes = 0;
+ int last_drawing_passes = 0;
+}
+
+HMODULE GWToolbox::GetDLLModule() {
+ return dllmodule;
+}
+
+DWORD __stdcall SafeThreadEntry(LPVOID module) {
+ dllmodule = (HMODULE)module;
+ __try {
+ return ThreadEntry(nullptr);
+ } __except ( EXCEPT_EXPRESSION_ENTRY ) {
+ Log::Log("SafeThreadEntry __except body\n");
+ return EXIT_SUCCESS;
+ }
+}
+
+DWORD __stdcall ThreadEntry(LPVOID) {
+ Log::Log("Initializing API\n");
+
+ GW::HookBase::Initialize();
+ if (!GW::Initialize()){
+ MessageBoxA(0, "Initialize Failed at finding all addresses, contact Developers about this.", "GWToolbox++ API Error", 0);
+ FreeLibraryAndExitThread(dllmodule, EXIT_SUCCESS);
+ return EXIT_SUCCESS;
+ }
+
+ Log::Log("Installing Cursor Fix\n");
+
+ InstallCursorFix();
+
+ Log::Log("Installing dx hooks\n");
+ GW::Render::SetRenderCallback([](IDirect3DDevice9* device) {
+ GWToolbox::Instance().Draw(device);
+ });
+ GW::Render::SetResetCallback([](IDirect3DDevice9* device) {
+ ImGui_ImplDX9_InvalidateDeviceObjects();
+ });
+
+ Log::Log("Installed dx hooks\n");
+
+ Log::InitializeChat();
+
+ Log::Log("Installed chat hooks\n");
+
+ GW::HookBase::EnableHooks();
+
+ Log::Log("Hooks Enabled!\n");
+
+ while (!tb_destroyed) { // wait until destruction
+ Sleep(100);
+
+#ifdef _DEBUG
+ if (GetAsyncKeyState(VK_END) & 1) {
+ GWToolbox::Instance().StartSelfDestruct();
+ break;
+ }
+#endif
+ }
+
+ Sleep(100);
+ Log::Log("Removing Cursor Fix\n");
+ UninstallCursorFix();
+ Sleep(100);
+ Log::Log("Closing log/console, bye!\n");
+ Log::Terminate();
+ Sleep(100);
+
+ GW::HookBase::Deinitialize(); // At this point every hook should be disable, so we only need to free the memory
+ FreeLibraryAndExitThread(dllmodule, EXIT_SUCCESS);
+}
+
+LRESULT CALLBACK SafeWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {
+ __try {
+ return WndProc(hWnd, Message, wParam, lParam);
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
+ }
+}
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {
+ static bool right_mouse_down = false;
+
+ if (!tb_initialized || tb_destroyed) {
+ return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
+ }
+
+ if (Message == WM_QUIT || Message == WM_CLOSE) {
+ GWToolbox::Instance().SaveSettings();
+ return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
+ }
+
+ if (Message == WM_RBUTTONDOWN) right_mouse_down = true;
+ if (Message == WM_RBUTTONDBLCLK) right_mouse_down = true;
+ if (Message == WM_RBUTTONUP) right_mouse_down = false;
+
+ GWToolbox::Instance().right_mouse_down = right_mouse_down;
+
+ // === Send events to ImGui ===
+ ImGuiIO& io = ImGui::GetIO();
+
+ switch (Message) {
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ if (!right_mouse_down) io.MouseDown[0] = true;
+ break;
+ case WM_LBUTTONUP:
+ io.MouseDown[0] = false;
+ break;
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONDBLCLK:
+ if (!right_mouse_down) {
+ io.KeysDown[VK_MBUTTON] = true;
+ io.MouseDown[2] = true;
+ }
+ break;
+ case WM_MBUTTONUP:
+ io.KeysDown[VK_MBUTTON] = false;
+ io.MouseDown[2] = false;
+ break;
+ case WM_MOUSEWHEEL:
+ if (!right_mouse_down) io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
+ break;
+ case WM_MOUSEMOVE:
+ if (!right_mouse_down) {
+ io.MousePos.x = (float)GET_X_LPARAM(lParam);
+ io.MousePos.y = (float)GET_Y_LPARAM(lParam);
+ }
+ break;
+ case WM_XBUTTONDOWN:
+ if (!right_mouse_down) {
+ if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) io.KeysDown[VK_XBUTTON1] = true;
+ if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2) io.KeysDown[VK_XBUTTON2] = true;
+ }
+ break;
+ case WM_XBUTTONUP:
+ if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) io.KeysDown[VK_XBUTTON1] = false;
+ if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2) io.KeysDown[VK_XBUTTON2] = false;
+ break;
+ case WM_KEYDOWN:
+ if (wParam < 256)
+ io.KeysDown[wParam] = true;
+ break;
+ case WM_KEYUP:
+ if (wParam < 256)
+ io.KeysDown[wParam] = false;
+ break;
+ case WM_CHAR: // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
+ if (wParam > 0 && wParam < 0x10000)
+ io.AddInputCharacter((unsigned short)wParam);
+ break;
+ default:
+ break;
+ }
+
+ // === Send events to toolbox ===
+ GWToolbox& tb = GWToolbox::Instance();
+ switch (Message) {
+ // Send button up mouse events to everything, to avoid being stuck on mouse-down
+ case WM_LBUTTONUP:
+ for (ToolboxModule* m : tb.GetModules()) {
+ m->WndProc(Message, wParam, lParam);
+ }
+ break;
+
+ // Other mouse events:
+ // - If right mouse down, leave it to gw
+ // - ImGui first (above), if WantCaptureMouse that's it
+ // - Toolbox module second (e.g.: minimap), if captured, that's it
+ // - otherwise pass to gw
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_MOUSEMOVE:
+ case WM_MOUSEWHEEL:
+ if (!right_mouse_down) {
+ if (io.WantCaptureMouse) return true;
+ bool captured = false;
+ for (ToolboxModule* m : tb.GetModules()) {
+ if (m->WndProc(Message, wParam, lParam)) captured = true;
+ }
+ if (captured) return true;
+ }
+ break;
+
+ // keyboard messages
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ if (io.WantTextInput) break; // if imgui wants them, send to imgui (above) and to gw
+ // else fallthrough
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ case WM_IME_CHAR:
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONDBLCLK:
+ case WM_XBUTTONUP:
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONDBLCLK:
+ case WM_MBUTTONUP:
+ if (io.WantTextInput) return true; // if imgui wants them, send just to imgui (above)
+
+ // send input to chat commands for camera movement
+ if (ChatCommands::Instance().WndProc(Message, wParam, lParam)) {
+ return true;
+ }
+
+ // send to toolbox modules
+ for (ToolboxModule* m : tb.GetModules()) {
+ m->WndProc(Message, wParam, lParam);
+ }
+ // note: capturing those events would prevent typing if you have a hotkey assigned to normal letters.
+ // We may want to not send events to toolbox if the player is typing in-game
+ // Otherwise, we may want to capture events.
+ // For that, we may want to only capture *successfull* hotkey activations.
+
+ // block alt-enter if in borderless to avoid graphic glitches (no reason to go fullscreen anyway)
+ if (GameSettings::Instance().borderlesswindow
+ && (GetAsyncKeyState(VK_MENU) < 0)
+ && (GetAsyncKeyState(VK_RETURN) < 0)) {
+ return true;
+ }
+ break;
+
+ case WM_SIZE:
+ // ImGui doesn't need this, it reads the viewport size directly
+ break;
+
+ default:
+ break;
+ }
+
+ return CallWindowProc((WNDPROC)OldWndProc, hWnd, Message, wParam, lParam);
+}
+
+void GWToolbox::Initialize() {
+ Log::Log("Creating Toolbox\n");
+ Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img"));
+ Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\bonds"));
+ Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\icons"));
+ Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\materials"));
+ Resources::Instance().EnsureFolderExists(Resources::GetPath(L"img\\pcons"));
+ Resources::Instance().EnsureFolderExists(Resources::GetPath(L"location logs"));
+ Resources::Instance().EnsureFileExists(Resources::GetPath(L"GWToolbox.ini"),
+ L"https://raw.githubusercontent.com/HasKha/GWToolboxpp/master/resources/GWToolbox.ini",
+ [](bool success) {
+ if (success) {
+ GWToolbox::Instance().OpenSettingsFile();
+ GWToolbox::Instance().LoadModuleSettings();
+ }
+ });
+ // if the file does not exist we'll load module settings once downloaded, but we need the file open
+ // in order to read defaults
+ OpenSettingsFile();
+ Resources::Instance().EnsureFileExists(Resources::GetPath(L"Markers.ini"),
+ L"https://raw.githubusercontent.com/HasKha/GWToolboxpp/master/resources/Markers.ini",
+ [](bool success) {
+ Minimap::Instance().custom_renderer.LoadMarkers();
+ });
+
+ Log::Log("Creating Modules\n");
+ std::vector core_modules;
+ core_modules.push_back(&Resources::Instance());
+ core_modules.push_back(&Updater::Instance());
+#ifdef ENABLE_LUA
+ core_modules.push_back(&LUAInterface::Instance());
+#endif
+ core_modules.push_back(&GameSettings::Instance());
+ core_modules.push_back(&ToolboxSettings::Instance());
+ core_modules.push_back(&ChatFilter::Instance());
+ core_modules.push_back(&ChatCommands::Instance());
+ core_modules.push_back(&ToolboxTheme::Instance());
+
+ for (ToolboxModule* core : core_modules) {
+ core->Initialize();
+ }
+ LoadModuleSettings(); // This will only read settings of the core modules (specified above)
+
+ // Loading all plugin modules.
+
+ std::vector plugin_modules;
+
+ WIN32_FIND_DATAW find_data;
+ HANDLE find_handle = FindFirstFileW(Resources::GetPath(L"plugins\\*.dll").c_str(), &find_data);
+ if (find_handle != INVALID_HANDLE_VALUE) {
+ do {
+ HMODULE dllmod = LoadLibraryW(find_data.cFileName);
+ if (!dllmod) {
+ Log::Warning("DLL plugin \"%S\" could not be loaded. LoadLibraryW Err %d", find_data.cFileName, GetLastError());
+ continue;
+ }
+ typedef ToolboxModule* InstanceFn_t();
+ InstanceFn_t* inst = (InstanceFn_t*)GetProcAddress(dllmod, "GWTB_Instance");
+ if (!inst) {
+ Log::Warning("DLL plugin \"%S\" could not be loaded. TB_Instance entry point not defined.", find_data.cFileName);
+ continue;
+ }
+ ToolboxModule* mod = inst();
+ if (!mod) {
+ Log::Warning("DLL plugin \"%S\" could not be loaded. Module does not exist.", find_data.cFileName);
+ continue;
+ }
+ dllhandles.push_back(dllmod);
+ plugin_modules.push_back(mod);
+ Log::LogW(L"DLL plugin \"%s\" loaded successfully.", find_data.cFileName);
+ } while (FindNextFileW(find_handle, &find_data));
+ }
+
+ for (ToolboxModule* plugin : plugin_modules) {
+ plugin->Initialize();
+ }
+
+ ToolboxSettings::Instance().InitializeModules(); // initialize all other modules as specified by the user
+
+ // Only read settings of non-core modules
+ for (ToolboxModule* module : modules) {
+ bool is_core = false;
+ for (ToolboxModule* core : core_modules) {
+ if (module == core) is_core = true;
+ }
+ if (!is_core) module->LoadSettings(inifile);
+ }
+
+ Updater::Instance().CheckForUpdate();
+
+ if (GW::Map::GetInstanceType() != GW::Constants::InstanceType::Loading
+ && GW::Agents::GetAgentArray().valid()
+ && GW::Agents::GetPlayer() != nullptr) {
+
+ DWORD playerNumber = GW::Agents::GetPlayer()->PlayerNumber;
+ Log::Info("Hello %ls!", GW::Agents::GetPlayerNameByLoginNumber(playerNumber));
+ }
+}
+
+void GWToolbox::OpenSettingsFile() {
+ Log::Log("Opening ini file\n");
+ if (inifile == nullptr) inifile = new CSimpleIni(false, false, false);
+ inifile->LoadFile(Resources::GetPath(L"GWToolbox.ini").c_str());
+}
+void GWToolbox::LoadModuleSettings() {
+ for (ToolboxModule* module : modules) {
+ module->LoadSettings(inifile);
+ }
+}
+
+void GWToolbox::SaveSettings() {
+ for (ToolboxModule* module : modules) {
+ module->SaveSettings(inifile);
+ }
+ if (inifile) inifile->SaveFile(Resources::GetPath(L"GWToolbox.ini").c_str());
+}
+
+void GWToolbox::Terminate() {
+ SaveSettings();
+ inifile->Reset();
+ delete inifile;
+
+ for (ToolboxModule* module : modules) {
+ module->Terminate();
+ }
+
+ if (GW::Map::GetInstanceType() != GW::Constants::InstanceType::Loading) {
+ Log::Info("Bye!");
+ }
+}
+
+void GWToolbox::Draw(IDirect3DDevice9* device) {
+
+ static HWND gw_window_handle = 0;
+ static DWORD last_tick_count;
+
+ // === initialization ===
+ if (!tb_initialized && !GWToolbox::Instance().must_self_destruct) {
+
+ Log::Log("installing event handler\n");
+ gw_window_handle = GW::MemoryMgr::GetGWWindowHandle();
+ OldWndProc = SetWindowLongPtr(gw_window_handle, GWL_WNDPROC, (long)SafeWndProc);
+ Log::Log("Installed input event handler, oldwndproc = 0x%X\n", OldWndProc);
+
+ ImGui::CreateContext();
+ ImGui_ImplDX9_Init(GW::MemoryMgr().GetGWWindowHandle(), device);
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseDrawCursor = false;
+ static Utf8 imgui_inifile = Resources::GetPathUtf8(L"interface.ini");
+ io.IniFilename = imgui_inifile.c_str();
+
+ Resources::Instance().EnsureFileExists(Resources::GetPath(L"Font.ttf"),
+ L"https://raw.githubusercontent.com/HasKha/GWToolboxpp/master/resources/Font.ttf",
+ [](bool success) {
+ if (success) {
+ GuiUtils::LoadFonts();
+ } else {
+ Log::Error("Cannot load font!");
+ }
+ });
+
+ GWToolbox::Instance().Initialize();
+
+ // Maybe temporary...
+ GW::HookBase::EnableHooks();
+
+ last_tick_count = GetTickCount();
+ tb_initialized = true;
+ }
+
+ // === runtime ===
+ if (tb_initialized
+ && !GWToolbox::Instance().must_self_destruct
+ && GW::Render::GetViewportWidth() > 0
+ && GW::Render::GetViewportHeight() > 0) {
+
+ if (!GW::UI::GetIsUIDrawn())
+ return;
+
+ ImGui_ImplDX9_NewFrame();
+
+ // Improve precision with QueryPerformanceCounter
+ DWORD tick = GetTickCount();
+ DWORD delta = tick - last_tick_count;
+ float delta_f = delta / 1000.f;
+
+ for (ToolboxModule* module : GWToolbox::Instance().modules) {
+ module->Update(delta_f);
+ }
+ last_tick_count = tick;
+
+ Resources::Instance().DxUpdate(device);
+
+ for (ToolboxUIElement* uielement : GWToolbox::Instance().uielements) {
+ uielement->Draw(device);
+ }
+
+#ifdef _DEBUG
+ // Feel free to uncomment to play with ImGui's features
+ //ImGui::ShowDemoWindow();
+ //ImGui::ShowStyleEditor(); // Warning, this WILL change your theme. Back up theme.ini first!
+#endif
+
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+ ImGui_ImplDX9_RenderDrawData(draw_data);
+ }
+
+ // === destruction ===
+ if (tb_initialized && GWToolbox::Instance().must_self_destruct) {
+ GWToolbox::Instance().Terminate();
+
+ ImGui_ImplDX9_Shutdown();
+ ImGui::DestroyContext();
+
+ Log::Log("Restoring input hook\n");
+ SetWindowLongPtr(gw_window_handle, GWL_WNDPROC, (long)OldWndProc);
+ Log::Log("Destroying directX hook\n");
+ GW::Render::RestoreHooks();
+ Log::Log("Destroying API\n");
+ GW::Terminate();
+ tb_destroyed = true;
+ }
+}
diff --git a/GWToolbox/GWToolbox/GWToolbox.h b/GWToolbox/GWToolbox/GWToolbox.h
index 6fb1d0a49..7556aa218 100644
--- a/GWToolbox/GWToolbox/GWToolbox.h
+++ b/GWToolbox/GWToolbox/GWToolbox.h
@@ -46,6 +46,7 @@ class GWToolbox {
private:
std::vector modules;
std::vector uielements;
+ std::vector dllhandles;
CSimpleIni* inifile = nullptr;
};
diff --git a/GWToolbox/GWToolbox/Modules/ChatFilter.cpp b/GWToolbox/GWToolbox/Modules/ChatFilter.cpp
index 7070ce4a7..9750b21c6 100644
--- a/GWToolbox/GWToolbox/Modules/ChatFilter.cpp
+++ b/GWToolbox/GWToolbox/Modules/ChatFilter.cpp
@@ -351,6 +351,8 @@ bool ChatFilter::ShouldIgnore(const wchar_t *message) {
case 0x152B: // you win 12 festival tickets
case 0x152C: // You win 3 festival tickets
return ninerings;
+ case 0x39CD: // you have a special item available:
+ return ninerings;
case 0x7B91: // x minutes of favor of the gods remaining. Note: full message is 0x8101 0x7B91 0xC686 0xE490 0x6922 0x101 0x100+value
case 0x7B92: // x more achievements must be performed to earn the favor of the gods. // 0x8101 0x7B92 0x8B0A 0x8DB5 0x5135 0x101 0x100+value
return favor;
diff --git a/GWToolbox/GWToolbox/Modules/GameSettings.cpp b/GWToolbox/GWToolbox/Modules/GameSettings.cpp
index ddfeaae7c..482234f32 100644
--- a/GWToolbox/GWToolbox/Modules/GameSettings.cpp
+++ b/GWToolbox/GWToolbox/Modules/GameSettings.cpp
@@ -357,9 +357,9 @@ void GameSettings::Initialize() {
}
{
- uintptr_t found = GW::Scanner::Find("\x8B\x9E\x7C\x0C\x00\x00\x2B\xC3\x8B", "xxxxxxxxx", 0);
- patches.push_back(new GW::MemoryPatcher(found - 0xB, "\xEB", 1));
- patches.push_back(new GW::MemoryPatcher(found + 0x12, "\xEB", 1));
+ uintptr_t found = GW::Scanner::Find("\x2B\x8E\x78\x0C\x00\x00\x3B\xC1\x7F", "xxxxxxxxx", 0);
+ patches.push_back(new GW::MemoryPatcher(found + 0xF, "\xEB", 1));
+ patches.push_back(new GW::MemoryPatcher(found + 0x1E, "\xEB", 1));
}
{
@@ -371,16 +371,16 @@ void GameSettings::Initialize() {
}
{
- uintptr_t found = GW::Scanner::Find("\x56\x57\x8B\xF9\x8B\x87\xF4\x0C\x00\x00\x85\xC0\x75\x14", "xxxxxxxxxxxxxx", 0);
+ uintptr_t found = GW::Scanner::Find("\x55\x8B\xEC\x51\x56\x57\x8B\xF9\x8B\x87\xF8\x0C\x00\x00", "xxxxxxxxxxxxxx", 0);
void *patch = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
- patches.push_back(new GW::MemoryPatcher(found + 0x86, patch, 10));
- patches.push_back(new GW::MemoryPatcher(found + 0x100, patch, 10));
- patches.push_back(new GW::MemoryPatcher(found + 0x13F, patch, 10));
+ patches.push_back(new GW::MemoryPatcher(found + 0x8A, patch, 10));
+ patches.push_back(new GW::MemoryPatcher(found + 0x10A, patch, 10));
+ patches.push_back(new GW::MemoryPatcher(found + 0x149, patch, 10));
}
#endif // ENABLE_BORDERLESS
{
// Patch that allow storage page (and Anniversary page) to work... (ask Ziox for more info)
- uintptr_t found = GW::Scanner::Find("\xEB\x20\x33\xC0\xBE\x06", "xxxxxx", -4);
+ uintptr_t found = GW::Scanner::Find("\xEB\x00\x33\xC0\xBE\x06", "x?xxxx", -4);
printf("[SCAN] StoragePatch = %p\n", (void *)found);
// Xunlai Chest has a behavior where if you
@@ -447,7 +447,7 @@ void GameSettings::LoadSettings(CSimpleIni* ini) {
GW::Chat::ShowTimestamps = ini->GetBoolValue(Name(), "show_timestamps", false);
GW::Chat::TimestampsColor = Colors::Load(ini, Name(), "timestamps_color", Colors::White());
- GW::Chat::KeepChatHistory = ini->GetBoolValue(Name(), "keep_chat_history", true);
+ // GW::Chat::KeepChatHistory = ini->GetBoolValue(Name(), "keep_chat_history", true); @Deprecated
openlinks = ini->GetBoolValue(Name(), VAR_NAME(openlinks), true);
auto_url = ini->GetBoolValue(Name(), VAR_NAME(auto_url), true);
@@ -486,7 +486,7 @@ void GameSettings::SaveSettings(CSimpleIni* ini) {
ini->SetBoolValue(Name(), "show_timestamps", GW::Chat::ShowTimestamps);
Colors::Save(ini, Name(), "timestamps_color", GW::Chat::TimestampsColor);
- ini->SetBoolValue(Name(), "keep_chat_history", GW::Chat::KeepChatHistory);
+ // ini->SetBoolValue(Name(), "keep_chat_history", GW::Chat::KeepChatHistory); @Deprecated
ini->SetBoolValue(Name(), VAR_NAME(openlinks), openlinks);
ini->SetBoolValue(Name(), VAR_NAME(auto_url), auto_url);
@@ -518,8 +518,8 @@ void GameSettings::DrawSettingInternal() {
}
ImGui::ShowHelp("Show timestamps in message history.");
- ImGui::Checkbox("Keep chat history.", &GW::Chat::KeepChatHistory);
- ImGui::ShowHelp("Messages in the chat do not disappear on character change.");
+ // ImGui::Checkbox("Keep chat history.", &GW::Chat::KeepChatHistory); @Deprecated
+ // ImGui::ShowHelp("Messages in the chat do not disappear on character change.");
if (ImGui::Checkbox("Open web links from templates", &openlinks)) {
GW::Chat::SetOpenLinks(openlinks);
diff --git a/GWToolbox/GWToolbox/Modules/ToolboxSettings.cpp b/GWToolbox/GWToolbox/Modules/ToolboxSettings.cpp
index c22c01ab7..9566a3155 100644
--- a/GWToolbox/GWToolbox/Modules/ToolboxSettings.cpp
+++ b/GWToolbox/GWToolbox/Modules/ToolboxSettings.cpp
@@ -129,10 +129,8 @@ void ToolboxSettings::DrawSettingInternal() {
}
void ToolboxSettings::DrawFreezeSetting() {
- if (ImGui::Checkbox("Unlock Move All", &move_all)) {
- ImGui::GetStyle().WindowBorderSize = (move_all ? 1.0f : 0.0f);
- }
- ImGui::ShowHelp("Will allow movement and resize of all widgets and windows");
+ ImGui::Checkbox("Unlock Move All", &move_all);
+ ImGui::ShowHelp("Will allow movement and resize of all widgets and windows");
}
void ToolboxSettings::LoadSettings(CSimpleIni* ini) {
@@ -184,6 +182,8 @@ void ToolboxSettings::SaveSettings(CSimpleIni* ini) {
}
void ToolboxSettings::Update(float delta) {
+ ImGui::GetStyle().WindowBorderSize = (move_all ? 1.0f : 0.0f);
+
// save location data
if (save_location_data && TIMER_DIFF(location_timer) > 1000) {
location_timer = TIMER_INIT();
diff --git a/GWToolbox/GWToolbox/Modules/ToolboxTheme.cpp b/GWToolbox/GWToolbox/Modules/ToolboxTheme.cpp
index dd5af7e80..f6714b0f0 100644
--- a/GWToolbox/GWToolbox/Modules/ToolboxTheme.cpp
+++ b/GWToolbox/GWToolbox/Modules/ToolboxTheme.cpp
@@ -32,12 +32,9 @@ ImGuiStyle ToolboxTheme::DefaultTheme() {
style.Colors[ImGuiCol_Button] = ImColor(0x99344870);
style.Colors[ImGuiCol_ButtonHovered] = ImColor(0xFF344870);
style.Colors[ImGuiCol_ButtonActive] = ImColor(0xFF283C68);
- style.Colors[ImGuiCol_CloseButton] = ImColor(0x80808080);
style.Colors[ImGuiCol_Header] = ImColor(0x73E62800);
style.Colors[ImGuiCol_HeaderHovered] = ImColor(0xCCF03200);
style.Colors[ImGuiCol_HeaderActive] = ImColor(0xCCFA3C00);
- style.Colors[ImGuiCol_CloseButtonHovered] = ImColor(0x99BDBDBD);
- style.Colors[ImGuiCol_CloseButtonActive] = ImColor(0xFFBDBDBD);
return style;
}
diff --git a/GWToolbox/GWToolbox/Windows/HeroBuildsWindow.cpp b/GWToolbox/GWToolbox/Windows/HeroBuildsWindow.cpp
index 583132243..3b24a62c4 100644
--- a/GWToolbox/GWToolbox/Windows/HeroBuildsWindow.cpp
+++ b/GWToolbox/GWToolbox/Windows/HeroBuildsWindow.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
#include "GuiUtils.h"
@@ -73,6 +74,8 @@ namespace {
"Mercenary Hero 4", "Mercenary Hero 5", "Mercenary Hero 6",
"Mercenary Hero 7", "Mercenary Hero 8", "Miku", "Zei Ri"
};
+
+ char MercHeroNames[8][20] = { 0 };
}
unsigned int HeroBuildsWindow::TeamHeroBuild::cur_ui_id = 0;
@@ -163,7 +166,23 @@ void HeroBuildsWindow::Draw(IDirect3DDevice9* pDevice) {
[](void* data, int idx, const char** out_text) -> bool {
if (idx < 0) return false;
if (idx >= hero_count) return false;
- *out_text = HeroName[HeroIndexToID[idx]];
+ auto id = HeroIndexToID[idx];
+ if (id < HeroID::Merc1 || id > HeroID::Merc8) {
+ *out_text = HeroName[HeroIndexToID[idx]];
+ return true;
+ }
+ bool match = false;
+ auto ctx = GW::GameContext::instance();
+ auto& hero_array = ctx->world->hero_info;
+ for (auto& hero : hero_array) {
+ if (hero.HeroID == id) {
+ match = true;
+ wcstombs(MercHeroNames[id - HeroID::Merc1], hero.name, 20);
+ *out_text = MercHeroNames[id - HeroID::Merc1];
+ }
+ }
+ if(!match)
+ *out_text = HeroName[id];
return true;
}, nullptr, hero_count)) {
builds_changed = true;
diff --git a/GWToolbox/GWToolbox/Windows/TravelWindow.cpp b/GWToolbox/GWToolbox/Windows/TravelWindow.cpp
index 12ee09e27..df81a8055 100644
--- a/GWToolbox/GWToolbox/Windows/TravelWindow.cpp
+++ b/GWToolbox/GWToolbox/Windows/TravelWindow.cpp
@@ -15,7 +15,7 @@
namespace {
bool outpost_name_array_getter(void* data, int idx, const char** out_text);
- bool ImInPresearing() { return GW::Map::GetCurrentMapInfo().Region == GW::Region::Presearing; }
+ bool ImInPresearing() { return GW::Map::GetCurrentMapInfo().Region == GW::Region_Presearing; }
}
void TravelWindow::Initialize() {
diff --git a/GWToolbox/GWToolbox/imgui_impl_dx9.cpp b/GWToolbox/GWToolbox/imgui_impl_dx9.cpp
index 34209b9ce..dea5c3fc8 100644
--- a/GWToolbox/GWToolbox/imgui_impl_dx9.cpp
+++ b/GWToolbox/GWToolbox/imgui_impl_dx9.cpp
@@ -1,12 +1,24 @@
// ImGui Win32 + DirectX9 binding
-// In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
+
+// Implemented features:
+// [X] User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
-#include
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
+// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
+// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavEnableSetMousePos is set).
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+
+#include "imgui.h"
#include "imgui_impl_dx9.h"
// DirectX
@@ -14,44 +26,42 @@
#define DIRECTINPUT_VERSION 0x0800
#include
-// Data
+// Win32 data
static HWND g_hWnd = 0;
static INT64 g_Time = 0;
static INT64 g_TicksPerSecond = 0;
+static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT;
+
+// DirectX data
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
static LPDIRECT3DTEXTURE9 g_FontTexture = NULL;
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
-struct CUSTOMVERTEX
-{
+struct CUSTOMVERTEX {
float pos[3];
D3DCOLOR col;
float uv[2];
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
-// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
-// If text or lines are blurry when integrating ImGui in your engine:
-// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
-void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
-{
+// Render function.
+// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
+void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) {
// Avoid rendering when minimized
ImGuiIO& io = ImGui::GetIO();
if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f)
return;
// Create and grow buffers if needed
- if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
- {
+ if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) {
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
return;
}
- if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
- {
+ if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
@@ -63,25 +73,31 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
return;
- // Copy and convert all vertices into a single contiguous buffer
+ // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
+ D3DMATRIX last_world, last_view, last_projection;
+ g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
+ g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
+ g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
+
+ // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
+ // FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and
+ // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
+ // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
CUSTOMVERTEX* vtx_dst;
ImDrawIdx* idx_dst;
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
return;
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
return;
- for (int n = 0; n < draw_data->CmdListsCount; n++)
- {
+ for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
- for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
- {
+ for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) {
vtx_dst->pos[0] = vtx_src->pos.x;
vtx_dst->pos[1] = vtx_src->pos.y;
vtx_dst->pos[2] = 0.0f;
- //vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9
- vtx_dst->col = vtx_src->col;
- vtx_dst->uv[0] = vtx_src->uv.x;
+ vtx_dst->col = vtx_src->col;
+ vtx_dst->uv[0] = vtx_src->uv.x;
vtx_dst->uv[1] = vtx_src->uv.y;
vtx_dst++;
vtx_src++;
@@ -104,7 +120,7 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
vp.MaxZ = 1.0f;
g_pd3dDevice->SetViewport(&vp);
- // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing
+ // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
g_pd3dDevice->SetPixelShader(NULL);
g_pd3dDevice->SetVertexShader(NULL);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
@@ -116,6 +132,7 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true);
+ g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
@@ -128,14 +145,14 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
// Setup orthographic projection matrix
// Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
{
- const float L = 0.5f, R = io.DisplaySize.x+0.5f, T = 0.5f, B = io.DisplaySize.y+0.5f;
+ const float L = 0.5f, R = io.DisplaySize.x + 0.5f, T = 0.5f, B = io.DisplaySize.y + 0.5f;
D3DMATRIX mat_identity = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } };
D3DMATRIX mat_projection =
{
- 2.0f/(R-L), 0.0f, 0.0f, 0.0f,
- 0.0f, 2.0f/(T-B), 0.0f, 0.0f,
+ 2.0f / (R - L), 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f / (T - B), 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
- (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f,
+ (L + R) / (L - R), (T + B) / (B - T), 0.5f, 1.0f,
};
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
@@ -145,58 +162,87 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
// Render command lists
int vtx_offset = 0;
int idx_offset = 0;
- for (int n = 0; n < draw_data->CmdListsCount; n++)
- {
+ for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n];
- for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
- {
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
- if (pcmd->UserCallback)
- {
+ if (pcmd->UserCallback) {
pcmd->UserCallback(cmd_list, pcmd);
- }
- else
- {
+ } else {
const RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
g_pd3dDevice->SetTexture(0, (LPDIRECT3DTEXTURE9)pcmd->TextureId);
g_pd3dDevice->SetScissorRect(&r);
- g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, idx_offset, pcmd->ElemCount/3);
+ g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, idx_offset, pcmd->ElemCount / 3);
}
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.Size;
}
+ // Restore the DX9 transform
+ g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
+ g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
+ g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
+
// Restore the DX9 state
d3d9_state_block->Apply();
d3d9_state_block->Release();
}
-static bool IsAnyMouseButtonDown()
-{
+static bool ImGui_ImplWin32_UpdateMouseCursor() {
ImGuiIO& io = ImGui::GetIO();
- for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++)
- if (io.MouseDown[n])
- return true;
- return false;
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return false;
+
+ ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
+ if (imgui_cursor == ImGuiMouseCursor_None) {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ ::SetCursor(NULL);
+ } else {
+ // Hardware cursor type
+ LPTSTR win32_cursor = IDC_ARROW;
+ switch (imgui_cursor) {
+ case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
+ case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
+ case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
+ case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
+ case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
+ case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
+ case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
+ }
+ ::SetCursor(::LoadCursor(NULL, win32_cursor));
+ }
+ return true;
}
-// We use the Win32 capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds.
-IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
+// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif
+
+// Process Win32 mouse/keyboard inputs.
+// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds.
+// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
+IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ if (ImGui::GetCurrentContext() == NULL)
+ return 0;
+
ImGuiIO& io = ImGui::GetIO();
- switch (msg)
- {
- case WM_LBUTTONDOWN:
- case WM_RBUTTONDOWN:
- case WM_MBUTTONDOWN:
+ switch (msg) {
+ case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
{
int button = 0;
- if (msg == WM_LBUTTONDOWN) button = 0;
- if (msg == WM_RBUTTONDOWN) button = 1;
- if (msg == WM_MBUTTONDOWN) button = 2;
- if (!IsAnyMouseButtonDown() && GetCapture() == NULL)
- SetCapture(hwnd);
+ if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0;
+ if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1;
+ if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2;
+ if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
+ ::SetCapture(hwnd);
io.MouseDown[button] = true;
return 0;
}
@@ -209,13 +255,16 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
if (msg == WM_RBUTTONUP) button = 1;
if (msg == WM_MBUTTONUP) button = 2;
io.MouseDown[button] = false;
- if (!IsAnyMouseButtonDown() && GetCapture() == hwnd)
- ReleaseCapture();
+ if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
+ ::ReleaseCapture();
return 0;
}
case WM_MOUSEWHEEL:
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return 0;
+ case WM_MOUSEHWHEEL:
+ io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
+ return 0;
case WM_MOUSEMOVE:
io.MousePos.x = (signed short)(lParam);
io.MousePos.y = (signed short)(lParam >> 16);
@@ -235,12 +284,15 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacter((unsigned short)wParam);
return 0;
+ case WM_SETCURSOR:
+ if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
+ return 1;
+ return 0;
}
return 0;
}
-bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
-{
+bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) {
g_hWnd = (HWND)hwnd;
g_pd3dDevice = device;
@@ -249,8 +301,13 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
return false;
+ // Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
- io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+
+ // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
+ io.KeyMap[ImGuiKey_Tab] = VK_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
@@ -259,8 +316,10 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END;
+ io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
+ io.KeyMap[ImGuiKey_Space] = VK_SPACE;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
io.KeyMap[ImGuiKey_A] = 'A';
@@ -270,22 +329,18 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
- io.RenderDrawListsFn = ImGui_ImplDX9_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
io.ImeWindowHandle = g_hWnd;
return true;
}
-void ImGui_ImplDX9_Shutdown()
-{
+void ImGui_ImplDX9_Shutdown() {
ImGui_ImplDX9_InvalidateDeviceObjects();
- ImGui::Shutdown();
g_pd3dDevice = NULL;
g_hWnd = 0;
}
-static bool ImGui_ImplDX9_CreateFontsTexture()
-{
+static bool ImGui_ImplDX9_CreateFontsTexture() {
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
@@ -309,8 +364,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
return true;
}
-bool ImGui_ImplDX9_CreateDeviceObjects()
-{
+bool ImGui_ImplDX9_CreateDeviceObjects() {
if (!g_pd3dDevice)
return false;
if (!ImGui_ImplDX9_CreateFontsTexture())
@@ -318,17 +372,14 @@ bool ImGui_ImplDX9_CreateDeviceObjects()
return true;
}
-void ImGui_ImplDX9_InvalidateDeviceObjects()
-{
+void ImGui_ImplDX9_InvalidateDeviceObjects() {
if (!g_pd3dDevice)
return;
- if (g_pVB)
- {
+ if (g_pVB) {
g_pVB->Release();
g_pVB = NULL;
}
- if (g_pIB)
- {
+ if (g_pIB) {
g_pIB->Release();
g_pIB = NULL;
}
@@ -342,8 +393,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
io.Fonts->TexID = NULL;
}
-void ImGui_ImplDX9_NewFrame(int client_width, int client_height)
-{
+void ImGui_ImplDX9_NewFrame() {
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
@@ -352,7 +402,7 @@ void ImGui_ImplDX9_NewFrame(int client_width, int client_height)
// Setup display size (every frame to accommodate for window resizing)
RECT rect;
GetClientRect(g_hWnd, &rect);
- io.DisplaySize = ImVec2(client_width, client_height); // ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
+ io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
// Setup time step
INT64 current_time;
@@ -370,18 +420,20 @@ void ImGui_ImplDX9_NewFrame(int client_width, int client_height)
// io.MouseDown : filled by WM_*BUTTON* events
// io.MouseWheel : filled by WM_MOUSEWHEEL events
- // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
- if (io.WantMoveMouse)
- {
+ // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+ if (io.WantSetMousePos) {
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
ClientToScreen(g_hWnd, &pos);
SetCursorPos(pos.x, pos.y);
}
- // Hide OS mouse cursor if ImGui is drawing it
- if (io.MouseDrawCursor)
- SetCursor(NULL);
+ // Update OS mouse cursor with the cursor requested by imgui
+ ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
+ if (g_LastMouseCursor != mouse_cursor) {
+ g_LastMouseCursor = mouse_cursor;
+ ImGui_ImplWin32_UpdateMouseCursor();
+ }
- // Start the frame
+ // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
ImGui::NewFrame();
}
diff --git a/GWToolbox/GWToolbox/imgui_impl_dx9.h b/GWToolbox/GWToolbox/imgui_impl_dx9.h
index 08c2b2c72..e0ea2deae 100644
--- a/GWToolbox/GWToolbox/imgui_impl_dx9.h
+++ b/GWToolbox/GWToolbox/imgui_impl_dx9.h
@@ -1,5 +1,7 @@
// ImGui Win32 + DirectX9 binding
-// In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
+
+// Implemented features:
+// [X] User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
@@ -10,7 +12,8 @@ struct IDirect3DDevice9;
IMGUI_API bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device);
IMGUI_API void ImGui_ImplDX9_Shutdown();
-IMGUI_API void ImGui_ImplDX9_NewFrame(int client_width, int client_height);
+IMGUI_API void ImGui_ImplDX9_NewFrame();
+IMGUI_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_API void ImGui_ImplDX9_InvalidateDeviceObjects();
@@ -20,5 +23,5 @@ IMGUI_API bool ImGui_ImplDX9_CreateDeviceObjects();
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
// Commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code.
/*
-IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
*/
diff --git a/GWToolbox/GWToolbox/main.cpp b/GWToolbox/GWToolbox/main.cpp
index bc1b4eee7..b1790fc9a 100644
--- a/GWToolbox/GWToolbox/main.cpp
+++ b/GWToolbox/GWToolbox/main.cpp
@@ -20,6 +20,8 @@ DWORD WINAPI init(HMODULE hModule){
if (!(found && *found)) {
MessageBoxA(0, "We can't determine if the character is ingame.\nContact the developpers.", "GWToolbox++ - Clientside Error Detected", 0);
FreeLibraryAndExitThread(hModule, EXIT_SUCCESS);
+ } else {
+ printf("[SCAN] is_ingame = %p\n", found);
}
DWORD *is_ingame = *found;
diff --git a/GWToolboxpp.sln b/GWToolboxpp.sln
index 14836cde2..e897af22f 100644
--- a/GWToolboxpp.sln
+++ b/GWToolboxpp.sln
@@ -17,7 +17,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GWCA", "Dependencies\GWCA\G
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LUA", "LUA\LUA.vcxproj", "{07E36EE0-D8A8-48F0-A872-681512E93CCD}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GWCA_Tests", "Dependencies\GWCA\Tests\GWCA_Tests.vcxproj", "{ECC70C1A-462D-4BF1-95CA-B8B95E6E01AC}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GWCA_Test_DLL", "Dependencies\GWCA\GWCA_Test_DLL\GWCA_Test_DLL.vcxproj", "{ECC70C1A-462D-4BF1-95CA-B8B95E6E01AC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GWCA_Test_Static", "Dependencies\GWCA\GWCA_Test_Static\GWCA_Test_Static.vcxproj", "{A917F016-425B-485A-AB6B-9F0331B5CF5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -45,6 +47,10 @@ Global
{ECC70C1A-462D-4BF1-95CA-B8B95E6E01AC}.Debug|Win32.Build.0 = Debug|Win32
{ECC70C1A-462D-4BF1-95CA-B8B95E6E01AC}.Release|Win32.ActiveCfg = Release|Win32
{ECC70C1A-462D-4BF1-95CA-B8B95E6E01AC}.Release|Win32.Build.0 = Release|Win32
+ {A917F016-425B-485A-AB6B-9F0331B5CF5D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A917F016-425B-485A-AB6B-9F0331B5CF5D}.Debug|Win32.Build.0 = Debug|Win32
+ {A917F016-425B-485A-AB6B-9F0331B5CF5D}.Release|Win32.ActiveCfg = Release|Win32
+ {A917F016-425B-485A-AB6B-9F0331B5CF5D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE