From 087dce7d51e8098f982d00c5b3b2e1eaf98eac71 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:33:48 +0100 Subject: [PATCH 1/9] localise QA locations --- src/GUI/Widgets/Options/COptionsWindow.cpp | 30 +++++++++++++++++++--- src/Resources/Locales/en_Main.json | 10 +++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/GUI/Widgets/Options/COptionsWindow.cpp b/src/GUI/Widgets/Options/COptionsWindow.cpp index fb20651..94ac46c 100644 --- a/src/GUI/Widgets/Options/COptionsWindow.cpp +++ b/src/GUI/Widgets/Options/COptionsWindow.cpp @@ -30,7 +30,7 @@ namespace GUI std::string CurrentlyEditing; char CurrentAPIKey[73]{}; - const char* qaLocations[] = { "Extend", "Under", "Bottom", "Custom" }; + const char* qaLocations[] = { "((000067))", "((000068))", "((000069))", "((000070))" }; const char** languages; int languagesIndex; int languagesSize; @@ -42,6 +42,14 @@ namespace GUI void KeybindsTab(); void APITab(); + static bool LocalizedItemsGetter(void* data, int idx, const char** out_text) + { + const char* const* items = (const char* const*)data; + if (out_text) + *out_text = items[idx]; + return true; + } + COptionsWindow::COptionsWindow(std::string aName) { Name = aName; @@ -136,10 +144,24 @@ namespace GUI } ImGui::Text(Language.Translate("((000050))")); - if (ImGui::Combo("##qalocation", (int*)&QuickAccess::Location, qaLocations, IM_ARRAYSIZE(qaLocations))) + if (ImGui::BeginCombo("##qalocation", Language.Translate(qaLocations[(int)QuickAccess::Location]))) { - Settings::Settings[OPT_QALOCATION] = QuickAccess::Location; - Settings::Save(); + for (int n = 0; n < IM_ARRAYSIZE(qaLocations); n++) + { + bool is_selected = ((int)QuickAccess::Location == n); // You can store your selection however you want, outside or inside your objects + if (ImGui::Selectable(Language.Translate(qaLocations[n]), is_selected)) + { + QuickAccess::Location = (EQAPosition)n; + Settings::Settings[OPT_QALOCATION] = QuickAccess::Location; + Settings::Save(); + } + if (is_selected) + { + ImGui::SetItemDefaultFocus(); // You may set the initial focus when opening the combo (scrolling + for keyboard navigation support) + } + } + + ImGui::EndCombo(); } ImGui::Text(Language.Translate("((000051))")); if (ImGui::InputFloat2("##qaoffset", (float*)&QuickAccess::Offset)) diff --git a/src/Resources/Locales/en_Main.json b/src/Resources/Locales/en_Main.json index 2dddb47..4f19620 100644 --- a/src/Resources/Locales/en_Main.json +++ b/src/Resources/Locales/en_Main.json @@ -22,8 +22,8 @@ "((000010))": "Addon requested incompatible API Version: %d", "((000011))": "Update", "((000012))": "This addon is currently locked and requires a restart for the update to take effect.", - "((000013))": "Resume Updates", - "((000014))": "Pause Updates", + "((000013))": "Enable Auto-Updates", + "((000014))": "Disable Auto-Updates", "((000015))": "Re-Enable", "((000016))": "Disable until Update", "((000017))": "This addon is currently locked disabling won't take effect until next game start.", @@ -75,6 +75,10 @@ "((000063))": "You will overwrite ", "((000064))": "Unbind", "((000065))": "Accept", - "((000066))": "Cancel" + "((000066))": "Cancel", + "((000067))": "Extend", + "((000068))": "Under", + "((000069))": "Bottom", + "((000070))": "Custom" } } \ No newline at end of file From 622ca924a05ce5f365582c6adf4c461ebd6ae2d4 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:58:49 +0100 Subject: [PATCH 2/9] fix isGameplay bleeding into laggy game --- src/Hooks.cpp | 2 ++ src/Mumble/Mumble.cpp | 4 +++- src/Shared.cpp | 2 ++ src/Shared.h | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Hooks.cpp b/src/Hooks.cpp index a0bf2fd..93de7a9 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -124,6 +124,8 @@ namespace Hooks GUI::Render(); } + FrameCounter++; + return Hooks::DXGI::Present(pChain, SyncInterval, Flags); } HRESULT __stdcall DXGIResizeBuffers(IDXGISwapChain* pChain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) diff --git a/src/Mumble/Mumble.cpp b/src/Mumble/Mumble.cpp index 93674dd..782f280 100644 --- a/src/Mumble/Mumble.cpp +++ b/src/Mumble/Mumble.cpp @@ -28,6 +28,7 @@ namespace Mumble static Vector3 prevAvPos{}; static Vector3 prevCamFront{}; static Identity prevIdentity{}; + static long long prevFrameCounter = 0; void Initialize() { @@ -98,7 +99,8 @@ namespace Mumble if (MumbleLink != nullptr) { - IsGameplay = prevTick != MumbleLink->UITick; + //IsGameplay = UI Tick changed and FrameCounter changed or it was gameplay + IsGameplay = (prevTick != MumbleLink->UITick && prevFrameCounter != FrameCounter) || IsGameplay; IsMoving = prevAvPos != MumbleLink->AvatarPosition; IsCameraMoving = prevCamFront != MumbleLink->CameraFront; diff --git a/src/Shared.cpp b/src/Shared.cpp index d06bf38..b81bfa4 100644 --- a/src/Shared.cpp +++ b/src/Shared.cpp @@ -12,6 +12,8 @@ AddonVersion Version = { V_MAJOR, V_MINOR, V_BUILD, V_REVISION }; std::vector Parameters = {}; std::vector RequestedAddons = {}; +long long FrameCounter = 0; + LinkedMem* MumbleLink = nullptr; Identity* MumbleIdentity = new Identity{}; bool IsMoving = false; diff --git a/src/Shared.h b/src/Shared.h index ef066c1..e57715c 100644 --- a/src/Shared.h +++ b/src/Shared.h @@ -28,6 +28,8 @@ extern AddonVersion Version; extern std::vector Parameters; extern std::vector RequestedAddons; +extern long long FrameCounter; + extern LinkedMem* MumbleLink; extern Identity* MumbleIdentity; extern bool IsMoving; From 269a842410ad4f21adbd446bae7d3498338efe34 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 14:36:24 +0100 Subject: [PATCH 3/9] fix mumble gameplay bleed for real this time --- src/GUI/Widgets/Overlay/CMumbleOverlay.cpp | 28 ++++++++++++++++++++++ src/Mumble/Mumble.cpp | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/GUI/Widgets/Overlay/CMumbleOverlay.cpp b/src/GUI/Widgets/Overlay/CMumbleOverlay.cpp index 576678f..bef95d0 100644 --- a/src/GUI/Widgets/Overlay/CMumbleOverlay.cpp +++ b/src/GUI/Widgets/Overlay/CMumbleOverlay.cpp @@ -245,6 +245,34 @@ namespace GUI } } ImGui::End(); + + ImGui::SetNextWindowBgAlpha(0.35f); + pos.x += size.x + 16.0f; + ImGui::SetNextWindowPos(pos); + ImGui::SetNextWindowSize(size); + if (ImGui::Begin("NexusLinkData", &Visible, WindowFlags_Overlay)) + { + ImGui::Text("Nexus Mumble Extensions"); + ImGui::Separator(); + if (ImGui::BeginTable("table_nexus", 2)) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text("frame"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%d", FrameCounter); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text("isMoving"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%s", IsMoving ? "true" : "false"); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text("isCameraMoving"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%s", IsCameraMoving ? "true" : "false"); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text("isGameplay"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%s", IsGameplay ? "true" : "false"); + + ImGui::EndTable(); + } + } + ImGui::End(); } else { diff --git a/src/Mumble/Mumble.cpp b/src/Mumble/Mumble.cpp index 782f280..31d686b 100644 --- a/src/Mumble/Mumble.cpp +++ b/src/Mumble/Mumble.cpp @@ -99,11 +99,11 @@ namespace Mumble if (MumbleLink != nullptr) { - //IsGameplay = UI Tick changed and FrameCounter changed or it was gameplay - IsGameplay = (prevTick != MumbleLink->UITick && prevFrameCounter != FrameCounter) || IsGameplay; + IsGameplay = prevTick != MumbleLink->UITick || (prevFrameCounter == FrameCounter && IsGameplay); IsMoving = prevAvPos != MumbleLink->AvatarPosition; IsCameraMoving = prevCamFront != MumbleLink->CameraFront; + prevFrameCounter = FrameCounter; prevTick = MumbleLink->UITick; prevAvPos = MumbleLink->AvatarPosition; prevCamFront = MumbleLink->CameraFront; From 1026b2dbb3f40824f1e3409a3d69fb5c79a8b142 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 15:10:55 +0100 Subject: [PATCH 4/9] added indicator for update checker --- src/GUI/Widgets/Addons/AddonItem.cpp | 47 +++++++++++-------- src/GUI/Widgets/Addons/CAddonsWindow.cpp | 60 +++++++++++++++++------- src/Loader/Addon.h | 2 + src/Resources/Locales/en_Main.json | 3 +- 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/src/GUI/Widgets/Addons/AddonItem.cpp b/src/GUI/Widgets/Addons/AddonItem.cpp index f4ea96c..5ca1914 100644 --- a/src/GUI/Widgets/Addons/AddonItem.cpp +++ b/src/GUI/Widgets/Addons/AddonItem.cpp @@ -115,30 +115,37 @@ namespace GUI ImGui::ImageButton(BtnOptions->Resource, ImVec2(size * Renderer::Scaling, size * Renderer::Scaling)); if (ImGui::BeginPopupContextItem("##AddonItemActionsMore")) { - if (ImGui::GW2::ContextMenuItem(("Update##" + sig).c_str(), Language.Translate("((000011))"), CtxMenuBullet->Resource, CtxMenuHighlight->Resource, ImVec2(btnWidth * ImGui::GetFontSize(), btnHeight))) + if (ImGui::GW2::ContextMenuItem(("Update##" + sig).c_str(), !aAddon->IsCheckingForUpdates ? Language.Translate("((000011))") : Language.Translate("((000071))"), CtxMenuBullet->Resource, CtxMenuHighlight->Resource, ImVec2(btnWidth * ImGui::GetFontSize(), btnHeight))) { - for (auto& it : Loader::Addons) + if (!aAddon->IsCheckingForUpdates) { - if (it.second->Definitions == aAddon->Definitions) + for (auto& it : Loader::Addons) { - std::filesystem::path tmpPath = it.first.string(); - signed int tmpSig = aAddon->Definitions->Signature; - std::string tmpName = aAddon->Definitions->Name; - AddonVersion tmpVers = aAddon->Definitions->Version; - EUpdateProvider tmpProv = aAddon->Definitions->Provider; - std::string tmpLink = aAddon->Definitions->UpdateLink != nullptr ? aAddon->Definitions->UpdateLink : ""; - - std::thread([tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink]() - { - if (Loader::UpdateAddon(tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink)) + if (it.second->Definitions == aAddon->Definitions) + { + aAddon->IsCheckingForUpdates = true; + + std::filesystem::path tmpPath = it.first.string(); + signed int tmpSig = aAddon->Definitions->Signature; + std::string tmpName = aAddon->Definitions->Name; + AddonVersion tmpVers = aAddon->Definitions->Version; + EUpdateProvider tmpProv = aAddon->Definitions->Provider; + std::string tmpLink = aAddon->Definitions->UpdateLink != nullptr ? aAddon->Definitions->UpdateLink : ""; + + std::thread([aAddon, tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink]() { - Loader::QueueAddon(ELoaderAction::Reload, tmpPath); - } - }) - .detach(); - - //LogDebug(CH_GUI, "Update called: %s", it.second->Definitions->Name); - break; + if (Loader::UpdateAddon(tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink)) + { + Loader::QueueAddon(ELoaderAction::Reload, tmpPath); + } + Sleep(1000); // arbitrary sleep otherwise the user never even sees "is checking..." + aAddon->IsCheckingForUpdates = false; + }) + .detach(); + + //LogDebug(CH_GUI, "Update called: %s", it.second->Definitions->Name); + break; + } } } } diff --git a/src/GUI/Widgets/Addons/CAddonsWindow.cpp b/src/GUI/Widgets/Addons/CAddonsWindow.cpp index 2c1e9c7..f3035e0 100644 --- a/src/GUI/Widgets/Addons/CAddonsWindow.cpp +++ b/src/GUI/Widgets/Addons/CAddonsWindow.cpp @@ -28,6 +28,9 @@ namespace GUI bool showInstalled = false; bool refreshHovered = false; + int queuedForCheck = 0; + int checkedForUpdates = -1; + CAddonsWindow::CAddonsWindow(std::string aName) { Name = aName; @@ -189,29 +192,52 @@ namespace GUI ShellExecuteA(NULL, "explore", strAddons.c_str(), NULL, NULL, SW_SHOW); } ImGui::SameLine(); - if (ImGui::GW2::Button(Language.Translate("((000035))"), ImVec2(ImGui::CalcTextSize(Language.Translate("((000035))")).x + 16.0f, btnHeight))) + float btnUpdateCheckWidth = ImGui::CalcTextSize(Language.Translate("((000035))")).x; + float btnUpdateCheckingWidth = ImGui::CalcTextSize(Language.Translate("((000071))")).x; + float btnUCWidth = btnUpdateCheckingWidth > btnUpdateCheckWidth ? btnUpdateCheckingWidth : btnUpdateCheckWidth; + + if (ImGui::GW2::Button(checkedForUpdates == -1 ? Language.Translate("((000035))") : Language.Translate("((000071))"), ImVec2(btnUCWidth + 16.0f, btnHeight))) { - const std::lock_guard lock(Loader::Mutex); + if (checkedForUpdates == -1) { - for (auto& [path, addon] : Loader::Addons) + const std::lock_guard lock(Loader::Mutex); { - if (nullptr == addon->Definitions) { continue; } + checkedForUpdates = 0; + queuedForCheck = 0; + /* pre-iterate to get the count of how many need to be checked, else one call might finish before the count can be incremented */ + for (auto& [path, addon] : Loader::Addons) + { + if (nullptr == addon->Definitions) { continue; } + queuedForCheck++; + } - std::filesystem::path tmpPath = path.string(); - signed int tmpSig = addon->Definitions->Signature; - std::string tmpName = addon->Definitions->Name; - AddonVersion tmpVers = addon->Definitions->Version; - EUpdateProvider tmpProv = addon->Definitions->Provider; - std::string tmpLink = addon->Definitions->UpdateLink != nullptr ? addon->Definitions->UpdateLink : ""; + for (auto& [path, addon] : Loader::Addons) + { + if (nullptr == addon->Definitions) { continue; } - std::thread([tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink]() - { - if (Loader::UpdateAddon(tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink)) + std::filesystem::path tmpPath = path.string(); + signed int tmpSig = addon->Definitions->Signature; + std::string tmpName = addon->Definitions->Name; + AddonVersion tmpVers = addon->Definitions->Version; + EUpdateProvider tmpProv = addon->Definitions->Provider; + std::string tmpLink = addon->Definitions->UpdateLink != nullptr ? addon->Definitions->UpdateLink : ""; + + std::thread([tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink]() { - Loader::QueueAddon(ELoaderAction::Reload, tmpPath); - } - }) - .detach(); + if (Loader::UpdateAddon(tmpPath, tmpSig, tmpName, tmpVers, tmpProv, tmpLink)) + { + Loader::QueueAddon(ELoaderAction::Reload, tmpPath); + } + checkedForUpdates++; + + if (checkedForUpdates == queuedForCheck) + { + checkedForUpdates = -1; + queuedForCheck = 0; + } + }) + .detach(); + } } } } diff --git a/src/Loader/Addon.h b/src/Loader/Addon.h index 9a53a25..740c202 100644 --- a/src/Loader/Addon.h +++ b/src/Loader/Addon.h @@ -15,10 +15,12 @@ struct Addon DWORD ModuleSize; std::vector MD5; AddonDefinition* Definitions; + bool ShouldDisableNextLaunch; bool IsPausingUpdates; bool WillBeUninstalled; bool IsDisabledUntilUpdate; + bool IsCheckingForUpdates; }; #endif \ No newline at end of file diff --git a/src/Resources/Locales/en_Main.json b/src/Resources/Locales/en_Main.json index 4f19620..7c20bc1 100644 --- a/src/Resources/Locales/en_Main.json +++ b/src/Resources/Locales/en_Main.json @@ -79,6 +79,7 @@ "((000067))": "Extend", "((000068))": "Under", "((000069))": "Bottom", - "((000070))": "Custom" + "((000070))": "Custom", + "((000071))": "Checking for Updates..." } } \ No newline at end of file From 0a4c522357429ecbabb9c98aa81ea432b33b0815 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 15:16:52 +0100 Subject: [PATCH 5/9] light up quickaccess if native is hovered --- src/GUI/Widgets/QuickAccess/QuickAccess.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/GUI/Widgets/QuickAccess/QuickAccess.cpp b/src/GUI/Widgets/QuickAccess/QuickAccess.cpp index 4e3189f..6763356 100644 --- a/src/GUI/Widgets/QuickAccess/QuickAccess.cpp +++ b/src/GUI/Widgets/QuickAccess/QuickAccess.cpp @@ -197,7 +197,17 @@ namespace GUI } } - bool newHoverState = ImGui::IsWindowHovered() || isActive; + bool isHoveringNative = false; + if (Location == EQAPosition::Extend) + { + ImVec2 mPos = ImGui::GetMousePos(); + if (mPos.x < pos.x - Offset.x && mPos.y < Renderer::Scaling * size) + { + isHoveringNative = true; + } + } + + bool newHoverState = ImGui::IsWindowHovered() || isActive || isHoveringNative; if (newHoverState != IsHovering) { if (newHoverState) { IsFadingIn = true; } From 661e7f5d96daf4340cc34cdc75fa6db30cf1864f Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:14:46 +0100 Subject: [PATCH 6/9] integrate arc if not nexus-addon --- src/Events/EventHandler.cpp | 8 + src/GUI/Widgets/Addons/CAddonsWindow.cpp | 5 +- src/GUI/Widgets/QuickAccess/QuickAccess.cpp | 2 +- src/Loader/Loader.cpp | 201 ++++++++++++++------ src/Loader/Loader.h | 11 ++ 5 files changed, 172 insertions(+), 55 deletions(-) diff --git a/src/Events/EventHandler.cpp b/src/Events/EventHandler.cpp index 1c46e18..a049fc7 100644 --- a/src/Events/EventHandler.cpp +++ b/src/Events/EventHandler.cpp @@ -8,6 +8,8 @@ #include "Consts.h" #include "Shared.h" +#include "Loader/Loader.h" + namespace Events { std::mutex Mutex; @@ -43,6 +45,12 @@ namespace Events const std::lock_guard lock(Mutex); { Registry[str].push_back(aConsumeEventCallback); + + /* dirty hack for arcdps (I hate my life) */ + if ((str == "EV_ARCDPS_COMBATEVENT_LOCAL_RAW" || str == "EV_ARCDPS_COMBATEVENT_SQUAD_RAW") && !Loader::IsArcdpsLoaded) + { + Loader::DetectArcdps(); + } } } diff --git a/src/GUI/Widgets/Addons/CAddonsWindow.cpp b/src/GUI/Widgets/Addons/CAddonsWindow.cpp index f3035e0..05f632d 100644 --- a/src/GUI/Widgets/Addons/CAddonsWindow.cpp +++ b/src/GUI/Widgets/Addons/CAddonsWindow.cpp @@ -258,7 +258,10 @@ namespace GUI { for (auto& [path, addon] : Loader::Addons) { - if (addon->Definitions != nullptr && addon->Definitions->Signature == libAddon->Signature) + // if libAddon already exist in installed addons + // or if arcdps is loaded another way and the libAddon is arc + if ((addon->Definitions != nullptr && addon->Definitions->Signature == libAddon->Signature) || + (Loader::IsArcdpsLoaded && libAddon->Signature == 0xFFF694D1)) { exists = true; break; diff --git a/src/GUI/Widgets/QuickAccess/QuickAccess.cpp b/src/GUI/Widgets/QuickAccess/QuickAccess.cpp index 6763356..a37d694 100644 --- a/src/GUI/Widgets/QuickAccess/QuickAccess.cpp +++ b/src/GUI/Widgets/QuickAccess/QuickAccess.cpp @@ -201,7 +201,7 @@ namespace GUI if (Location == EQAPosition::Extend) { ImVec2 mPos = ImGui::GetMousePos(); - if (mPos.x < pos.x - Offset.x && mPos.y < Renderer::Scaling * size) + if (mPos.x != -FLT_MAX && mPos.y != -FLT_MAX && mPos.x < pos.x - Offset.x && mPos.y < Renderer::Scaling * size) { isHoveringNative = true; } diff --git a/src/Loader/Loader.cpp b/src/Loader/Loader.cpp index 7196784..3ca62e1 100644 --- a/src/Loader/Loader.cpp +++ b/src/Loader/Loader.cpp @@ -66,6 +66,10 @@ namespace Loader PIDLIST_ABSOLUTE FSItemList; ULONG FSNotifierID; + HMODULE ArcdpsHandle = nullptr; + bool IsArcdpsLoaded = false; + bool IsArcdpsBridgeDeployed = false; + std::string extDll = ".dll"; std::string extUpdate = ".update"; std::string extOld = ".old"; @@ -715,8 +719,17 @@ namespace Loader } } + /* if someone wants to do shenanigans and inject a different integration module */ + if (tmpDefs->Signature == 0xFED81763 && aPath != Path::F_ARCDPSINTEGRATION) + { + FreeLibrary(addon->Module); + addon->State = EAddonState::NotLoadedIncompatible; + addon->Module = nullptr; + return; + } + /* don't load addons that weren't requested or loaded last time (ignore arcdps integration) */ - if (firstLoad && !shouldLoad && tmpDefs->Signature != -19392669) + if (firstLoad && !shouldLoad && tmpDefs->Signature != 0xFED81763) { LogInfo(CH_LOADER, "\"%s\" was not requested via start parameter or last state was disabled. Skipped.", strFile.c_str(), tmpDefs->Signature); FreeLibrary(addon->Module); @@ -768,43 +781,6 @@ namespace Loader GetModuleInformation(GetCurrentProcess(), addon->Module, &moduleInfo, sizeof(moduleInfo)); addon->ModuleSize = moduleInfo.SizeOfImage; - /* arcdps integration detection & deploy */ - typedef int (*addextension2)(HINSTANCE); - addextension2 exp_addextension2 = nullptr; - if (addon->Definitions->Signature == 0xFFF694D1) - { - if (true == FindFunction(addon->Module, &exp_addextension2, "addextension2")) - { - LPVOID res{}; DWORD sz{}; - GetResource(NexusHandle, MAKEINTRESOURCE(RES_ARCDPS_INTEGRATION), "DLL", &res, &sz); - - try - { - if (std::filesystem::exists(Path::F_ARCDPSINTEGRATION)) - { - std::filesystem::remove(Path::F_ARCDPSINTEGRATION); - } - - std::ofstream file(Path::F_ARCDPSINTEGRATION, std::ios::binary); - file.write((const char*)res, sz); - file.close(); - - // reload is set to true because the dll is always deployed from resource - // and since it's locked it would not load here directly but instead after checking for updates (which does not apply to it) - LoadAddon(Path::F_ARCDPSINTEGRATION, true); - } - catch (std::filesystem::filesystem_error fErr) - { - LogDebug(CH_LOADER, "%s", fErr.what()); - return; - } - } - else - { - LogWarning(CH_LOADER, "Addon with signature \"0xFFF694D1\" found but \"addextension2\" is not exported. ArcDPS combat events won't be relayed."); - } - } - addon->Definitions->Load(api); Events::Raise(EV_ADDON_LOADED, &addon->Definitions->Signature); Events::Raise(EV_MUMBLE_IDENTITY_UPDATED, MumbleIdentity); @@ -822,23 +798,17 @@ namespace Loader LogInfo(CH_LOADER, "Loaded addon: %s (Signature %d) [%p - %p] (API Version %d was requested.)", strFile.c_str(), addon->Definitions->Signature, addon->Module, ((PBYTE)addon->Module) + moduleInfo.SizeOfImage, addon->Definitions->APIVersion); } - /* arcdps integration initialisation */ - if (exp_addextension2) + /* if arcdps */ + if (addon->Definitions->Signature == 0xFFF694D1) { - auto it = Addons.find(Path::F_ARCDPSINTEGRATION); + ArcdpsHandle = addon->Module; + IsArcdpsLoaded = true; - if (it != Addons.end()) - { - if (it->second->Module) - { - int result = exp_addextension2(it->second->Module); - LogInfo(CH_LOADER, "Deployed ArcDPS Integration. Result: %d", result); - } - else - { - LogWarning(CH_LOADER, "ArcDPS Integration module was null."); - } - } + DeployArcdpsBridge(); + } + else if (addon->Definitions->Signature == 0xFED81763 && ArcdpsHandle) /* if arcdps bridge */ + { + InitializeArcdpsBridge(addon->Module); } } void UnloadAddon(const std::filesystem::path& aPath, bool aIsShutdown) @@ -1714,4 +1684,129 @@ namespace Loader return "(null)"; } + + void DetectArcdps() + { + if (IsArcdpsLoaded) + { + return; + } + + // The following code is a bit ugly and repetitive, but this is because for each of these dlls you need to check whether it is arcdps + + if (State::IsChainloading && std::filesystem::exists(Path::F_CHAINLOAD_DLL)) + { + HMODULE hModule = GetModuleHandle(Path::F_CHAINLOAD_DLL.string().c_str()); + + void* func = nullptr; + + if (hModule) + { + if (true == FindFunction(hModule, &func, "addextension2")) + { + ArcdpsHandle = hModule; + IsArcdpsLoaded = true; + + LogInfo(CH_LOADER, "ArcDPS is not loaded as Nexus addon but was detected as Chainload."); + + DeployArcdpsBridge(); + return; + } + } + } + + std::filesystem::path alArc = Path::D_GW2_ADDONS / "arcdps" / "gw2addon_arcdps.dll"; + if (std::filesystem::exists(alArc)) + { + HMODULE hModule = GetModuleHandle(alArc.string().c_str()); + + void* func = nullptr; + + if (hModule) + { + if (true == FindFunction(hModule, &func, "addextension2")) + { + ArcdpsHandle = hModule; + IsArcdpsLoaded = true; + + LogInfo(CH_LOADER, "ArcDPS is not loaded as Nexus addon but was detected as Addon-Loader addon."); + + DeployArcdpsBridge(); + return; + } + } + } + + std::filesystem::path proxyArc = Path::D_GW2 / "d3d11.dll"; + if (std::filesystem::exists(proxyArc)) + { + HMODULE hModule = GetModuleHandle(proxyArc.string().c_str()); + + void* func = nullptr; + + if (hModule) + { + if (true == FindFunction(hModule, &func, "addextension2")) + { + ArcdpsHandle = hModule; + IsArcdpsLoaded = true; + + LogInfo(CH_LOADER, "ArcDPS is not loaded as Nexus addon but was detected as Proxy."); + + DeployArcdpsBridge(); + return; + } + } + } + } + void DeployArcdpsBridge() + { + /* write bridge to disk and queue load */ + LPVOID res{}; DWORD sz{}; + GetResource(NexusHandle, MAKEINTRESOURCE(RES_ARCDPS_INTEGRATION), "DLL", &res, &sz); + + try + { + if (std::filesystem::exists(Path::F_ARCDPSINTEGRATION)) + { + std::filesystem::remove(Path::F_ARCDPSINTEGRATION); + } + + std::ofstream file(Path::F_ARCDPSINTEGRATION, std::ios::binary); + file.write((const char*)res, sz); + file.close(); + + // reload is set to true because the dll is always deployed from resource + // and since it's locked it would not load here directly but instead after checking for updates (which does not apply to it) + QueueAddon(ELoaderAction::Reload, Path::F_ARCDPSINTEGRATION); + } + catch (std::filesystem::filesystem_error fErr) + { + LogDebug(CH_LOADER, "%s", fErr.what()); + return; + } + } + void InitializeArcdpsBridge(HMODULE aBridgeModule) + { + if (IsArcdpsBridgeDeployed || !aBridgeModule || !IsArcdpsLoaded) + { + return; + } + + /* arcdps integration detection & deploy */ + typedef int (*addextension2)(HINSTANCE); + addextension2 exp_addextension2 = nullptr; + + if (true == FindFunction(ArcdpsHandle, &exp_addextension2, "addextension2")) + { + int result = exp_addextension2(aBridgeModule); + LogInfo(CH_LOADER, "Deployed ArcDPS Integration. Result: %d", result); + } + else + { + LogWarning(CH_LOADER, "Addon with signature \"0xFFF694D1\" found but \"addextension2\" is not exported. ArcDPS combat events won't be relayed."); + } + + IsArcdpsBridgeDeployed = true; + } } diff --git a/src/Loader/Loader.h b/src/Loader/Loader.h index f30b38c..889ad60 100644 --- a/src/Loader/Loader.h +++ b/src/Loader/Loader.h @@ -42,6 +42,10 @@ namespace Loader extern PIDLIST_ABSOLUTE FSItemList; extern ULONG FSNotifierID; + extern HMODULE ArcdpsHandle; + extern bool IsArcdpsLoaded; + extern bool IsArcdpsBridgeDeployed; + /* Registers the addon directory update notifications and loads all addons. */ void Initialize(); /* Deregisters the directory updates and unloads all addons. */ @@ -95,6 +99,13 @@ namespace Loader /* HELPER: Returns the name of the owning addon. Similar to ::Verify. */ std::string GetOwner(void* aAddress); + + /* Detect if ArcDPS is not loaded as Nexus addon and deploy bridge if found. */ + void DetectArcdps(); + /* Write ArcDPS Bridge to disk and queue load. */ + void DeployArcdpsBridge(); + /* Initialize ArcDPS Bridge. */ + void InitializeArcdpsBridge(HMODULE aBridgeModule); } #endif \ No newline at end of file From c9929255ad0ee3aaf0e042001987ffb43d98be05 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:08:19 +0100 Subject: [PATCH 7/9] custom texture override --- src/Textures/TextureLoader.cpp | 59 +++++++++++++++++++++++++++++++--- src/Textures/TextureLoader.h | 3 ++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/Textures/TextureLoader.cpp b/src/Textures/TextureLoader.cpp index c17e063..2788b4e 100644 --- a/src/Textures/TextureLoader.cpp +++ b/src/Textures/TextureLoader.cpp @@ -44,7 +44,11 @@ namespace TextureLoader { Texture* result = Get(aIdentifier); - if (!result) + if (OverrideTexture(aIdentifier, nullptr)) + { + return result; + } + else if (!result) { LoadFromFile(aIdentifier, aFilename, nullptr); } @@ -55,7 +59,11 @@ namespace TextureLoader { Texture* result = Get(aIdentifier); - if (!result) + if (OverrideTexture(aIdentifier, nullptr)) + { + return result; + } + else if (!result) { LoadFromResource(aIdentifier, aResourceID, aModule, nullptr); } @@ -66,7 +74,11 @@ namespace TextureLoader { Texture* result = Get(aIdentifier); - if (!result) + if (OverrideTexture(aIdentifier, nullptr)) + { + return result; + } + else if (!result) { LoadFromURL(aIdentifier, aRemote, aEndpoint, nullptr); } @@ -77,7 +89,11 @@ namespace TextureLoader { Texture* result = Get(aIdentifier); - if (!result) + if (OverrideTexture(aIdentifier, nullptr)) + { + return result; + } + else if (!result) { LoadFromMemory(aIdentifier, aData, aSize, nullptr); } @@ -117,6 +133,10 @@ namespace TextureLoader } return; } + else if (OverrideTexture(aIdentifier, aCallback)) + { + return; + } if (!std::filesystem::exists(aFilename)) { @@ -146,6 +166,10 @@ namespace TextureLoader } return; } + else if (OverrideTexture(aIdentifier, aCallback)) + { + return; + } HRSRC imageResHandle = FindResourceA(aModule, MAKEINTRESOURCEA(aResourceID), "PNG"); if (!imageResHandle) @@ -197,6 +221,10 @@ namespace TextureLoader } return; } + else if (OverrideTexture(aIdentifier, aCallback)) + { + return; + } httplib::Client client(aRemote); client.enable_server_certificate_verification(false); @@ -244,6 +272,10 @@ namespace TextureLoader } return; } + else if (OverrideTexture(aIdentifier, aCallback)) + { + return; + } int image_width = 0; int image_height = 0; @@ -253,6 +285,25 @@ namespace TextureLoader QueueTexture(str.c_str(), image_data, image_width, image_height, aCallback); } + bool OverrideTexture(const char* aIdentifier, TEXTURES_RECEIVECALLBACK aCallback) + { + std::string file = aIdentifier; + file.append(".png"); + std::filesystem::path customPath = Path::D_GW2_ADDONS_NEXUS / "Textures" / file.c_str(); + + if (std::filesystem::exists(customPath)) + { + // Load from disk into a raw RGBA buffer + int image_width = 0; + int image_height = 0; + unsigned char* image_data = stbi_load(customPath.string().c_str(), &image_width, &image_height, NULL, 4); + + QueueTexture(aIdentifier, image_data, image_width, image_height, aCallback); + return true; + } + return false; + } + void ProcessQueue() { const std::lock_guard lock(Mutex); diff --git a/src/Textures/TextureLoader.h b/src/Textures/TextureLoader.h index d43d4a3..fd345cd 100644 --- a/src/Textures/TextureLoader.h +++ b/src/Textures/TextureLoader.h @@ -40,6 +40,9 @@ namespace TextureLoader /* Requests to load a texture from memory. */ void LoadFromMemory(const char* aIdentifier, void* aData, size_t aSize, TEXTURES_RECEIVECALLBACK aCallback); + /* Loads a custom user texture from disk if it exists, rather than the provided method. */ + bool OverrideTexture(const char* aIdentifier, TEXTURES_RECEIVECALLBACK aCallback); + /* Processes all currently queued textures. */ void ProcessQueue(); From 5cf712e577eec4a70a8b3a4af2e7c2aae0c1f0d6 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 20:47:37 +0100 Subject: [PATCH 8/9] more localisation support add glyph ranges fix resizing of tabs in addons window --- src/GUI/GUI.cpp | 43 ++++++++++++++++-------- src/GUI/Widgets/Addons/CAddonsWindow.cpp | 12 ++++--- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/GUI/GUI.cpp b/src/GUI/GUI.cpp index a207b6d..919cf58 100644 --- a/src/GUI/GUI.cpp +++ b/src/GUI/GUI.cpp @@ -640,18 +640,33 @@ namespace GUI std::filesystem::path fontPath{}; + ImVector ranges; + + ImFontGlyphRangesBuilder rb{}; + ImWchar rangesLatinExt[] = + { + 0x0100, 0x017F, + 0x0180, 0x024F, + 0, + }; + rb.AddRanges(io.Fonts->GetGlyphRangesDefault()); + rb.AddRanges(rangesLatinExt); + rb.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); + rb.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); + rb.BuildRanges(&ranges); + /* add user font, or fallback to default */ if (!LinkArcDPSStyle && std::filesystem::exists(Path::F_FONT)) { fontPath = Path::F_FONT; std::string strFont = Path::F_FONT.string(); - io.Fonts->AddFontFromFileTTF(strFont.c_str(), FontSize, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); + io.Fonts->AddFontFromFileTTF(strFont.c_str(), FontSize, nullptr, ranges.Data); } else if (LinkArcDPSStyle && std::filesystem::exists(Path::D_GW2_ADDONS / "arcdps" / "arcdps_font.ttf")) { fontPath = Path::D_GW2_ADDONS / "arcdps" / "arcdps_font.ttf"; std::string strFont = (Path::D_GW2_ADDONS / "arcdps" / "arcdps_font.ttf").string(); - io.Fonts->AddFontFromFileTTF(strFont.c_str(), FontSize, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); + io.Fonts->AddFontFromFileTTF(strFont.c_str(), FontSize, nullptr, ranges.Data); } else { @@ -673,35 +688,35 @@ namespace GUI /* small UI*/ FontIndex.emplace(EFont::Menomonia_Small, io.Fonts->AddFontFromMemoryTTF(resM, szM, 16.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 16.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 16.0f, &config, ranges.Data); } FontIndex.emplace(EFont::MenomoniaBig_Small, io.Fonts->AddFontFromMemoryTTF(resM, szM, 22.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 22.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 22.0f, &config, ranges.Data); } FontIndex.emplace(EFont::Trebuchet_Small, io.Fonts->AddFontFromMemoryTTF(resT, szT, 15.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 15.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 15.0f, &config, ranges.Data); } /* normal UI*/ FontIndex.emplace(EFont::Menomonia_Normal, io.Fonts->AddFontFromMemoryTTF(resM, szM, 18.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 18.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 18.0f, &config, ranges.Data); } FontIndex.emplace(EFont::MenomoniaBig_Normal, io.Fonts->AddFontFromMemoryTTF(resM, szM, 24.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 24.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 24.0f, &config, ranges.Data); } FontIndex.emplace(EFont::Trebuchet_Normal, io.Fonts->AddFontFromMemoryTTF(resT, szT, 16.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 16.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 16.0f, &config, ranges.Data); } /* large UI*/ FontIndex.emplace(EFont::Menomonia_Large, io.Fonts->AddFontFromMemoryTTF(resM, szM, 20.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 20.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 20.0f, &config, ranges.Data); } FontIndex.emplace(EFont::MenomoniaBig_Large, io.Fonts->AddFontFromMemoryTTF(resM, szM, 26.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 26.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 26.0f, &config, ranges.Data); } FontIndex.emplace(EFont::Trebuchet_Large, io.Fonts->AddFontFromMemoryTTF(resT, szT, 17.5f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 17.5f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 17.5f, &config, ranges.Data); } /* larger UI*/ FontIndex.emplace(EFont::Menomonia_Larger, io.Fonts->AddFontFromMemoryTTF(resM, szM, 22.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 22.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 22.0f, &config, ranges.Data); } FontIndex.emplace(EFont::MenomoniaBig_Larger, io.Fonts->AddFontFromMemoryTTF(resM, szM, 28.0f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 28.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 28.0f, &config, ranges.Data); } FontIndex.emplace(EFont::Trebuchet_Larger, io.Fonts->AddFontFromMemoryTTF(resT, szT, 19.5f)); - if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 19.5f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); } + if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 19.5f, &config, ranges.Data); } } io.Fonts->Build(); diff --git a/src/GUI/Widgets/Addons/CAddonsWindow.cpp b/src/GUI/Widgets/Addons/CAddonsWindow.cpp index 05f632d..37f4180 100644 --- a/src/GUI/Widgets/Addons/CAddonsWindow.cpp +++ b/src/GUI/Widgets/Addons/CAddonsWindow.cpp @@ -106,8 +106,12 @@ namespace GUI ImVec2 text1sz = ImGui::CalcTextSize(Language.Translate("((000031))")); ImVec2 text2sz = ImGui::CalcTextSize(Language.Translate("((000032))")); - ImVec2 text1offset = ImVec2(((92.0f * Renderer::Scaling) - text1sz.x) / 2, ((24.0f * Renderer::Scaling) - text1sz.y) / 2); - ImVec2 text2offset = ImVec2(((92.0f * Renderer::Scaling) - text2sz.x) / 2, ((24.0f * Renderer::Scaling) - text2sz.y) / 2); + + float tab1width = 92.0f > text1sz.x ? 92.0f : text1sz.x + 50.0f; + float tab2width = 92.0f > text2sz.x ? 92.0f : text2sz.x + 50.0f; + + ImVec2 text1offset = ImVec2(((tab1width * Renderer::Scaling) - text1sz.x) / 2, ((24.0f * Renderer::Scaling) - text1sz.y) / 2); + ImVec2 text2offset = ImVec2(((tab2width * Renderer::Scaling) - text2sz.x) / 2, ((24.0f * Renderer::Scaling) - text2sz.y) / 2); ImVec2 tab1origin = ImGui::GetCursorPos(); // 28.0f, 28.0f @@ -116,7 +120,7 @@ namespace GUI ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); - if (ImGui::ImageButton(!Tab1Hovered ? TabBtn->Resource : TabBtnHover->Resource, ImVec2(92.0f * Renderer::Scaling, 24.0f * Renderer::Scaling))) + if (ImGui::ImageButton(!Tab1Hovered ? TabBtn->Resource : TabBtnHover->Resource, ImVec2(tab1width * Renderer::Scaling, 24.0f * Renderer::Scaling))) { TabIndex = 0; } @@ -126,7 +130,7 @@ namespace GUI ImVec2 tab2origin = ImGui::GetCursorPos(); - if (ImGui::ImageButton(!Tab2Hovered ? TabBtn->Resource : TabBtnHover->Resource, ImVec2(92.0f * Renderer::Scaling, 24.0f * Renderer::Scaling))) + if (ImGui::ImageButton(!Tab2Hovered ? TabBtn->Resource : TabBtnHover->Resource, ImVec2(tab2width * Renderer::Scaling, 24.0f * Renderer::Scaling))) { TabIndex = 1; } From 903a817a4de1241604f8deb83cd9758ab213c0d0 Mon Sep 17 00:00:00 2001 From: Delta <46466697+DeltaGW2@users.noreply.github.com> Date: Sun, 17 Mar 2024 20:55:33 +0100 Subject: [PATCH 9/9] gw2 font glyphranges --- src/GUI/GUI.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/GUI/GUI.cpp b/src/GUI/GUI.cpp index 919cf58..36281d1 100644 --- a/src/GUI/GUI.cpp +++ b/src/GUI/GUI.cpp @@ -687,35 +687,35 @@ namespace GUI config.MergeMode = true; /* small UI*/ - FontIndex.emplace(EFont::Menomonia_Small, io.Fonts->AddFontFromMemoryTTF(resM, szM, 16.0f)); + FontIndex.emplace(EFont::Menomonia_Small, io.Fonts->AddFontFromMemoryTTF(resM, szM, 16.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 16.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::MenomoniaBig_Small, io.Fonts->AddFontFromMemoryTTF(resM, szM, 22.0f)); + FontIndex.emplace(EFont::MenomoniaBig_Small, io.Fonts->AddFontFromMemoryTTF(resM, szM, 22.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 22.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::Trebuchet_Small, io.Fonts->AddFontFromMemoryTTF(resT, szT, 15.0f)); + FontIndex.emplace(EFont::Trebuchet_Small, io.Fonts->AddFontFromMemoryTTF(resT, szT, 15.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 15.0f, &config, ranges.Data); } /* normal UI*/ - FontIndex.emplace(EFont::Menomonia_Normal, io.Fonts->AddFontFromMemoryTTF(resM, szM, 18.0f)); + FontIndex.emplace(EFont::Menomonia_Normal, io.Fonts->AddFontFromMemoryTTF(resM, szM, 18.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 18.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::MenomoniaBig_Normal, io.Fonts->AddFontFromMemoryTTF(resM, szM, 24.0f)); + FontIndex.emplace(EFont::MenomoniaBig_Normal, io.Fonts->AddFontFromMemoryTTF(resM, szM, 24.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 24.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::Trebuchet_Normal, io.Fonts->AddFontFromMemoryTTF(resT, szT, 16.0f)); + FontIndex.emplace(EFont::Trebuchet_Normal, io.Fonts->AddFontFromMemoryTTF(resT, szT, 16.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 16.0f, &config, ranges.Data); } /* large UI*/ - FontIndex.emplace(EFont::Menomonia_Large, io.Fonts->AddFontFromMemoryTTF(resM, szM, 20.0f)); + FontIndex.emplace(EFont::Menomonia_Large, io.Fonts->AddFontFromMemoryTTF(resM, szM, 20.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 20.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::MenomoniaBig_Large, io.Fonts->AddFontFromMemoryTTF(resM, szM, 26.0f)); + FontIndex.emplace(EFont::MenomoniaBig_Large, io.Fonts->AddFontFromMemoryTTF(resM, szM, 26.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 26.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::Trebuchet_Large, io.Fonts->AddFontFromMemoryTTF(resT, szT, 17.5f)); + FontIndex.emplace(EFont::Trebuchet_Large, io.Fonts->AddFontFromMemoryTTF(resT, szT, 17.5f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 17.5f, &config, ranges.Data); } /* larger UI*/ - FontIndex.emplace(EFont::Menomonia_Larger, io.Fonts->AddFontFromMemoryTTF(resM, szM, 22.0f)); + FontIndex.emplace(EFont::Menomonia_Larger, io.Fonts->AddFontFromMemoryTTF(resM, szM, 22.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 22.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::MenomoniaBig_Larger, io.Fonts->AddFontFromMemoryTTF(resM, szM, 28.0f)); + FontIndex.emplace(EFont::MenomoniaBig_Larger, io.Fonts->AddFontFromMemoryTTF(resM, szM, 28.0f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 28.0f, &config, ranges.Data); } - FontIndex.emplace(EFont::Trebuchet_Larger, io.Fonts->AddFontFromMemoryTTF(resT, szT, 19.5f)); + FontIndex.emplace(EFont::Trebuchet_Larger, io.Fonts->AddFontFromMemoryTTF(resT, szT, 19.5f, 0, ranges.Data)); if (!fontPath.empty()) { io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(), 19.5f, &config, ranges.Data); } }