mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-02 13:53:40 +01:00
Merge branch 'imgui-bindings' into api13
# Conflicts: # Dalamud/Game/Gui/GameGui.cs # Dalamud/Interface/Internal/UiDebug.cs # Dalamud/Interface/Internal/Windows/Data/Widgets/AddonWidget.cs # Dalamud/Interface/Internal/Windows/SelfTest/Steps/ItemPayloadSelfTestStep.cs
This commit is contained in:
commit
bd52c60c6f
1006 changed files with 1126138 additions and 4022 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -328,3 +328,6 @@ ASALocalRun/
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
.mfractor/
|
.mfractor/
|
||||||
|
|
||||||
|
# HexaGen generated files
|
||||||
|
#imgui/**/Generated/**/*
|
||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -1,6 +1,3 @@
|
||||||
[submodule "lib/ImGuiScene"]
|
|
||||||
path = lib/ImGuiScene
|
|
||||||
url = https://github.com/goatcorp/ImGuiScene
|
|
||||||
[submodule "lib/FFXIVClientStructs"]
|
[submodule "lib/FFXIVClientStructs"]
|
||||||
path = lib/FFXIVClientStructs
|
path = lib/FFXIVClientStructs
|
||||||
url = https://github.com/aers/FFXIVClientStructs
|
url = https://github.com/aers/FFXIVClientStructs
|
||||||
|
|
@ -19,3 +16,6 @@
|
||||||
[submodule "lib/cimguizmo"]
|
[submodule "lib/cimguizmo"]
|
||||||
path = lib/cimguizmo
|
path = lib/cimguizmo
|
||||||
url = https://github.com/goatcorp/gc-cimguizmo
|
url = https://github.com/goatcorp/gc-cimguizmo
|
||||||
|
[submodule "lib/Hexa.NET.ImGui"]
|
||||||
|
path = lib/Hexa.NET.ImGui
|
||||||
|
url = https://github.com/goatcorp/Hexa.NET.ImGui.git
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<PreprocessorDefinitions>CPPDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>CPPDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
|
@ -66,6 +65,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
|
||||||
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">26812</DisableSpecificWarnings>
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">26812</DisableSpecificWarnings>
|
||||||
|
|
@ -80,6 +80,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
|
||||||
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">26812</DisableSpecificWarnings>
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">26812</DisableSpecificWarnings>
|
||||||
|
|
@ -203,7 +204,6 @@
|
||||||
<Target Name="CopyOutputDlls" AfterTargets="PostBuildEvent">
|
<Target Name="CopyOutputDlls" AfterTargets="PostBuildEvent">
|
||||||
<Copy SourceFiles="$(OutDir)$(TargetName).dll" DestinationFolder="..\bin\$(Configuration)\" />
|
<Copy SourceFiles="$(OutDir)$(TargetName).dll" DestinationFolder="..\bin\$(Configuration)\" />
|
||||||
<Copy SourceFiles="$(OutDir)$(TargetName).pdb" DestinationFolder="..\bin\$(Configuration)\" />
|
<Copy SourceFiles="$(OutDir)$(TargetName).pdb" DestinationFolder="..\bin\$(Configuration)\" />
|
||||||
|
|
||||||
<Copy SourceFiles="$(OutDir)nethost.dll" DestinationFolder="..\bin\$(Configuration)\" />
|
<Copy SourceFiles="$(OutDir)nethost.dll" DestinationFolder="..\bin\$(Configuration)\" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ void from_json(const nlohmann::json& json, DalamudStartInfo& config) {
|
||||||
config.NoLoadThirdPartyPlugins = json.value("NoLoadThirdPartyPlugins", config.NoLoadThirdPartyPlugins);
|
config.NoLoadThirdPartyPlugins = json.value("NoLoadThirdPartyPlugins", config.NoLoadThirdPartyPlugins);
|
||||||
|
|
||||||
config.BootLogPath = json.value("BootLogPath", config.BootLogPath);
|
config.BootLogPath = json.value("BootLogPath", config.BootLogPath);
|
||||||
|
config.BootDebugDirectX = json.value("BootDebugDirectX", config.BootDebugDirectX);
|
||||||
config.BootShowConsole = json.value("BootShowConsole", config.BootShowConsole);
|
config.BootShowConsole = json.value("BootShowConsole", config.BootShowConsole);
|
||||||
config.BootDisableFallbackConsole = json.value("BootDisableFallbackConsole", config.BootDisableFallbackConsole);
|
config.BootDisableFallbackConsole = json.value("BootDisableFallbackConsole", config.BootDisableFallbackConsole);
|
||||||
config.BootWaitMessageBox = json.value("BootWaitMessageBox", config.BootWaitMessageBox);
|
config.BootWaitMessageBox = json.value("BootWaitMessageBox", config.BootWaitMessageBox);
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ struct DalamudStartInfo {
|
||||||
bool NoLoadThirdPartyPlugins;
|
bool NoLoadThirdPartyPlugins;
|
||||||
|
|
||||||
std::string BootLogPath;
|
std::string BootLogPath;
|
||||||
|
bool BootDebugDirectX = false;
|
||||||
bool BootShowConsole = false;
|
bool BootShowConsole = false;
|
||||||
bool BootDisableFallbackConsole = false;
|
bool BootDisableFallbackConsole = false;
|
||||||
WaitMessageboxFlags BootWaitMessageBox = WaitMessageboxFlags::None;
|
WaitMessageboxFlags BootWaitMessageBox = WaitMessageboxFlags::None;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <dxgi1_3.h>
|
||||||
|
|
||||||
#include "DalamudStartInfo.h"
|
#include "DalamudStartInfo.h"
|
||||||
|
#include "hooks.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "veh.h"
|
#include "veh.h"
|
||||||
|
|
@ -90,6 +94,69 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
||||||
if ((g_startInfo.BootWaitMessageBox & DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize) != DalamudStartInfo::WaitMessageboxFlags::None)
|
if ((g_startInfo.BootWaitMessageBox & DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize) != DalamudStartInfo::WaitMessageboxFlags::None)
|
||||||
MessageBoxW(nullptr, L"Press OK to continue (BeforeInitialize)", L"Dalamud Boot", MB_OK);
|
MessageBoxW(nullptr, L"Press OK to continue (BeforeInitialize)", L"Dalamud Boot", MB_OK);
|
||||||
|
|
||||||
|
if (g_startInfo.BootDebugDirectX) {
|
||||||
|
logging::I("Enabling DirectX Debugging.");
|
||||||
|
|
||||||
|
const auto hD3D11 = GetModuleHandleW(L"d3d11.dll");
|
||||||
|
const auto hDXGI = GetModuleHandleW(L"dxgi.dll");
|
||||||
|
const auto pfnD3D11CreateDevice = static_cast<decltype(&D3D11CreateDevice)>(
|
||||||
|
hD3D11 ? static_cast<void*>(GetProcAddress(hD3D11, "D3D11CreateDevice")) : nullptr);
|
||||||
|
if (pfnD3D11CreateDevice) {
|
||||||
|
static hooks::direct_hook<decltype(D3D11CreateDevice)> s_hookD3D11CreateDevice(
|
||||||
|
"d3d11.dll!D3D11CreateDevice",
|
||||||
|
pfnD3D11CreateDevice);
|
||||||
|
s_hookD3D11CreateDevice.set_detour([](
|
||||||
|
IDXGIAdapter* pAdapter,
|
||||||
|
D3D_DRIVER_TYPE DriverType,
|
||||||
|
HMODULE Software,
|
||||||
|
UINT Flags,
|
||||||
|
const D3D_FEATURE_LEVEL* pFeatureLevels,
|
||||||
|
UINT FeatureLevels,
|
||||||
|
UINT SDKVersion,
|
||||||
|
ID3D11Device** ppDevice,
|
||||||
|
D3D_FEATURE_LEVEL* pFeatureLevel,
|
||||||
|
ID3D11DeviceContext** ppImmediateContext
|
||||||
|
) -> HRESULT {
|
||||||
|
return s_hookD3D11CreateDevice.call_original(
|
||||||
|
pAdapter,
|
||||||
|
DriverType,
|
||||||
|
Software,
|
||||||
|
(Flags & ~D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY) | D3D11_CREATE_DEVICE_DEBUG,
|
||||||
|
pFeatureLevels,
|
||||||
|
FeatureLevels,
|
||||||
|
SDKVersion,
|
||||||
|
ppDevice,
|
||||||
|
pFeatureLevel,
|
||||||
|
ppImmediateContext);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logging::W("Could not find d3d11!D3D11CreateDevice.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto pfnCreateDXGIFactory = static_cast<decltype(&CreateDXGIFactory)>(
|
||||||
|
hDXGI ? static_cast<void*>(GetProcAddress(hDXGI, "CreateDXGIFactory")) : nullptr);
|
||||||
|
const auto pfnCreateDXGIFactory1 = static_cast<decltype(&CreateDXGIFactory1)>(
|
||||||
|
hDXGI ? static_cast<void*>(GetProcAddress(hDXGI, "CreateDXGIFactory1")) : nullptr);
|
||||||
|
static const auto pfnCreateDXGIFactory2 = static_cast<decltype(&CreateDXGIFactory2)>(
|
||||||
|
hDXGI ? static_cast<void*>(GetProcAddress(hDXGI, "CreateDXGIFactory2")) : nullptr);
|
||||||
|
if (pfnCreateDXGIFactory2) {
|
||||||
|
static hooks::direct_hook<decltype(CreateDXGIFactory)> s_hookCreateDXGIFactory(
|
||||||
|
"dxgi.dll!CreateDXGIFactory",
|
||||||
|
pfnCreateDXGIFactory);
|
||||||
|
static hooks::direct_hook<decltype(CreateDXGIFactory1)> s_hookCreateDXGIFactory1(
|
||||||
|
"dxgi.dll!CreateDXGIFactory1",
|
||||||
|
pfnCreateDXGIFactory1);
|
||||||
|
s_hookCreateDXGIFactory.set_detour([](REFIID riid, _COM_Outptr_ void **ppFactory) -> HRESULT {
|
||||||
|
return pfnCreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, ppFactory);
|
||||||
|
});
|
||||||
|
s_hookCreateDXGIFactory1.set_detour([](REFIID riid, _COM_Outptr_ void **ppFactory) -> HRESULT {
|
||||||
|
return pfnCreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, ppFactory);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logging::W("Could not find dxgi!CreateDXGIFactory2.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (minHookLoaded) {
|
if (minHookLoaded) {
|
||||||
logging::I("Applying fixes...");
|
logging::I("Applying fixes...");
|
||||||
xivfixes::apply_all(true);
|
xivfixes::apply_all(true);
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,11 @@ public record DalamudStartInfo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool BootShowConsole { get; set; }
|
public bool BootShowConsole { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether to enable D3D11 and DXGI debugging if possible.
|
||||||
|
/// </summary>
|
||||||
|
public bool BootDebugDirectX { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether the fallback console should be shown, if needed.
|
/// Gets or sets a value indicating whether the fallback console should be shown, if needed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,6 @@
|
||||||
<ProjectReference Include="..\Dalamud\Dalamud.csproj">
|
<ProjectReference Include="..\Dalamud\Dalamud.csproj">
|
||||||
<Private>false</Private>
|
<Private>false</Private>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj">
|
|
||||||
<Private>false</Private>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\lib\ImGuiScene\ImGuiScene\ImGuiScene.csproj">
|
|
||||||
<Private>false</Private>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj">
|
|
||||||
<Private>false</Private>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.CorePlugin
|
namespace Dalamud.CorePlugin
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<PreprocessorDefinitions>CPPDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>CPPDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
|
@ -56,6 +55,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ namespace Dalamud.Injector
|
||||||
|
|
||||||
startInfo = ExtractAndInitializeStartInfoFromArguments(startInfo, args);
|
startInfo = ExtractAndInitializeStartInfoFromArguments(startInfo, args);
|
||||||
// Remove already handled arguments
|
// Remove already handled arguments
|
||||||
|
args.Remove("--debug-directx");
|
||||||
args.Remove("--console");
|
args.Remove("--console");
|
||||||
args.Remove("--msgbox1");
|
args.Remove("--msgbox1");
|
||||||
args.Remove("--msgbox2");
|
args.Remove("--msgbox2");
|
||||||
|
|
@ -464,6 +465,7 @@ namespace Dalamud.Injector
|
||||||
startInfo.LogName ??= string.Empty;
|
startInfo.LogName ??= string.Empty;
|
||||||
|
|
||||||
// Set boot defaults
|
// Set boot defaults
|
||||||
|
startInfo.BootDebugDirectX = args.Contains("--debug-directx");
|
||||||
startInfo.BootShowConsole = args.Contains("--console");
|
startInfo.BootShowConsole = args.Contains("--console");
|
||||||
startInfo.BootEnableEtw = args.Contains("--etw");
|
startInfo.BootEnableEtw = args.Contains("--etw");
|
||||||
startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);
|
startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);
|
||||||
|
|
|
||||||
58
Dalamud.sln
58
Dalamud.sln
|
|
@ -32,12 +32,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud.Test", "Dalamud.Tes
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{E15BDA6D-E881-4482-94BA-BE5527E917FF}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{E15BDA6D-E881-4482-94BA-BE5527E917FF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGui.NET-472", "lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj", "{0483026E-C6CE-4B1A-AA68-46544C08140B}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGuiScene", "lib\ImGuiScene\ImGuiScene\ImGuiScene.csproj", "{C0E7E797-4FBF-4F46-BC57-463F3719BA7A}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDL2-CS", "lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj", "{2F7FF0A8-B619-4572-86C7-71E46FE22FB8}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud.CorePlugin", "Dalamud.CorePlugin\Dalamud.CorePlugin.csproj", "{4AFDB34A-7467-4D41-B067-53BC4101D9D0}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud.CorePlugin", "Dalamud.CorePlugin\Dalamud.CorePlugin.csproj", "{4AFDB34A-7467-4D41-B067-53BC4101D9D0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFXIVClientStructs", "lib\FFXIVClientStructs\FFXIVClientStructs\FFXIVClientStructs.csproj", "{C9B87BD7-AF49-41C3-91F1-D550ADEB7833}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFXIVClientStructs", "lib\FFXIVClientStructs\FFXIVClientStructs\FFXIVClientStructs.csproj", "{C9B87BD7-AF49-41C3-91F1-D550ADEB7833}"
|
||||||
|
|
@ -68,6 +62,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cimplot", "external\cimplot
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cimguizmo", "external\cimguizmo\cimguizmo.vcxproj", "{F258347D-31BE-4605-98CE-40E43BDF6F9D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cimguizmo", "external\cimguizmo\cimguizmo.vcxproj", "{F258347D-31BE-4605-98CE-40E43BDF6F9D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Bindings.ImGui", "imgui\Dalamud.Bindings.ImGui\Dalamud.Bindings.ImGui.csproj", "{B0AA8737-33A3-4766-8CBE-A48F2EF283BA}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Bindings.ImGuizmo", "imgui\Dalamud.Bindings.ImGuizmo\Dalamud.Bindings.ImGuizmo.csproj", "{5E6EDD75-AE95-43A6-9D67-95B840EB4B71}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Bindings.ImPlot", "imgui\Dalamud.Bindings.ImPlot\Dalamud.Bindings.ImPlot.csproj", "{9C70BD06-D52C-425E-9C14-5D66BC6046EF}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bindings", "Bindings", "{A217B3DF-607A-4EFB-B107-3C4809348043}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneImGuiTestbed", "imgui\StandaloneImGuiTestbed\StandaloneImGuiTestbed.csproj", "{4702A911-2513-478C-A434-2776393FDE77}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImGuiScene", "imgui\ImGuiScene\ImGuiScene.csproj", "{66753AC7-0029-4373-9CC4-7760B1F46141}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -98,18 +104,6 @@ Global
|
||||||
{C8004563-1806-4329-844F-0EF6274291FC}.Debug|Any CPU.Build.0 = Debug|x64
|
{C8004563-1806-4329-844F-0EF6274291FC}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{C8004563-1806-4329-844F-0EF6274291FC}.Release|Any CPU.ActiveCfg = Release|x64
|
{C8004563-1806-4329-844F-0EF6274291FC}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
{C8004563-1806-4329-844F-0EF6274291FC}.Release|Any CPU.Build.0 = Release|x64
|
{C8004563-1806-4329-844F-0EF6274291FC}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|Any CPU.ActiveCfg = Debug|x64
|
|
||||||
{0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|Any CPU.Build.0 = Debug|x64
|
|
||||||
{0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|Any CPU.ActiveCfg = Release|x64
|
|
||||||
{0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|Any CPU.Build.0 = Release|x64
|
|
||||||
{C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|Any CPU.ActiveCfg = Debug|x64
|
|
||||||
{C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|Any CPU.Build.0 = Debug|x64
|
|
||||||
{C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|Any CPU.ActiveCfg = Release|x64
|
|
||||||
{C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|Any CPU.Build.0 = Release|x64
|
|
||||||
{2F7FF0A8-B619-4572-86C7-71E46FE22FB8}.Debug|Any CPU.ActiveCfg = Debug|x64
|
|
||||||
{2F7FF0A8-B619-4572-86C7-71E46FE22FB8}.Debug|Any CPU.Build.0 = Debug|x64
|
|
||||||
{2F7FF0A8-B619-4572-86C7-71E46FE22FB8}.Release|Any CPU.ActiveCfg = Release|x64
|
|
||||||
{2F7FF0A8-B619-4572-86C7-71E46FE22FB8}.Release|Any CPU.Build.0 = Release|x64
|
|
||||||
{4AFDB34A-7467-4D41-B067-53BC4101D9D0}.Debug|Any CPU.ActiveCfg = Debug|x64
|
{4AFDB34A-7467-4D41-B067-53BC4101D9D0}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
{4AFDB34A-7467-4D41-B067-53BC4101D9D0}.Debug|Any CPU.Build.0 = Debug|x64
|
{4AFDB34A-7467-4D41-B067-53BC4101D9D0}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{4AFDB34A-7467-4D41-B067-53BC4101D9D0}.Release|Any CPU.ActiveCfg = Release|x64
|
{4AFDB34A-7467-4D41-B067-53BC4101D9D0}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
|
@ -154,6 +148,26 @@ Global
|
||||||
{F258347D-31BE-4605-98CE-40E43BDF6F9D}.Debug|Any CPU.Build.0 = Debug|x64
|
{F258347D-31BE-4605-98CE-40E43BDF6F9D}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{F258347D-31BE-4605-98CE-40E43BDF6F9D}.Release|Any CPU.ActiveCfg = Release|x64
|
{F258347D-31BE-4605-98CE-40E43BDF6F9D}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
{F258347D-31BE-4605-98CE-40E43BDF6F9D}.Release|Any CPU.Build.0 = Release|x64
|
{F258347D-31BE-4605-98CE-40E43BDF6F9D}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{B0AA8737-33A3-4766-8CBE-A48F2EF283BA}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{B0AA8737-33A3-4766-8CBE-A48F2EF283BA}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{B0AA8737-33A3-4766-8CBE-A48F2EF283BA}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{B0AA8737-33A3-4766-8CBE-A48F2EF283BA}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{5E6EDD75-AE95-43A6-9D67-95B840EB4B71}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{5E6EDD75-AE95-43A6-9D67-95B840EB4B71}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{5E6EDD75-AE95-43A6-9D67-95B840EB4B71}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{5E6EDD75-AE95-43A6-9D67-95B840EB4B71}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{9C70BD06-D52C-425E-9C14-5D66BC6046EF}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{9C70BD06-D52C-425E-9C14-5D66BC6046EF}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{9C70BD06-D52C-425E-9C14-5D66BC6046EF}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{9C70BD06-D52C-425E-9C14-5D66BC6046EF}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{4702A911-2513-478C-A434-2776393FDE77}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{4702A911-2513-478C-A434-2776393FDE77}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{4702A911-2513-478C-A434-2776393FDE77}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{4702A911-2513-478C-A434-2776393FDE77}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{66753AC7-0029-4373-9CC4-7760B1F46141}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{66753AC7-0029-4373-9CC4-7760B1F46141}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{66753AC7-0029-4373-9CC4-7760B1F46141}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{66753AC7-0029-4373-9CC4-7760B1F46141}.Release|Any CPU.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -161,9 +175,6 @@ Global
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{5B832F73-5F54-4ADC-870F-D0095EF72C9A} = {19775C83-7117-4A5F-AA00-18889F46A490}
|
{5B832F73-5F54-4ADC-870F-D0095EF72C9A} = {19775C83-7117-4A5F-AA00-18889F46A490}
|
||||||
{8874326B-E755-4D13-90B4-59AB263A3E6B} = {19775C83-7117-4A5F-AA00-18889F46A490}
|
{8874326B-E755-4D13-90B4-59AB263A3E6B} = {19775C83-7117-4A5F-AA00-18889F46A490}
|
||||||
{0483026E-C6CE-4B1A-AA68-46544C08140B} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
|
||||||
{C0E7E797-4FBF-4F46-BC57-463F3719BA7A} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
|
||||||
{2F7FF0A8-B619-4572-86C7-71E46FE22FB8} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
|
||||||
{4AFDB34A-7467-4D41-B067-53BC4101D9D0} = {8F079208-C227-4D96-9427-2BEBE0003944}
|
{4AFDB34A-7467-4D41-B067-53BC4101D9D0} = {8F079208-C227-4D96-9427-2BEBE0003944}
|
||||||
{C9B87BD7-AF49-41C3-91F1-D550ADEB7833} = {8BBACF2D-7AB8-4610-A115-0E363D35C291}
|
{C9B87BD7-AF49-41C3-91F1-D550ADEB7833} = {8BBACF2D-7AB8-4610-A115-0E363D35C291}
|
||||||
{E0D51896-604F-4B40-8CFE-51941607B3A1} = {8BBACF2D-7AB8-4610-A115-0E363D35C291}
|
{E0D51896-604F-4B40-8CFE-51941607B3A1} = {8BBACF2D-7AB8-4610-A115-0E363D35C291}
|
||||||
|
|
@ -175,6 +186,11 @@ Global
|
||||||
{8BBACF2D-7AB8-4610-A115-0E363D35C291} = {E15BDA6D-E881-4482-94BA-BE5527E917FF}
|
{8BBACF2D-7AB8-4610-A115-0E363D35C291} = {E15BDA6D-E881-4482-94BA-BE5527E917FF}
|
||||||
{76CAA246-C405-4A8C-B0AE-F4A0EF3D4E16} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
{76CAA246-C405-4A8C-B0AE-F4A0EF3D4E16} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
||||||
{F258347D-31BE-4605-98CE-40E43BDF6F9D} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
{F258347D-31BE-4605-98CE-40E43BDF6F9D} = {DBE5345E-6594-4A59-B183-1C3D5592269D}
|
||||||
|
{B0AA8737-33A3-4766-8CBE-A48F2EF283BA} = {A217B3DF-607A-4EFB-B107-3C4809348043}
|
||||||
|
{5E6EDD75-AE95-43A6-9D67-95B840EB4B71} = {A217B3DF-607A-4EFB-B107-3C4809348043}
|
||||||
|
{9C70BD06-D52C-425E-9C14-5D66BC6046EF} = {A217B3DF-607A-4EFB-B107-3C4809348043}
|
||||||
|
{4702A911-2513-478C-A434-2776393FDE77} = {A217B3DF-607A-4EFB-B107-3C4809348043}
|
||||||
|
{66753AC7-0029-4373-9CC4-7760B1F46141} = {A217B3DF-607A-4EFB-B107-3C4809348043}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {79B65AC9-C940-410E-AB61-7EA7E12C7599}
|
SolutionGuid = {79B65AC9-C940-410E-AB61-7EA7E12C7599}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ using Dalamud.Utility;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
namespace Dalamud.Configuration.Internal;
|
namespace Dalamud.Configuration.Internal;
|
||||||
|
|
||||||
|
|
@ -592,11 +593,15 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
||||||
{
|
{
|
||||||
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gfx/animation/animation_win.cc;l=29?q=ReducedMotion&ss=chromium
|
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gfx/animation/animation_win.cc;l=29?q=ReducedMotion&ss=chromium
|
||||||
var winAnimEnabled = 0;
|
var winAnimEnabled = 0;
|
||||||
var success = NativeFunctions.SystemParametersInfo(
|
var success = false;
|
||||||
(uint)NativeFunctions.AccessibilityParameter.SPI_GETCLIENTAREAANIMATION,
|
unsafe
|
||||||
0,
|
{
|
||||||
ref winAnimEnabled,
|
success = Windows.Win32.PInvoke.SystemParametersInfo(
|
||||||
0);
|
SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETCLIENTAREAANIMATION,
|
||||||
|
0,
|
||||||
|
&winAnimEnabled,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@ using Dalamud.Plugin.Internal;
|
||||||
using Dalamud.Storage;
|
using Dalamud.Storage;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Dalamud.Utility.Timing;
|
using Dalamud.Utility.Timing;
|
||||||
using PInvoke;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.Security;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
[assembly: InternalsVisibleTo("Dalamud.CorePlugin")]
|
[assembly: InternalsVisibleTo("Dalamud.CorePlugin")]
|
||||||
|
|
@ -29,7 +30,7 @@ namespace Dalamud;
|
||||||
/// The main Dalamud class containing all subsystems.
|
/// The main Dalamud class containing all subsystems.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.ProvidedService]
|
[ServiceManager.ProvidedService]
|
||||||
internal sealed class Dalamud : IServiceType
|
internal sealed unsafe class Dalamud : IServiceType
|
||||||
{
|
{
|
||||||
#region Internals
|
#region Internals
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ internal sealed class Dalamud : IServiceType
|
||||||
{
|
{
|
||||||
Log.Verbose("=============== GAME THREAD KICKOFF ===============");
|
Log.Verbose("=============== GAME THREAD KICKOFF ===============");
|
||||||
Timings.Event("Game thread kickoff");
|
Timings.Event("Game thread kickoff");
|
||||||
NativeFunctions.SetEvent(mainThreadContinueEvent);
|
Windows.Win32.PInvoke.SetEvent(new HANDLE(mainThreadContinueEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleServiceInitFailure(Task t)
|
void HandleServiceInitFailure(Task t)
|
||||||
|
|
@ -116,9 +117,9 @@ internal sealed class Dalamud : IServiceType
|
||||||
HandleServiceInitFailure(t);
|
HandleServiceInitFailure(t);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.DefaultExceptionFilter = NativeFunctions.SetUnhandledExceptionFilter(nint.Zero);
|
this.DefaultExceptionFilter = SetExceptionHandler(nint.Zero);
|
||||||
NativeFunctions.SetUnhandledExceptionFilter(this.DefaultExceptionFilter);
|
SetExceptionHandler(this.DefaultExceptionFilter);
|
||||||
Log.Debug($"SE default exception filter at {this.DefaultExceptionFilter.ToInt64():X}");
|
Log.Debug($"SE default exception filter at {new IntPtr(this.DefaultExceptionFilter):X}");
|
||||||
|
|
||||||
var debugSig = "40 55 53 57 48 8D AC 24 70 AD FF FF";
|
var debugSig = "40 55 53 57 48 8D AC 24 70 AD FF FF";
|
||||||
this.DebugExceptionFilter = Service<TargetSigScanner>.Get().ScanText(debugSig);
|
this.DebugExceptionFilter = Service<TargetSigScanner>.Get().ScanText(debugSig);
|
||||||
|
|
@ -170,8 +171,9 @@ internal sealed class Dalamud : IServiceType
|
||||||
if (!reportCrashesSetting && !pmHasDevPlugins)
|
if (!reportCrashesSetting && !pmHasDevPlugins)
|
||||||
{
|
{
|
||||||
// Leaking on purpose for now
|
// Leaking on purpose for now
|
||||||
var attribs = Kernel32.SECURITY_ATTRIBUTES.Create();
|
var attribs = default(SECURITY_ATTRIBUTES);
|
||||||
Kernel32.CreateMutex(attribs, false, "DALAMUD_CRASHES_NO_MORE");
|
attribs.nLength = (uint)Unsafe.SizeOf<SECURITY_ATTRIBUTES>();
|
||||||
|
Windows.Win32.PInvoke.CreateMutex(attribs, false, "DALAMUD_CRASHES_NO_MORE");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.unloadSignal.Set();
|
this.unloadSignal.Set();
|
||||||
|
|
@ -189,27 +191,29 @@ internal sealed class Dalamud : IServiceType
|
||||||
/// Replace the current exception handler with the default one.
|
/// Replace the current exception handler with the default one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void UseDefaultExceptionHandler() =>
|
internal void UseDefaultExceptionHandler() =>
|
||||||
this.SetExceptionHandler(this.DefaultExceptionFilter);
|
SetExceptionHandler(this.DefaultExceptionFilter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Replace the current exception handler with a debug one.
|
/// Replace the current exception handler with a debug one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void UseDebugExceptionHandler() =>
|
internal void UseDebugExceptionHandler() =>
|
||||||
this.SetExceptionHandler(this.DebugExceptionFilter);
|
SetExceptionHandler(this.DebugExceptionFilter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disable the current exception handler.
|
/// Disable the current exception handler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void UseNoExceptionHandler() =>
|
internal void UseNoExceptionHandler() =>
|
||||||
this.SetExceptionHandler(nint.Zero);
|
SetExceptionHandler(nint.Zero);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper function to set the exception handler.
|
/// Helper function to set the exception handler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SetExceptionHandler(nint newFilter)
|
private static nint SetExceptionHandler(nint newFilter)
|
||||||
{
|
{
|
||||||
var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(newFilter);
|
var oldFilter =
|
||||||
Log.Debug("Set ExceptionFilter to {0}, old: {1}", newFilter, oldFilter);
|
Windows.Win32.PInvoke.SetUnhandledExceptionFilter((delegate* unmanaged[Stdcall]<global::Windows.Win32.System.Diagnostics.Debug.EXCEPTION_POINTERS*, int>)newFilter);
|
||||||
|
Log.Debug("Set ExceptionFilter to {0}, old: {1}", newFilter, (nint)oldFilter);
|
||||||
|
return (nint)oldFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupClientStructsResolver(DirectoryInfo cacheDir)
|
private void SetupClientStructsResolver(DirectoryInfo cacheDir)
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
<Nullable>annotations</Nullable>
|
<Nullable>annotations</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
|
||||||
|
<!-- Enable when cswin32 properly supports implementing COM interfaces and we can
|
||||||
|
make IDropTarget work -->
|
||||||
|
<!-- <DisableRuntimeMarshalling>true</DisableRuntimeMarshalling> -->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Label="Configuration">
|
<PropertyGroup Label="Configuration">
|
||||||
|
|
@ -66,10 +70,12 @@
|
||||||
<PackageReference Include="Lumina" Version="$(LuminaVersion)" />
|
<PackageReference Include="Lumina" Version="$(LuminaVersion)" />
|
||||||
<PackageReference Include="Lumina.Excel" Version="$(LuminaExcelVersion)" />
|
<PackageReference Include="Lumina.Excel" Version="$(LuminaExcelVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0-preview.1.24081.5" />
|
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0-preview.1.24081.5" />
|
||||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.46-beta">
|
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.183">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="MinSharp" Version="1.0.4" />
|
<PackageReference Include="MinSharp" Version="1.0.4" />
|
||||||
|
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
|
||||||
|
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />
|
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />
|
||||||
<PackageReference Include="Serilog" Version="4.0.2" />
|
<PackageReference Include="Serilog" Version="4.0.2" />
|
||||||
<PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" />
|
<PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" />
|
||||||
|
|
@ -87,13 +93,22 @@
|
||||||
<PackageReference Include="System.Resources.Extensions" Version="8.0.0" />
|
<PackageReference Include="System.Resources.Extensions" Version="8.0.0" />
|
||||||
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.22621.2" />
|
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.22621.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Interface\ImGuiBackend\Renderers\imgui-frag.hlsl.bytes">
|
||||||
|
<LogicalName>imgui-frag.hlsl.bytes</LogicalName>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Interface\ImGuiBackend\Renderers\imgui-vertex.hlsl.bytes">
|
||||||
|
<LogicalName>imgui-vertex.hlsl.bytes</LogicalName>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Dalamud.Common\Dalamud.Common.csproj" />
|
<ProjectReference Include="..\Dalamud.Common\Dalamud.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\imgui\Dalamud.Bindings.ImGuizmo\Dalamud.Bindings.ImGuizmo.csproj" />
|
||||||
|
<ProjectReference Include="..\imgui\Dalamud.Bindings.ImGui\Dalamud.Bindings.ImGui.csproj" />
|
||||||
|
<ProjectReference Include="..\imgui\Dalamud.Bindings.ImPlot\Dalamud.Bindings.ImPlot.csproj" />
|
||||||
|
<ProjectReference Include="..\imgui\ImGuiScene\ImGuiScene.csproj" />
|
||||||
<ProjectReference Include="..\lib\FFXIVClientStructs\FFXIVClientStructs\FFXIVClientStructs.csproj" />
|
<ProjectReference Include="..\lib\FFXIVClientStructs\FFXIVClientStructs\FFXIVClientStructs.csproj" />
|
||||||
<ProjectReference Include="..\lib\FFXIVClientStructs\InteropGenerator.Runtime\InteropGenerator.Runtime.csproj" />
|
<ProjectReference Include="..\lib\FFXIVClientStructs\InteropGenerator.Runtime\InteropGenerator.Runtime.csproj" />
|
||||||
<ProjectReference Include="..\lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj" />
|
|
||||||
<ProjectReference Include="..\lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj" />
|
|
||||||
<ProjectReference Include="..\lib\ImGuiScene\ImGuiScene\ImGuiScene.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interface_005Cfontawesome/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interface_005Cfontawesome/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Int64 x:Key="/Default/PerformanceThreshold/AnalysisFileSizeThreshold/=CSHARP/@EntryIndexedValue">300000</s:Int64>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interface_005Ctextures_005Ctexturewraps_005Cinternal_005Cdrawlisttexturewrap/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -15,12 +17,11 @@ using Dalamud.Storage;
|
||||||
using Dalamud.Support;
|
using Dalamud.Support;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PInvoke;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Core;
|
using Serilog.Core;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
using static Dalamud.NativeFunctions;
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
namespace Dalamud;
|
namespace Dalamud;
|
||||||
|
|
||||||
|
|
@ -58,7 +59,7 @@ public sealed class EntryPoint
|
||||||
var info = JsonConvert.DeserializeObject<DalamudStartInfo>(infoStr)!;
|
var info = JsonConvert.DeserializeObject<DalamudStartInfo>(infoStr)!;
|
||||||
|
|
||||||
if ((info.BootWaitMessageBox & 4) != 0)
|
if ((info.BootWaitMessageBox & 4) != 0)
|
||||||
MessageBoxW(IntPtr.Zero, "Press OK to continue (BeforeDalamudConstruct)", "Dalamud Boot", MessageBoxType.Ok);
|
Windows.Win32.PInvoke.MessageBox(HWND.Null, "Press OK to continue (BeforeDalamudConstruct)", "Dalamud Boot", MESSAGEBOX_STYLE.MB_OK);
|
||||||
|
|
||||||
new Thread(() => RunThread(info, mainThreadContinueEvent)).Start();
|
new Thread(() => RunThread(info, mainThreadContinueEvent)).Start();
|
||||||
}
|
}
|
||||||
|
|
@ -135,6 +136,8 @@ public sealed class EntryPoint
|
||||||
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
|
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
|
||||||
private static void RunThread(DalamudStartInfo info, IntPtr mainThreadContinueEvent)
|
private static void RunThread(DalamudStartInfo info, IntPtr mainThreadContinueEvent)
|
||||||
{
|
{
|
||||||
|
NativeLibrary.Load(Path.Combine(info.WorkingDirectory!, "cimgui.dll"));
|
||||||
|
|
||||||
// Setup logger
|
// Setup logger
|
||||||
InitLogging(info.LogPath!, info.BootShowConsole, true, info.LogName);
|
InitLogging(info.LogPath!, info.BootShowConsole, true, info.LogName);
|
||||||
SerilogEventSink.Instance.LogLine += SerilogOnLogLine;
|
SerilogEventSink.Instance.LogLine += SerilogOnLogLine;
|
||||||
|
|
@ -259,10 +262,12 @@ public sealed class EntryPoint
|
||||||
var symbolPath = Path.Combine(info.AssetDirectory, "UIRes", "pdb");
|
var symbolPath = Path.Combine(info.AssetDirectory, "UIRes", "pdb");
|
||||||
var searchPath = $".;{symbolPath}";
|
var searchPath = $".;{symbolPath}";
|
||||||
|
|
||||||
// Remove any existing Symbol Handler and Init a new one with our search path added
|
var currentProcess = Windows.Win32.PInvoke.GetCurrentProcess_SafeHandle();
|
||||||
SymCleanup(GetCurrentProcess());
|
|
||||||
|
|
||||||
if (!SymInitialize(GetCurrentProcess(), searchPath, true))
|
// Remove any existing Symbol Handler and Init a new one with our search path added
|
||||||
|
Windows.Win32.PInvoke.SymCleanup(currentProcess);
|
||||||
|
|
||||||
|
if (!Windows.Win32.PInvoke.SymInitialize(currentProcess, searchPath, true))
|
||||||
throw new Win32Exception();
|
throw new Win32Exception();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -304,14 +309,14 @@ public sealed class EntryPoint
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
const MessageBoxType flags = NativeFunctions.MessageBoxType.YesNo | NativeFunctions.MessageBoxType.IconError | NativeFunctions.MessageBoxType.SystemModal;
|
const MESSAGEBOX_STYLE flags = MESSAGEBOX_STYLE.MB_YESNO | MESSAGEBOX_STYLE.MB_ICONERROR | MESSAGEBOX_STYLE.MB_SYSTEMMODAL;
|
||||||
var result = MessageBoxW(
|
var result = Windows.Win32.PInvoke.MessageBox(
|
||||||
Process.GetCurrentProcess().MainWindowHandle,
|
new HWND(Process.GetCurrentProcess().MainWindowHandle),
|
||||||
$"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\n{ex.GetType().Name}\n{info}\n\n{pluginInfo}More information has been recorded separately{supportText}.\n\nDo you want to disable all plugins the next time you start the game?",
|
$"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\n{ex.GetType().Name}\n{info}\n\n{pluginInfo}More information has been recorded separately{supportText}.\n\nDo you want to disable all plugins the next time you start the game?",
|
||||||
"Dalamud",
|
"Dalamud",
|
||||||
flags);
|
flags);
|
||||||
|
|
||||||
if (result == (int)User32.MessageBoxResult.IDYES)
|
if (result == MESSAGEBOX_RESULT.IDYES)
|
||||||
{
|
{
|
||||||
Log.Information("User chose to disable plugins on next launch...");
|
Log.Information("User chose to disable plugins on next launch...");
|
||||||
var config = Service<DalamudConfiguration>.Get();
|
var config = Service<DalamudConfiguration>.Get();
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Input;
|
using FFXIVClientStructs.FFXIV.Client.System.Input;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.GamePad;
|
namespace Dalamud.Game.ClientState.GamePad;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using Dalamud.Game.NativeWrapper;
|
using Dalamud.Game.NativeWrapper;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
|
@ -19,8 +20,6 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
using FFXIVClientStructs.FFXIV.Common.Component.BGCollision;
|
using FFXIVClientStructs.FFXIV.Common.Component.BGCollision;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Vector2 = System.Numerics.Vector2;
|
using Vector2 = System.Numerics.Vector2;
|
||||||
using Vector3 = System.Numerics.Vector3;
|
using Vector3 = System.Numerics.Vector3;
|
||||||
using Vector4 = System.Numerics.Vector4;
|
using Vector4 = System.Numerics.Vector4;
|
||||||
|
|
|
||||||
|
|
@ -55,4 +55,37 @@ internal sealed class WinSockHandlers : IInternalDisposableService
|
||||||
|
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Native ws2_32 functions.
|
||||||
|
/// </summary>
|
||||||
|
private static class NativeFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// See https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-setsockopt.
|
||||||
|
/// The setsockopt function sets a socket option.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socket">
|
||||||
|
/// A descriptor that identifies a socket.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="level">
|
||||||
|
/// The level at which the option is defined (for example, SOL_SOCKET).
|
||||||
|
/// </param>
|
||||||
|
/// <param name="optName">
|
||||||
|
/// The socket option for which the value is to be set (for example, SO_BROADCAST). The optname parameter must be a
|
||||||
|
/// socket option defined within the specified level, or behavior is undefined.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="optVal">
|
||||||
|
/// A pointer to the buffer in which the value for the requested option is specified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="optLen">
|
||||||
|
/// The size, in bytes, of the buffer pointed to by the optval parameter.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If no error occurs, setsockopt returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error
|
||||||
|
/// code can be retrieved by calling WSAGetLastError.
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("ws2_32.dll", CallingConvention = CallingConvention.Winapi, EntryPoint = "setsockopt")]
|
||||||
|
public static extern int SetSockOpt(IntPtr socket, SocketOptionLevel level, SocketOptionName optName, ref IntPtr optVal, int optLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,11 +201,11 @@ public abstract class Hook<T> : IDalamudHook where T : Delegate
|
||||||
if (EnvironmentConfiguration.DalamudForceMinHook)
|
if (EnvironmentConfiguration.DalamudForceMinHook)
|
||||||
useMinHook = true;
|
useMinHook = true;
|
||||||
|
|
||||||
var moduleHandle = NativeFunctions.GetModuleHandleW(moduleName);
|
using var moduleHandle = Windows.Win32.PInvoke.GetModuleHandle(moduleName);
|
||||||
if (moduleHandle == IntPtr.Zero)
|
if (moduleHandle.IsInvalid)
|
||||||
throw new Exception($"Could not get a handle to module {moduleName}");
|
throw new Exception($"Could not get a handle to module {moduleName}");
|
||||||
|
|
||||||
var procAddress = NativeFunctions.GetProcAddress(moduleHandle, exportName);
|
var procAddress = (nint)Windows.Win32.PInvoke.GetProcAddress(moduleHandle, exportName);
|
||||||
if (procAddress == IntPtr.Zero)
|
if (procAddress == IntPtr.Zero)
|
||||||
throw new Exception($"Could not get the address of {moduleName}::{exportName}");
|
throw new Exception($"Could not get the address of {moduleName}::{exportName}");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using Dalamud.Memory;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Windows.Win32.System.Memory;
|
||||||
|
|
||||||
|
using Win32Exception = System.ComponentModel.Win32Exception;
|
||||||
|
|
||||||
namespace Dalamud.Hooking.Internal;
|
namespace Dalamud.Hooking.Internal;
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ namespace Dalamud.Hooking.Internal;
|
||||||
/// Manages a hook with MinHook.
|
/// Manages a hook with MinHook.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Delegate type to represents a function prototype. This must be the same prototype as original function do.</typeparam>
|
/// <typeparam name="T">Delegate type to represents a function prototype. This must be the same prototype as original function do.</typeparam>
|
||||||
internal class FunctionPointerVariableHook<T> : Hook<T>
|
internal unsafe class FunctionPointerVariableHook<T> : Hook<T>
|
||||||
where T : Delegate
|
where T : Delegate
|
||||||
{
|
{
|
||||||
private readonly nint pfnDetour;
|
private readonly nint pfnDetour;
|
||||||
|
|
@ -55,11 +56,11 @@ internal class FunctionPointerVariableHook<T> : Hook<T>
|
||||||
// Note: WINE seemingly tries to clean up all heap allocations on process exit.
|
// Note: WINE seemingly tries to clean up all heap allocations on process exit.
|
||||||
// We want our allocation to be kept there forever, until no running thread remains.
|
// We want our allocation to be kept there forever, until no running thread remains.
|
||||||
// Therefore we're using VirtualAlloc instead of HeapCreate/HeapAlloc.
|
// Therefore we're using VirtualAlloc instead of HeapCreate/HeapAlloc.
|
||||||
var pfnThunkBytes = (byte*)NativeFunctions.VirtualAlloc(
|
var pfnThunkBytes = (byte*)Windows.Win32.PInvoke.VirtualAlloc(
|
||||||
0,
|
null,
|
||||||
12,
|
12,
|
||||||
NativeFunctions.AllocationType.Reserve | NativeFunctions.AllocationType.Commit,
|
VIRTUAL_ALLOCATION_TYPE.MEM_RESERVE | VIRTUAL_ALLOCATION_TYPE.MEM_COMMIT,
|
||||||
MemoryProtection.ExecuteReadWrite);
|
PAGE_PROTECTION_FLAGS.PAGE_EXECUTE_READWRITE);
|
||||||
if (pfnThunkBytes == null)
|
if (pfnThunkBytes == null)
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("Failed to allocate memory for import hooks.");
|
throw new OutOfMemoryException("Failed to allocate memory for import hooks.");
|
||||||
|
|
@ -78,10 +79,10 @@ internal class FunctionPointerVariableHook<T> : Hook<T>
|
||||||
|
|
||||||
this.ppfnThunkJumpTarget = this.pfnThunk + 2;
|
this.ppfnThunkJumpTarget = this.pfnThunk + 2;
|
||||||
|
|
||||||
if (!NativeFunctions.VirtualProtect(
|
if (!Windows.Win32.PInvoke.VirtualProtect(
|
||||||
this.Address,
|
this.Address.ToPointer(),
|
||||||
(UIntPtr)Marshal.SizeOf<IntPtr>(),
|
(UIntPtr)Marshal.SizeOf<IntPtr>(),
|
||||||
MemoryProtection.ExecuteReadWrite,
|
PAGE_PROTECTION_FLAGS.PAGE_EXECUTE_READWRITE,
|
||||||
out var oldProtect))
|
out var oldProtect))
|
||||||
{
|
{
|
||||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||||
|
|
@ -93,7 +94,7 @@ internal class FunctionPointerVariableHook<T> : Hook<T>
|
||||||
Marshal.WriteIntPtr(this.Address, this.pfnThunk);
|
Marshal.WriteIntPtr(this.Address, this.pfnThunk);
|
||||||
|
|
||||||
// This really should not fail, but then even if it does, whatever.
|
// This really should not fail, but then even if it does, whatever.
|
||||||
NativeFunctions.VirtualProtect(this.Address, (UIntPtr)Marshal.SizeOf<IntPtr>(), oldProtect, out _);
|
Windows.Win32.PInvoke.VirtualProtect(this.Address.ToPointer(), (UIntPtr)Marshal.SizeOf<IntPtr>(), oldProtect, out _);
|
||||||
|
|
||||||
// Add afterwards, so the hookIdent starts at 0.
|
// Add afterwards, so the hookIdent starts at 0.
|
||||||
indexList.Add(this);
|
indexList.Add(this);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Common.Math;
|
using FFXIVClientStructs.FFXIV.Common.Math;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,9 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Components;
|
namespace Dalamud.Interface.Components;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Interface.DragDrop;
|
namespace Dalamud.Interface.DragDrop;
|
||||||
|
|
@ -32,7 +31,7 @@ internal partial class DragDropManager : IInternalDisposableService, IDragDropMa
|
||||||
Service<InterfaceManager.InterfaceManagerWithScene>.GetAsync()
|
Service<InterfaceManager.InterfaceManagerWithScene>.GetAsync()
|
||||||
.ContinueWith(t =>
|
.ContinueWith(t =>
|
||||||
{
|
{
|
||||||
this.windowHandlePtr = t.Result.Manager.WindowHandlePtr;
|
this.windowHandlePtr = t.Result.Manager.GameWindowHandle;
|
||||||
this.Enable();
|
this.Enable();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +102,7 @@ internal partial class DragDropManager : IInternalDisposableService, IDragDropMa
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IDragDropManager.CreateImGuiSource(string, Func{IDragDropManager, bool}, Func{IDragDropManager, bool})"/>
|
/// <inheritdoc cref="IDragDropManager.CreateImGuiSource(string, Func{IDragDropManager, bool}, Func{IDragDropManager, bool})"/>
|
||||||
public void CreateImGuiSource(string label, Func<IDragDropManager, bool> validityCheck, Func<IDragDropManager, bool> tooltipBuilder)
|
public unsafe void CreateImGuiSource(string label, Func<IDragDropManager, bool> validityCheck, Func<IDragDropManager, bool> tooltipBuilder)
|
||||||
{
|
{
|
||||||
if (!this.IsDragging && !this.IsDropping())
|
if (!this.IsDragging && !this.IsDropping())
|
||||||
{
|
{
|
||||||
|
|
@ -115,7 +114,7 @@ internal partial class DragDropManager : IInternalDisposableService, IDragDropMa
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SetDragDropPayload(label, nint.Zero, 0);
|
ImGui.SetDragDropPayload(label, null, 0);
|
||||||
if (this.CheckTooltipFrame(out var frame) && tooltipBuilder(this))
|
if (this.CheckTooltipFrame(out var frame) && tooltipBuilder(this))
|
||||||
{
|
{
|
||||||
this.lastTooltipFrame = frame;
|
this.lastTooltipFrame = frame;
|
||||||
|
|
@ -136,7 +135,7 @@ internal partial class DragDropManager : IInternalDisposableService, IDragDropMa
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
if (ImGui.AcceptDragDropPayload(label, ImGuiDragDropFlags.AcceptBeforeDelivery).NativePtr != null && this.IsDropping())
|
if (ImGui.AcceptDragDropPayload(label, ImGuiDragDropFlags.AcceptBeforeDelivery).Handle != null && this.IsDropping())
|
||||||
{
|
{
|
||||||
this.lastDropFrame = -2;
|
this.lastDropFrame = -2;
|
||||||
files = this.Files;
|
files = this.Files;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ using System.Linq;
|
||||||
using System.Runtime.InteropServices.ComTypes;
|
using System.Runtime.InteropServices.ComTypes;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using ImGuiNET;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Interface.DragDrop;
|
namespace Dalamud.Interface.DragDrop;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
using Dalamud.Storage.Assets;
|
using Dalamud.Storage.Assets;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
namespace Dalamud.Interface.FontIdentifier;
|
namespace Dalamud.Interface.FontIdentifier;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
namespace Dalamud.Interface.FontIdentifier;
|
namespace Dalamud.Interface.FontIdentifier;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.GameFonts;
|
using Dalamud.Interface.GameFonts;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
namespace Dalamud.Interface.FontIdentifier;
|
namespace Dalamud.Interface.FontIdentifier;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.FontIdentifier;
|
namespace Dalamud.Interface.FontIdentifier;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.FontIdentifier;
|
namespace Dalamud.Interface.FontIdentifier;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,9 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Interface.FontIdentifier;
|
namespace Dalamud.Interface.FontIdentifier;
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,10 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
namespace Dalamud.Interface.GameFonts;
|
namespace Dalamud.Interface.GameFonts;
|
||||||
|
|
||||||
|
|
|
||||||
252
Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs
Normal file
252
Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Bindings.ImGuizmo;
|
||||||
|
using Dalamud.Bindings.ImPlot;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.Helpers;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.InputHandler;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.Renderers;
|
||||||
|
using Dalamud.Utility;
|
||||||
|
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Backend for ImGui, using <see cref="Dx11Renderer"/> and <see cref="Win32InputHandler"/>.
|
||||||
|
/// </summary>
|
||||||
|
[SuppressMessage(
|
||||||
|
"StyleCop.CSharp.LayoutRules",
|
||||||
|
"SA1519:Braces should not be omitted from multi-line child statement",
|
||||||
|
Justification = "Multiple fixed/using scopes")]
|
||||||
|
internal sealed unsafe class Dx11Win32Backend : IWin32Backend
|
||||||
|
{
|
||||||
|
private readonly Dx11Renderer imguiRenderer;
|
||||||
|
private readonly Win32InputHandler imguiInput;
|
||||||
|
|
||||||
|
private ComPtr<IDXGISwapChain> swapChainPossiblyWrapped;
|
||||||
|
private ComPtr<IDXGISwapChain> swapChain;
|
||||||
|
private ComPtr<ID3D11Device> device;
|
||||||
|
private ComPtr<ID3D11DeviceContext> deviceContext;
|
||||||
|
|
||||||
|
private int targetWidth;
|
||||||
|
private int targetHeight;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Dx11Win32Backend"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="swapChain">The pointer to an instance of <see cref="IDXGISwapChain"/>. The reference is copied.</param>
|
||||||
|
public Dx11Win32Backend(IDXGISwapChain* swapChain)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.swapChainPossiblyWrapped = new(swapChain);
|
||||||
|
this.swapChain = new(swapChain);
|
||||||
|
fixed (ComPtr<IDXGISwapChain>* ppSwapChain = &this.swapChain)
|
||||||
|
ReShadePeeler.PeelSwapChain(ppSwapChain);
|
||||||
|
|
||||||
|
fixed (Guid* guid = &IID.IID_ID3D11Device)
|
||||||
|
fixed (ID3D11Device** pp = &this.device.GetPinnableReference())
|
||||||
|
this.swapChain.Get()->GetDevice(guid, (void**)pp).ThrowOnError();
|
||||||
|
|
||||||
|
fixed (ID3D11DeviceContext** pp = &this.deviceContext.GetPinnableReference())
|
||||||
|
this.device.Get()->GetImmediateContext(pp);
|
||||||
|
|
||||||
|
using var buffer = default(ComPtr<ID3D11Resource>);
|
||||||
|
fixed (Guid* guid = &IID.IID_ID3D11Resource)
|
||||||
|
this.swapChain.Get()->GetBuffer(0, guid, (void**)buffer.GetAddressOf()).ThrowOnError();
|
||||||
|
|
||||||
|
var desc = default(DXGI_SWAP_CHAIN_DESC);
|
||||||
|
this.swapChain.Get()->GetDesc(&desc).ThrowOnError();
|
||||||
|
this.targetWidth = (int)desc.BufferDesc.Width;
|
||||||
|
this.targetHeight = (int)desc.BufferDesc.Height;
|
||||||
|
this.WindowHandle = desc.OutputWindow;
|
||||||
|
|
||||||
|
var ctx = ImGui.CreateContext();
|
||||||
|
ImGuizmo.SetImGuiContext(ctx);
|
||||||
|
ImPlot.SetImGuiContext(ctx);
|
||||||
|
ImPlot.CreateContext();
|
||||||
|
|
||||||
|
ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.DockingEnable | ImGuiConfigFlags.ViewportsEnable;
|
||||||
|
|
||||||
|
this.imguiRenderer = new(this.SwapChain, this.Device, this.DeviceContext);
|
||||||
|
this.imguiInput = new(this.WindowHandle);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
this.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="Dx11Win32Backend"/> class.
|
||||||
|
/// </summary>
|
||||||
|
~Dx11Win32Backend() => this.ReleaseUnmanagedResources();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public event IImGuiBackend.BuildUiDelegate? BuildUi;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public event IImGuiBackend.NewInputFrameDelegate? NewInputFrame;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public event IImGuiBackend.NewRenderFrameDelegate? NewRenderFrame;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool UpdateCursor
|
||||||
|
{
|
||||||
|
get => this.imguiInput.UpdateCursor;
|
||||||
|
set => this.imguiInput.UpdateCursor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string? IniPath
|
||||||
|
{
|
||||||
|
get => this.imguiInput.IniPath;
|
||||||
|
set => this.imguiInput.IniPath = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IImGuiInputHandler InputHandler => this.imguiInput;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IImGuiRenderer Renderer => this.imguiRenderer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the pointer to an instance of <see cref="IDXGISwapChain"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IDXGISwapChain* SwapChain => this.swapChain;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the pointer to an instance of <see cref="ID3D11Device"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ID3D11Device* Device => this.device;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the pointer to an instance of <see cref="ID3D11Device"/>, in <see cref="nint"/>.
|
||||||
|
/// </summary>
|
||||||
|
public nint DeviceHandle => (nint)this.device.Get();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the pointer to an instance of <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ID3D11DeviceContext* DeviceContext => this.deviceContext;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the window handle.
|
||||||
|
/// </summary>
|
||||||
|
public HWND WindowHandle { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.ReleaseUnmanagedResources();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public nint? ProcessWndProcW(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam) =>
|
||||||
|
this.imguiInput.ProcessWndProcW(hWnd, msg, wParam, lParam);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Render()
|
||||||
|
{
|
||||||
|
this.imguiRenderer.OnNewFrame();
|
||||||
|
this.NewRenderFrame?.Invoke();
|
||||||
|
this.imguiInput.NewFrame(this.targetWidth, this.targetHeight);
|
||||||
|
this.NewInputFrame?.Invoke();
|
||||||
|
|
||||||
|
ImGui.NewFrame();
|
||||||
|
ImGuizmo.BeginFrame();
|
||||||
|
|
||||||
|
this.BuildUi?.Invoke();
|
||||||
|
|
||||||
|
ImGui.Render();
|
||||||
|
|
||||||
|
this.imguiRenderer.RenderDrawData(ImGui.GetDrawData());
|
||||||
|
|
||||||
|
ImGui.UpdatePlatformWindows();
|
||||||
|
ImGui.RenderPlatformWindowsDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void OnPreResize() => this.imguiRenderer.OnPreResize();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void OnPostResize(int newWidth, int newHeight)
|
||||||
|
{
|
||||||
|
this.imguiRenderer.OnPostResize(newWidth, newHeight);
|
||||||
|
this.targetWidth = newWidth;
|
||||||
|
this.targetHeight = newHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void InvalidateFonts() => this.imguiRenderer.RebuildFontTexture();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsImGuiCursor(nint cursorHandle) => this.imguiInput.IsImGuiCursor(cursorHandle);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsAttachedToPresentationTarget(nint targetHandle) =>
|
||||||
|
AreIUnknownEqual(this.swapChain.Get(), (IUnknown*)targetHandle)
|
||||||
|
|| AreIUnknownEqual(this.swapChainPossiblyWrapped.Get(), (IUnknown*)targetHandle);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsMainViewportFullScreen()
|
||||||
|
{
|
||||||
|
BOOL fullscreen;
|
||||||
|
this.swapChain.Get()->GetFullscreenState(&fullscreen, null);
|
||||||
|
return fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AreIUnknownEqual<T1, T2>(T1* punk1, T2* punk2)
|
||||||
|
where T1 : unmanaged, IUnknown.Interface
|
||||||
|
where T2 : unmanaged, IUnknown.Interface
|
||||||
|
{
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void)
|
||||||
|
// For any given COM object (also known as a COM component), a specific query for the IUnknown interface on any
|
||||||
|
// of the object's interfaces must always return the same pointer value.
|
||||||
|
|
||||||
|
if (punk1 is null || punk2 is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fixed (Guid* iid = &IID.IID_IUnknown)
|
||||||
|
{
|
||||||
|
using var u1 = default(ComPtr<IUnknown>);
|
||||||
|
if (punk1->QueryInterface(iid, (void**)u1.GetAddressOf()).FAILED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
using var u2 = default(ComPtr<IUnknown>);
|
||||||
|
if (punk2->QueryInterface(iid, (void**)u2.GetAddressOf()).FAILED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return u1.Get() == u2.Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseUnmanagedResources()
|
||||||
|
{
|
||||||
|
if (this.device.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.imguiRenderer?.Dispose();
|
||||||
|
this.imguiInput?.Dispose();
|
||||||
|
|
||||||
|
ImPlot.DestroyContext();
|
||||||
|
ImGui.DestroyContext();
|
||||||
|
|
||||||
|
this.swapChain.Dispose();
|
||||||
|
this.deviceContext.Dispose();
|
||||||
|
this.device.Dispose();
|
||||||
|
this.swapChainPossiblyWrapped.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,655 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Helpers.D3D11;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
internal unsafe struct D3D11DeviceContextStateBackup : IDisposable
|
||||||
|
{
|
||||||
|
private InputAssemblerState inputAssemblerState;
|
||||||
|
private RasterizerState rasterizerState;
|
||||||
|
private OutputMergerState outputMergerState;
|
||||||
|
private VertexShaderState vertexShaderState;
|
||||||
|
private HullShaderState hullShaderState;
|
||||||
|
private DomainShaderState domainShaderState;
|
||||||
|
private GeometryShaderState geometryShaderState;
|
||||||
|
private PixelShaderState pixelShaderState;
|
||||||
|
private ComputeShaderState computeShaderState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="D3D11DeviceContextStateBackup"/> struct,
|
||||||
|
/// by capturing all states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="featureLevel">The feature level.</param>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
public D3D11DeviceContextStateBackup(D3D_FEATURE_LEVEL featureLevel, ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
this.inputAssemblerState = InputAssemblerState.From(ctx);
|
||||||
|
this.rasterizerState = RasterizerState.From(ctx);
|
||||||
|
this.outputMergerState = OutputMergerState.From(featureLevel, ctx);
|
||||||
|
this.vertexShaderState = VertexShaderState.From(ctx);
|
||||||
|
this.hullShaderState = HullShaderState.From(ctx);
|
||||||
|
this.domainShaderState = DomainShaderState.From(ctx);
|
||||||
|
this.geometryShaderState = GeometryShaderState.From(ctx);
|
||||||
|
this.pixelShaderState = PixelShaderState.From(ctx);
|
||||||
|
this.computeShaderState = ComputeShaderState.From(featureLevel, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.inputAssemblerState.Dispose();
|
||||||
|
this.rasterizerState.Dispose();
|
||||||
|
this.outputMergerState.Dispose();
|
||||||
|
this.vertexShaderState.Dispose();
|
||||||
|
this.hullShaderState.Dispose();
|
||||||
|
this.domainShaderState.Dispose();
|
||||||
|
this.geometryShaderState.Dispose();
|
||||||
|
this.pixelShaderState.Dispose();
|
||||||
|
this.computeShaderState.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Input Assembler states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct InputAssemblerState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11InputLayout> layout;
|
||||||
|
private ComPtr<ID3D11Buffer> indexBuffer;
|
||||||
|
private DXGI_FORMAT indexFormat;
|
||||||
|
private uint indexOffset;
|
||||||
|
private D3D_PRIMITIVE_TOPOLOGY topology;
|
||||||
|
private fixed ulong buffers[BufferCount];
|
||||||
|
private fixed uint strides[BufferCount];
|
||||||
|
private fixed uint offsets[BufferCount];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="InputAssemblerState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static InputAssemblerState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(InputAssemblerState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
ctx->IAGetInputLayout(state.layout.GetAddressOf());
|
||||||
|
ctx->IAGetPrimitiveTopology(&state.topology);
|
||||||
|
ctx->IAGetIndexBuffer(state.indexBuffer.GetAddressOf(), &state.indexFormat, &state.indexOffset);
|
||||||
|
ctx->IAGetVertexBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers, state.strides, state.offsets);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (InputAssemblerState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->IASetInputLayout(pThis->layout);
|
||||||
|
ctx->IASetPrimitiveTopology(pThis->topology);
|
||||||
|
ctx->IASetIndexBuffer(pThis->indexBuffer, pThis->indexFormat, pThis->indexOffset);
|
||||||
|
ctx->IASetVertexBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers, pThis->strides, pThis->offsets);
|
||||||
|
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->layout.Dispose();
|
||||||
|
pThis->indexBuffer.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Rasterizer states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct RasterizerState : IDisposable
|
||||||
|
{
|
||||||
|
private const int Count = TerraFX.Interop.DirectX.D3D11.D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX;
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11RasterizerState> state;
|
||||||
|
private fixed byte viewports[24 * Count];
|
||||||
|
private fixed ulong scissorRects[16 * Count];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="RasterizerState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static RasterizerState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(RasterizerState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
ctx->RSGetState(state.state.GetAddressOf());
|
||||||
|
uint n = Count;
|
||||||
|
ctx->RSGetViewports(&n, (D3D11_VIEWPORT*)state.viewports);
|
||||||
|
n = Count;
|
||||||
|
ctx->RSGetScissorRects(&n, (RECT*)state.scissorRects);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (RasterizerState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->RSSetState(pThis->state);
|
||||||
|
ctx->RSSetViewports(Count, (D3D11_VIEWPORT*)pThis->viewports);
|
||||||
|
ctx->RSSetScissorRects(Count, (RECT*)pThis->scissorRects);
|
||||||
|
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->state.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Output Merger states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct OutputMergerState : IDisposable
|
||||||
|
{
|
||||||
|
private const int RtvCount = TerraFX.Interop.DirectX.D3D11.D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
|
||||||
|
private const int UavCountMax = TerraFX.Interop.DirectX.D3D11.D3D11_1_UAV_SLOT_COUNT;
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11BlendState> blendState;
|
||||||
|
private fixed float blendFactor[4];
|
||||||
|
private uint sampleMask;
|
||||||
|
private uint stencilRef;
|
||||||
|
private ComPtr<ID3D11DepthStencilState> depthStencilState;
|
||||||
|
private fixed ulong rtvs[RtvCount]; // ID3D11RenderTargetView*[RtvCount]
|
||||||
|
private ComPtr<ID3D11DepthStencilView> dsv;
|
||||||
|
private fixed ulong uavs[UavCountMax]; // ID3D11UnorderedAccessView*[UavCount]
|
||||||
|
private int uavCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="OutputMergerState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="featureLevel">The feature level.</param>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static OutputMergerState From(D3D_FEATURE_LEVEL featureLevel, ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(OutputMergerState);
|
||||||
|
state.uavCount = featureLevel >= D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_1
|
||||||
|
? TerraFX.Interop.DirectX.D3D11.D3D11_1_UAV_SLOT_COUNT
|
||||||
|
: TerraFX.Interop.DirectX.D3D11.D3D11_PS_CS_UAV_REGISTER_COUNT;
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
ctx->OMGetBlendState(state.blendState.GetAddressOf(), state.blendFactor, &state.sampleMask);
|
||||||
|
ctx->OMGetDepthStencilState(state.depthStencilState.GetAddressOf(), &state.stencilRef);
|
||||||
|
ctx->OMGetRenderTargetsAndUnorderedAccessViews(
|
||||||
|
RtvCount,
|
||||||
|
(ID3D11RenderTargetView**)state.rtvs,
|
||||||
|
state.dsv.GetAddressOf(),
|
||||||
|
0,
|
||||||
|
(uint)state.uavCount,
|
||||||
|
(ID3D11UnorderedAccessView**)state.uavs);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (OutputMergerState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->OMSetBlendState(pThis->blendState, pThis->blendFactor, pThis->sampleMask);
|
||||||
|
ctx->OMSetDepthStencilState(pThis->depthStencilState, pThis->stencilRef);
|
||||||
|
var rtvc = (uint)RtvCount;
|
||||||
|
while (rtvc > 0 && pThis->rtvs[rtvc - 1] == 0)
|
||||||
|
rtvc--;
|
||||||
|
|
||||||
|
var uavlb = rtvc;
|
||||||
|
while (uavlb < this.uavCount && pThis->uavs[uavlb] == 0)
|
||||||
|
uavlb++;
|
||||||
|
|
||||||
|
var uavc = (uint)this.uavCount;
|
||||||
|
while (uavc > uavlb && pThis->uavs[uavc - 1] == 0)
|
||||||
|
uavlb--;
|
||||||
|
uavc -= uavlb;
|
||||||
|
|
||||||
|
ctx->OMSetRenderTargetsAndUnorderedAccessViews(
|
||||||
|
rtvc,
|
||||||
|
(ID3D11RenderTargetView**)pThis->rtvs,
|
||||||
|
pThis->dsv,
|
||||||
|
uavc == 0 ? 0 : uavlb,
|
||||||
|
uavc,
|
||||||
|
uavc == 0 ? null : (ID3D11UnorderedAccessView**)pThis->uavs,
|
||||||
|
null);
|
||||||
|
|
||||||
|
this.context.Reset();
|
||||||
|
this.blendState.Reset();
|
||||||
|
this.depthStencilState.Reset();
|
||||||
|
this.dsv.Reset();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11RenderTargetView>>(pThis->rtvs, RtvCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11UnorderedAccessView>>(pThis->uavs, this.uavCount))
|
||||||
|
b.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Vertex Shader states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct VertexShaderState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
|
||||||
|
private const int SamplerCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
private const int ResourceCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
private const int ClassInstanceCount = 256; // According to msdn
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11VertexShader> shader;
|
||||||
|
private fixed ulong insts[ClassInstanceCount];
|
||||||
|
private fixed ulong buffers[BufferCount];
|
||||||
|
private fixed ulong samplers[SamplerCount];
|
||||||
|
private fixed ulong resources[ResourceCount];
|
||||||
|
private uint instCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="VertexShaderState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static VertexShaderState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(VertexShaderState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
state.instCount = ClassInstanceCount;
|
||||||
|
ctx->VSGetShader(state.shader.GetAddressOf(), (ID3D11ClassInstance**)state.insts, &state.instCount);
|
||||||
|
ctx->VSGetConstantBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers);
|
||||||
|
ctx->VSGetSamplers(0, SamplerCount, (ID3D11SamplerState**)state.samplers);
|
||||||
|
ctx->VSGetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)state.resources);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (VertexShaderState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->VSSetShader(pThis->shader, (ID3D11ClassInstance**)pThis->insts, pThis->instCount);
|
||||||
|
ctx->VSSetConstantBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers);
|
||||||
|
ctx->VSSetSamplers(0, SamplerCount, (ID3D11SamplerState**)pThis->samplers);
|
||||||
|
ctx->VSSetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)pThis->resources);
|
||||||
|
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11SamplerState>>(pThis->samplers, SamplerCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ShaderResourceView>>(pThis->resources, ResourceCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ClassInstance>>(pThis->insts, (int)pThis->instCount))
|
||||||
|
b.Dispose();
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->shader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Hull Shader states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct HullShaderState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
|
||||||
|
private const int SamplerCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
private const int ResourceCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
private const int ClassInstanceCount = 256; // According to msdn
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11HullShader> shader;
|
||||||
|
private fixed ulong insts[ClassInstanceCount];
|
||||||
|
private fixed ulong buffers[BufferCount];
|
||||||
|
private fixed ulong samplers[SamplerCount];
|
||||||
|
private fixed ulong resources[ResourceCount];
|
||||||
|
private uint instCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="HullShaderState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static HullShaderState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(HullShaderState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
state.instCount = ClassInstanceCount;
|
||||||
|
ctx->HSGetShader(state.shader.GetAddressOf(), (ID3D11ClassInstance**)state.insts, &state.instCount);
|
||||||
|
ctx->HSGetConstantBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers);
|
||||||
|
ctx->HSGetSamplers(0, SamplerCount, (ID3D11SamplerState**)state.samplers);
|
||||||
|
ctx->HSGetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)state.resources);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (HullShaderState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->HSSetShader(pThis->shader, (ID3D11ClassInstance**)pThis->insts, pThis->instCount);
|
||||||
|
ctx->HSSetConstantBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers);
|
||||||
|
ctx->HSSetSamplers(0, SamplerCount, (ID3D11SamplerState**)pThis->samplers);
|
||||||
|
ctx->HSSetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)pThis->resources);
|
||||||
|
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11SamplerState>>(pThis->samplers, SamplerCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ShaderResourceView>>(pThis->resources, ResourceCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ClassInstance>>(pThis->insts, (int)pThis->instCount))
|
||||||
|
b.Dispose();
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->shader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Domain Shader states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct DomainShaderState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
|
||||||
|
private const int SamplerCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
private const int ResourceCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
private const int ClassInstanceCount = 256; // According to msdn
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11DomainShader> shader;
|
||||||
|
private fixed ulong insts[ClassInstanceCount];
|
||||||
|
private fixed ulong buffers[BufferCount];
|
||||||
|
private fixed ulong samplers[SamplerCount];
|
||||||
|
private fixed ulong resources[ResourceCount];
|
||||||
|
private uint instCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="DomainShaderState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static DomainShaderState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(DomainShaderState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
state.instCount = ClassInstanceCount;
|
||||||
|
ctx->DSGetShader(state.shader.GetAddressOf(), (ID3D11ClassInstance**)state.insts, &state.instCount);
|
||||||
|
ctx->DSGetConstantBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers);
|
||||||
|
ctx->DSGetSamplers(0, SamplerCount, (ID3D11SamplerState**)state.samplers);
|
||||||
|
ctx->DSGetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)state.resources);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (DomainShaderState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->DSSetShader(pThis->shader, (ID3D11ClassInstance**)pThis->insts, pThis->instCount);
|
||||||
|
ctx->DSSetConstantBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers);
|
||||||
|
ctx->DSSetSamplers(0, SamplerCount, (ID3D11SamplerState**)pThis->samplers);
|
||||||
|
ctx->DSSetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)pThis->resources);
|
||||||
|
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11SamplerState>>(pThis->samplers, SamplerCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ShaderResourceView>>(pThis->resources, ResourceCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ClassInstance>>(pThis->insts, (int)pThis->instCount))
|
||||||
|
b.Dispose();
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->shader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Geometry Shader states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct GeometryShaderState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
|
||||||
|
private const int SamplerCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
private const int ResourceCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
private const int ClassInstanceCount = 256; // According to msdn
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11GeometryShader> shader;
|
||||||
|
private fixed ulong insts[ClassInstanceCount];
|
||||||
|
private fixed ulong buffers[BufferCount];
|
||||||
|
private fixed ulong samplers[SamplerCount];
|
||||||
|
private fixed ulong resources[ResourceCount];
|
||||||
|
private uint instCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="GeometryShaderState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static GeometryShaderState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(GeometryShaderState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
state.instCount = ClassInstanceCount;
|
||||||
|
ctx->GSGetShader(state.shader.GetAddressOf(), (ID3D11ClassInstance**)state.insts, &state.instCount);
|
||||||
|
ctx->GSGetConstantBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers);
|
||||||
|
ctx->GSGetSamplers(0, SamplerCount, (ID3D11SamplerState**)state.samplers);
|
||||||
|
ctx->GSGetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)state.resources);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (GeometryShaderState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->GSSetShader(pThis->shader, (ID3D11ClassInstance**)pThis->insts, pThis->instCount);
|
||||||
|
ctx->GSSetConstantBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers);
|
||||||
|
ctx->GSSetSamplers(0, SamplerCount, (ID3D11SamplerState**)pThis->samplers);
|
||||||
|
ctx->GSSetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)pThis->resources);
|
||||||
|
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11SamplerState>>(pThis->samplers, SamplerCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ShaderResourceView>>(pThis->resources, ResourceCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ClassInstance>>(pThis->insts, (int)pThis->instCount))
|
||||||
|
b.Dispose();
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->shader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Pixel Shader states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct PixelShaderState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
|
||||||
|
private const int SamplerCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
private const int ResourceCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
private const int ClassInstanceCount = 256; // According to msdn
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11PixelShader> shader;
|
||||||
|
private fixed ulong insts[ClassInstanceCount];
|
||||||
|
private fixed ulong buffers[BufferCount];
|
||||||
|
private fixed ulong samplers[SamplerCount];
|
||||||
|
private fixed ulong resources[ResourceCount];
|
||||||
|
private uint instCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="PixelShaderState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static PixelShaderState From(ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(PixelShaderState);
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
state.instCount = ClassInstanceCount;
|
||||||
|
ctx->PSGetShader(state.shader.GetAddressOf(), (ID3D11ClassInstance**)state.insts, &state.instCount);
|
||||||
|
ctx->PSGetConstantBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers);
|
||||||
|
ctx->PSGetSamplers(0, SamplerCount, (ID3D11SamplerState**)state.samplers);
|
||||||
|
ctx->PSGetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)state.resources);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (PixelShaderState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->PSSetShader(pThis->shader, (ID3D11ClassInstance**)pThis->insts, pThis->instCount);
|
||||||
|
ctx->PSSetConstantBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers);
|
||||||
|
ctx->PSSetSamplers(0, SamplerCount, (ID3D11SamplerState**)pThis->samplers);
|
||||||
|
ctx->PSSetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)pThis->resources);
|
||||||
|
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11SamplerState>>(pThis->samplers, SamplerCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ShaderResourceView>>(pThis->resources, ResourceCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ClassInstance>>(pThis->insts, (int)pThis->instCount))
|
||||||
|
b.Dispose();
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->shader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures Compute Shader states of a <see cref="ID3D11DeviceContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct ComputeShaderState : IDisposable
|
||||||
|
{
|
||||||
|
private const int BufferCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT;
|
||||||
|
private const int SamplerCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
private const int ResourceCount = TerraFX.Interop.DirectX.D3D11.D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
private const int InstanceCount = 256; // According to msdn
|
||||||
|
private const int UavCountMax = TerraFX.Interop.DirectX.D3D11.D3D11_1_UAV_SLOT_COUNT;
|
||||||
|
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11ComputeShader> shader;
|
||||||
|
private fixed ulong insts[InstanceCount]; // ID3D11ClassInstance*[BufferCount]
|
||||||
|
private fixed ulong buffers[BufferCount]; // ID3D11Buffer*[BufferCount]
|
||||||
|
private fixed ulong samplers[SamplerCount]; // ID3D11SamplerState*[SamplerCount]
|
||||||
|
private fixed ulong resources[ResourceCount]; // ID3D11ShaderResourceView*[ResourceCount]
|
||||||
|
private fixed ulong uavs[UavCountMax]; // ID3D11UnorderedAccessView*[UavCountMax]
|
||||||
|
private uint instCount;
|
||||||
|
private int uavCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="ComputeShaderState"/> from <paramref name="ctx"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="featureLevel">The feature level.</param>
|
||||||
|
/// <param name="ctx">The device context.</param>
|
||||||
|
/// <returns>The captured state.</returns>
|
||||||
|
public static ComputeShaderState From(D3D_FEATURE_LEVEL featureLevel, ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
var state = default(ComputeShaderState);
|
||||||
|
state.uavCount = featureLevel >= D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_1
|
||||||
|
? TerraFX.Interop.DirectX.D3D11.D3D11_1_UAV_SLOT_COUNT
|
||||||
|
: TerraFX.Interop.DirectX.D3D11.D3D11_PS_CS_UAV_REGISTER_COUNT;
|
||||||
|
state.context.Attach(ctx);
|
||||||
|
ctx->AddRef();
|
||||||
|
state.instCount = InstanceCount;
|
||||||
|
ctx->CSGetShader(state.shader.GetAddressOf(), (ID3D11ClassInstance**)state.insts, &state.instCount);
|
||||||
|
ctx->CSGetConstantBuffers(0, BufferCount, (ID3D11Buffer**)state.buffers);
|
||||||
|
ctx->CSGetSamplers(0, SamplerCount, (ID3D11SamplerState**)state.samplers);
|
||||||
|
ctx->CSGetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)state.resources);
|
||||||
|
ctx->CSGetUnorderedAccessViews(0, (uint)state.uavCount, (ID3D11UnorderedAccessView**)state.uavs);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
if (ctx is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fixed (ComputeShaderState* pThis = &this)
|
||||||
|
{
|
||||||
|
ctx->CSSetShader(pThis->shader, (ID3D11ClassInstance**)pThis->insts, pThis->instCount);
|
||||||
|
ctx->CSSetConstantBuffers(0, BufferCount, (ID3D11Buffer**)pThis->buffers);
|
||||||
|
ctx->CSSetSamplers(0, SamplerCount, (ID3D11SamplerState**)pThis->samplers);
|
||||||
|
ctx->CSSetShaderResources(0, ResourceCount, (ID3D11ShaderResourceView**)pThis->resources);
|
||||||
|
ctx->CSSetUnorderedAccessViews(0, (uint)this.uavCount, (ID3D11UnorderedAccessView**)pThis->uavs, null);
|
||||||
|
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11Buffer>>(pThis->buffers, BufferCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11SamplerState>>(pThis->samplers, SamplerCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ShaderResourceView>>(pThis->resources, ResourceCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11ClassInstance>>(pThis->insts, (int)pThis->instCount))
|
||||||
|
b.Dispose();
|
||||||
|
foreach (ref var b in new Span<ComPtr<ID3D11UnorderedAccessView>>(pThis->uavs, this.uavCount))
|
||||||
|
b.Dispose();
|
||||||
|
pThis->context.Dispose();
|
||||||
|
pThis->shader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Dalamud/Interface/ImGuiBackend/Helpers/D3D11/Extensions.cs
Normal file
26
Dalamud/Interface/ImGuiBackend/Helpers/D3D11/Extensions.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Dalamud.Utility;
|
||||||
|
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Helpers.D3D11;
|
||||||
|
|
||||||
|
/// <summary>Utility extension methods for D3D11 objects.</summary>
|
||||||
|
internal static class Extensions
|
||||||
|
{
|
||||||
|
/// <summary>Sets the name for debugging.</summary>
|
||||||
|
/// <param name="child">D3D11 object.</param>
|
||||||
|
/// <param name="name">Debug name.</param>
|
||||||
|
/// <typeparam name="T">Object type.</typeparam>
|
||||||
|
public static unsafe void SetDebugName<T>(ref this T child, string name)
|
||||||
|
where T : unmanaged, ID3D11DeviceChild.Interface
|
||||||
|
{
|
||||||
|
var len = Encoding.UTF8.GetByteCount(name);
|
||||||
|
var buf = stackalloc byte[len + 1];
|
||||||
|
Encoding.UTF8.GetBytes(name, new(buf, len + 1));
|
||||||
|
buf[len] = 0;
|
||||||
|
fixed (Guid* pId = &DirectX.WKPDID_D3DDebugObjectName)
|
||||||
|
child.SetPrivateData(pId, (uint)(len + 1), buf).ThrowOnError();
|
||||||
|
}
|
||||||
|
}
|
||||||
165
Dalamud/Interface/ImGuiBackend/Helpers/ImGuiViewportHelpers.cs
Normal file
165
Dalamud/Interface/ImGuiBackend/Helpers/ImGuiViewportHelpers.cs
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
using static TerraFX.Interop.Windows.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Helpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helpers for using ImGui Viewports.
|
||||||
|
/// </summary>
|
||||||
|
internal static class ImGuiViewportHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when a window should be created.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
public delegate void CreateWindowDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when a window should be destroyed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
public delegate void DestroyWindowDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when a window should be resized.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="size">Size of the new window.</param>
|
||||||
|
public delegate void SetWindowSizeDelegate(ImGuiViewportPtr viewport, Vector2 size);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when a window should be rendered.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="v">Custom user-provided argument from <see cref="ImGui.RenderPlatformWindowsDefault()"/>.</param>
|
||||||
|
public delegate void RenderWindowDelegate(ImGuiViewportPtr viewport, nint v);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when buffers for the window should be swapped.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="v">Custom user-provided argument from <see cref="ImGui.RenderPlatformWindowsDefault()"/>.</param>
|
||||||
|
public delegate void SwapBuffersDelegate(ImGuiViewportPtr viewport, nint v);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window should be showed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
public delegate void ShowWindowDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window should be updated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
public delegate void UpdateWindowDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window position is queried.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="returnStorage">The return value storage.</param>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <returns>Same value with <paramref name="returnStorage"/>.</returns>
|
||||||
|
public unsafe delegate Vector2* GetWindowPosDelegate(Vector2* returnStorage, ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window should be moved.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="pos">The new position.</param>
|
||||||
|
public delegate void SetWindowPosDelegate(ImGuiViewportPtr viewport, Vector2 pos);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window size is queried.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="returnStorage">The return value storage.</param>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <returns>Same value with <paramref name="returnStorage"/>.</returns>
|
||||||
|
public unsafe delegate Vector2* GetWindowSizeDelegate(Vector2* returnStorage, ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window should be given focus.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
public delegate void SetWindowFocusDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window is focused.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <returns>Whether the window is focused.</returns>
|
||||||
|
public delegate bool GetWindowFocusDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when whether the window is minimized is queried.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <returns>Whether the window is minimized.</returns>
|
||||||
|
public delegate bool GetWindowMinimizedDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window title should be changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="title">The new title.</param>
|
||||||
|
public delegate void SetWindowTitleDelegate(ImGuiViewportPtr viewport, string title);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window alpha should be changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="alpha">The new alpha.</param>
|
||||||
|
public delegate void SetWindowAlphaDelegate(ImGuiViewportPtr viewport, float alpha);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the IME input position should be changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <param name="pos">The new position.</param>
|
||||||
|
public delegate void SetImeInputPosDelegate(ImGuiViewportPtr viewport, Vector2 pos);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when the window's DPI scale value is queried.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
/// <returns>The DPI scale.</returns>
|
||||||
|
public delegate float GetWindowDpiScaleDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate to be called when viewport is changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">An instance of <see cref="ImGuiViewportPtr"/>.</param>
|
||||||
|
public delegate void ChangedViewportDelegate(ImGuiViewportPtr viewport);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disables ImGui from disabling alpha for Viewport window backgrounds.
|
||||||
|
/// </summary>
|
||||||
|
public static unsafe void EnableViewportWindowBackgroundAlpha()
|
||||||
|
{
|
||||||
|
// TODO: patch imgui.cpp:6126, which disables background transparency for extra viewport windows
|
||||||
|
var offset = 0x00007FFB6ADA632C - 0x00007FFB6AD60000;
|
||||||
|
offset += Process.GetCurrentProcess().Modules.Cast<ProcessModule>().First(x => x.ModuleName == "cimgui.dll")
|
||||||
|
.BaseAddress;
|
||||||
|
var b = (byte*)offset;
|
||||||
|
uint old;
|
||||||
|
if (!VirtualProtect(b, 1, PAGE.PAGE_EXECUTE_READWRITE, &old))
|
||||||
|
{
|
||||||
|
throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())
|
||||||
|
?? throw new InvalidOperationException($"{nameof(VirtualProtect)} failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
*b = 0xEB;
|
||||||
|
if (!VirtualProtect(b, 1, old, &old))
|
||||||
|
{
|
||||||
|
throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())
|
||||||
|
?? throw new InvalidOperationException($"{nameof(VirtualProtect)} failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
230
Dalamud/Interface/ImGuiBackend/Helpers/ReShadePeeler.cs
Normal file
230
Dalamud/Interface/ImGuiBackend/Helpers/ReShadePeeler.cs
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
using static TerraFX.Interop.Windows.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Helpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Peels ReShade off stuff.
|
||||||
|
/// </summary>
|
||||||
|
[SuppressMessage(
|
||||||
|
"StyleCop.CSharp.LayoutRules",
|
||||||
|
"SA1519:Braces should not be omitted from multi-line child statement",
|
||||||
|
Justification = "Multiple fixed blocks")]
|
||||||
|
internal static unsafe class ReShadePeeler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Peels <see cref="IDXGISwapChain"/> if it is wrapped by ReShade.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comptr">[inout] The COM pointer to an instance of <see cref="IDXGISwapChain"/>.</param>
|
||||||
|
/// <typeparam name="T">A COM type that is or extends <see cref="IDXGISwapChain"/>.</typeparam>
|
||||||
|
/// <returns><c>true</c> if peeled.</returns>
|
||||||
|
public static bool PeelSwapChain<T>(ComPtr<T>* comptr)
|
||||||
|
where T : unmanaged, IDXGISwapChain.Interface =>
|
||||||
|
PeelIUnknown(comptr, sizeof(IDXGISwapChain.Vtbl<IDXGISwapChain>));
|
||||||
|
|
||||||
|
private static bool PeelIUnknown<T>(ComPtr<T>* comptr, nint vtblSize)
|
||||||
|
where T : unmanaged, IUnknown.Interface
|
||||||
|
{
|
||||||
|
var changed = false;
|
||||||
|
while (comptr->Get() != null && IsReShadedComObject(comptr->Get()))
|
||||||
|
{
|
||||||
|
// Expectation: the pointer to the underlying object should come early after the overriden vtable.
|
||||||
|
for (nint i = 8; i <= 0x20; i += 8)
|
||||||
|
{
|
||||||
|
var ppObjectBehind = (nint)comptr->Get() + i;
|
||||||
|
|
||||||
|
// Is the thing directly pointed from the address an actual something in the memory?
|
||||||
|
if (!IsValidReadableMemoryAddress(ppObjectBehind, 8))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var pObjectBehind = *(nint*)ppObjectBehind;
|
||||||
|
|
||||||
|
// Is the address of vtable readable?
|
||||||
|
if (!IsValidReadableMemoryAddress(pObjectBehind, sizeof(nint)))
|
||||||
|
continue;
|
||||||
|
var pObjectBehindVtbl = *(nint*)pObjectBehind;
|
||||||
|
|
||||||
|
// Is the vtable itself readable?
|
||||||
|
if (!IsValidReadableMemoryAddress(pObjectBehindVtbl, vtblSize))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Are individual functions in vtable executable?
|
||||||
|
var valid = true;
|
||||||
|
for (var j = 0; valid && j < vtblSize; j += sizeof(nint))
|
||||||
|
valid &= IsValidExecutableMemoryAddress(*(nint*)(pObjectBehindVtbl + j), 1);
|
||||||
|
if (!valid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Interpret the object as an IUnknown.
|
||||||
|
// Note that `using` is not used, and `Attach` is used. We do not alter the reference count yet.
|
||||||
|
var punk = default(ComPtr<IUnknown>);
|
||||||
|
punk.Attach((IUnknown*)pObjectBehind);
|
||||||
|
|
||||||
|
// Is the IUnknown object also the type we want?
|
||||||
|
using var comptr2 = default(ComPtr<T>);
|
||||||
|
if (punk.As(&comptr2).FAILED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
comptr2.Swap(comptr);
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changed)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool BelongsInReShadeDll(nint ptr)
|
||||||
|
{
|
||||||
|
foreach (ProcessModule processModule in Process.GetCurrentProcess().Modules)
|
||||||
|
{
|
||||||
|
if (ptr < processModule.BaseAddress)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var dosh = (IMAGE_DOS_HEADER*)processModule.BaseAddress;
|
||||||
|
var nth = (IMAGE_NT_HEADERS64*)(processModule.BaseAddress + dosh->e_lfanew);
|
||||||
|
if (ptr >= processModule.BaseAddress + nth->OptionalHeader.SizeOfImage)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fixed (byte* pfn0 = "CreateDXGIFactory"u8)
|
||||||
|
fixed (byte* pfn1 = "D2D1CreateDevice"u8)
|
||||||
|
fixed (byte* pfn2 = "D3D10CreateDevice"u8)
|
||||||
|
fixed (byte* pfn3 = "D3D11CreateDevice"u8)
|
||||||
|
fixed (byte* pfn4 = "D3D12CreateDevice"u8)
|
||||||
|
fixed (byte* pfn5 = "glBegin"u8)
|
||||||
|
fixed (byte* pfn6 = "vkCreateDevice"u8)
|
||||||
|
{
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn0) == 0)
|
||||||
|
continue;
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn1) == 0)
|
||||||
|
continue;
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn2) == 0)
|
||||||
|
continue;
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn3) == 0)
|
||||||
|
continue;
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn4) == 0)
|
||||||
|
continue;
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn5) == 0)
|
||||||
|
continue;
|
||||||
|
if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn6) == 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileInfo = FileVersionInfo.GetVersionInfo(processModule.FileName);
|
||||||
|
|
||||||
|
if (fileInfo.FileDescription == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!fileInfo.FileDescription.Contains("GShade") && !fileInfo.FileDescription.Contains("ReShade"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsReShadedComObject<T>(T* obj)
|
||||||
|
where T : unmanaged, IUnknown.Interface
|
||||||
|
{
|
||||||
|
if (!IsValidReadableMemoryAddress((nint)obj, sizeof(nint)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var vtbl = (nint**)Marshal.ReadIntPtr((nint)obj);
|
||||||
|
if (!IsValidReadableMemoryAddress((nint)vtbl, sizeof(nint) * 3))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
var pfn = Marshal.ReadIntPtr((nint)(vtbl + i));
|
||||||
|
if (!IsValidExecutableMemoryAddress(pfn, 1))
|
||||||
|
return false;
|
||||||
|
if (!BelongsInReShadeDll(pfn))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidReadableMemoryAddress(nint p, nint size)
|
||||||
|
{
|
||||||
|
while (size > 0)
|
||||||
|
{
|
||||||
|
if (!IsValidUserspaceMemoryAddress(p))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
if (VirtualQuery((void*)p, &mbi, (nuint)sizeof(MEMORY_BASIC_INFORMATION)) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mbi is not
|
||||||
|
{
|
||||||
|
State: MEM.MEM_COMMIT,
|
||||||
|
Protect: PAGE.PAGE_READONLY or PAGE.PAGE_READWRITE or PAGE.PAGE_EXECUTE_READ
|
||||||
|
or PAGE.PAGE_EXECUTE_READWRITE,
|
||||||
|
})
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var regionSize = (nint)((mbi.RegionSize + 0xFFFUL) & ~0x1000UL);
|
||||||
|
var checkedSize = ((nint)mbi.BaseAddress + regionSize) - p;
|
||||||
|
size -= checkedSize;
|
||||||
|
p += checkedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidExecutableMemoryAddress(nint p, nint size)
|
||||||
|
{
|
||||||
|
while (size > 0)
|
||||||
|
{
|
||||||
|
if (!IsValidUserspaceMemoryAddress(p))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
if (VirtualQuery((void*)p, &mbi, (nuint)sizeof(MEMORY_BASIC_INFORMATION)) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mbi is not
|
||||||
|
{
|
||||||
|
State: MEM.MEM_COMMIT,
|
||||||
|
Protect: PAGE.PAGE_EXECUTE or PAGE.PAGE_EXECUTE_READ or PAGE.PAGE_EXECUTE_READWRITE
|
||||||
|
or PAGE.PAGE_EXECUTE_WRITECOPY,
|
||||||
|
})
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var regionSize = (nint)((mbi.RegionSize + 0xFFFUL) & ~0x1000UL);
|
||||||
|
var checkedSize = ((nint)mbi.BaseAddress + regionSize) - p;
|
||||||
|
size -= checkedSize;
|
||||||
|
p += checkedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool IsValidUserspaceMemoryAddress(nint p)
|
||||||
|
{
|
||||||
|
// https://learn.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces
|
||||||
|
// A 64-bit process on 64-bit Windows has a virtual address space within the 128-terabyte range
|
||||||
|
// 0x000'00000000 through 0x7FFF'FFFFFFFF.
|
||||||
|
return p >= 0x10000 && p <= unchecked((nint)0x7FFF_FFFFFFFFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
Dalamud/Interface/ImGuiBackend/IImGuiBackend.cs
Normal file
72
Dalamud/Interface/ImGuiBackend/IImGuiBackend.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
using Dalamud.Interface.ImGuiBackend.InputHandler;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.Renderers;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend;
|
||||||
|
|
||||||
|
/// <summary>Backend for ImGui.</summary>
|
||||||
|
internal interface IImGuiBackend : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>Delegate to be called when ImGui should be used to layout now.</summary>
|
||||||
|
public delegate void BuildUiDelegate();
|
||||||
|
|
||||||
|
/// <summary>Delegate to be called on new input frame.</summary>
|
||||||
|
public delegate void NewInputFrameDelegate();
|
||||||
|
|
||||||
|
/// <summary>Delegaet to be called on new render frame.</summary>
|
||||||
|
public delegate void NewRenderFrameDelegate();
|
||||||
|
|
||||||
|
/// <summary>User methods invoked every ImGui frame to construct custom UIs.</summary>
|
||||||
|
event BuildUiDelegate? BuildUi;
|
||||||
|
|
||||||
|
/// <summary>User methods invoked every ImGui frame on handling inputs.</summary>
|
||||||
|
event NewInputFrameDelegate? NewInputFrame;
|
||||||
|
|
||||||
|
/// <summary>User methods invoked every ImGui frame on handling renders.</summary>
|
||||||
|
event NewRenderFrameDelegate? NewRenderFrame;
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether the cursor should be overridden with the ImGui cursor.
|
||||||
|
/// </summary>
|
||||||
|
bool UpdateCursor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets the path of ImGui configuration .ini file.</summary>
|
||||||
|
string? IniPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets the device handle.</summary>
|
||||||
|
nint DeviceHandle { get; }
|
||||||
|
|
||||||
|
/// <summary>Gets the input handler.</summary>
|
||||||
|
IImGuiInputHandler InputHandler { get; }
|
||||||
|
|
||||||
|
/// <summary>Gets the renderer.</summary>
|
||||||
|
IImGuiRenderer Renderer { get; }
|
||||||
|
|
||||||
|
/// <summary>Performs a render cycle.</summary>
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
/// <summary>Handles stuff before resizing happens.</summary>
|
||||||
|
void OnPreResize();
|
||||||
|
|
||||||
|
/// <summary>Handles stuff after resizing happens.</summary>
|
||||||
|
/// <param name="newWidth">The new width.</param>
|
||||||
|
/// <param name="newHeight">The new height.</param>
|
||||||
|
void OnPostResize(int newWidth, int newHeight);
|
||||||
|
|
||||||
|
/// <summary>Invalidates fonts immediately.</summary>
|
||||||
|
/// <remarks>Call this while handling <see cref="NewRenderFrame"/>.</remarks>
|
||||||
|
void InvalidateFonts();
|
||||||
|
|
||||||
|
/// <summary>Determines if <paramref name="cursorHandle"/> is owned by this.</summary>
|
||||||
|
/// <param name="cursorHandle">The cursor.</param>
|
||||||
|
/// <returns>Whether it is the case.</returns>
|
||||||
|
bool IsImGuiCursor(nint cursorHandle);
|
||||||
|
|
||||||
|
/// <summary>Determines if this instance of <see cref="IImGuiBackend"/> is rendering to
|
||||||
|
/// <paramref name="targetHandle"/>. </summary>
|
||||||
|
/// <param name="targetHandle">The present target handle.</param>
|
||||||
|
/// <returns>Whether it is the case.</returns>
|
||||||
|
bool IsAttachedToPresentationTarget(nint targetHandle);
|
||||||
|
|
||||||
|
/// <summary>Determines if the main viewport is full screen. </summary>
|
||||||
|
/// <returns>Whether it is the case.</returns>
|
||||||
|
bool IsMainViewportFullScreen();
|
||||||
|
}
|
||||||
15
Dalamud/Interface/ImGuiBackend/IWin32Backend.cs
Normal file
15
Dalamud/Interface/ImGuiBackend/IWin32Backend.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend;
|
||||||
|
|
||||||
|
/// <summary><see cref="IImGuiBackend"/> with Win32 support.</summary>
|
||||||
|
internal interface IWin32Backend : IImGuiBackend
|
||||||
|
{
|
||||||
|
/// <summary>Processes window messages.</summary>
|
||||||
|
/// <param name="hWnd">Handle of the window.</param>
|
||||||
|
/// <param name="msg">Type of window message.</param>
|
||||||
|
/// <param name="wParam">wParam.</param>
|
||||||
|
/// <param name="lParam">lParam.</param>
|
||||||
|
/// <returns>Return value.</returns>
|
||||||
|
public nint? ProcessWndProcW(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.InputHandler;
|
||||||
|
|
||||||
|
/// <summary>A simple shared public interface that all ImGui input implementations follows.</summary>
|
||||||
|
internal interface IImGuiInputHandler : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>Gets or sets a value indicating whether the cursor should be overridden with the ImGui cursor.
|
||||||
|
/// </summary>
|
||||||
|
public bool UpdateCursor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets the path of ImGui configuration .ini file.</summary>
|
||||||
|
string? IniPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Determines if <paramref name="cursorHandle"/> is owned by this.</summary>
|
||||||
|
/// <param name="cursorHandle">The cursor.</param>
|
||||||
|
/// <returns>Whether it is the case.</returns>
|
||||||
|
public bool IsImGuiCursor(nint cursorHandle);
|
||||||
|
|
||||||
|
/// <summary>Marks the beginning of a new frame.</summary>
|
||||||
|
/// <param name="width">The width of the new frame.</param>
|
||||||
|
/// <param name="height">The height of the new frame.</param>
|
||||||
|
void NewFrame(int width, int height);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,309 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.InputHandler;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An implementation of <see cref="IImGuiInputHandler"/>, using Win32 APIs.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed partial class Win32InputHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a <see cref="VK"/> to <see cref="ImGuiKey"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The virtual key.</param>
|
||||||
|
/// <returns>The corresponding <see cref="ImGuiKey"/>.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ImGuiKey VirtualKeyToImGuiKey(int key) => key switch
|
||||||
|
{
|
||||||
|
VK.VK_TAB => ImGuiKey.Tab,
|
||||||
|
VK.VK_LEFT => ImGuiKey.LeftArrow,
|
||||||
|
VK.VK_RIGHT => ImGuiKey.RightArrow,
|
||||||
|
VK.VK_UP => ImGuiKey.UpArrow,
|
||||||
|
VK.VK_DOWN => ImGuiKey.DownArrow,
|
||||||
|
VK.VK_PRIOR => ImGuiKey.PageUp,
|
||||||
|
VK.VK_NEXT => ImGuiKey.PageDown,
|
||||||
|
VK.VK_HOME => ImGuiKey.Home,
|
||||||
|
VK.VK_END => ImGuiKey.End,
|
||||||
|
VK.VK_INSERT => ImGuiKey.Insert,
|
||||||
|
VK.VK_DELETE => ImGuiKey.Delete,
|
||||||
|
VK.VK_BACK => ImGuiKey.Backspace,
|
||||||
|
VK.VK_SPACE => ImGuiKey.Space,
|
||||||
|
VK.VK_RETURN => ImGuiKey.Enter,
|
||||||
|
VK.VK_ESCAPE => ImGuiKey.Escape,
|
||||||
|
VK.VK_OEM_7 => ImGuiKey.Apostrophe,
|
||||||
|
VK.VK_OEM_COMMA => ImGuiKey.Comma,
|
||||||
|
VK.VK_OEM_MINUS => ImGuiKey.Minus,
|
||||||
|
VK.VK_OEM_PERIOD => ImGuiKey.Period,
|
||||||
|
VK.VK_OEM_2 => ImGuiKey.Slash,
|
||||||
|
VK.VK_OEM_1 => ImGuiKey.Semicolon,
|
||||||
|
VK.VK_OEM_PLUS => ImGuiKey.Equal,
|
||||||
|
VK.VK_OEM_4 => ImGuiKey.LeftBracket,
|
||||||
|
VK.VK_OEM_5 => ImGuiKey.Backslash,
|
||||||
|
VK.VK_OEM_6 => ImGuiKey.RightBracket,
|
||||||
|
VK.VK_OEM_3 => ImGuiKey.GraveAccent,
|
||||||
|
VK.VK_CAPITAL => ImGuiKey.CapsLock,
|
||||||
|
VK.VK_SCROLL => ImGuiKey.ScrollLock,
|
||||||
|
VK.VK_NUMLOCK => ImGuiKey.NumLock,
|
||||||
|
VK.VK_SNAPSHOT => ImGuiKey.PrintScreen,
|
||||||
|
VK.VK_PAUSE => ImGuiKey.Pause,
|
||||||
|
VK.VK_NUMPAD0 => ImGuiKey.Keypad0,
|
||||||
|
VK.VK_NUMPAD1 => ImGuiKey.Keypad1,
|
||||||
|
VK.VK_NUMPAD2 => ImGuiKey.Keypad2,
|
||||||
|
VK.VK_NUMPAD3 => ImGuiKey.Keypad3,
|
||||||
|
VK.VK_NUMPAD4 => ImGuiKey.Keypad4,
|
||||||
|
VK.VK_NUMPAD5 => ImGuiKey.Keypad5,
|
||||||
|
VK.VK_NUMPAD6 => ImGuiKey.Keypad6,
|
||||||
|
VK.VK_NUMPAD7 => ImGuiKey.Keypad7,
|
||||||
|
VK.VK_NUMPAD8 => ImGuiKey.Keypad8,
|
||||||
|
VK.VK_NUMPAD9 => ImGuiKey.Keypad9,
|
||||||
|
VK.VK_DECIMAL => ImGuiKey.KeypadDecimal,
|
||||||
|
VK.VK_DIVIDE => ImGuiKey.KeypadDivide,
|
||||||
|
VK.VK_MULTIPLY => ImGuiKey.KeypadMultiply,
|
||||||
|
VK.VK_SUBTRACT => ImGuiKey.KeypadSubtract,
|
||||||
|
VK.VK_ADD => ImGuiKey.KeypadAdd,
|
||||||
|
VK.VK_RETURN + 256 => ImGuiKey.KeypadEnter,
|
||||||
|
VK.VK_LSHIFT => ImGuiKey.LeftShift,
|
||||||
|
VK.VK_LCONTROL => ImGuiKey.LeftCtrl,
|
||||||
|
VK.VK_LMENU => ImGuiKey.LeftAlt,
|
||||||
|
VK.VK_LWIN => ImGuiKey.LeftSuper,
|
||||||
|
VK.VK_RSHIFT => ImGuiKey.RightShift,
|
||||||
|
VK.VK_RCONTROL => ImGuiKey.RightCtrl,
|
||||||
|
VK.VK_RMENU => ImGuiKey.RightAlt,
|
||||||
|
VK.VK_RWIN => ImGuiKey.RightSuper,
|
||||||
|
VK.VK_APPS => ImGuiKey.Menu,
|
||||||
|
'0' => ImGuiKey.Key0,
|
||||||
|
'1' => ImGuiKey.Key1,
|
||||||
|
'2' => ImGuiKey.Key2,
|
||||||
|
'3' => ImGuiKey.Key3,
|
||||||
|
'4' => ImGuiKey.Key4,
|
||||||
|
'5' => ImGuiKey.Key5,
|
||||||
|
'6' => ImGuiKey.Key6,
|
||||||
|
'7' => ImGuiKey.Key7,
|
||||||
|
'8' => ImGuiKey.Key8,
|
||||||
|
'9' => ImGuiKey.Key9,
|
||||||
|
'A' => ImGuiKey.A,
|
||||||
|
'B' => ImGuiKey.B,
|
||||||
|
'C' => ImGuiKey.C,
|
||||||
|
'D' => ImGuiKey.D,
|
||||||
|
'E' => ImGuiKey.E,
|
||||||
|
'F' => ImGuiKey.F,
|
||||||
|
'G' => ImGuiKey.G,
|
||||||
|
'H' => ImGuiKey.H,
|
||||||
|
'I' => ImGuiKey.I,
|
||||||
|
'J' => ImGuiKey.J,
|
||||||
|
'K' => ImGuiKey.K,
|
||||||
|
'L' => ImGuiKey.L,
|
||||||
|
'M' => ImGuiKey.M,
|
||||||
|
'N' => ImGuiKey.N,
|
||||||
|
'O' => ImGuiKey.O,
|
||||||
|
'P' => ImGuiKey.P,
|
||||||
|
'Q' => ImGuiKey.Q,
|
||||||
|
'R' => ImGuiKey.R,
|
||||||
|
'S' => ImGuiKey.S,
|
||||||
|
'T' => ImGuiKey.T,
|
||||||
|
'U' => ImGuiKey.U,
|
||||||
|
'V' => ImGuiKey.V,
|
||||||
|
'W' => ImGuiKey.W,
|
||||||
|
'X' => ImGuiKey.X,
|
||||||
|
'Y' => ImGuiKey.Y,
|
||||||
|
'Z' => ImGuiKey.Z,
|
||||||
|
VK.VK_F1 => ImGuiKey.F1,
|
||||||
|
VK.VK_F2 => ImGuiKey.F2,
|
||||||
|
VK.VK_F3 => ImGuiKey.F3,
|
||||||
|
VK.VK_F4 => ImGuiKey.F4,
|
||||||
|
VK.VK_F5 => ImGuiKey.F5,
|
||||||
|
VK.VK_F6 => ImGuiKey.F6,
|
||||||
|
VK.VK_F7 => ImGuiKey.F7,
|
||||||
|
VK.VK_F8 => ImGuiKey.F8,
|
||||||
|
VK.VK_F9 => ImGuiKey.F9,
|
||||||
|
VK.VK_F10 => ImGuiKey.F10,
|
||||||
|
VK.VK_F11 => ImGuiKey.F11,
|
||||||
|
VK.VK_F12 => ImGuiKey.F12,
|
||||||
|
_ => ImGuiKey.None,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a <see cref="ImGuiKey"/> to <see cref="VK"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The ImGui key.</param>
|
||||||
|
/// <returns>The corresponding <see cref="VK"/>.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int ImGuiKeyToVirtualKey(ImGuiKey key) => key switch
|
||||||
|
{
|
||||||
|
ImGuiKey.Tab => VK.VK_TAB,
|
||||||
|
ImGuiKey.LeftArrow => VK.VK_LEFT,
|
||||||
|
ImGuiKey.RightArrow => VK.VK_RIGHT,
|
||||||
|
ImGuiKey.UpArrow => VK.VK_UP,
|
||||||
|
ImGuiKey.DownArrow => VK.VK_DOWN,
|
||||||
|
ImGuiKey.PageUp => VK.VK_PRIOR,
|
||||||
|
ImGuiKey.PageDown => VK.VK_NEXT,
|
||||||
|
ImGuiKey.Home => VK.VK_HOME,
|
||||||
|
ImGuiKey.End => VK.VK_END,
|
||||||
|
ImGuiKey.Insert => VK.VK_INSERT,
|
||||||
|
ImGuiKey.Delete => VK.VK_DELETE,
|
||||||
|
ImGuiKey.Backspace => VK.VK_BACK,
|
||||||
|
ImGuiKey.Space => VK.VK_SPACE,
|
||||||
|
ImGuiKey.Enter => VK.VK_RETURN,
|
||||||
|
ImGuiKey.Escape => VK.VK_ESCAPE,
|
||||||
|
ImGuiKey.Apostrophe => VK.VK_OEM_7,
|
||||||
|
ImGuiKey.Comma => VK.VK_OEM_COMMA,
|
||||||
|
ImGuiKey.Minus => VK.VK_OEM_MINUS,
|
||||||
|
ImGuiKey.Period => VK.VK_OEM_PERIOD,
|
||||||
|
ImGuiKey.Slash => VK.VK_OEM_2,
|
||||||
|
ImGuiKey.Semicolon => VK.VK_OEM_1,
|
||||||
|
ImGuiKey.Equal => VK.VK_OEM_PLUS,
|
||||||
|
ImGuiKey.LeftBracket => VK.VK_OEM_4,
|
||||||
|
ImGuiKey.Backslash => VK.VK_OEM_5,
|
||||||
|
ImGuiKey.RightBracket => VK.VK_OEM_6,
|
||||||
|
ImGuiKey.GraveAccent => VK.VK_OEM_3,
|
||||||
|
ImGuiKey.CapsLock => VK.VK_CAPITAL,
|
||||||
|
ImGuiKey.ScrollLock => VK.VK_SCROLL,
|
||||||
|
ImGuiKey.NumLock => VK.VK_NUMLOCK,
|
||||||
|
ImGuiKey.PrintScreen => VK.VK_SNAPSHOT,
|
||||||
|
ImGuiKey.Pause => VK.VK_PAUSE,
|
||||||
|
ImGuiKey.Keypad0 => VK.VK_NUMPAD0,
|
||||||
|
ImGuiKey.Keypad1 => VK.VK_NUMPAD1,
|
||||||
|
ImGuiKey.Keypad2 => VK.VK_NUMPAD2,
|
||||||
|
ImGuiKey.Keypad3 => VK.VK_NUMPAD3,
|
||||||
|
ImGuiKey.Keypad4 => VK.VK_NUMPAD4,
|
||||||
|
ImGuiKey.Keypad5 => VK.VK_NUMPAD5,
|
||||||
|
ImGuiKey.Keypad6 => VK.VK_NUMPAD6,
|
||||||
|
ImGuiKey.Keypad7 => VK.VK_NUMPAD7,
|
||||||
|
ImGuiKey.Keypad8 => VK.VK_NUMPAD8,
|
||||||
|
ImGuiKey.Keypad9 => VK.VK_NUMPAD9,
|
||||||
|
ImGuiKey.KeypadDecimal => VK.VK_DECIMAL,
|
||||||
|
ImGuiKey.KeypadDivide => VK.VK_DIVIDE,
|
||||||
|
ImGuiKey.KeypadMultiply => VK.VK_MULTIPLY,
|
||||||
|
ImGuiKey.KeypadSubtract => VK.VK_SUBTRACT,
|
||||||
|
ImGuiKey.KeypadAdd => VK.VK_ADD,
|
||||||
|
ImGuiKey.KeypadEnter => VK.VK_RETURN + 256,
|
||||||
|
ImGuiKey.LeftShift => VK.VK_LSHIFT,
|
||||||
|
ImGuiKey.LeftCtrl => VK.VK_LCONTROL,
|
||||||
|
ImGuiKey.LeftAlt => VK.VK_LMENU,
|
||||||
|
ImGuiKey.LeftSuper => VK.VK_LWIN,
|
||||||
|
ImGuiKey.RightShift => VK.VK_RSHIFT,
|
||||||
|
ImGuiKey.RightCtrl => VK.VK_RCONTROL,
|
||||||
|
ImGuiKey.RightAlt => VK.VK_RMENU,
|
||||||
|
ImGuiKey.RightSuper => VK.VK_RWIN,
|
||||||
|
ImGuiKey.Menu => VK.VK_APPS,
|
||||||
|
ImGuiKey.Key0 => '0',
|
||||||
|
ImGuiKey.Key1 => '1',
|
||||||
|
ImGuiKey.Key2 => '2',
|
||||||
|
ImGuiKey.Key3 => '3',
|
||||||
|
ImGuiKey.Key4 => '4',
|
||||||
|
ImGuiKey.Key5 => '5',
|
||||||
|
ImGuiKey.Key6 => '6',
|
||||||
|
ImGuiKey.Key7 => '7',
|
||||||
|
ImGuiKey.Key8 => '8',
|
||||||
|
ImGuiKey.Key9 => '9',
|
||||||
|
ImGuiKey.A => 'A',
|
||||||
|
ImGuiKey.B => 'B',
|
||||||
|
ImGuiKey.C => 'C',
|
||||||
|
ImGuiKey.D => 'D',
|
||||||
|
ImGuiKey.E => 'E',
|
||||||
|
ImGuiKey.F => 'F',
|
||||||
|
ImGuiKey.G => 'G',
|
||||||
|
ImGuiKey.H => 'H',
|
||||||
|
ImGuiKey.I => 'I',
|
||||||
|
ImGuiKey.J => 'J',
|
||||||
|
ImGuiKey.K => 'K',
|
||||||
|
ImGuiKey.L => 'L',
|
||||||
|
ImGuiKey.M => 'M',
|
||||||
|
ImGuiKey.N => 'N',
|
||||||
|
ImGuiKey.O => 'O',
|
||||||
|
ImGuiKey.P => 'P',
|
||||||
|
ImGuiKey.Q => 'Q',
|
||||||
|
ImGuiKey.R => 'R',
|
||||||
|
ImGuiKey.S => 'S',
|
||||||
|
ImGuiKey.T => 'T',
|
||||||
|
ImGuiKey.U => 'U',
|
||||||
|
ImGuiKey.V => 'V',
|
||||||
|
ImGuiKey.W => 'W',
|
||||||
|
ImGuiKey.X => 'X',
|
||||||
|
ImGuiKey.Y => 'Y',
|
||||||
|
ImGuiKey.Z => 'Z',
|
||||||
|
ImGuiKey.F1 => VK.VK_F1,
|
||||||
|
ImGuiKey.F2 => VK.VK_F2,
|
||||||
|
ImGuiKey.F3 => VK.VK_F3,
|
||||||
|
ImGuiKey.F4 => VK.VK_F4,
|
||||||
|
ImGuiKey.F5 => VK.VK_F5,
|
||||||
|
ImGuiKey.F6 => VK.VK_F6,
|
||||||
|
ImGuiKey.F7 => VK.VK_F7,
|
||||||
|
ImGuiKey.F8 => VK.VK_F8,
|
||||||
|
ImGuiKey.F9 => VK.VK_F9,
|
||||||
|
ImGuiKey.F10 => VK.VK_F10,
|
||||||
|
ImGuiKey.F11 => VK.VK_F11,
|
||||||
|
ImGuiKey.F12 => VK.VK_F12,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool IsGamepadKey(ImGuiKey key) => (int)key is >= 617 and <= 640;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool IsModKey(ImGuiKey key) =>
|
||||||
|
key is ImGuiKey.LeftShift
|
||||||
|
or ImGuiKey.RightShift
|
||||||
|
or ImGuiKey.ModShift
|
||||||
|
or ImGuiKey.LeftCtrl
|
||||||
|
or ImGuiKey.ModCtrl
|
||||||
|
or ImGuiKey.LeftAlt
|
||||||
|
or ImGuiKey.RightAlt
|
||||||
|
or ImGuiKey.ModAlt;
|
||||||
|
|
||||||
|
private static void AddKeyEvent(ImGuiKey key, bool down, int nativeKeycode, int nativeScancode = -1)
|
||||||
|
{
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
io.AddKeyEvent(key, down);
|
||||||
|
io.SetKeyEventNativeData(key, nativeKeycode, nativeScancode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateKeyModifiers()
|
||||||
|
{
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
io.AddKeyEvent(ImGuiKey.ModCtrl, IsVkDown(VK.VK_CONTROL));
|
||||||
|
io.AddKeyEvent(ImGuiKey.ModShift, IsVkDown(VK.VK_SHIFT));
|
||||||
|
io.AddKeyEvent(ImGuiKey.ModAlt, IsVkDown(VK.VK_MENU));
|
||||||
|
io.AddKeyEvent(ImGuiKey.ModSuper, IsVkDown(VK.VK_APPS));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpAllKeys()
|
||||||
|
{
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
for (var i = (int)ImGuiKey.NamedKeyBegin; i < (int)ImGuiKey.NamedKeyEnd; i++)
|
||||||
|
io.AddKeyEvent((ImGuiKey)i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpAllMouseButton()
|
||||||
|
{
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
for (var i = 0; i < io.MouseDown.Length; i++)
|
||||||
|
io.MouseDown[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsVkDown(int key) => (TerraFX.Interop.Windows.Windows.GetKeyState(key) & 0x8000) != 0;
|
||||||
|
|
||||||
|
private static int GetButton(uint msg, WPARAM wParam) => msg switch
|
||||||
|
{
|
||||||
|
WM.WM_LBUTTONUP or WM.WM_LBUTTONDOWN or WM.WM_LBUTTONDBLCLK => 0,
|
||||||
|
WM.WM_RBUTTONUP or WM.WM_RBUTTONDOWN or WM.WM_RBUTTONDBLCLK => 1,
|
||||||
|
WM.WM_MBUTTONUP or WM.WM_MBUTTONDOWN or WM.WM_MBUTTONDBLCLK => 2,
|
||||||
|
WM.WM_XBUTTONUP or WM.WM_XBUTTONDOWN or WM.WM_XBUTTONDBLCLK =>
|
||||||
|
TerraFX.Interop.Windows.Windows.GET_XBUTTON_WPARAM(wParam) == TerraFX.Interop.Windows.Windows.XBUTTON1 ? 3 : 4,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
private static void ViewportFlagsToWin32Styles(ImGuiViewportFlags flags, out int style, out int exStyle)
|
||||||
|
{
|
||||||
|
style = (int)(flags.HasFlag(ImGuiViewportFlags.NoDecoration) ? WS.WS_POPUP : WS.WS_OVERLAPPEDWINDOW);
|
||||||
|
exStyle =
|
||||||
|
(int)(flags.HasFlag(ImGuiViewportFlags.NoTaskBarIcon) ? WS.WS_EX_TOOLWINDOW : (uint)WS.WS_EX_APPWINDOW);
|
||||||
|
exStyle |= WS.WS_EX_NOREDIRECTIONBITMAP;
|
||||||
|
if (flags.HasFlag(ImGuiViewportFlags.TopMost))
|
||||||
|
exStyle |= WS.WS_EX_TOPMOST;
|
||||||
|
}
|
||||||
|
}
|
||||||
1031
Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs
Normal file
1031
Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,372 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.Helpers;
|
||||||
|
using Dalamud.Utility;
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
using static TerraFX.Interop.Windows.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Renderers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deals with rendering ImGui using DirectX 11.
|
||||||
|
/// See https://github.com/ocornut/imgui/blob/master/examples/imgui_impl_dx11.cpp for the original implementation.
|
||||||
|
/// </summary>
|
||||||
|
[SuppressMessage(
|
||||||
|
"StyleCop.CSharp.LayoutRules",
|
||||||
|
"SA1519:Braces should not be omitted from multi-line child statement",
|
||||||
|
Justification = "Multiple fixed/using scopes")]
|
||||||
|
internal unsafe partial class Dx11Renderer
|
||||||
|
{
|
||||||
|
private class ViewportHandler : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Dx11Renderer renderer;
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "NotAccessedField.Local", Justification = "Keeping reference alive")]
|
||||||
|
private readonly ImGuiViewportHelpers.CreateWindowDelegate cwd;
|
||||||
|
|
||||||
|
public ViewportHandler(Dx11Renderer renderer)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
|
||||||
|
var pio = ImGui.GetPlatformIO();
|
||||||
|
pio.RendererCreateWindow = Marshal.GetFunctionPointerForDelegate(this.cwd = this.OnCreateWindow).ToPointer();
|
||||||
|
pio.RendererDestroyWindow = (delegate* unmanaged<ImGuiViewportPtr, void>)&OnDestroyWindow;
|
||||||
|
pio.RendererSetWindowSize = (delegate* unmanaged<ImGuiViewportPtr, Vector2, void>)&OnSetWindowSize;
|
||||||
|
pio.RendererRenderWindow = (delegate* unmanaged<ImGuiViewportPtr, nint, void>)&OnRenderWindow;
|
||||||
|
pio.RendererSwapBuffers = (delegate* unmanaged<ImGuiViewportPtr, nint, void>)&OnSwapBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ViewportHandler() => ReleaseUnmanagedResources();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ReleaseUnmanagedResources();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReleaseUnmanagedResources()
|
||||||
|
{
|
||||||
|
var pio = ImGui.GetPlatformIO();
|
||||||
|
pio.RendererCreateWindow = null;
|
||||||
|
pio.RendererDestroyWindow = null;
|
||||||
|
pio.RendererSetWindowSize = null;
|
||||||
|
pio.RendererRenderWindow = null;
|
||||||
|
pio.RendererSwapBuffers = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
private static void OnDestroyWindow(ImGuiViewportPtr viewport)
|
||||||
|
{
|
||||||
|
if (viewport.RendererUserData == null)
|
||||||
|
return;
|
||||||
|
ViewportData.Attach(viewport.RendererUserData).Dispose();
|
||||||
|
viewport.RendererUserData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
private static void OnSetWindowSize(ImGuiViewportPtr viewport, Vector2 size) =>
|
||||||
|
ViewportData.Attach(viewport.RendererUserData).ResizeBuffers((int)size.X, (int)size.Y, true);
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
private static void OnRenderWindow(ImGuiViewportPtr viewport, nint v) =>
|
||||||
|
ViewportData.Attach(viewport.RendererUserData).Draw(viewport.DrawData, true);
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
private static void OnSwapBuffers(ImGuiViewportPtr viewport, nint v) =>
|
||||||
|
ViewportData.Attach(viewport.RendererUserData).PresentIfSwapChainAvailable();
|
||||||
|
|
||||||
|
private void OnCreateWindow(ImGuiViewportPtr viewport)
|
||||||
|
{
|
||||||
|
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
|
||||||
|
// Some backend will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
|
||||||
|
var hWnd = viewport.PlatformHandleRaw;
|
||||||
|
if (hWnd == null)
|
||||||
|
hWnd = viewport.PlatformHandle;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
viewport.RendererUserData = ViewportData.CreateDComposition(this.renderer, (HWND)hWnd).Handle;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
viewport.RendererUserData = ViewportData.Create(this.renderer, (HWND)hWnd).Handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ViewportData : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Dx11Renderer parent;
|
||||||
|
|
||||||
|
private GCHandle selfGcHandle;
|
||||||
|
private ComPtr<IDXGISwapChain> swapChain;
|
||||||
|
private ComPtr<ID3D11Texture2D> renderTarget;
|
||||||
|
private ComPtr<ID3D11RenderTargetView> renderTargetView;
|
||||||
|
private ComPtr<IDCompositionVisual> dcompVisual;
|
||||||
|
private ComPtr<IDCompositionTarget> dcompTarget;
|
||||||
|
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
public ViewportData(
|
||||||
|
Dx11Renderer parent,
|
||||||
|
IDXGISwapChain* swapChain,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
IDCompositionVisual* dcompVisual,
|
||||||
|
IDCompositionTarget* dcompTarget)
|
||||||
|
{
|
||||||
|
this.parent = parent;
|
||||||
|
this.swapChain = new(swapChain);
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
if (dcompVisual is not null)
|
||||||
|
this.dcompVisual = new(dcompVisual);
|
||||||
|
if (dcompTarget is not null)
|
||||||
|
this.dcompTarget = new(dcompTarget);
|
||||||
|
this.selfGcHandle = GCHandle.Alloc(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDXGISwapChain* SwapChain => this.swapChain;
|
||||||
|
|
||||||
|
public void* Handle => GCHandle.ToIntPtr(this.selfGcHandle).ToPointer();
|
||||||
|
|
||||||
|
private DXGI_FORMAT RtvFormat => this.parent.rtvFormat;
|
||||||
|
|
||||||
|
public static ViewportData Attach(void* handle) =>
|
||||||
|
(ViewportData)GCHandle.FromIntPtr(new IntPtr(handle)).Target ?? throw new InvalidOperationException();
|
||||||
|
|
||||||
|
public static ViewportData Create(
|
||||||
|
Dx11Renderer renderer,
|
||||||
|
IDXGISwapChain* swapChain,
|
||||||
|
IDCompositionVisual* dcompVisual,
|
||||||
|
IDCompositionTarget* dcompTarget)
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
|
swapChain->GetDesc(&desc).ThrowOnError();
|
||||||
|
return new(
|
||||||
|
renderer,
|
||||||
|
swapChain,
|
||||||
|
(int)desc.BufferDesc.Width,
|
||||||
|
(int)desc.BufferDesc.Height,
|
||||||
|
dcompVisual,
|
||||||
|
dcompTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ViewportData CreateDComposition(Dx11Renderer renderer, HWND hWnd)
|
||||||
|
{
|
||||||
|
if (renderer.dcompDevice.IsEmpty())
|
||||||
|
throw new NotSupportedException();
|
||||||
|
|
||||||
|
var mvsd = default(DXGI_SWAP_CHAIN_DESC);
|
||||||
|
renderer.mainViewport.SwapChain->GetDesc(&mvsd).ThrowOnError();
|
||||||
|
|
||||||
|
using var dxgiFactory = default(ComPtr<IDXGIFactory4>);
|
||||||
|
fixed (Guid* piidFactory = &IID.IID_IDXGIFactory4)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DirectX.CreateDXGIFactory2(
|
||||||
|
DXGI.DXGI_CREATE_FACTORY_DEBUG,
|
||||||
|
piidFactory,
|
||||||
|
(void**)dxgiFactory.GetAddressOf()).ThrowOnError();
|
||||||
|
#else
|
||||||
|
DirectX.CreateDXGIFactory1(piidFactory, (void**)dxgiFactory.GetAddressOf()).ThrowOnError();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT rc;
|
||||||
|
if (!GetWindowRect(hWnd, &rc) || rc.right == rc.left || rc.bottom == rc.top)
|
||||||
|
rc = new(0, 0, 4, 4);
|
||||||
|
|
||||||
|
using var swapChain1 = default(ComPtr<IDXGISwapChain1>);
|
||||||
|
var sd1 = new DXGI_SWAP_CHAIN_DESC1
|
||||||
|
{
|
||||||
|
Width = (uint)(rc.right - rc.left),
|
||||||
|
Height = (uint)(rc.bottom - rc.top),
|
||||||
|
Format = renderer.rtvFormat,
|
||||||
|
Stereo = false,
|
||||||
|
SampleDesc = new(1, 0),
|
||||||
|
BufferUsage = DXGI.DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||||
|
BufferCount = Math.Max(2u, mvsd.BufferCount),
|
||||||
|
Scaling = DXGI_SCALING.DXGI_SCALING_STRETCH,
|
||||||
|
SwapEffect = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||||
|
AlphaMode = DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED,
|
||||||
|
Flags = 0,
|
||||||
|
};
|
||||||
|
dxgiFactory.Get()->CreateSwapChainForComposition(
|
||||||
|
(IUnknown*)renderer.device.Get(),
|
||||||
|
&sd1,
|
||||||
|
null,
|
||||||
|
swapChain1.GetAddressOf()).ThrowOnError();
|
||||||
|
|
||||||
|
if (ReShadePeeler.PeelSwapChain(&swapChain1))
|
||||||
|
{
|
||||||
|
swapChain1.Get()->ResizeBuffers(sd1.BufferCount, sd1.Width, sd1.Height, sd1.Format, sd1.Flags)
|
||||||
|
.ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
using var dcTarget = default(ComPtr<IDCompositionTarget>);
|
||||||
|
renderer.dcompDevice.Get()->CreateTargetForHwnd(hWnd, BOOL.TRUE, dcTarget.GetAddressOf());
|
||||||
|
|
||||||
|
using var dcVisual = default(ComPtr<IDCompositionVisual>);
|
||||||
|
renderer.dcompDevice.Get()->CreateVisual(dcVisual.GetAddressOf()).ThrowOnError();
|
||||||
|
|
||||||
|
dcVisual.Get()->SetContent((IUnknown*)swapChain1.Get()).ThrowOnError();
|
||||||
|
dcTarget.Get()->SetRoot(dcVisual).ThrowOnError();
|
||||||
|
renderer.dcompDevice.Get()->Commit().ThrowOnError();
|
||||||
|
|
||||||
|
using var swapChain = default(ComPtr<IDXGISwapChain>);
|
||||||
|
swapChain1.As(&swapChain).ThrowOnError();
|
||||||
|
return Create(renderer, swapChain, dcVisual, dcTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ViewportData Create(Dx11Renderer renderer, HWND hWnd)
|
||||||
|
{
|
||||||
|
using var dxgiFactory = default(ComPtr<IDXGIFactory>);
|
||||||
|
fixed (Guid* piidFactory = &IID.IID_IDXGIFactory)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DirectX.CreateDXGIFactory2(
|
||||||
|
DXGI.DXGI_CREATE_FACTORY_DEBUG,
|
||||||
|
piidFactory,
|
||||||
|
(void**)dxgiFactory.GetAddressOf()).ThrowOnError();
|
||||||
|
#else
|
||||||
|
DirectX.CreateDXGIFactory(piidFactory, (void**)dxgiFactory.GetAddressOf()).ThrowOnError();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create swapchain
|
||||||
|
using var swapChain = default(ComPtr<IDXGISwapChain>);
|
||||||
|
var desc = new DXGI_SWAP_CHAIN_DESC
|
||||||
|
{
|
||||||
|
BufferDesc =
|
||||||
|
{
|
||||||
|
Format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
},
|
||||||
|
SampleDesc = new(1, 0),
|
||||||
|
BufferUsage = DXGI.DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||||
|
BufferCount = 1,
|
||||||
|
OutputWindow = hWnd,
|
||||||
|
Windowed = true,
|
||||||
|
SwapEffect = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_DISCARD,
|
||||||
|
};
|
||||||
|
dxgiFactory.Get()->CreateSwapChain((IUnknown*)renderer.device.Get(), &desc, swapChain.GetAddressOf())
|
||||||
|
.ThrowOnError();
|
||||||
|
|
||||||
|
if (ReShadePeeler.PeelSwapChain(&swapChain))
|
||||||
|
{
|
||||||
|
swapChain.Get()->ResizeBuffers(
|
||||||
|
desc.BufferCount,
|
||||||
|
desc.BufferDesc.Width,
|
||||||
|
desc.BufferDesc.Height,
|
||||||
|
desc.BufferDesc.Format,
|
||||||
|
desc.Flags)
|
||||||
|
.ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Create(renderer, swapChain, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!this.selfGcHandle.IsAllocated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.ResetBuffers();
|
||||||
|
this.dcompVisual.Reset();
|
||||||
|
this.dcompTarget.Reset();
|
||||||
|
this.swapChain.Reset();
|
||||||
|
this.selfGcHandle.Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(ImDrawDataPtr drawData, bool clearRenderTarget)
|
||||||
|
{
|
||||||
|
if (this.width < 1 || this.height < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.EnsureRenderTarget();
|
||||||
|
this.parent.RenderDrawDataInternal(this.renderTargetView, drawData, clearRenderTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PresentIfSwapChainAvailable()
|
||||||
|
{
|
||||||
|
if (this.width < 1 || this.height < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!this.swapChain.IsEmpty())
|
||||||
|
this.swapChain.Get()->Present(0, 0).ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetBuffers()
|
||||||
|
{
|
||||||
|
this.renderTargetView.Reset();
|
||||||
|
this.renderTarget.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResizeBuffers(int newWidth, int newHeight, bool resizeSwapChain)
|
||||||
|
{
|
||||||
|
this.ResetBuffers();
|
||||||
|
|
||||||
|
this.width = newWidth;
|
||||||
|
this.height = newHeight;
|
||||||
|
if (this.width < 1 || this.height < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (resizeSwapChain && !this.swapChain.IsEmpty())
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
|
this.swapChain.Get()->GetDesc(&desc).ThrowOnError();
|
||||||
|
this.swapChain.Get()->ResizeBuffers(
|
||||||
|
desc.BufferCount,
|
||||||
|
(uint)newWidth,
|
||||||
|
(uint)newHeight,
|
||||||
|
DXGI_FORMAT.DXGI_FORMAT_UNKNOWN,
|
||||||
|
desc.Flags).ThrowOnError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureRenderTarget()
|
||||||
|
{
|
||||||
|
if (!this.renderTarget.IsEmpty() && !this.renderTargetView.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.ResetBuffers();
|
||||||
|
|
||||||
|
fixed (ID3D11Texture2D** pprt = &this.renderTarget.GetPinnableReference())
|
||||||
|
fixed (ID3D11RenderTargetView** pprtv = &this.renderTargetView.GetPinnableReference())
|
||||||
|
{
|
||||||
|
if (this.swapChain.IsEmpty())
|
||||||
|
{
|
||||||
|
var desc = new D3D11_TEXTURE2D_DESC
|
||||||
|
{
|
||||||
|
Width = (uint)this.width,
|
||||||
|
Height = (uint)this.height,
|
||||||
|
MipLevels = 1,
|
||||||
|
ArraySize = 1,
|
||||||
|
Format = this.RtvFormat,
|
||||||
|
SampleDesc = new(1, 0),
|
||||||
|
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
|
||||||
|
BindFlags = (uint)D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE,
|
||||||
|
CPUAccessFlags = 0,
|
||||||
|
MiscFlags = (uint)D3D11_RESOURCE_MISC_FLAG.D3D11_RESOURCE_MISC_SHARED_NTHANDLE,
|
||||||
|
};
|
||||||
|
this.parent.device.Get()->CreateTexture2D(&desc, null, pprt).ThrowOnError();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed (Guid* piid = &IID.IID_ID3D11Texture2D)
|
||||||
|
{
|
||||||
|
this.swapChain.Get()->GetBuffer(0u, piid, (void**)pprt)
|
||||||
|
.ThrowOnError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parent.device.Get()->CreateRenderTargetView((ID3D11Resource*)*pprt, null, pprtv).ThrowOnError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
686
Dalamud/Interface/ImGuiBackend/Renderers/Dx11Renderer.cs
Normal file
686
Dalamud/Interface/ImGuiBackend/Renderers/Dx11Renderer.cs
Normal file
|
|
@ -0,0 +1,686 @@
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.Helpers;
|
||||||
|
using Dalamud.Interface.ImGuiBackend.Helpers.D3D11;
|
||||||
|
using Dalamud.Interface.Textures;
|
||||||
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
|
using Dalamud.Interface.Textures.TextureWraps.Internal;
|
||||||
|
using Dalamud.Interface.Utility;
|
||||||
|
using Dalamud.Utility;
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Renderers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deals with rendering ImGui using DirectX 11.
|
||||||
|
/// See https://github.com/ocornut/imgui/blob/master/examples/imgui_impl_dx11.cpp for the original implementation.
|
||||||
|
/// </summary>
|
||||||
|
[SuppressMessage(
|
||||||
|
"StyleCop.CSharp.LayoutRules",
|
||||||
|
"SA1519:Braces should not be omitted from multi-line child statement",
|
||||||
|
Justification = "Multiple fixed/using scopes")]
|
||||||
|
internal unsafe partial class Dx11Renderer : IImGuiRenderer
|
||||||
|
{
|
||||||
|
private readonly List<IDalamudTextureWrap> fontTextures = new();
|
||||||
|
private readonly D3D_FEATURE_LEVEL featureLevel;
|
||||||
|
private readonly ViewportHandler viewportHandler;
|
||||||
|
private readonly nint renderNamePtr;
|
||||||
|
private readonly DXGI_FORMAT rtvFormat;
|
||||||
|
private readonly ViewportData mainViewport;
|
||||||
|
|
||||||
|
private bool releaseUnmanagedResourceCalled;
|
||||||
|
|
||||||
|
private ComPtr<ID3D11Device> device;
|
||||||
|
private ComPtr<ID3D11DeviceContext> context;
|
||||||
|
private ComPtr<ID3D11VertexShader> vertexShader;
|
||||||
|
private ComPtr<ID3D11PixelShader> pixelShader;
|
||||||
|
private ComPtr<ID3D11SamplerState> sampler;
|
||||||
|
private ComPtr<ID3D11InputLayout> inputLayout;
|
||||||
|
private ComPtr<ID3D11Buffer> vertexConstantBuffer;
|
||||||
|
private ComPtr<ID3D11BlendState> blendState;
|
||||||
|
private ComPtr<ID3D11RasterizerState> rasterizerState;
|
||||||
|
private ComPtr<ID3D11DepthStencilState> depthStencilState;
|
||||||
|
private ComPtr<ID3D11Buffer> vertexBuffer;
|
||||||
|
private ComPtr<ID3D11Buffer> indexBuffer;
|
||||||
|
private int vertexBufferSize;
|
||||||
|
private int indexBufferSize;
|
||||||
|
|
||||||
|
private ComPtr<IDCompositionDevice> dcompDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Dx11Renderer"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="swapChain">The swap chain.</param>
|
||||||
|
/// <param name="device">A pointer to an instance of <see cref="ID3D11Device"/>.</param>
|
||||||
|
/// <param name="context">A pointer to an instance of <see cref="ID3D11DeviceContext"/>.</param>
|
||||||
|
public Dx11Renderer(IDXGISwapChain* swapChain, ID3D11Device* device, ID3D11DeviceContext* context)
|
||||||
|
{
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
if (ImGui.GetIO().Handle->BackendRendererName is not null)
|
||||||
|
throw new InvalidOperationException("ImGui backend renderer seems to be have been already attached.");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
|
swapChain->GetDesc(&desc).ThrowOnError();
|
||||||
|
this.rtvFormat = desc.BufferDesc.Format;
|
||||||
|
this.device = new(device);
|
||||||
|
this.context = new(context);
|
||||||
|
this.featureLevel = device->GetFeatureLevel();
|
||||||
|
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset | ImGuiBackendFlags.RendererHasViewports;
|
||||||
|
|
||||||
|
this.renderNamePtr = Marshal.StringToHGlobalAnsi("imgui_impl_dx11_c#");
|
||||||
|
io.Handle->BackendRendererName = (byte*)this.renderNamePtr;
|
||||||
|
|
||||||
|
if (io.ConfigFlags.HasFlag(ImGuiConfigFlags.ViewportsEnable))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fixed (IDCompositionDevice** pp = &this.dcompDevice.GetPinnableReference())
|
||||||
|
fixed (Guid* piidDCompositionDevice = &IID.IID_IDCompositionDevice)
|
||||||
|
DirectX.DCompositionCreateDevice(null, piidDCompositionDevice, (void**)pp).ThrowOnError();
|
||||||
|
|
||||||
|
ImGuiViewportHelpers.EnableViewportWindowBackgroundAlpha();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// don't care; not using DComposition then
|
||||||
|
}
|
||||||
|
|
||||||
|
this.viewportHandler = new(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mainViewport = ViewportData.Create(this, swapChain, null, null);
|
||||||
|
var vp = ImGui.GetPlatformIO().Viewports[0];
|
||||||
|
vp.RendererUserData = this.mainViewport.Handle;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
this.ReleaseUnmanagedResources();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="Dx11Renderer"/> class.
|
||||||
|
/// </summary>
|
||||||
|
~Dx11Renderer() => this.ReleaseUnmanagedResources();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.ReleaseUnmanagedResources();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void OnNewFrame()
|
||||||
|
{
|
||||||
|
this.EnsureDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void OnPreResize() => this.mainViewport.ResetBuffers();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void OnPostResize(int width, int height) => this.mainViewport.ResizeBuffers(width, height, false);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RenderDrawData(ImDrawDataPtr drawData) =>
|
||||||
|
this.mainViewport.Draw(drawData, this.mainViewport.SwapChain == null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rebuilds font texture.
|
||||||
|
/// </summary>
|
||||||
|
public void RebuildFontTexture()
|
||||||
|
{
|
||||||
|
foreach (var fontResourceView in this.fontTextures)
|
||||||
|
fontResourceView.Dispose();
|
||||||
|
this.fontTextures.Clear();
|
||||||
|
|
||||||
|
this.CreateFontsTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IDalamudTextureWrap CreateTexture2D(
|
||||||
|
ReadOnlySpan<byte> data,
|
||||||
|
RawImageSpecification specs,
|
||||||
|
bool cpuRead,
|
||||||
|
bool cpuWrite,
|
||||||
|
bool allowRenderTarget,
|
||||||
|
[CallerMemberName] string debugName = "")
|
||||||
|
{
|
||||||
|
if (cpuRead && cpuWrite)
|
||||||
|
throw new ArgumentException("cpuRead and cpuWrite cannot be set at the same time.");
|
||||||
|
|
||||||
|
var cpuaf = default(D3D11_CPU_ACCESS_FLAG);
|
||||||
|
if (cpuRead)
|
||||||
|
cpuaf |= D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ;
|
||||||
|
if (cpuWrite)
|
||||||
|
cpuaf |= D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE;
|
||||||
|
|
||||||
|
D3D11_USAGE usage;
|
||||||
|
if (cpuRead)
|
||||||
|
usage = D3D11_USAGE.D3D11_USAGE_STAGING;
|
||||||
|
else if (cpuWrite)
|
||||||
|
usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC;
|
||||||
|
else
|
||||||
|
usage = D3D11_USAGE.D3D11_USAGE_DEFAULT;
|
||||||
|
|
||||||
|
var texDesc = new D3D11_TEXTURE2D_DESC
|
||||||
|
{
|
||||||
|
Width = (uint)specs.Width,
|
||||||
|
Height = (uint)specs.Height,
|
||||||
|
MipLevels = 1,
|
||||||
|
ArraySize = 1,
|
||||||
|
Format = specs.Format,
|
||||||
|
SampleDesc = new(1, 0),
|
||||||
|
Usage = usage,
|
||||||
|
BindFlags = (uint)(D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE |
|
||||||
|
(allowRenderTarget ? D3D11_BIND_FLAG.D3D11_BIND_RENDER_TARGET : 0)),
|
||||||
|
CPUAccessFlags = (uint)cpuaf,
|
||||||
|
MiscFlags = 0,
|
||||||
|
};
|
||||||
|
using var texture = default(ComPtr<ID3D11Texture2D>);
|
||||||
|
if (data.IsEmpty)
|
||||||
|
{
|
||||||
|
Marshal.ThrowExceptionForHR(this.device.Get()->CreateTexture2D(&texDesc, null, texture.GetAddressOf()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed (void* dataPtr = data)
|
||||||
|
{
|
||||||
|
var subrdata = new D3D11_SUBRESOURCE_DATA { pSysMem = dataPtr, SysMemPitch = (uint)specs.Pitch };
|
||||||
|
Marshal.ThrowExceptionForHR(
|
||||||
|
this.device.Get()->CreateTexture2D(&texDesc, &subrdata, texture.GetAddressOf()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
texture.Get()->SetDebugName($"Texture:{debugName}:SRV");
|
||||||
|
|
||||||
|
using var srvTemp = default(ComPtr<ID3D11ShaderResourceView>);
|
||||||
|
var srvDesc = new D3D11_SHADER_RESOURCE_VIEW_DESC(
|
||||||
|
texture,
|
||||||
|
D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D);
|
||||||
|
this.device.Get()->CreateShaderResourceView((ID3D11Resource*)texture.Get(), &srvDesc, srvTemp.GetAddressOf())
|
||||||
|
.ThrowOnError();
|
||||||
|
srvTemp.Get()->SetDebugName($"Texture:{debugName}:SRV");
|
||||||
|
|
||||||
|
return new UnknownTextureWrap((IUnknown*)srvTemp.Get(), specs.Width, specs.Height, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderDrawDataInternal(
|
||||||
|
ID3D11RenderTargetView* renderTargetView,
|
||||||
|
ImDrawDataPtr drawData,
|
||||||
|
bool clearRenderTarget)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized
|
||||||
|
if (drawData.DisplaySize.X <= 0 || drawData.DisplaySize.Y <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using var oldState = new D3D11DeviceContextStateBackup(this.featureLevel, this.context.Get());
|
||||||
|
|
||||||
|
// Setup desired DX state
|
||||||
|
this.SetupRenderState(drawData);
|
||||||
|
|
||||||
|
this.context.Get()->OMSetRenderTargets(1, &renderTargetView, null);
|
||||||
|
if (clearRenderTarget)
|
||||||
|
{
|
||||||
|
var color = default(Vector4);
|
||||||
|
this.context.Get()->ClearRenderTargetView(renderTargetView, (float*)&color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drawData.Valid || drawData.CmdListsCount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var cmdLists = new Span<ImDrawListPtr>(drawData.Handle->CmdLists, drawData.Handle->CmdListsCount);
|
||||||
|
|
||||||
|
// Create and grow vertex/index buffers if needed
|
||||||
|
if (this.vertexBufferSize < drawData.TotalVtxCount)
|
||||||
|
this.vertexBuffer.Dispose();
|
||||||
|
if (this.vertexBuffer.Get() is null)
|
||||||
|
{
|
||||||
|
this.vertexBufferSize = drawData.TotalVtxCount + 5000;
|
||||||
|
var desc = new D3D11_BUFFER_DESC(
|
||||||
|
(uint)(sizeof(ImDrawVert) * this.vertexBufferSize),
|
||||||
|
(uint)D3D11_BIND_FLAG.D3D11_BIND_VERTEX_BUFFER,
|
||||||
|
D3D11_USAGE.D3D11_USAGE_DYNAMIC,
|
||||||
|
(uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE);
|
||||||
|
var buffer = default(ID3D11Buffer*);
|
||||||
|
this.device.Get()->CreateBuffer(&desc, null, &buffer).ThrowOnError();
|
||||||
|
this.vertexBuffer.Attach(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.indexBufferSize < drawData.TotalIdxCount)
|
||||||
|
this.indexBuffer.Dispose();
|
||||||
|
if (this.indexBuffer.Get() is null)
|
||||||
|
{
|
||||||
|
this.indexBufferSize = drawData.TotalIdxCount + 5000;
|
||||||
|
var desc = new D3D11_BUFFER_DESC(
|
||||||
|
(uint)(sizeof(ushort) * this.indexBufferSize),
|
||||||
|
(uint)D3D11_BIND_FLAG.D3D11_BIND_INDEX_BUFFER,
|
||||||
|
D3D11_USAGE.D3D11_USAGE_DYNAMIC,
|
||||||
|
(uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE);
|
||||||
|
var buffer = default(ID3D11Buffer*);
|
||||||
|
this.device.Get()->CreateBuffer(&desc, null, &buffer).ThrowOnError();
|
||||||
|
this.indexBuffer.Attach(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload vertex/index data into a single contiguous GPU buffer
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var vertexData = default(D3D11_MAPPED_SUBRESOURCE);
|
||||||
|
var indexData = default(D3D11_MAPPED_SUBRESOURCE);
|
||||||
|
this.context.Get()->Map(
|
||||||
|
(ID3D11Resource*)this.vertexBuffer.Get(),
|
||||||
|
0,
|
||||||
|
D3D11_MAP.D3D11_MAP_WRITE_DISCARD,
|
||||||
|
0,
|
||||||
|
&vertexData).ThrowOnError();
|
||||||
|
this.context.Get()->Map(
|
||||||
|
(ID3D11Resource*)this.indexBuffer.Get(),
|
||||||
|
0,
|
||||||
|
D3D11_MAP.D3D11_MAP_WRITE_DISCARD,
|
||||||
|
0,
|
||||||
|
&indexData).ThrowOnError();
|
||||||
|
|
||||||
|
var targetVertices = new Span<ImDrawVert>(vertexData.pData, this.vertexBufferSize);
|
||||||
|
var targetIndices = new Span<ushort>(indexData.pData, this.indexBufferSize);
|
||||||
|
foreach (ref var cmdList in cmdLists)
|
||||||
|
{
|
||||||
|
var vertices = new ImVectorWrapper<ImDrawVert>(cmdList.Handle->VtxBuffer.ToUntyped());
|
||||||
|
var indices = new ImVectorWrapper<ushort>(cmdList.Handle->IdxBuffer.ToUntyped());
|
||||||
|
|
||||||
|
vertices.DataSpan.CopyTo(targetVertices);
|
||||||
|
indices.DataSpan.CopyTo(targetIndices);
|
||||||
|
|
||||||
|
targetVertices = targetVertices[vertices.Length..];
|
||||||
|
targetIndices = targetIndices[indices.Length..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.context.Get()->Unmap((ID3D11Resource*)this.vertexBuffer.Get(), 0);
|
||||||
|
this.context.Get()->Unmap((ID3D11Resource*)this.indexBuffer.Get(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup orthographic projection matrix into our constant buffer.
|
||||||
|
// Our visible imgui space lies from DisplayPos (LT) to DisplayPos+DisplaySize (RB).
|
||||||
|
// DisplayPos is (0,0) for single viewport apps.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = default(D3D11_MAPPED_SUBRESOURCE);
|
||||||
|
this.context.Get()->Map(
|
||||||
|
(ID3D11Resource*)this.vertexConstantBuffer.Get(),
|
||||||
|
0,
|
||||||
|
D3D11_MAP.D3D11_MAP_WRITE_DISCARD,
|
||||||
|
0,
|
||||||
|
&data).ThrowOnError();
|
||||||
|
*(Matrix4x4*)data.pData = Matrix4x4.CreateOrthographicOffCenter(
|
||||||
|
drawData.DisplayPos.X,
|
||||||
|
drawData.DisplayPos.X + drawData.DisplaySize.X,
|
||||||
|
drawData.DisplayPos.Y + drawData.DisplaySize.Y,
|
||||||
|
drawData.DisplayPos.Y,
|
||||||
|
1f,
|
||||||
|
0f);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.context.Get()->Unmap((ID3D11Resource*)this.vertexConstantBuffer.Get(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||||
|
var vertexOffset = 0;
|
||||||
|
var indexOffset = 0;
|
||||||
|
var clipOff = new Vector4(drawData.DisplayPos, drawData.DisplayPos.X, drawData.DisplayPos.Y);
|
||||||
|
this.context.Get()->PSSetShader(this.pixelShader, null, 0);
|
||||||
|
this.context.Get()->PSSetSamplers(0, 1, this.sampler.GetAddressOf());
|
||||||
|
foreach (ref var cmdList in cmdLists)
|
||||||
|
{
|
||||||
|
var cmds = new ImVectorWrapper<ImDrawCmd>(cmdList.Handle->CmdBuffer.ToUntyped());
|
||||||
|
foreach (ref var cmd in cmds.DataSpan)
|
||||||
|
{
|
||||||
|
switch ((ImDrawCallbackEnum)(nint)cmd.UserCallback)
|
||||||
|
{
|
||||||
|
case ImDrawCallbackEnum.Empty:
|
||||||
|
{
|
||||||
|
var clipV4 = cmd.ClipRect - clipOff;
|
||||||
|
var clipRect = new RECT((int)clipV4.X, (int)clipV4.Y, (int)clipV4.Z, (int)clipV4.W);
|
||||||
|
|
||||||
|
// Skip the draw if nothing would be visible
|
||||||
|
if (clipRect.left >= clipRect.right || clipRect.top >= clipRect.bottom)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
this.context.Get()->RSSetScissorRects(1, &clipRect);
|
||||||
|
|
||||||
|
// Bind texture and draw
|
||||||
|
var srv = (ID3D11ShaderResourceView*)cmd.TextureId.Handle;
|
||||||
|
this.context.Get()->PSSetShaderResources(0, 1, &srv);
|
||||||
|
this.context.Get()->DrawIndexed(
|
||||||
|
cmd.ElemCount,
|
||||||
|
(uint)(cmd.IdxOffset + indexOffset),
|
||||||
|
(int)(cmd.VtxOffset + vertexOffset));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ImDrawCallbackEnum.ResetRenderState:
|
||||||
|
{
|
||||||
|
// Special callback value used by the user to request the renderer to reset render state.
|
||||||
|
this.SetupRenderState(drawData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
|
var cb = (delegate*<ImDrawListPtr, ref ImDrawCmd, void>)cmd.UserCallback;
|
||||||
|
cb(cmdList, ref cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indexOffset += cmdList.IdxBuffer.Size;
|
||||||
|
vertexOffset += cmdList.VtxBuffer.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds fonts as necessary, and uploads the built data onto the GPU.<br />
|
||||||
|
/// No-op if it has already been done.
|
||||||
|
/// </summary>
|
||||||
|
private void CreateFontsTexture()
|
||||||
|
{
|
||||||
|
if (this.device.IsEmpty())
|
||||||
|
throw new ObjectDisposedException(nameof(Dx11Renderer));
|
||||||
|
|
||||||
|
if (this.fontTextures.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
if (io.Fonts.Textures.Size == 0)
|
||||||
|
io.Fonts.Build();
|
||||||
|
|
||||||
|
for (int textureIndex = 0, textureCount = io.Fonts.Textures.Size;
|
||||||
|
textureIndex < textureCount;
|
||||||
|
textureIndex++)
|
||||||
|
{
|
||||||
|
int width = 0, height = 0, bytespp = 0;
|
||||||
|
byte* fontPixels = null;
|
||||||
|
|
||||||
|
// Build texture atlas
|
||||||
|
io.Fonts.GetTexDataAsRGBA32(
|
||||||
|
textureIndex,
|
||||||
|
&fontPixels,
|
||||||
|
ref width,
|
||||||
|
ref height,
|
||||||
|
ref bytespp);
|
||||||
|
|
||||||
|
var tex = this.CreateTexture2D(
|
||||||
|
new(fontPixels, width * height * bytespp),
|
||||||
|
new(width, height, (int)DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM, width * bytespp),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
$"Font#{textureIndex}");
|
||||||
|
io.Fonts.SetTexID(textureIndex, tex.Handle);
|
||||||
|
this.fontTextures.Add(tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
io.Fonts.ClearTexData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the device context's render state to what we would use for rendering ImGui by default.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="drawData">The relevant ImGui draw data.</param>
|
||||||
|
private void SetupRenderState(ImDrawDataPtr drawData)
|
||||||
|
{
|
||||||
|
var ctx = this.context.Get();
|
||||||
|
ctx->IASetInputLayout(this.inputLayout);
|
||||||
|
var buffer = this.vertexBuffer.Get();
|
||||||
|
var stride = (uint)sizeof(ImDrawVert);
|
||||||
|
var offset = 0u;
|
||||||
|
ctx->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
|
||||||
|
ctx->IASetIndexBuffer(this.indexBuffer, DXGI_FORMAT.DXGI_FORMAT_R16_UINT, 0);
|
||||||
|
ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY.D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
|
||||||
|
var viewport = new D3D11_VIEWPORT(0, 0, drawData.DisplaySize.X, drawData.DisplaySize.Y);
|
||||||
|
ctx->RSSetState(this.rasterizerState);
|
||||||
|
ctx->RSSetViewports(1, &viewport);
|
||||||
|
|
||||||
|
var blendColor = default(Vector4);
|
||||||
|
ctx->OMSetBlendState(this.blendState, (float*)&blendColor, 0xffffffff);
|
||||||
|
ctx->OMSetDepthStencilState(this.depthStencilState, 0);
|
||||||
|
|
||||||
|
ctx->VSSetShader(this.vertexShader.Get(), null, 0);
|
||||||
|
buffer = this.vertexConstantBuffer.Get();
|
||||||
|
ctx->VSSetConstantBuffers(0, 1, &buffer);
|
||||||
|
|
||||||
|
// PS handled later
|
||||||
|
|
||||||
|
ctx->GSSetShader(null, null, 0);
|
||||||
|
ctx->HSSetShader(null, null, 0);
|
||||||
|
ctx->DSSetShader(null, null, 0);
|
||||||
|
ctx->CSSetShader(null, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates objects from the device as necessary.<br />
|
||||||
|
/// No-op if objects already are built.
|
||||||
|
/// </summary>
|
||||||
|
private void EnsureDeviceObjects()
|
||||||
|
{
|
||||||
|
if (this.device.IsEmpty())
|
||||||
|
throw new ObjectDisposedException(nameof(Dx11Renderer));
|
||||||
|
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
// Create the vertex shader
|
||||||
|
if (this.vertexShader.IsEmpty() || this.inputLayout.IsEmpty())
|
||||||
|
{
|
||||||
|
using var stream = assembly.GetManifestResourceStream("imgui-vertex.hlsl.bytes")!;
|
||||||
|
var array = ArrayPool<byte>.Shared.Rent((int)stream.Length);
|
||||||
|
stream.ReadExactly(array, 0, (int)stream.Length);
|
||||||
|
fixed (byte* pArray = array)
|
||||||
|
fixed (ID3D11VertexShader** ppShader = &this.vertexShader.GetPinnableReference())
|
||||||
|
fixed (ID3D11InputLayout** ppInputLayout = &this.inputLayout.GetPinnableReference())
|
||||||
|
fixed (void* pszPosition = "POSITION"u8)
|
||||||
|
fixed (void* pszTexCoord = "TEXCOORD"u8)
|
||||||
|
fixed (void* pszColor = "COLOR"u8)
|
||||||
|
{
|
||||||
|
this.device.Get()->CreateVertexShader(pArray, (nuint)stream.Length, null, ppShader).ThrowOnError();
|
||||||
|
|
||||||
|
var ied = stackalloc D3D11_INPUT_ELEMENT_DESC[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
SemanticName = (sbyte*)pszPosition,
|
||||||
|
Format = DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT,
|
||||||
|
AlignedByteOffset = uint.MaxValue,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
SemanticName = (sbyte*)pszTexCoord,
|
||||||
|
Format = DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT,
|
||||||
|
AlignedByteOffset = uint.MaxValue,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
SemanticName = (sbyte*)pszColor,
|
||||||
|
Format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
AlignedByteOffset = uint.MaxValue,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.device.Get()->CreateInputLayout(ied, 3, pArray, (nuint)stream.Length, ppInputLayout)
|
||||||
|
.ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayPool<byte>.Shared.Return(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the pixel shader
|
||||||
|
if (this.pixelShader.IsEmpty())
|
||||||
|
{
|
||||||
|
using var stream = assembly.GetManifestResourceStream("imgui-frag.hlsl.bytes")!;
|
||||||
|
var array = ArrayPool<byte>.Shared.Rent((int)stream.Length);
|
||||||
|
stream.ReadExactly(array, 0, (int)stream.Length);
|
||||||
|
fixed (byte* pArray = array)
|
||||||
|
fixed (ID3D11PixelShader** ppShader = &this.pixelShader.GetPinnableReference())
|
||||||
|
this.device.Get()->CreatePixelShader(pArray, (nuint)stream.Length, null, ppShader).ThrowOnError();
|
||||||
|
ArrayPool<byte>.Shared.Return(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the sampler state
|
||||||
|
if (this.sampler.IsEmpty())
|
||||||
|
{
|
||||||
|
var samplerDesc = new D3D11_SAMPLER_DESC
|
||||||
|
{
|
||||||
|
Filter = D3D11_FILTER.D3D11_FILTER_MIN_MAG_MIP_LINEAR,
|
||||||
|
AddressU = D3D11_TEXTURE_ADDRESS_MODE.D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
AddressV = D3D11_TEXTURE_ADDRESS_MODE.D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
AddressW = D3D11_TEXTURE_ADDRESS_MODE.D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
MipLODBias = 0,
|
||||||
|
MaxAnisotropy = 0,
|
||||||
|
ComparisonFunc = D3D11_COMPARISON_FUNC.D3D11_COMPARISON_ALWAYS,
|
||||||
|
MinLOD = 0,
|
||||||
|
MaxLOD = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
fixed (ID3D11SamplerState** ppSampler = &this.sampler.GetPinnableReference())
|
||||||
|
this.device.Get()->CreateSamplerState(&samplerDesc, ppSampler).ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the constant buffer
|
||||||
|
if (this.vertexConstantBuffer.IsEmpty())
|
||||||
|
{
|
||||||
|
var bufferDesc = new D3D11_BUFFER_DESC(
|
||||||
|
(uint)sizeof(Matrix4x4),
|
||||||
|
(uint)D3D11_BIND_FLAG.D3D11_BIND_CONSTANT_BUFFER,
|
||||||
|
D3D11_USAGE.D3D11_USAGE_DYNAMIC,
|
||||||
|
(uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE);
|
||||||
|
fixed (ID3D11Buffer** ppBuffer = &this.vertexConstantBuffer.GetPinnableReference())
|
||||||
|
this.device.Get()->CreateBuffer(&bufferDesc, null, ppBuffer).ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the blending setup
|
||||||
|
if (this.blendState.IsEmpty())
|
||||||
|
{
|
||||||
|
var blendStateDesc = new D3D11_BLEND_DESC
|
||||||
|
{
|
||||||
|
RenderTarget =
|
||||||
|
{
|
||||||
|
e0 =
|
||||||
|
{
|
||||||
|
BlendEnable = true,
|
||||||
|
SrcBlend = D3D11_BLEND.D3D11_BLEND_SRC_ALPHA,
|
||||||
|
DestBlend = D3D11_BLEND.D3D11_BLEND_INV_SRC_ALPHA,
|
||||||
|
BlendOp = D3D11_BLEND_OP.D3D11_BLEND_OP_ADD,
|
||||||
|
SrcBlendAlpha = D3D11_BLEND.D3D11_BLEND_INV_DEST_ALPHA,
|
||||||
|
DestBlendAlpha = D3D11_BLEND.D3D11_BLEND_ONE,
|
||||||
|
BlendOpAlpha = D3D11_BLEND_OP.D3D11_BLEND_OP_ADD,
|
||||||
|
RenderTargetWriteMask = (byte)D3D11_COLOR_WRITE_ENABLE.D3D11_COLOR_WRITE_ENABLE_ALL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
fixed (ID3D11BlendState** ppBlendState = &this.blendState.GetPinnableReference())
|
||||||
|
this.device.Get()->CreateBlendState(&blendStateDesc, ppBlendState).ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the rasterizer state
|
||||||
|
if (this.rasterizerState.IsEmpty())
|
||||||
|
{
|
||||||
|
var rasterizerDesc = new D3D11_RASTERIZER_DESC
|
||||||
|
{
|
||||||
|
FillMode = D3D11_FILL_MODE.D3D11_FILL_SOLID,
|
||||||
|
CullMode = D3D11_CULL_MODE.D3D11_CULL_NONE,
|
||||||
|
ScissorEnable = true,
|
||||||
|
DepthClipEnable = true,
|
||||||
|
};
|
||||||
|
fixed (ID3D11RasterizerState** ppRasterizerState = &this.rasterizerState.GetPinnableReference())
|
||||||
|
this.device.Get()->CreateRasterizerState(&rasterizerDesc, ppRasterizerState).ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the depth-stencil State
|
||||||
|
if (this.depthStencilState.IsEmpty())
|
||||||
|
{
|
||||||
|
var dsDesc = new D3D11_DEPTH_STENCIL_DESC
|
||||||
|
{
|
||||||
|
DepthEnable = false,
|
||||||
|
DepthWriteMask = D3D11_DEPTH_WRITE_MASK.D3D11_DEPTH_WRITE_MASK_ALL,
|
||||||
|
DepthFunc = D3D11_COMPARISON_FUNC.D3D11_COMPARISON_ALWAYS,
|
||||||
|
StencilEnable = false,
|
||||||
|
StencilReadMask = byte.MaxValue,
|
||||||
|
StencilWriteMask = byte.MaxValue,
|
||||||
|
FrontFace =
|
||||||
|
{
|
||||||
|
StencilFailOp = D3D11_STENCIL_OP.D3D11_STENCIL_OP_KEEP,
|
||||||
|
StencilDepthFailOp = D3D11_STENCIL_OP.D3D11_STENCIL_OP_KEEP,
|
||||||
|
StencilPassOp = D3D11_STENCIL_OP.D3D11_STENCIL_OP_KEEP,
|
||||||
|
StencilFunc = D3D11_COMPARISON_FUNC.D3D11_COMPARISON_ALWAYS,
|
||||||
|
},
|
||||||
|
BackFace =
|
||||||
|
{
|
||||||
|
StencilFailOp = D3D11_STENCIL_OP.D3D11_STENCIL_OP_KEEP,
|
||||||
|
StencilDepthFailOp = D3D11_STENCIL_OP.D3D11_STENCIL_OP_KEEP,
|
||||||
|
StencilPassOp = D3D11_STENCIL_OP.D3D11_STENCIL_OP_KEEP,
|
||||||
|
StencilFunc = D3D11_COMPARISON_FUNC.D3D11_COMPARISON_ALWAYS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
fixed (ID3D11DepthStencilState** ppDepthStencilState = &this.depthStencilState.GetPinnableReference())
|
||||||
|
this.device.Get()->CreateDepthStencilState(&dsDesc, ppDepthStencilState).ThrowOnError();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.CreateFontsTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseUnmanagedResources()
|
||||||
|
{
|
||||||
|
if (this.releaseUnmanagedResourceCalled)
|
||||||
|
return;
|
||||||
|
this.releaseUnmanagedResourceCalled = true;
|
||||||
|
|
||||||
|
this.mainViewport.Dispose();
|
||||||
|
var vp = ImGui.GetPlatformIO().Viewports[0];
|
||||||
|
vp.RendererUserData = null;
|
||||||
|
ImGui.DestroyPlatformWindows();
|
||||||
|
|
||||||
|
this.viewportHandler.Dispose();
|
||||||
|
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
if (io.Handle->BackendRendererName == (void*)this.renderNamePtr)
|
||||||
|
io.Handle->BackendRendererName = null;
|
||||||
|
if (this.renderNamePtr != 0)
|
||||||
|
Marshal.FreeHGlobal(this.renderNamePtr);
|
||||||
|
|
||||||
|
foreach (var fontResourceView in this.fontTextures)
|
||||||
|
fontResourceView.Dispose();
|
||||||
|
|
||||||
|
foreach (var i in Enumerable.Range(0, io.Fonts.Textures.Size))
|
||||||
|
io.Fonts.SetTexID(i, ImTextureID.Null);
|
||||||
|
|
||||||
|
this.device.Reset();
|
||||||
|
this.context.Reset();
|
||||||
|
this.vertexShader.Reset();
|
||||||
|
this.pixelShader.Reset();
|
||||||
|
this.sampler.Reset();
|
||||||
|
this.inputLayout.Reset();
|
||||||
|
this.vertexConstantBuffer.Reset();
|
||||||
|
this.blendState.Reset();
|
||||||
|
this.rasterizerState.Reset();
|
||||||
|
this.depthStencilState.Reset();
|
||||||
|
this.vertexBuffer.Reset();
|
||||||
|
this.indexBuffer.Reset();
|
||||||
|
this.dcompDevice.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Dalamud/Interface/ImGuiBackend/Renderers/IImGuiRenderer.cs
Normal file
42
Dalamud/Interface/ImGuiBackend/Renderers/IImGuiRenderer.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.Textures;
|
||||||
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiBackend.Renderers;
|
||||||
|
|
||||||
|
/// <summary>A simple shared public interface that all ImGui render implementations follow.</summary>
|
||||||
|
internal interface IImGuiRenderer : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>Load an image from a span of bytes of specified format.</summary>
|
||||||
|
/// <param name="data">The data to load.</param>
|
||||||
|
/// <param name="specs">Texture specifications.</param>
|
||||||
|
/// <param name="cpuRead">Whether to support reading from CPU, while disabling reading from GPU.</param>
|
||||||
|
/// <param name="cpuWrite">Whether to support writing from CPU, while disabling writing from GPU.</param>
|
||||||
|
/// <param name="allowRenderTarget">Whether to allow rendering to this texture.</param>
|
||||||
|
/// <param name="debugName">Name for debugging.</param>
|
||||||
|
/// <returns>A texture, ready to use in ImGui.</returns>
|
||||||
|
IDalamudTextureWrap CreateTexture2D(
|
||||||
|
ReadOnlySpan<byte> data,
|
||||||
|
RawImageSpecification specs,
|
||||||
|
bool cpuRead,
|
||||||
|
bool cpuWrite,
|
||||||
|
bool allowRenderTarget,
|
||||||
|
[CallerMemberName] string debugName = "");
|
||||||
|
|
||||||
|
/// <summary>Notifies that the window is about to be resized.</summary>
|
||||||
|
void OnPreResize();
|
||||||
|
|
||||||
|
/// <summary>Notifies that the window has been resized.</summary>
|
||||||
|
/// <param name="width">The new window width.</param>
|
||||||
|
/// <param name="height">The new window height.</param>
|
||||||
|
void OnPostResize(int width, int height);
|
||||||
|
|
||||||
|
/// <summary>Marks the beginning of a new frame.</summary>
|
||||||
|
void OnNewFrame();
|
||||||
|
|
||||||
|
/// <summary>Renders the draw data.</summary>
|
||||||
|
/// <param name="drawData">The draw data.</param>
|
||||||
|
void RenderDrawData(ImDrawDataPtr drawData);
|
||||||
|
}
|
||||||
BIN
Dalamud/Interface/ImGuiBackend/Renderers/imgui-frag.hlsl.bytes
Normal file
BIN
Dalamud/Interface/ImGuiBackend/Renderers/imgui-frag.hlsl.bytes
Normal file
Binary file not shown.
BIN
Dalamud/Interface/ImGuiBackend/Renderers/imgui-vertex.hlsl.bytes
Normal file
BIN
Dalamud/Interface/ImGuiBackend/Renderers/imgui-vertex.hlsl.bytes
Normal file
Binary file not shown.
|
|
@ -3,9 +3,10 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiFileDialog;
|
namespace Dalamud.Interface.ImGuiFileDialog;
|
||||||
|
|
||||||
|
|
@ -152,7 +153,7 @@ public partial class FileDialog
|
||||||
|
|
||||||
private void DrawPathComposer()
|
private void DrawPathComposer()
|
||||||
{
|
{
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(InterfaceManager.IconFont);
|
||||||
if (ImGui.Button(this.pathInputActivated ? FontAwesomeIcon.Times.ToIconString() : FontAwesomeIcon.Edit.ToIconString()))
|
if (ImGui.Button(this.pathInputActivated ? FontAwesomeIcon.Times.ToIconString() : FontAwesomeIcon.Edit.ToIconString()))
|
||||||
{
|
{
|
||||||
this.pathInputActivated = !this.pathInputActivated;
|
this.pathInputActivated = !this.pathInputActivated;
|
||||||
|
|
@ -205,7 +206,7 @@ public partial class FileDialog
|
||||||
|
|
||||||
private void DrawSearchBar()
|
private void DrawSearchBar()
|
||||||
{
|
{
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(InterfaceManager.IconFont);
|
||||||
if (ImGui.Button(FontAwesomeIcon.Home.ToIconString()))
|
if (ImGui.Button(FontAwesomeIcon.Home.ToIconString()))
|
||||||
{
|
{
|
||||||
this.SetPath(".");
|
this.SetPath(".");
|
||||||
|
|
@ -239,7 +240,7 @@ public partial class FileDialog
|
||||||
{
|
{
|
||||||
if (this.flags.HasFlag(ImGuiFileDialogFlags.DisableCreateDirectoryButton)) return;
|
if (this.flags.HasFlag(ImGuiFileDialogFlags.DisableCreateDirectoryButton)) return;
|
||||||
|
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(InterfaceManager.IconFont);
|
||||||
if (ImGui.Button(FontAwesomeIcon.FolderPlus.ToIconString()) && !this.createDirectoryMode)
|
if (ImGui.Button(FontAwesomeIcon.FolderPlus.ToIconString()) && !this.createDirectoryMode)
|
||||||
{
|
{
|
||||||
this.createDirectoryMode = true;
|
this.createDirectoryMode = true;
|
||||||
|
|
@ -328,7 +329,7 @@ public partial class FileDialog
|
||||||
this.selectedSideBar = qa.Text;
|
this.selectedSideBar = qa.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(InterfaceManager.IconFont);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.SetCursorPosX(0);
|
ImGui.SetCursorPosX(0);
|
||||||
ImGui.TextUnformatted(qa.Icon.ToIconString());
|
ImGui.TextUnformatted(qa.Icon.ToIconString());
|
||||||
|
|
@ -380,11 +381,7 @@ public partial class FileDialog
|
||||||
|
|
||||||
if (this.filteredFiles.Count > 0)
|
if (this.filteredFiles.Count > 0)
|
||||||
{
|
{
|
||||||
ImGuiListClipperPtr clipper;
|
var clipper = ImGui.ImGuiListClipper();
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (this.filesLock)
|
lock (this.filesLock)
|
||||||
{
|
{
|
||||||
|
|
@ -479,7 +476,7 @@ public partial class FileDialog
|
||||||
{
|
{
|
||||||
const ImGuiSelectableFlags flags = ImGuiSelectableFlags.AllowDoubleClick | ImGuiSelectableFlags.SpanAllColumns;
|
const ImGuiSelectableFlags flags = ImGuiSelectableFlags.AllowDoubleClick | ImGuiSelectableFlags.SpanAllColumns;
|
||||||
|
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(InterfaceManager.IconFont);
|
||||||
|
|
||||||
ImGui.TextUnformatted(icon.ToIconString());
|
ImGui.TextUnformatted(icon.ToIconString());
|
||||||
ImGui.PopFont();
|
ImGui.PopFont();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiFileDialog;
|
namespace Dalamud.Interface.ImGuiFileDialog;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiFileDialog;
|
namespace Dalamud.Interface.ImGuiFileDialog;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.FontIdentifier;
|
using Dalamud.Interface.FontIdentifier;
|
||||||
|
|
@ -12,9 +13,6 @@ using Dalamud.Interface.ManagedFontAtlas;
|
||||||
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
|
@ -207,8 +205,8 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
|
|
||||||
/// <summary>Gets or sets a value indicating whether this popup should be modal, blocking everything behind from
|
/// <summary>Gets or sets a value indicating whether this popup should be modal, blocking everything behind from
|
||||||
/// being interacted.</summary>
|
/// being interacted.</summary>
|
||||||
/// <remarks>If <c>true</c>, then <see cref="ImGui.BeginPopupModal(string, ref bool, ImGuiWindowFlags)"/> will be
|
/// <remarks>If <c>true</c>, then <see cref="ImGui.BeginPopupModal(ImU8String, ref bool, ImGuiWindowFlags)"/> will be
|
||||||
/// used. Otherwise, <see cref="ImGui.Begin(string, ref bool, ImGuiWindowFlags)"/> will be used.</remarks>
|
/// used. Otherwise, <see cref="ImGui.Begin(ImU8String, ref bool, ImGuiWindowFlags)"/> will be used.</remarks>
|
||||||
public bool IsModal { get; set; } = true;
|
public bool IsModal { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>Gets or sets the window flags.</summary>
|
/// <summary>Gets or sets the window flags.</summary>
|
||||||
|
|
@ -432,7 +430,7 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
this.firstDrawAfterRefresh = false;
|
this.firstDrawAfterRefresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float GetDistanceFromMonitor(Vector2 point, ImGuiPlatformMonitorPtr monitor)
|
private static float GetDistanceFromMonitor(Vector2 point, ImGuiPlatformMonitor monitor)
|
||||||
{
|
{
|
||||||
var lt = monitor.MainPos;
|
var lt = monitor.MainPos;
|
||||||
var rb = monitor.MainPos + monitor.MainSize;
|
var rb = monitor.MainPos + monitor.MainSize;
|
||||||
|
|
@ -560,21 +558,10 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||||
using (this.fontHandle?.Push())
|
using (this.fontHandle?.Push())
|
||||||
{
|
{
|
||||||
unsafe
|
ImGui.InputTextMultiline(
|
||||||
{
|
"##fontPreviewText"u8,
|
||||||
fixed (byte* buf = this.fontPreviewText)
|
this.fontPreviewText,
|
||||||
fixed (byte* label = "##fontPreviewText"u8)
|
ImGui.GetContentRegionAvail());
|
||||||
{
|
|
||||||
ImGuiNative.igInputTextMultiline(
|
|
||||||
label,
|
|
||||||
buf,
|
|
||||||
(uint)this.fontPreviewText.Length,
|
|
||||||
ImGui.GetContentRegionAvail(),
|
|
||||||
ImGuiInputTextFlags.None,
|
|
||||||
null,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -610,15 +597,15 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
ref this.familySearch,
|
ref this.familySearch,
|
||||||
255,
|
255,
|
||||||
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory,
|
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory,
|
||||||
data =>
|
(ref ImGuiInputTextCallbackData data) =>
|
||||||
{
|
{
|
||||||
if (families.Count == 0)
|
if (families.Count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var baseIndex = this.selectedFamilyIndex;
|
var baseIndex = this.selectedFamilyIndex;
|
||||||
if (data->SelectionStart == 0 && data->SelectionEnd == data->BufTextLen)
|
if (data.SelectionStart == 0 && data.SelectionEnd == data.BufTextLen)
|
||||||
{
|
{
|
||||||
switch (data->EventKey)
|
switch (data.EventKey)
|
||||||
{
|
{
|
||||||
case ImGuiKey.DownArrow:
|
case ImGuiKey.DownArrow:
|
||||||
this.selectedFamilyIndex = (this.selectedFamilyIndex + 1) % families.Count;
|
this.selectedFamilyIndex = (this.selectedFamilyIndex + 1) % families.Count;
|
||||||
|
|
@ -634,13 +621,13 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
ImGuiHelpers.SetTextFromCallback(
|
ImGuiHelpers.SetTextFromCallback(
|
||||||
data,
|
ref data,
|
||||||
this.ExtractName(families[this.selectedFamilyIndex]));
|
this.ExtractName(families[this.selectedFamilyIndex]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (data->EventKey)
|
switch (data.EventKey)
|
||||||
{
|
{
|
||||||
case ImGuiKey.DownArrow:
|
case ImGuiKey.DownArrow:
|
||||||
this.selectedFamilyIndex = families.FindIndex(
|
this.selectedFamilyIndex = families.FindIndex(
|
||||||
|
|
@ -691,7 +678,7 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
|
|
||||||
if (ImGui.BeginChild("##familyList", ImGui.GetContentRegionAvail()))
|
if (ImGui.BeginChild("##familyList", ImGui.GetContentRegionAvail()))
|
||||||
{
|
{
|
||||||
var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
|
var clipper = ImGui.ImGuiListClipper();
|
||||||
var lineHeight = ImGui.GetTextLineHeightWithSpacing();
|
var lineHeight = ImGui.GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
if ((changed || this.firstDrawAfterRefresh) && this.selectedFamilyIndex != -1)
|
if ((changed || this.firstDrawAfterRefresh) && this.selectedFamilyIndex != -1)
|
||||||
|
|
@ -778,15 +765,15 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
ref this.fontSearch,
|
ref this.fontSearch,
|
||||||
255,
|
255,
|
||||||
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory,
|
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory,
|
||||||
data =>
|
(ref ImGuiInputTextCallbackData data) =>
|
||||||
{
|
{
|
||||||
if (fonts.Count == 0)
|
if (fonts.Count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var baseIndex = this.selectedFontIndex;
|
var baseIndex = this.selectedFontIndex;
|
||||||
if (data->SelectionStart == 0 && data->SelectionEnd == data->BufTextLen)
|
if (data.SelectionStart == 0 && data.SelectionEnd == data.BufTextLen)
|
||||||
{
|
{
|
||||||
switch (data->EventKey)
|
switch (data.EventKey)
|
||||||
{
|
{
|
||||||
case ImGuiKey.DownArrow:
|
case ImGuiKey.DownArrow:
|
||||||
this.selectedFontIndex = (this.selectedFontIndex + 1) % fonts.Count;
|
this.selectedFontIndex = (this.selectedFontIndex + 1) % fonts.Count;
|
||||||
|
|
@ -801,13 +788,13 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
ImGuiHelpers.SetTextFromCallback(
|
ImGuiHelpers.SetTextFromCallback(
|
||||||
data,
|
ref data,
|
||||||
this.ExtractName(fonts[this.selectedFontIndex]));
|
this.ExtractName(fonts[this.selectedFontIndex]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (data->EventKey)
|
switch (data.EventKey)
|
||||||
{
|
{
|
||||||
case ImGuiKey.DownArrow:
|
case ImGuiKey.DownArrow:
|
||||||
this.selectedFontIndex = fonts.FindIndex(
|
this.selectedFontIndex = fonts.FindIndex(
|
||||||
|
|
@ -858,7 +845,7 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
|
|
||||||
if (ImGui.BeginChild("##fontList"))
|
if (ImGui.BeginChild("##fontList"))
|
||||||
{
|
{
|
||||||
var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
|
var clipper = ImGui.ImGuiListClipper();
|
||||||
var lineHeight = ImGui.GetTextLineHeightWithSpacing();
|
var lineHeight = ImGui.GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
if ((changed || this.firstDrawAfterRefresh) && this.selectedFontIndex != -1)
|
if ((changed || this.firstDrawAfterRefresh) && this.selectedFontIndex != -1)
|
||||||
|
|
@ -927,9 +914,9 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
255,
|
255,
|
||||||
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory |
|
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory |
|
||||||
ImGuiInputTextFlags.CharsDecimal,
|
ImGuiInputTextFlags.CharsDecimal,
|
||||||
data =>
|
(ref ImGuiInputTextCallbackData data) =>
|
||||||
{
|
{
|
||||||
switch (data->EventKey)
|
switch (data.EventKey)
|
||||||
{
|
{
|
||||||
case ImGuiKey.DownArrow:
|
case ImGuiKey.DownArrow:
|
||||||
this.selectedFont = this.selectedFont with
|
this.selectedFont = this.selectedFont with
|
||||||
|
|
@ -948,7 +935,7 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
ImGuiHelpers.SetTextFromCallback(data, $"{this.selectedFont.SizePt:0.##}");
|
ImGuiHelpers.SetTextFromCallback(ref data, $"{this.selectedFont.SizePt:0.##}");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}))
|
}))
|
||||||
|
|
@ -962,7 +949,7 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
|
|
||||||
if (ImGui.BeginChild("##fontSizeList"))
|
if (ImGui.BeginChild("##fontSizeList"))
|
||||||
{
|
{
|
||||||
var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
|
var clipper = ImGui.ImGuiListClipper();
|
||||||
var lineHeight = ImGui.GetTextLineHeightWithSpacing();
|
var lineHeight = ImGui.GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
if (changed && this.selectedFontIndex != -1)
|
if (changed && this.selectedFontIndex != -1)
|
||||||
|
|
@ -1131,19 +1118,19 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
255,
|
255,
|
||||||
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory |
|
ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.CallbackHistory |
|
||||||
ImGuiInputTextFlags.CharsDecimal,
|
ImGuiInputTextFlags.CharsDecimal,
|
||||||
data =>
|
(ref ImGuiInputTextCallbackData data) =>
|
||||||
{
|
{
|
||||||
switch (data->EventKey)
|
switch (data.EventKey)
|
||||||
{
|
{
|
||||||
case ImGuiKey.DownArrow:
|
case ImGuiKey.DownArrow:
|
||||||
changed2 = true;
|
changed2 = true;
|
||||||
value = Math.Min(max, (MathF.Round(value / step) * step) + step);
|
value = Math.Min(max, (MathF.Round(value / step) * step) + step);
|
||||||
ImGuiHelpers.SetTextFromCallback(data, $"{value:0.##}");
|
ImGuiHelpers.SetTextFromCallback(ref data, $"{value:0.##}");
|
||||||
break;
|
break;
|
||||||
case ImGuiKey.UpArrow:
|
case ImGuiKey.UpArrow:
|
||||||
changed2 = true;
|
changed2 = true;
|
||||||
value = Math.Max(min, (MathF.Round(value / step) * step) - step);
|
value = Math.Max(min, (MathF.Round(value / step) * step) - step);
|
||||||
ImGuiHelpers.SetTextFromCallback(data, $"{value:0.##}");
|
ImGuiHelpers.SetTextFromCallback(ref data, $"{value:0.##}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification.Internal;
|
namespace Dalamud.Interface.ImGuiNotification.Internal;
|
||||||
|
|
||||||
/// <summary>Represents an active notification.</summary>
|
/// <summary>Represents an active notification.</summary>
|
||||||
|
|
@ -155,7 +154,11 @@ internal sealed partial class ActiveNotification
|
||||||
|
|
||||||
if (!isTakingKeyboardInput && !isHovered && isFocused)
|
if (!isTakingKeyboardInput && !isHovered && isFocused)
|
||||||
{
|
{
|
||||||
ImGui.SetWindowFocus(null);
|
unsafe
|
||||||
|
{
|
||||||
|
ImGui.SetWindowFocus((byte*)null);
|
||||||
|
}
|
||||||
|
|
||||||
isFocused = false;
|
isFocused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,7 +218,7 @@ internal sealed partial class ActiveNotification
|
||||||
/// <summary>Calculates the effective expiry, taking ImGui window state into account.</summary>
|
/// <summary>Calculates the effective expiry, taking ImGui window state into account.</summary>
|
||||||
/// <param name="warrantsExtension">Notification will not dismiss while this paramter is <c>true</c>.</param>
|
/// <param name="warrantsExtension">Notification will not dismiss while this paramter is <c>true</c>.</param>
|
||||||
/// <returns>The calculated effective expiry.</returns>
|
/// <returns>The calculated effective expiry.</returns>
|
||||||
/// <remarks>Expected to be called BETWEEN <see cref="ImGui.Begin(string)"/> and <see cref="ImGui.End"/>.</remarks>
|
/// <remarks>Expected to be called BETWEEN <see cref="ImGui.Begin(ImU8String, ImGuiWindowFlags)"/> and <see cref="ImGui.End()"/>.</remarks>
|
||||||
private DateTime CalculateEffectiveExpiry(ref bool warrantsExtension)
|
private DateTime CalculateEffectiveExpiry(ref bool warrantsExtension)
|
||||||
{
|
{
|
||||||
DateTime expiry;
|
DateTime expiry;
|
||||||
|
|
@ -596,9 +599,9 @@ internal sealed partial class ActiveNotification
|
||||||
verts[vertPtr++] = lastOff;
|
verts[vertPtr++] = lastOff;
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
var dlist = ImGui.GetWindowDrawList().NativePtr;
|
var dlist = ImGui.GetWindowDrawList().Handle;
|
||||||
fixed (Vector2* pvert = verts)
|
fixed (Vector2* pvert = verts)
|
||||||
ImGuiNative.ImDrawList_AddConvexPolyFilled(dlist, pvert, vertPtr, color);
|
dlist->AddConvexPolyFilled(pvert, vertPtr, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Game.Gui;
|
using Dalamud.Game.Gui;
|
||||||
using Dalamud.Interface.GameFonts;
|
using Dalamud.Interface.GameFonts;
|
||||||
|
|
@ -13,8 +14,6 @@ using Dalamud.IoC.Internal;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification.Internal;
|
namespace Dalamud.Interface.ImGuiNotification.Internal;
|
||||||
|
|
||||||
/// <summary>Class handling notifications/toasts in ImGui.</summary>
|
/// <summary>Class handling notifications/toasts in ImGui.</summary>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification.Internal;
|
namespace Dalamud.Interface.ImGuiNotification.Internal;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Internal.Windows;
|
using Dalamud.Interface.Internal.Windows;
|
||||||
|
|
@ -13,8 +14,6 @@ using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Storage.Assets;
|
using Dalamud.Storage.Assets;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification;
|
namespace Dalamud.Interface.ImGuiNotification;
|
||||||
|
|
||||||
/// <summary>Utilities for implementing stuff under <see cref="ImGuiNotification"/>.</summary>
|
/// <summary>Utilities for implementing stuff under <see cref="ImGuiNotification"/>.</summary>
|
||||||
|
|
@ -56,7 +55,7 @@ public static class NotificationUtilities
|
||||||
using (fontHandle.Push())
|
using (fontHandle.Push())
|
||||||
{
|
{
|
||||||
var font = ImGui.GetFont();
|
var font = ImGui.GetFont();
|
||||||
var glyphPtr = (ImGuiHelpers.ImFontGlyphReal*)font.FindGlyphNoFallback(c).NativePtr;
|
var glyphPtr = (ImGuiHelpers.ImFontGlyphReal*)font.FindGlyphNoFallback(c);
|
||||||
if (glyphPtr is null)
|
if (glyphPtr is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -103,7 +102,7 @@ public static class NotificationUtilities
|
||||||
return false;
|
return false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var handle = texture.ImGuiHandle;
|
var handle = texture.Handle;
|
||||||
var size = texture.Size;
|
var size = texture.Size;
|
||||||
if (size.X > maxCoord.X - minCoord.X)
|
if (size.X > maxCoord.X - minCoord.X)
|
||||||
size *= (maxCoord.X - minCoord.X) / size.X;
|
size *= (maxCoord.X - minCoord.X) / size.X;
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,15 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using BitFaster.Caching.Lru;
|
using BitFaster.Caching.Lru;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Data;
|
using Dalamud.Data;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Interface.ImGuiSeStringRenderer.Internal.TextProcessing;
|
using Dalamud.Interface.ImGuiSeStringRenderer.Internal.TextProcessing;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
using Lumina.Text;
|
using Lumina.Text;
|
||||||
using Lumina.Text.Parse;
|
using Lumina.Text.Parse;
|
||||||
|
|
@ -58,7 +54,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
|
||||||
private readonly SeStringColorStackSet colorStackSet;
|
private readonly SeStringColorStackSet colorStackSet;
|
||||||
|
|
||||||
/// <summary>Splits a draw list so that different layers of a single glyph can be drawn out of order.</summary>
|
/// <summary>Splits a draw list so that different layers of a single glyph can be drawn out of order.</summary>
|
||||||
private ImDrawListSplitter* splitter = ImGuiNative.ImDrawListSplitter_ImDrawListSplitter();
|
private ImDrawListSplitter* splitter = ImGui.ImDrawListSplitter();
|
||||||
|
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
private SeStringRenderer(DataManager dm, TargetSigScanner sigScanner)
|
private SeStringRenderer(DataManager dm, TargetSigScanner sigScanner)
|
||||||
|
|
@ -146,15 +142,23 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
|
||||||
size = Vector2.Max(size, fragment.Offset + new Vector2(fragment.VisibleWidth, state.LineHeight));
|
size = Vector2.Max(size, fragment.Offset + new Vector2(fragment.VisibleWidth, state.LineHeight));
|
||||||
|
|
||||||
// If we're not drawing at all, stop further processing.
|
// If we're not drawing at all, stop further processing.
|
||||||
if (state.DrawList.NativePtr is null)
|
if (state.DrawList.Handle is null)
|
||||||
return new() { Size = size };
|
return new() { Size = size };
|
||||||
|
|
||||||
state.SplitDrawList();
|
state.SplitDrawList();
|
||||||
|
|
||||||
// Handle cases where ImGui.AlignTextToFramePadding has been called.
|
// Handle cases where ImGui.AlignTextToFramePadding has been called.
|
||||||
var pCurrentWindow = *(nint*)(ImGui.GetCurrentContext() + ImGuiContextCurrentWindowOffset);
|
var context = ImGui.GetCurrentContext();
|
||||||
var pWindowDc = pCurrentWindow + ImGuiWindowDcOffset;
|
var currLineTextBaseOffset = 0f;
|
||||||
var currLineTextBaseOffset = *(float*)(pWindowDc + ImGuiWindowTempDataCurrLineTextBaseOffset);
|
if (!context.IsNull)
|
||||||
|
{
|
||||||
|
var currentWindow = context.CurrentWindow;
|
||||||
|
if (!currentWindow.IsNull)
|
||||||
|
{
|
||||||
|
currLineTextBaseOffset = currentWindow.DC.CurrLineTextBaseOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var itemSize = size;
|
var itemSize = size;
|
||||||
if (currLineTextBaseOffset != 0f)
|
if (currLineTextBaseOffset != 0f)
|
||||||
{
|
{
|
||||||
|
|
@ -280,7 +284,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
|
||||||
{
|
{
|
||||||
if (this.splitter is not null)
|
if (this.splitter is not null)
|
||||||
{
|
{
|
||||||
ImGuiNative.ImDrawListSplitter_destroy(this.splitter);
|
this.splitter->Destroy();
|
||||||
this.splitter = null;
|
this.splitter = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +491,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
|
||||||
if (gfdTextureSrv != 0)
|
if (gfdTextureSrv != 0)
|
||||||
{
|
{
|
||||||
state.Draw(
|
state.Draw(
|
||||||
gfdTextureSrv,
|
new ImTextureID(gfdTextureSrv),
|
||||||
offset + new Vector2(x, MathF.Round((state.LineHeight - size.Y) / 2)),
|
offset + new Vector2(x, MathF.Round((state.LineHeight - size.Y) / 2)),
|
||||||
size,
|
size,
|
||||||
useHq ? gfdEntry.HqUv0 : gfdEntry.Uv0,
|
useHq ? gfdEntry.HqUv0 : gfdEntry.Uv0,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
using Lumina.Text.Payloads;
|
using Lumina.Text.Payloads;
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ public record struct SeStringDrawParams
|
||||||
public SeStringReplacementEntity.GetEntityDelegate? GetEntity { get; set; }
|
public SeStringReplacementEntity.GetEntityDelegate? GetEntity { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the screen offset of the left top corner.</summary>
|
/// <summary>Gets or sets the screen offset of the left top corner.</summary>
|
||||||
/// <value>Screen offset to draw at, or <c>null</c> to use <see cref="ImGui.GetCursorScreenPos"/>.</value>
|
/// <value>Screen offset to draw at, or <c>null</c> to use <see cref="ImGui.GetCursorScreenPos()"/>.</value>
|
||||||
public Vector2? ScreenOffset { get; set; }
|
public Vector2? ScreenOffset { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the font to use.</summary>
|
/// <summary>Gets or sets the font to use.</summary>
|
||||||
|
|
@ -40,7 +40,7 @@ public record struct SeStringDrawParams
|
||||||
|
|
||||||
/// <summary>Gets or sets the wrapping width.</summary>
|
/// <summary>Gets or sets the wrapping width.</summary>
|
||||||
/// <value>Width in pixels, or <c>null</c> to wrap at the end of available content region from
|
/// <value>Width in pixels, or <c>null</c> to wrap at the end of available content region from
|
||||||
/// <see cref="ImGui.GetContentRegionAvail"/> (the default).</value>
|
/// <see cref="ImGui.GetContentRegionAvail()"/> (the default).</value>
|
||||||
public float? WrapWidth { get; set; }
|
public float? WrapWidth { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the thickness of underline under links.</summary>
|
/// <summary>Gets or sets the thickness of underline under links.</summary>
|
||||||
|
|
@ -105,8 +105,8 @@ public record struct SeStringDrawParams
|
||||||
|
|
||||||
/// <summary>Gets the effective font.</summary>
|
/// <summary>Gets the effective font.</summary>
|
||||||
internal readonly unsafe ImFont* EffectiveFont =>
|
internal readonly unsafe ImFont* EffectiveFont =>
|
||||||
(this.Font ?? ImGui.GetFont()) is var f && f.NativePtr is not null
|
(this.Font ?? ImGui.GetFont()) is var f && f.Handle is not null
|
||||||
? f.NativePtr
|
? f.Handle
|
||||||
: throw new ArgumentException("Specified font is empty.");
|
: throw new ArgumentException("Specified font is empty.");
|
||||||
|
|
||||||
/// <summary>Gets the effective line height in pixels.</summary>
|
/// <summary>Gets the effective line height in pixels.</summary>
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,10 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.ImGuiSeStringRenderer.Internal;
|
using Dalamud.Interface.ImGuiSeStringRenderer.Internal;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Lumina.Text.Payloads;
|
using Lumina.Text.Payloads;
|
||||||
using Lumina.Text.ReadOnly;
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
|
|
@ -150,7 +147,7 @@ public unsafe ref struct SeStringDrawState
|
||||||
/// <param name="channelIndex">Channel to switch to.</param>
|
/// <param name="channelIndex">Channel to switch to.</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void SetCurrentChannel(SeStringDrawChannel channelIndex) =>
|
public readonly void SetCurrentChannel(SeStringDrawChannel channelIndex) =>
|
||||||
ImGuiNative.ImDrawListSplitter_SetCurrentChannel(this.splitter, this.drawList, (int)channelIndex);
|
this.splitter->SetCurrentChannel(this.drawList, (int)channelIndex);
|
||||||
|
|
||||||
/// <summary>Draws a single texture.</summary>
|
/// <summary>Draws a single texture.</summary>
|
||||||
/// <param name="igTextureId">ImGui texture ID to draw from.</param>
|
/// <param name="igTextureId">ImGui texture ID to draw from.</param>
|
||||||
|
|
@ -160,7 +157,7 @@ public unsafe ref struct SeStringDrawState
|
||||||
/// <param name="uv1">Right bottom corner of the glyph w.r.t. its glyph origin in the source texture.</param>
|
/// <param name="uv1">Right bottom corner of the glyph w.r.t. its glyph origin in the source texture.</param>
|
||||||
/// <param name="color">Color of the glyph in RGBA.</param>
|
/// <param name="color">Color of the glyph in RGBA.</param>
|
||||||
public readonly void Draw(
|
public readonly void Draw(
|
||||||
nint igTextureId,
|
ImTextureID igTextureId,
|
||||||
Vector2 offset,
|
Vector2 offset,
|
||||||
Vector2 size,
|
Vector2 size,
|
||||||
Vector2 uv0,
|
Vector2 uv0,
|
||||||
|
|
@ -193,7 +190,7 @@ public unsafe ref struct SeStringDrawState
|
||||||
/// top and bottom pixels to apply faux italicization by <see cref="Vector2.X"/> and <see cref="Vector2.Y"/>
|
/// top and bottom pixels to apply faux italicization by <see cref="Vector2.X"/> and <see cref="Vector2.Y"/>
|
||||||
/// respectively.</param>
|
/// respectively.</param>
|
||||||
public readonly void Draw(
|
public readonly void Draw(
|
||||||
nint igTextureId,
|
ImTextureID igTextureId,
|
||||||
Vector2 offset,
|
Vector2 offset,
|
||||||
Vector2 xy0,
|
Vector2 xy0,
|
||||||
Vector2 xy1,
|
Vector2 xy1,
|
||||||
|
|
@ -305,7 +302,7 @@ public unsafe ref struct SeStringDrawState
|
||||||
internal readonly ref ImGuiHelpers.ImFontGlyphReal FindGlyph(Rune rune)
|
internal readonly ref ImGuiHelpers.ImFontGlyphReal FindGlyph(Rune rune)
|
||||||
{
|
{
|
||||||
var p = rune.Value is >= ushort.MinValue and < ushort.MaxValue
|
var p = rune.Value is >= ushort.MinValue and < ushort.MaxValue
|
||||||
? ImGuiNative.ImFont_FindGlyph(this.Font, (ushort)rune.Value)
|
? this.Font->FindGlyph((ushort)rune.Value)
|
||||||
: this.Font->FallbackGlyph;
|
: this.Font->FallbackGlyph;
|
||||||
return ref *(ImGuiHelpers.ImFontGlyphReal*)p;
|
return ref *(ImGuiHelpers.ImFontGlyphReal*)p;
|
||||||
}
|
}
|
||||||
|
|
@ -340,8 +337,7 @@ public unsafe ref struct SeStringDrawState
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return MathF.Round(
|
return MathF.Round(
|
||||||
ImGuiNative.ImFont_GetDistanceAdjustmentForPair(
|
this.Font->GetDistanceAdjustmentForPair(
|
||||||
this.Font,
|
|
||||||
(ushort)left.Value,
|
(ushort)left.Value,
|
||||||
(ushort)right.Value) * this.FontSizeScale);
|
(ushort)right.Value) * this.FontSizeScale);
|
||||||
}
|
}
|
||||||
|
|
@ -398,9 +394,9 @@ public unsafe ref struct SeStringDrawState
|
||||||
/// <summary>Splits the draw list.</summary>
|
/// <summary>Splits the draw list.</summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal readonly void SplitDrawList() =>
|
internal readonly void SplitDrawList() =>
|
||||||
ImGuiNative.ImDrawListSplitter_Split(this.splitter, this.drawList, ChannelCount);
|
this.splitter->Split(this.drawList, ChannelCount);
|
||||||
|
|
||||||
/// <summary>Merges the draw list.</summary>
|
/// <summary>Merges the draw list.</summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal readonly void MergeDrawList() => ImGuiNative.ImDrawListSplitter_Merge(this.splitter, this.drawList);
|
internal readonly void MergeDrawList() => this.splitter->Merge(this.drawList);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,14 @@ internal class AssertHandler : IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="AssertHandler"/> class.
|
/// Initializes a new instance of the <see cref="AssertHandler"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AssertHandler()
|
public unsafe AssertHandler()
|
||||||
{
|
{
|
||||||
this.callback = (expr, file, line) => this.OnImGuiAssert(expr, file, line);
|
this.callback = this.OnImGuiAssert;
|
||||||
}
|
}
|
||||||
|
|
||||||
private delegate void AssertCallbackDelegate(
|
private unsafe delegate void AssertCallbackDelegate(
|
||||||
[MarshalAs(UnmanagedType.LPStr)] string expr,
|
void* expr,
|
||||||
[MarshalAs(UnmanagedType.LPStr)] string file,
|
void* file,
|
||||||
int line);
|
int line);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -53,15 +53,15 @@ internal class AssertHandler : IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register the cimgui assert handler with the native library.
|
/// Register the cimgui assert handler with the native library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Setup()
|
public unsafe void Setup()
|
||||||
{
|
{
|
||||||
CustomNativeFunctions.igCustom_SetAssertCallback(this.callback);
|
CustomNativeFunctions.igCustom_SetAssertCallback(Marshal.GetFunctionPointerForDelegate(this.callback).ToPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unregister the cimgui assert handler with the native library.
|
/// Unregister the cimgui assert handler with the native library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Shutdown()
|
public unsafe void Shutdown()
|
||||||
{
|
{
|
||||||
CustomNativeFunctions.igCustom_SetAssertCallback(null);
|
CustomNativeFunctions.igCustom_SetAssertCallback(null);
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +72,19 @@ internal class AssertHandler : IDisposable
|
||||||
this.Shutdown();
|
this.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnImGuiAssert(string expr, string file, int line)
|
private unsafe void OnImGuiAssert(void* pExpr, void* pFile, int line)
|
||||||
{
|
{
|
||||||
|
var expr = Marshal.PtrToStringAnsi(new IntPtr(pExpr));
|
||||||
|
var file = Marshal.PtrToStringAnsi(new IntPtr(pFile));
|
||||||
|
if (expr == null || file == null)
|
||||||
|
{
|
||||||
|
Log.Warning("ImGui assertion failed: {Expr} at {File}:{Line} (failed to parse)",
|
||||||
|
expr,
|
||||||
|
file,
|
||||||
|
line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var key = $"{file}:{line}";
|
var key = $"{file}:{line}";
|
||||||
if (this.ignoredAsserts.Contains(key))
|
if (this.ignoredAsserts.Contains(key))
|
||||||
return;
|
return;
|
||||||
|
|
@ -218,11 +229,11 @@ internal class AssertHandler : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CustomNativeFunctions
|
private static unsafe class CustomNativeFunctions
|
||||||
{
|
{
|
||||||
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
|
||||||
#pragma warning disable SA1300
|
#pragma warning disable SA1300
|
||||||
public static extern void igCustom_SetAssertCallback(AssertCallbackDelegate? callback);
|
public static extern void igCustom_SetAssertCallback(void* cb);
|
||||||
#pragma warning restore SA1300
|
#pragma warning restore SA1300
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,12 +140,6 @@ internal class DalamudCommands : IServiceType
|
||||||
"Open Dalamud's startup timing profiler."),
|
"Open Dalamud's startup timing profiler."),
|
||||||
});
|
});
|
||||||
|
|
||||||
commandManager.AddHandler("/imdebug", new CommandInfo(this.OnDebugImInfoCommand)
|
|
||||||
{
|
|
||||||
HelpMessage = "ImGui DEBUG",
|
|
||||||
ShowInHelp = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
commandManager.AddHandler("/xlcopylog", new CommandInfo(this.OnCopyLogCommand)
|
commandManager.AddHandler("/xlcopylog", new CommandInfo(this.OnCopyLogCommand)
|
||||||
{
|
{
|
||||||
HelpMessage = Loc.Localize(
|
HelpMessage = Loc.Localize(
|
||||||
|
|
@ -305,29 +299,6 @@ internal class DalamudCommands : IServiceType
|
||||||
Service<DalamudInterface>.Get().ToggleLogWindow();
|
Service<DalamudInterface>.Get().ToggleLogWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDebugImInfoCommand(string command, string arguments)
|
|
||||||
{
|
|
||||||
var io = Service<InterfaceManager>.Get().LastImGuiIoPtr;
|
|
||||||
var info = $"WantCaptureKeyboard: {io.WantCaptureKeyboard}\n";
|
|
||||||
info += $"WantCaptureMouse: {io.WantCaptureMouse}\n";
|
|
||||||
info += $"WantSetMousePos: {io.WantSetMousePos}\n";
|
|
||||||
info += $"WantTextInput: {io.WantTextInput}\n";
|
|
||||||
info += $"WantSaveIniSettings: {io.WantSaveIniSettings}\n";
|
|
||||||
info += $"BackendFlags: {(int)io.BackendFlags}\n";
|
|
||||||
info += $"DeltaTime: {io.DeltaTime}\n";
|
|
||||||
info += $"DisplaySize: {io.DisplaySize.X} {io.DisplaySize.Y}\n";
|
|
||||||
info += $"Framerate: {io.Framerate}\n";
|
|
||||||
info += $"MetricsActiveWindows: {io.MetricsActiveWindows}\n";
|
|
||||||
info += $"MetricsRenderWindows: {io.MetricsRenderWindows}\n";
|
|
||||||
info += $"MousePos: {io.MousePos.X} {io.MousePos.Y}\n";
|
|
||||||
info += $"MouseClicked: {io.MouseClicked}\n";
|
|
||||||
info += $"MouseDown: {io.MouseDown}\n";
|
|
||||||
info += $"NavActive: {io.NavActive}\n";
|
|
||||||
info += $"NavVisible: {io.NavVisible}\n";
|
|
||||||
|
|
||||||
Log.Information(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnVersionInfoCommand(string command, string arguments)
|
private void OnVersionInfoCommand(string command, string arguments)
|
||||||
{
|
{
|
||||||
var chatGui = Service<ChatGui>.Get();
|
var chatGui = Service<ChatGui>.Get();
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Unicode;
|
using System.Text.Unicode;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Hooking.WndProcHook;
|
using Dalamud.Hooking.WndProcHook;
|
||||||
|
|
@ -19,8 +20,6 @@ using Dalamud.Interface.GameFonts;
|
||||||
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
#if IMEDEBUG
|
#if IMEDEBUG
|
||||||
using Serilog;
|
using Serilog;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -136,7 +135,8 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
this.interfaceManager = imws.Manager;
|
this.interfaceManager = imws.Manager;
|
||||||
this.setPlatformImeDataDelegate = this.ImGuiSetPlatformImeData;
|
this.setPlatformImeDataDelegate = this.ImGuiSetPlatformImeData;
|
||||||
|
|
||||||
ImGui.GetIO().SetPlatformImeDataFn = Marshal.GetFunctionPointerForDelegate(this.setPlatformImeDataDelegate);
|
var io = ImGui.GetIO();
|
||||||
|
io.SetPlatformImeDataFn = Marshal.GetFunctionPointerForDelegate(this.setPlatformImeDataDelegate).ToPointer();
|
||||||
this.interfaceManager.Draw += this.Draw;
|
this.interfaceManager.Draw += this.Draw;
|
||||||
this.wndProcHookManager.PreWndProc += this.WndProcHookManagerOnPreWndProc;
|
this.wndProcHookManager.PreWndProc += this.WndProcHookManagerOnPreWndProc;
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +169,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
return true;
|
return true;
|
||||||
if (!ImGui.GetIO().ConfigInputTextCursorBlink)
|
if (!ImGui.GetIO().ConfigInputTextCursorBlink)
|
||||||
return true;
|
return true;
|
||||||
var textState = CustomNativeFunctions.igCustom_GetInputTextState();
|
var textState = GetInputTextState();
|
||||||
if (textState->Id == 0 || (textState->Flags & ImGuiInputTextFlags.ReadOnly) != 0)
|
if (textState->Id == 0 || (textState->Flags & ImGuiInputTextFlags.ReadOnly) != 0)
|
||||||
return true;
|
return true;
|
||||||
if (textState->CursorAnim <= 0)
|
if (textState->CursorAnim <= 0)
|
||||||
|
|
@ -227,6 +227,12 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ImGuiInputTextStateWrapper* GetInputTextState()
|
||||||
|
{
|
||||||
|
var ctx = ImGui.GetCurrentContext();
|
||||||
|
return (ImGuiInputTextStateWrapper*)&ctx.Handle->InputTextState;
|
||||||
|
}
|
||||||
|
|
||||||
private static (string String, bool Supported) ToUcs2(char* data, int nc = -1)
|
private static (string String, bool Supported) ToUcs2(char* data, int nc = -1)
|
||||||
{
|
{
|
||||||
if (nc == -1)
|
if (nc == -1)
|
||||||
|
|
@ -278,7 +284,10 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
private void ReleaseUnmanagedResources()
|
private void ReleaseUnmanagedResources()
|
||||||
{
|
{
|
||||||
if (ImGuiHelpers.IsImGuiInitialized)
|
if (ImGuiHelpers.IsImGuiInitialized)
|
||||||
ImGui.GetIO().SetPlatformImeDataFn = nint.Zero;
|
{
|
||||||
|
var io = ImGui.GetIO();
|
||||||
|
io.SetPlatformImeDataFn = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WndProcHookManagerOnPreWndProc(WndProcEventArgs args)
|
private void WndProcHookManagerOnPreWndProc(WndProcEventArgs args)
|
||||||
|
|
@ -322,7 +331,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var textState = CustomNativeFunctions.igCustom_GetInputTextState();
|
var textState = GetInputTextState();
|
||||||
var invalidTarget = textState->Id == 0 || (textState->Flags & ImGuiInputTextFlags.ReadOnly) != 0;
|
var invalidTarget = textState->Id == 0 || (textState->Flags & ImGuiInputTextFlags.ReadOnly) != 0;
|
||||||
|
|
||||||
#if IMEDEBUG
|
#if IMEDEBUG
|
||||||
|
|
@ -552,7 +561,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
|
|
||||||
this.ReflectCharacterEncounters(newString);
|
this.ReflectCharacterEncounters(newString);
|
||||||
|
|
||||||
var textState = CustomNativeFunctions.igCustom_GetInputTextState();
|
var textState = GetInputTextState();
|
||||||
if (this.temporaryUndoSelection is not null)
|
if (this.temporaryUndoSelection is not null)
|
||||||
{
|
{
|
||||||
textState->Undo();
|
textState->Undo();
|
||||||
|
|
@ -611,7 +620,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
this.compositionCursorOffset = 0;
|
this.compositionCursorOffset = 0;
|
||||||
this.temporaryUndoSelection = null;
|
this.temporaryUndoSelection = null;
|
||||||
|
|
||||||
var textState = CustomNativeFunctions.igCustom_GetInputTextState();
|
var textState = GetInputTextState();
|
||||||
textState->Stb.SelectStart = textState->Stb.Cursor = textState->Stb.SelectEnd;
|
textState->Stb.SelectStart = textState->Stb.Cursor = textState->Stb.SelectEnd;
|
||||||
|
|
||||||
this.candidateStrings.Clear();
|
this.candidateStrings.Clear();
|
||||||
|
|
@ -670,7 +679,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var viewport = ime.associatedViewport;
|
var viewport = ime.associatedViewport;
|
||||||
if (viewport.NativePtr is null)
|
if (viewport.Handle is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var drawCand = ime.candidateStrings.Count != 0;
|
var drawCand = ime.candidateStrings.Count != 0;
|
||||||
|
|
@ -963,7 +972,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
private struct ImGuiInputTextState
|
private struct ImGuiInputTextStateWrapper
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
public int CurLenW;
|
public int CurLenW;
|
||||||
|
|
@ -981,7 +990,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
public bool Edited;
|
public bool Edited;
|
||||||
public ImGuiInputTextFlags Flags;
|
public ImGuiInputTextFlags Flags;
|
||||||
|
|
||||||
public ImVectorWrapper<char> TextW => new((ImVector*)&this.ThisPtr->TextWRaw);
|
public ImVectorWrapper<char> TextW => new((ImVector*)&this.ThisWrapperPtr->TextWRaw);
|
||||||
|
|
||||||
public (int Start, int End, int Cursor) SelectionTuple
|
public (int Start, int End, int Cursor) SelectionTuple
|
||||||
{
|
{
|
||||||
|
|
@ -989,6 +998,8 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
set => (this.Stb.SelectStart, this.Stb.SelectEnd, this.Stb.Cursor) = value;
|
set => (this.Stb.SelectStart, this.Stb.SelectEnd, this.Stb.Cursor) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ImGuiInputTextStateWrapper* ThisWrapperPtr => (ImGuiInputTextStateWrapper*)Unsafe.AsPointer(ref this);
|
||||||
|
|
||||||
private ImGuiInputTextState* ThisPtr => (ImGuiInputTextState*)Unsafe.AsPointer(ref this);
|
private ImGuiInputTextState* ThisPtr => (ImGuiInputTextState*)Unsafe.AsPointer(ref this);
|
||||||
|
|
||||||
public void SetSelectionRange(int offset, int length, int relativeCursorOffset)
|
public void SetSelectionRange(int offset, int length, int relativeCursorOffset)
|
||||||
|
|
@ -1016,14 +1027,14 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
(s, e) = (e, s);
|
(s, e) = (e, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Undo() => CustomNativeFunctions.igCustom_StbTextUndo(this.ThisPtr);
|
public void Undo() => ImGuiP.Custom_StbTextUndo(this.ThisPtr);
|
||||||
|
|
||||||
public bool MakeUndoReplace(int offset, int oldLength, int newLength)
|
public bool MakeUndoReplace(int offset, int oldLength, int newLength)
|
||||||
{
|
{
|
||||||
if (oldLength == 0 && newLength == 0)
|
if (oldLength == 0 && newLength == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CustomNativeFunctions.igCustom_StbTextMakeUndoReplace(this.ThisPtr, offset, oldLength, newLength);
|
ImGuiP.Custom_StbTextMakeUndoReplace(this.ThisPtr, offset, oldLength, newLength);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1099,20 +1110,6 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CustomNativeFunctions
|
|
||||||
{
|
|
||||||
#pragma warning disable SA1300
|
|
||||||
[DllImport("cimgui")]
|
|
||||||
public static extern ImGuiInputTextState* igCustom_GetInputTextState();
|
|
||||||
|
|
||||||
[DllImport("cimgui")]
|
|
||||||
public static extern void igCustom_StbTextMakeUndoReplace(ImGuiInputTextState* str, int where, int old_length, int new_length);
|
|
||||||
|
|
||||||
[DllImport("cimgui")]
|
|
||||||
public static extern void igCustom_StbTextUndo(ImGuiInputTextState* str);
|
|
||||||
#pragma warning restore SA1300
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IMEDEBUG
|
#if IMEDEBUG
|
||||||
private static class ImeDebug
|
private static class ImeDebug
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Bindings.ImPlot;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Console;
|
using Dalamud.Console;
|
||||||
using Dalamud.Game.Addon.Lifecycle;
|
using Dalamud.Game.Addon.Lifecycle;
|
||||||
|
|
@ -33,15 +35,9 @@ using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Internal;
|
using Dalamud.Plugin.Internal;
|
||||||
using Dalamud.Storage.Assets;
|
using Dalamud.Storage.Assets;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using ImPlotNET;
|
|
||||||
using PInvoke;
|
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal;
|
namespace Dalamud.Interface.Internal;
|
||||||
|
|
@ -582,9 +578,12 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
|
|
||||||
// Release focus of any ImGui window if we click into the game.
|
// Release focus of any ImGui window if we click into the game.
|
||||||
var io = ImGui.GetIO();
|
var io = ImGui.GetIO();
|
||||||
if (!io.WantCaptureMouse && (User32.GetKeyState((int)User32.VirtualKey.VK_LBUTTON) & 0x8000) != 0)
|
if (!io.WantCaptureMouse && (global::Windows.Win32.PInvoke.GetKeyState((int)VirtualKey.LBUTTON) & 0x8000) != 0)
|
||||||
{
|
{
|
||||||
ImGui.SetWindowFocus(null);
|
unsafe
|
||||||
|
{
|
||||||
|
ImGui.SetWindowFocus((byte*)null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -641,10 +640,10 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
ImGui.SetNextItemWidth(40);
|
ImGui.SetNextItemWidth(40);
|
||||||
if (ImGui.Button("###devMenuOpener", new Vector2(20, 20)))
|
if (ImGui.Button("###devMenuOpener", new Vector2(20, 20)))
|
||||||
this.isImGuiDrawDevMenu = true;
|
this.isImGuiDrawDevMenu = true;
|
||||||
|
|
||||||
ImGui.End();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
|
||||||
if (EnvironmentConfiguration.DalamudForceMinHook)
|
if (EnvironmentConfiguration.DalamudForceMinHook)
|
||||||
{
|
{
|
||||||
ImGui.SetNextWindowPos(windowPos, ImGuiCond.Always);
|
ImGui.SetNextWindowPos(windowPos, ImGuiCond.Always);
|
||||||
|
|
@ -665,7 +664,7 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawDevMenu()
|
private unsafe void DrawDevMenu()
|
||||||
{
|
{
|
||||||
if (this.isImGuiDrawDevMenu)
|
if (this.isImGuiDrawDevMenu)
|
||||||
{
|
{
|
||||||
|
|
@ -706,7 +705,7 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
}
|
}
|
||||||
|
|
||||||
var logSynchronously = this.configuration.LogSynchronously;
|
var logSynchronously = this.configuration.LogSynchronously;
|
||||||
if (ImGui.MenuItem("Log Synchronously", null, ref logSynchronously))
|
if (ImGui.MenuItem("Log Synchronously", (byte*)null, ref logSynchronously))
|
||||||
{
|
{
|
||||||
this.configuration.LogSynchronously = logSynchronously;
|
this.configuration.LogSynchronously = logSynchronously;
|
||||||
this.configuration.QueueSave();
|
this.configuration.QueueSave();
|
||||||
|
|
@ -845,7 +844,7 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
ImGui.EndMenu();
|
ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.MenuItem("Report crashes at shutdown", null, this.configuration.ReportShutdownCrashes))
|
if (ImGui.MenuItem("Report crashes at shutdown", (byte*)null, this.configuration.ReportShutdownCrashes))
|
||||||
{
|
{
|
||||||
this.configuration.ReportShutdownCrashes = !this.configuration.ReportShutdownCrashes;
|
this.configuration.ReportShutdownCrashes = !this.configuration.ReportShutdownCrashes;
|
||||||
this.configuration.QueueSave();
|
this.configuration.QueueSave();
|
||||||
|
|
@ -858,9 +857,9 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
this.OpenBranchSwitcher();
|
this.OpenBranchSwitcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.MenuItem(this.dalamud.StartInfo.GameVersion?.ToString() ?? "Unknown version", false);
|
ImGui.MenuItem(this.dalamud.StartInfo.GameVersion?.ToString() ?? "Unknown version", false, false);
|
||||||
ImGui.MenuItem($"D: {Util.GetScmVersion()} CS: {Util.GetGitHashClientStructs()}[{FFXIVClientStructs.ThisAssembly.Git.Commits}]", false);
|
ImGui.MenuItem($"D: {Util.GetScmVersion()} CS: {Util.GetGitHashClientStructs()}[{FFXIVClientStructs.ThisAssembly.Git.Commits}]", false, false);
|
||||||
ImGui.MenuItem($"CLR: {Environment.Version}", false);
|
ImGui.MenuItem($"CLR: {Environment.Version}", false, false);
|
||||||
|
|
||||||
ImGui.EndMenu();
|
ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
|
|
@ -887,7 +886,7 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
}
|
}
|
||||||
|
|
||||||
var assertsEnabled = this.configuration.ImGuiAssertsEnabledAtStartup ?? false;
|
var assertsEnabled = this.configuration.ImGuiAssertsEnabledAtStartup ?? false;
|
||||||
if (ImGui.MenuItem("Enable asserts at startup", null, assertsEnabled))
|
if (ImGui.MenuItem("Enable asserts at startup", (byte*)null, assertsEnabled))
|
||||||
{
|
{
|
||||||
this.configuration.ImGuiAssertsEnabledAtStartup = !assertsEnabled;
|
this.configuration.ImGuiAssertsEnabledAtStartup = !assertsEnabled;
|
||||||
this.configuration.QueueSave();
|
this.configuration.QueueSave();
|
||||||
|
|
@ -897,7 +896,7 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
|
|
||||||
if (ImGui.MenuItem("Clear focus"))
|
if (ImGui.MenuItem("Clear focus"))
|
||||||
{
|
{
|
||||||
ImGui.SetWindowFocus(null);
|
ImGui.SetWindowFocus((byte*)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.MenuItem("Clear stacks"))
|
if (ImGui.MenuItem("Clear stacks"))
|
||||||
|
|
@ -938,7 +937,7 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
Log.Information(info);
|
Log.Information(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.MenuItem("Show dev bar info", null, this.configuration.ShowDevBarInfo))
|
if (ImGui.MenuItem("Show dev bar info", (byte*)null, this.configuration.ShowDevBarInfo))
|
||||||
{
|
{
|
||||||
this.configuration.ShowDevBarInfo = !this.configuration.ShowDevBarInfo;
|
this.configuration.ShowDevBarInfo = !this.configuration.ShowDevBarInfo;
|
||||||
}
|
}
|
||||||
|
|
@ -1009,12 +1008,12 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
if (ImGui.MenuItem("Load all API levels (ONLY FOR DEVELOPERS!!!)", null, pluginManager.LoadAllApiLevels))
|
if (ImGui.MenuItem("Load all API levels", (byte*)null, pluginManager.LoadAllApiLevels))
|
||||||
{
|
{
|
||||||
pluginManager.LoadAllApiLevels = !pluginManager.LoadAllApiLevels;
|
pluginManager.LoadAllApiLevels = !pluginManager.LoadAllApiLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.MenuItem("Load blacklisted plugins", null, pluginManager.LoadBannedPlugins))
|
if (ImGui.MenuItem("Load blacklisted plugins", (byte*)null, pluginManager.LoadBannedPlugins))
|
||||||
{
|
{
|
||||||
pluginManager.LoadBannedPlugins = !pluginManager.LoadBannedPlugins;
|
pluginManager.LoadBannedPlugins = !pluginManager.LoadBannedPlugins;
|
||||||
}
|
}
|
||||||
|
|
@ -1025,8 +1024,8 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
ImGui.MenuItem("API Level:" + PluginManager.DalamudApiLevel, false);
|
ImGui.MenuItem("API Level:" + PluginManager.DalamudApiLevel, false, false);
|
||||||
ImGui.MenuItem("Loaded plugins:" + pluginManager.InstalledPlugins.Count(), false);
|
ImGui.MenuItem("Loaded plugins:" + pluginManager.InstalledPlugins.Count(), false, false);
|
||||||
ImGui.EndMenu();
|
ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.DesignSystem;
|
namespace Dalamud.Interface.Internal.DesignSystem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,13 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Plugin.Internal;
|
using Dalamud.Plugin.Internal;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.DesignSystem;
|
namespace Dalamud.Interface.Internal.DesignSystem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,10 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Gui.Toast;
|
using Dalamud.Game.Gui.Toast;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Logging.Internal;
|
using Dalamud.Logging.Internal;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
using static TerraFX.Interop.Windows.Windows;
|
using static TerraFX.Interop.Windows.Windows;
|
||||||
|
|
@ -38,9 +35,9 @@ namespace Dalamud.Interface.Internal;
|
||||||
internal sealed unsafe class ImGuiClipboardFunctionProvider : IInternalDisposableService
|
internal sealed unsafe class ImGuiClipboardFunctionProvider : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new(nameof(ImGuiClipboardFunctionProvider));
|
private static readonly ModuleLog Log = new(nameof(ImGuiClipboardFunctionProvider));
|
||||||
private readonly nint clipboardUserDataOriginal;
|
private readonly void* clipboardUserDataOriginal;
|
||||||
private readonly nint setTextOriginal;
|
private readonly void* setTextOriginal;
|
||||||
private readonly nint getTextOriginal;
|
private readonly void* getTextOriginal;
|
||||||
|
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ToastGui toastGui = Service<ToastGui>.Get();
|
private readonly ToastGui toastGui = Service<ToastGui>.Get();
|
||||||
|
|
@ -58,9 +55,9 @@ internal sealed unsafe class ImGuiClipboardFunctionProvider : IInternalDisposabl
|
||||||
this.clipboardUserDataOriginal = io.ClipboardUserData;
|
this.clipboardUserDataOriginal = io.ClipboardUserData;
|
||||||
this.setTextOriginal = io.SetClipboardTextFn;
|
this.setTextOriginal = io.SetClipboardTextFn;
|
||||||
this.getTextOriginal = io.GetClipboardTextFn;
|
this.getTextOriginal = io.GetClipboardTextFn;
|
||||||
io.ClipboardUserData = GCHandle.ToIntPtr(this.clipboardUserData = GCHandle.Alloc(this));
|
io.ClipboardUserData = GCHandle.ToIntPtr(this.clipboardUserData = GCHandle.Alloc(this)).ToPointer();
|
||||||
io.SetClipboardTextFn = (nint)(delegate* unmanaged<nint, byte*, void>)&StaticSetClipboardTextImpl;
|
io.SetClipboardTextFn = (delegate* unmanaged<nint, byte*, void>)&StaticSetClipboardTextImpl;
|
||||||
io.GetClipboardTextFn = (nint)(delegate* unmanaged<nint, byte*>)&StaticGetClipboardTextImpl;
|
io.GetClipboardTextFn = (delegate* unmanaged<nint, byte*>)&StaticGetClipboardTextImpl;
|
||||||
|
|
||||||
this.clipboardData = new(0);
|
this.clipboardData = new(0);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -119,13 +119,13 @@ internal unsafe partial class InterfaceManager
|
||||||
|
|
||||||
this.ResizeBuffers?.InvokeSafely();
|
this.ResizeBuffers?.InvokeSafely();
|
||||||
|
|
||||||
this.scene?.OnPreResize();
|
this.backend?.OnPreResize();
|
||||||
|
|
||||||
var ret = this.dxgiSwapChainResizeBuffersHook!.Original(swapChain, bufferCount, width, height, newFormat, swapChainFlags);
|
var ret = this.dxgiSwapChainResizeBuffersHook!.Original(swapChain, bufferCount, width, height, newFormat, swapChainFlags);
|
||||||
if (ret == DXGI.DXGI_ERROR_INVALID_CALL)
|
if (ret == DXGI.DXGI_ERROR_INVALID_CALL)
|
||||||
Log.Error("invalid call to resizeBuffers");
|
Log.Error("invalid call to resizeBuffers");
|
||||||
|
|
||||||
this.scene?.OnPostResize((int)width, (int)height);
|
this.backend?.OnPostResize((int)width, (int)height);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,23 +14,23 @@ internal unsafe partial class InterfaceManager
|
||||||
private void ReShadeAddonInterfaceOnDestroySwapChain(ref ReShadeAddonInterface.ApiObject swapChain)
|
private void ReShadeAddonInterfaceOnDestroySwapChain(ref ReShadeAddonInterface.ApiObject swapChain)
|
||||||
{
|
{
|
||||||
var swapChainNative = swapChain.GetNative<IDXGISwapChain>();
|
var swapChainNative = swapChain.GetNative<IDXGISwapChain>();
|
||||||
if (this.scene?.SwapChain.NativePointer != (nint)swapChainNative)
|
if (this.backend?.IsAttachedToPresentationTarget((nint)swapChainNative) is not true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.scene?.OnPreResize();
|
this.backend?.OnPreResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReShadeAddonInterfaceOnInitSwapChain(ref ReShadeAddonInterface.ApiObject swapChain)
|
private void ReShadeAddonInterfaceOnInitSwapChain(ref ReShadeAddonInterface.ApiObject swapChain)
|
||||||
{
|
{
|
||||||
var swapChainNative = swapChain.GetNative<IDXGISwapChain>();
|
var swapChainNative = swapChain.GetNative<IDXGISwapChain>();
|
||||||
if (this.scene?.SwapChain.NativePointer != (nint)swapChainNative)
|
if (this.backend?.IsAttachedToPresentationTarget((nint)swapChainNative) is not true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC desc;
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
if (swapChainNative->GetDesc(&desc).FAILED)
|
if (swapChainNative->GetDesc(&desc).FAILED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.scene?.OnPostResize((int)desc.BufferDesc.Width, (int)desc.BufferDesc.Height);
|
this.backend?.OnPostResize((int)desc.BufferDesc.Width, (int)desc.BufferDesc.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReShadeAddonInterfaceOnPresent(
|
private void ReShadeAddonInterfaceOnPresent(
|
||||||
|
|
@ -42,16 +42,16 @@ internal unsafe partial class InterfaceManager
|
||||||
{
|
{
|
||||||
var swapChainNative = swapChain.GetNative<IDXGISwapChain>();
|
var swapChainNative = swapChain.GetNative<IDXGISwapChain>();
|
||||||
|
|
||||||
if (this.RenderDalamudCheckAndInitialize(swapChainNative, 0) is { } activeScene)
|
if (this.RenderDalamudCheckAndInitialize(swapChainNative, 0) is { } activebackend)
|
||||||
this.RenderDalamudDraw(activeScene);
|
this.RenderDalamudDraw(activebackend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReShadeAddonInterfaceOnReShadeOverlay(ref ReShadeAddonInterface.ApiObject runtime)
|
private void ReShadeAddonInterfaceOnReShadeOverlay(ref ReShadeAddonInterface.ApiObject runtime)
|
||||||
{
|
{
|
||||||
var swapChainNative = runtime.GetNative<IDXGISwapChain>();
|
var swapChainNative = runtime.GetNative<IDXGISwapChain>();
|
||||||
|
|
||||||
if (this.RenderDalamudCheckAndInitialize(swapChainNative, 0) is { } activeScene)
|
if (this.RenderDalamudCheckAndInitialize(swapChainNative, 0) is { } activebackend)
|
||||||
this.RenderDalamudDraw(activeScene);
|
this.RenderDalamudDraw(activebackend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int AsReShadeAddonDxgiSwapChainResizeBuffersDetour(
|
private int AsReShadeAddonDxgiSwapChainResizeBuffersDetour(
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.ClientState.GamePad;
|
using Dalamud.Game.ClientState.GamePad;
|
||||||
|
|
@ -17,6 +17,7 @@ using Dalamud.Game.ClientState.Keys;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Hooking.Internal;
|
using Dalamud.Hooking.Internal;
|
||||||
using Dalamud.Hooking.WndProcHook;
|
using Dalamud.Hooking.WndProcHook;
|
||||||
|
using Dalamud.Interface.ImGuiBackend;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.ImGuiNotification.Internal;
|
using Dalamud.Interface.ImGuiNotification.Internal;
|
||||||
using Dalamud.Interface.Internal.Asserts;
|
using Dalamud.Interface.Internal.Asserts;
|
||||||
|
|
@ -33,20 +34,16 @@ using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Dalamud.Utility.Timing;
|
using Dalamud.Utility.Timing;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using ImGuiScene;
|
|
||||||
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
using PInvoke;
|
|
||||||
|
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
using static TerraFX.Interop.Windows.Windows;
|
||||||
|
|
||||||
using CSFramework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
|
using CSFramework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
|
||||||
|
|
||||||
|
using DWMWINDOWATTRIBUTE = Windows.Win32.Graphics.Dwm.DWMWINDOWATTRIBUTE;
|
||||||
|
|
||||||
// general dev notes, here because it's easiest
|
// general dev notes, here because it's easiest
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -102,7 +99,7 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
|
|
||||||
private readonly AssertHandler assertHandler = new();
|
private readonly AssertHandler assertHandler = new();
|
||||||
|
|
||||||
private RawDX11Scene? scene;
|
private IWin32Backend? backend;
|
||||||
|
|
||||||
private Hook<SetCursorDelegate>? setCursorHook;
|
private Hook<SetCursorDelegate>? setCursorHook;
|
||||||
private Hook<ReShadeDxgiSwapChainPresentDelegate>? reShadeDxgiSwapChainPresentHook;
|
private Hook<ReShadeDxgiSwapChainPresentDelegate>? reShadeDxgiSwapChainPresentHook;
|
||||||
|
|
@ -115,9 +112,9 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
private ILockedImFont? defaultFontResourceLock;
|
private ILockedImFont? defaultFontResourceLock;
|
||||||
|
|
||||||
// can't access imgui IO before first present call
|
// can't access imgui IO before first present call
|
||||||
private bool lastWantCapture = false;
|
private HWND gameWindowHandle;
|
||||||
|
private bool lastWantCapture;
|
||||||
private bool isOverrideGameCursor = true;
|
private bool isOverrideGameCursor = true;
|
||||||
private IntPtr gameWindowHandle;
|
|
||||||
|
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
private InterfaceManager()
|
private InterfaceManager()
|
||||||
|
|
@ -126,12 +123,12 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||||
private delegate IntPtr SetCursorDelegate(IntPtr hCursor);
|
private delegate nint SetCursorDelegate(nint hCursor);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This event gets called each frame to facilitate ImGui drawing.
|
/// This event gets called each frame to facilitate ImGui drawing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event RawDX11Scene.BuildUIDelegate? Draw;
|
public event IImGuiBackend.BuildUiDelegate? Draw;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This event gets called when ResizeBuffers is called.
|
/// This event gets called when ResizeBuffers is called.
|
||||||
|
|
@ -199,36 +196,26 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the DX11 scene.
|
/// Gets the DX11 scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RawDX11Scene? Scene => this.scene;
|
public IImGuiBackend? Backend => this.backend;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the D3D11 device instance.
|
|
||||||
/// </summary>
|
|
||||||
public SharpDX.Direct3D11.Device? Device => this.scene?.Device;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the address handle to the main process window.
|
|
||||||
/// </summary>
|
|
||||||
public IntPtr WindowHandlePtr => this.scene?.WindowHandlePtr ?? IntPtr.Zero;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether the game's cursor should be overridden with the ImGui cursor.
|
/// Gets or sets a value indicating whether the game's cursor should be overridden with the ImGui cursor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool OverrideGameCursor
|
public bool OverrideGameCursor
|
||||||
{
|
{
|
||||||
get => this.scene?.UpdateCursor ?? this.isOverrideGameCursor;
|
get => this.backend?.UpdateCursor ?? this.isOverrideGameCursor;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
this.isOverrideGameCursor = value;
|
this.isOverrideGameCursor = value;
|
||||||
if (this.scene != null)
|
if (this.backend != null)
|
||||||
this.scene.UpdateCursor = value;
|
this.backend.UpdateCursor = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the Dalamud interface ready to use.
|
/// Gets a value indicating whether the Dalamud interface ready to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsReady => this.scene != null;
|
public bool IsReady => this.backend != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether Draw events should be dispatched.
|
/// Gets or sets a value indicating whether Draw events should be dispatched.
|
||||||
|
|
@ -242,20 +229,24 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating the native handle of the game main window.
|
/// Gets a value indicating the native handle of the game main window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr GameWindowHandle
|
public unsafe HWND GameWindowHandle
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (this.gameWindowHandle == 0)
|
if (this.gameWindowHandle == 0)
|
||||||
{
|
{
|
||||||
nint gwh = 0;
|
var gwh = default(HWND);
|
||||||
while ((gwh = NativeFunctions.FindWindowEx(0, gwh, "FFXIVGAME", 0)) != 0)
|
fixed (char* pClass = "FFXIVGAME")
|
||||||
{
|
{
|
||||||
_ = User32.GetWindowThreadProcessId(gwh, out var pid);
|
while ((gwh = FindWindowExW(default, gwh, (ushort*)pClass, default)) != default)
|
||||||
if (pid == Environment.ProcessId && User32.IsWindowVisible(gwh))
|
|
||||||
{
|
{
|
||||||
this.gameWindowHandle = gwh;
|
uint pid;
|
||||||
break;
|
_ = GetWindowThreadProcessId(gwh, &pid);
|
||||||
|
if (pid == Environment.ProcessId && IsWindowVisible(gwh))
|
||||||
|
{
|
||||||
|
this.gameWindowHandle = gwh;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +315,7 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
this.IconFontHandle = null;
|
this.IconFontHandle = null;
|
||||||
|
|
||||||
Interlocked.Exchange(ref this.dalamudAtlas, null)?.Dispose();
|
Interlocked.Exchange(ref this.dalamudAtlas, null)?.Dispose();
|
||||||
Interlocked.Exchange(ref this.scene, null)?.Dispose();
|
Interlocked.Exchange(ref this.backend, null)?.Dispose();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -459,27 +450,27 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
/// Get video memory information.
|
/// Get video memory information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The currently used video memory, or null if not available.</returns>
|
/// <returns>The currently used video memory, or null if not available.</returns>
|
||||||
public (long Used, long Available)? GetD3dMemoryInfo()
|
public unsafe (long Used, long Available)? GetD3dMemoryInfo()
|
||||||
{
|
{
|
||||||
if (this.Device == null)
|
if (this.backend?.DeviceHandle is 0 or null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
try
|
using var device = default(ComPtr<IDXGIDevice>);
|
||||||
{
|
using var adapter = default(ComPtr<IDXGIAdapter>);
|
||||||
var dxgiDev = this.Device.QueryInterfaceOrNull<SharpDX.DXGI.Device>();
|
using var adapter4 = default(ComPtr<IDXGIAdapter4>);
|
||||||
var dxgiAdapter = dxgiDev?.Adapter.QueryInterfaceOrNull<SharpDX.DXGI.Adapter4>();
|
|
||||||
if (dxgiAdapter == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var memInfo = dxgiAdapter.QueryVideoMemoryInfo(0, SharpDX.DXGI.MemorySegmentGroup.Local);
|
if (new ComPtr<IUnknown>((IUnknown*)this.backend.DeviceHandle).As(&device).FAILED)
|
||||||
return (memInfo.CurrentUsage, memInfo.CurrentReservation);
|
return null;
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
if (device.Get()->GetAdapter(adapter.GetAddressOf()).FAILED)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (adapter.As(&adapter4).FAILED)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var vmi = default(DXGI_QUERY_VIDEO_MEMORY_INFO);
|
||||||
|
adapter4.Get()->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP.DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &vmi);
|
||||||
|
return ((long)vmi.CurrentUsage, (long)vmi.CurrentReservation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -488,23 +479,24 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ClearStacks()
|
public void ClearStacks()
|
||||||
{
|
{
|
||||||
this.scene?.ClearStacksOnContext();
|
ImGuiHelpers.ClearStacksOnContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Toggle Windows 11 immersive mode on the game window.
|
/// Toggle Windows 11 immersive mode on the game window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="enabled">Value.</param>
|
/// <param name="enabled">Value.</param>
|
||||||
internal void SetImmersiveMode(bool enabled)
|
internal unsafe void SetImmersiveMode(bool enabled)
|
||||||
{
|
{
|
||||||
if (this.GameWindowHandle == 0)
|
if (this.GameWindowHandle == 0)
|
||||||
throw new InvalidOperationException("Game window is not yet ready.");
|
throw new InvalidOperationException("Game window is not yet ready.");
|
||||||
var value = enabled ? 1 : 0;
|
|
||||||
((HRESULT)NativeFunctions.DwmSetWindowAttribute(
|
var value = enabled ? 1u : 0u;
|
||||||
this.GameWindowHandle,
|
global::Windows.Win32.PInvoke.DwmSetWindowAttribute(
|
||||||
NativeFunctions.DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE,
|
new(new IntPtr(this.GameWindowHandle.Value)),
|
||||||
ref value,
|
DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||||
sizeof(int))).ThrowOnError();
|
&value,
|
||||||
|
sizeof(uint)).ThrowOnFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InterfaceManager WhenFontsReady()
|
private static InterfaceManager WhenFontsReady()
|
||||||
|
|
@ -537,9 +529,9 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
/// and initializes ImGui for drawing.</summary>
|
/// and initializes ImGui for drawing.</summary>
|
||||||
/// <param name="swapChain">The swap chain to test and initialize ImGui with if conditions are met.</param>
|
/// <param name="swapChain">The swap chain to test and initialize ImGui with if conditions are met.</param>
|
||||||
/// <param name="flags">Flags passed to <see cref="IDXGISwapChain.Present"/>.</param>
|
/// <param name="flags">Flags passed to <see cref="IDXGISwapChain.Present"/>.</param>
|
||||||
/// <returns>An initialized instance of <see cref="RawDX11Scene"/>, or <c>null</c> if <paramref name="swapChain"/>
|
/// <returns>An initialized instance of <see cref="IDXGISwapChain"/>, or <c>null</c> if <paramref name="swapChain"/>
|
||||||
/// is not the main swap chain.</returns>
|
/// is not the main swap chain.</returns>
|
||||||
private unsafe RawDX11Scene? RenderDalamudCheckAndInitialize(IDXGISwapChain* swapChain, uint flags)
|
private unsafe IImGuiBackend? RenderDalamudCheckAndInitialize(IDXGISwapChain* swapChain, uint flags)
|
||||||
{
|
{
|
||||||
// Quoting ReShade dxgi_swapchain.cpp DXGISwapChain::on_present:
|
// Quoting ReShade dxgi_swapchain.cpp DXGISwapChain::on_present:
|
||||||
// > Some D3D11 games test presentation for timing and composition purposes
|
// > Some D3D11 games test presentation for timing and composition purposes
|
||||||
|
|
@ -552,7 +544,7 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
|
|
||||||
Debug.Assert(this.dalamudAtlas is not null, "dalamudAtlas should have been set already");
|
Debug.Assert(this.dalamudAtlas is not null, "dalamudAtlas should have been set already");
|
||||||
|
|
||||||
var activeScene = this.scene ?? this.InitScene(swapChain);
|
var activeBackend = this.backend ?? this.InitBackend(swapChain);
|
||||||
|
|
||||||
if (!this.dalamudAtlas!.HasBuiltAtlas)
|
if (!this.dalamudAtlas!.HasBuiltAtlas)
|
||||||
{
|
{
|
||||||
|
|
@ -566,12 +558,12 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return activeScene;
|
return activeBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Draws Dalamud to the given scene representing the ImGui context.</summary>
|
/// <summary>Draws Dalamud to the given scene representing the ImGui context.</summary>
|
||||||
/// <param name="activeScene">The scene to draw to.</param>
|
/// <param name="activeBackend">The scene to draw to.</param>
|
||||||
private void RenderDalamudDraw(RawDX11Scene activeScene)
|
private void RenderDalamudDraw(IImGuiBackend activeBackend)
|
||||||
{
|
{
|
||||||
this.CumulativePresentCalls++;
|
this.CumulativePresentCalls++;
|
||||||
this.IsMainThreadInPresent = true;
|
this.IsMainThreadInPresent = true;
|
||||||
|
|
@ -584,7 +576,7 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
|
|
||||||
// Enable viewports if there are no issues.
|
// Enable viewports if there are no issues.
|
||||||
var viewportsEnable = this.dalamudConfiguration.IsDisableViewport ||
|
var viewportsEnable = this.dalamudConfiguration.IsDisableViewport ||
|
||||||
activeScene.SwapChain.IsFullScreen ||
|
activeBackend.IsMainViewportFullScreen() ||
|
||||||
ImGui.GetPlatformIO().Monitors.Size == 1;
|
ImGui.GetPlatformIO().Monitors.Size == 1;
|
||||||
if (viewportsEnable)
|
if (viewportsEnable)
|
||||||
ImGui.GetIO().ConfigFlags &= ~ImGuiConfigFlags.ViewportsEnable;
|
ImGui.GetIO().ConfigFlags &= ~ImGuiConfigFlags.ViewportsEnable;
|
||||||
|
|
@ -592,41 +584,48 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;
|
ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;
|
||||||
|
|
||||||
// Call drawing functions, which in turn will call Draw event.
|
// Call drawing functions, which in turn will call Draw event.
|
||||||
activeScene.Render();
|
activeBackend.Render();
|
||||||
|
|
||||||
this.PostImGuiRender();
|
this.PostImGuiRender();
|
||||||
this.IsMainThreadInPresent = false;
|
this.IsMainThreadInPresent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe RawDX11Scene InitScene(IDXGISwapChain* swapChain)
|
private unsafe IImGuiBackend InitBackend(IDXGISwapChain* swapChain)
|
||||||
{
|
{
|
||||||
RawDX11Scene newScene;
|
IWin32Backend newBackend;
|
||||||
using (Timings.Start("IM Scene Init"))
|
using (Timings.Start("IM Scene Init"))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
newBackend = new Dx11Win32Backend(swapChain);
|
||||||
this.assertHandler.Setup();
|
this.assertHandler.Setup();
|
||||||
newScene = new RawDX11Scene((nint)swapChain);
|
|
||||||
}
|
}
|
||||||
catch (DllNotFoundException ex)
|
catch (DllNotFoundException ex)
|
||||||
{
|
{
|
||||||
Service<InterfaceManagerWithScene>.ProvideException(ex);
|
Service<InterfaceManagerWithScene>.ProvideException(ex);
|
||||||
Log.Error(ex, "Could not load ImGui dependencies.");
|
Log.Error(ex, "Could not load ImGui dependencies.");
|
||||||
|
|
||||||
var res = User32.MessageBox(
|
fixed (void* lpText =
|
||||||
IntPtr.Zero,
|
"Dalamud plugins require the Microsoft Visual C++ Redistributable to be installed.\nPlease install the runtime from the official Microsoft website or disable Dalamud.\n\nDo you want to download the redistributable now?")
|
||||||
"Dalamud plugins require the Microsoft Visual C++ Redistributable to be installed.\nPlease install the runtime from the official Microsoft website or disable Dalamud.\n\nDo you want to download the redistributable now?",
|
|
||||||
"Dalamud Error",
|
|
||||||
User32.MessageBoxOptions.MB_YESNO | User32.MessageBoxOptions.MB_TOPMOST | User32.MessageBoxOptions.MB_ICONERROR);
|
|
||||||
|
|
||||||
if (res == User32.MessageBoxResult.IDYES)
|
|
||||||
{
|
{
|
||||||
var psi = new ProcessStartInfo
|
fixed (void* lpCaption = "Dalamud Error")
|
||||||
{
|
{
|
||||||
FileName = "https://aka.ms/vs/16/release/vc_redist.x64.exe",
|
var res = MessageBoxW(
|
||||||
UseShellExecute = true,
|
default,
|
||||||
};
|
(ushort*)lpText,
|
||||||
Process.Start(psi);
|
(ushort*)lpCaption,
|
||||||
|
MB.MB_YESNO | MB.MB_TOPMOST | MB.MB_ICONERROR);
|
||||||
|
|
||||||
|
if (res == IDYES)
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "https://aka.ms/vs/16/release/vc_redist.x64.exe",
|
||||||
|
UseShellExecute = true,
|
||||||
|
};
|
||||||
|
Process.Start(psi);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment.Exit(-1);
|
Environment.Exit(-1);
|
||||||
|
|
@ -638,7 +637,8 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
var startInfo = Service<Dalamud>.Get().StartInfo;
|
var startInfo = Service<Dalamud>.Get().StartInfo;
|
||||||
var configuration = Service<DalamudConfiguration>.Get();
|
var configuration = Service<DalamudConfiguration>.Get();
|
||||||
|
|
||||||
var iniFileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(startInfo.ConfigurationPath)!, "dalamudUI.ini"));
|
var iniFileInfo = new FileInfo(
|
||||||
|
Path.Combine(Path.GetDirectoryName(startInfo.ConfigurationPath)!, "dalamudUI.ini"));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -661,16 +661,18 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
Log.Error(ex, "Could not delete dalamudUI.ini");
|
Log.Error(ex, "Could not delete dalamudUI.ini");
|
||||||
}
|
}
|
||||||
|
|
||||||
newScene.UpdateCursor = this.isOverrideGameCursor;
|
newBackend.UpdateCursor = this.isOverrideGameCursor;
|
||||||
newScene.ImGuiIniPath = iniFileInfo.FullName;
|
newBackend.IniPath = iniFileInfo.FullName;
|
||||||
newScene.OnBuildUI += this.Display;
|
newBackend.BuildUi += this.Display;
|
||||||
newScene.OnNewInputFrame += this.OnNewInputFrame;
|
newBackend.NewInputFrame += this.OnNewInputFrame;
|
||||||
|
|
||||||
StyleModel.TransferOldModels();
|
StyleModel.TransferOldModels();
|
||||||
|
|
||||||
if (configuration.SavedStyles == null || configuration.SavedStyles.All(x => x.Name != StyleModelV1.DalamudStandard.Name))
|
if (configuration.SavedStyles == null ||
|
||||||
|
configuration.SavedStyles.All(x => x.Name != StyleModelV1.DalamudStandard.Name))
|
||||||
{
|
{
|
||||||
configuration.SavedStyles = new List<StyleModel> { StyleModelV1.DalamudStandard, StyleModelV1.DalamudClassic };
|
configuration.SavedStyles = new List<StyleModel>
|
||||||
|
{ StyleModelV1.DalamudStandard, StyleModelV1.DalamudClassic };
|
||||||
configuration.ChosenStyle = StyleModelV1.DalamudStandard.Name;
|
configuration.ChosenStyle = StyleModelV1.DalamudStandard.Name;
|
||||||
}
|
}
|
||||||
else if (configuration.SavedStyles.Count == 1)
|
else if (configuration.SavedStyles.Count == 1)
|
||||||
|
|
@ -726,16 +728,16 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
Log.Information("[IM] Scene & ImGui setup OK!");
|
Log.Information("[IM] Scene & ImGui setup OK!");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scene = newScene;
|
this.backend = newBackend;
|
||||||
Service<InterfaceManagerWithScene>.Provide(new(this));
|
Service<InterfaceManagerWithScene>.Provide(new(this));
|
||||||
|
|
||||||
this.wndProcHookManager.PreWndProc += this.WndProcHookManagerOnPreWndProc;
|
this.wndProcHookManager.PreWndProc += this.WndProcHookManagerOnPreWndProc;
|
||||||
return newScene;
|
return newBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void WndProcHookManagerOnPreWndProc(WndProcEventArgs args)
|
private void WndProcHookManagerOnPreWndProc(WndProcEventArgs args)
|
||||||
{
|
{
|
||||||
var r = this.scene?.ProcessWndProcW(args.Hwnd, (User32.WindowMessage)args.Message, args.WParam, args.LParam);
|
var r = this.backend?.ProcessWndProcW(args.Hwnd, args.Message, args.WParam, args.LParam);
|
||||||
if (r is not null)
|
if (r is not null)
|
||||||
args.SuppressWithValue(r.Value);
|
args.SuppressWithValue(r.Value);
|
||||||
}
|
}
|
||||||
|
|
@ -792,7 +794,7 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
SizePx = Service<FontAtlasFactory>.Get().DefaultFontSpec.SizePx,
|
SizePx = Service<FontAtlasFactory>.Get().DefaultFontSpec.SizePx,
|
||||||
GlyphRanges = new ushort[] { 0x20, 0x20, 0x00 },
|
GlyphRanges = [0x20, 0x20, 0x00],
|
||||||
})));
|
})));
|
||||||
this.MonoFontHandle = (FontHandle)this.dalamudAtlas.NewDelegateFontHandle(
|
this.MonoFontHandle = (FontHandle)this.dalamudAtlas.NewDelegateFontHandle(
|
||||||
e => e.OnPreBuild(
|
e => e.OnPreBuild(
|
||||||
|
|
@ -825,7 +827,7 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
// Update the ImGui default font.
|
// Update the ImGui default font.
|
||||||
ImGui.GetIO().NativePtr->FontDefault = fontLocked.ImFont;
|
ImGui.GetIO().Handle->FontDefault = fontLocked.ImFont;
|
||||||
|
|
||||||
// Update the reference to the resources of the default font.
|
// Update the reference to the resources of the default font.
|
||||||
this.defaultFontResourceLock?.Dispose();
|
this.defaultFontResourceLock?.Dispose();
|
||||||
|
|
@ -1057,13 +1059,13 @@ internal partial class InterfaceManager : IInternalDisposableService
|
||||||
this.dxgiSwapChainHook?.Enable();
|
this.dxgiSwapChainHook?.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr SetCursorDetour(IntPtr hCursor)
|
private nint SetCursorDetour(nint hCursor)
|
||||||
{
|
{
|
||||||
if (this.lastWantCapture && (!this.scene?.IsImGuiCursor(hCursor) ?? false) && this.OverrideGameCursor)
|
if (this.lastWantCapture && (!this.backend?.IsImGuiCursor(hCursor) ?? false) && this.OverrideGameCursor)
|
||||||
return IntPtr.Zero;
|
return default;
|
||||||
|
|
||||||
return this.setCursorHook?.IsDisposed is not false
|
return this.setCursorHook?.IsDisposed is not false
|
||||||
? User32.SetCursor(new(hCursor, false)).DangerousGetHandle()
|
? SetCursor((HCURSOR)hCursor)
|
||||||
: this.setCursorHook.Original(hCursor);
|
: this.setCursorHook.Original(hCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Gui;
|
using Dalamud.Game.Gui;
|
||||||
using Dalamud.Interface.ImGuiSeStringRenderer.Internal;
|
using Dalamud.Interface.ImGuiSeStringRenderer.Internal;
|
||||||
|
|
@ -10,7 +11,7 @@ using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
// Customised version of https://github.com/aers/FFXIVUIDebug
|
// Customised version of https://github.com/aers/FFXIVUIDebug
|
||||||
|
|
||||||
|
|
@ -87,7 +88,7 @@ internal unsafe class UiDebug
|
||||||
var addonName = atkUnitBase->NameString;
|
var addonName = atkUnitBase->NameString;
|
||||||
var agent = Service<GameGui>.Get().FindAgentInterface(atkUnitBase);
|
var agent = Service<GameGui>.Get().FindAgentInterface(atkUnitBase);
|
||||||
|
|
||||||
ImGui.Text($"{addonName}");
|
ImGui.Text(addonName);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, isVisible ? 0xFF00FF00 : 0xFF0000FF);
|
ImGui.PushStyleColor(ImGuiCol.Text, isVisible ? 0xFF00FF00 : 0xFF0000FF);
|
||||||
ImGui.Text(isVisible ? "Visible" : "Not Visible");
|
ImGui.Text(isVisible ? "Visible" : "Not Visible");
|
||||||
|
|
@ -211,7 +212,7 @@ internal unsafe class UiDebug
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
Service<SeStringRenderer>.Get().Draw(textNode->NodeText);
|
Service<SeStringRenderer>.Get().Draw(textNode->NodeText);
|
||||||
|
|
||||||
ImGui.InputText($"Replace Text##{(ulong)textNode:X}", new IntPtr(textNode->NodeText.StringPtr), (uint)textNode->NodeText.BufSize);
|
ImGui.InputText($"Replace Text##{(ulong)textNode:X}", new(textNode->NodeText.StringPtr, (int)textNode->NodeText.BufSize));
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button($"Encode##{(ulong)textNode:X}"))
|
if (ImGui.Button($"Encode##{(ulong)textNode:X}"))
|
||||||
|
|
@ -299,7 +300,7 @@ internal unsafe class UiDebug
|
||||||
if (ImGui.TreeNode($"Texture##{(ulong)kernelTexture->D3D11ShaderResourceView:X}"))
|
if (ImGui.TreeNode($"Texture##{(ulong)kernelTexture->D3D11ShaderResourceView:X}"))
|
||||||
{
|
{
|
||||||
ImGui.Image(
|
ImGui.Image(
|
||||||
new IntPtr(kernelTexture->D3D11ShaderResourceView),
|
new ImTextureID(kernelTexture->D3D11ShaderResourceView),
|
||||||
new Vector2(kernelTexture->ActualWidth, kernelTexture->ActualHeight));
|
new Vector2(kernelTexture->ActualWidth, kernelTexture->ActualHeight));
|
||||||
ImGui.TreePop();
|
ImGui.TreePop();
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +311,7 @@ internal unsafe class UiDebug
|
||||||
$"Texture##{(ulong)textureInfo->AtkTexture.KernelTexture->D3D11ShaderResourceView:X}"))
|
$"Texture##{(ulong)textureInfo->AtkTexture.KernelTexture->D3D11ShaderResourceView:X}"))
|
||||||
{
|
{
|
||||||
ImGui.Image(
|
ImGui.Image(
|
||||||
new IntPtr(textureInfo->AtkTexture.KernelTexture->D3D11ShaderResourceView),
|
new ImTextureID(textureInfo->AtkTexture.KernelTexture->D3D11ShaderResourceView),
|
||||||
new Vector2(
|
new Vector2(
|
||||||
textureInfo->AtkTexture.KernelTexture->ActualWidth,
|
textureInfo->AtkTexture.KernelTexture->ActualWidth,
|
||||||
textureInfo->AtkTexture.KernelTexture->ActualHeight));
|
textureInfo->AtkTexture.KernelTexture->ActualHeight));
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
@ -112,7 +112,7 @@ public unsafe partial class AddonTree
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ImGui.TextColored(new(1, 0, 0, 1), $"{ex}");
|
ImGui.TextColored(new Vector4(1, 0, 0, 1), $"{ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,9 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static Dalamud.Interface.FontAwesomeIcon;
|
using static Dalamud.Interface.FontAwesomeIcon;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.ElementSelector;
|
using static Dalamud.Interface.Internal.UiDebug2.ElementSelector;
|
||||||
|
|
@ -122,7 +121,7 @@ public unsafe partial class AddonTree : IDisposable
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextColored(isVisible ? new(0.1f, 1f, 0.1f, 1f) : new(0.6f, 0.6f, 0.6f, 1), isVisible ? "Visible" : "Not Visible");
|
ImGui.TextColored(isVisible ? new Vector4(0.1f, 1f, 0.1f, 1f) : new(0.6f, 0.6f, 0.6f, 1), isVisible ? "Visible" : "Not Visible");
|
||||||
|
|
||||||
ImGui.SameLine(ImGui.GetWindowWidth() - 100);
|
ImGui.SameLine(ImGui.GetWindowWidth() - 100);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static ImGuiNET.ImGuiTableColumnFlags;
|
using static Dalamud.Bindings.ImGui.ImGuiTableColumnFlags;
|
||||||
using static ImGuiNET.ImGuiTableFlags;
|
using static Dalamud.Bindings.ImGui.ImGuiTableFlags;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
||||||
|
|
@ -58,11 +57,11 @@ public static class Events
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.TextUnformatted($"{evt->State.StateFlags}");
|
ImGui.TextUnformatted($"{evt->State.StateFlags}");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.TextUnformatted($"{evt->State.UnkFlags1}");
|
ImGui.TextUnformatted($"{evt->State.ReturnFlags}");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGuiHelpers.ClickToCopyText($"{(nint)evt->Target:X}", null, new Vector4(0.6f, 0.6f, 0.6f, 1));
|
ImGuiHelpers.ClickToCopyText($"{(nint)evt->Target:X}", default, new Vector4(0.6f, 0.6f, 0.6f, 1));
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGuiHelpers.ClickToCopyText($"{(nint)evt->Listener:X}", null, new Vector4(0.6f, 0.6f, 0.6f, 1));
|
ImGuiHelpers.ClickToCopyText($"{(nint)evt->Listener:X}", default, new Vector4(0.6f, 0.6f, 0.6f, 1));
|
||||||
evt = evt->NextEvent;
|
evt = evt->NextEvent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
||||||
using static Dalamud.Utility.Util;
|
using static Dalamud.Utility.Util;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,20 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiColorEditFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiInputTextFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTableColumnFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTableFlags;
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static Dalamud.Interface.FontAwesomeIcon;
|
using static Dalamud.Interface.FontAwesomeIcon;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
||||||
using static Dalamud.Interface.Utility.ImGuiHelpers;
|
using static Dalamud.Interface.Utility.ImGuiHelpers;
|
||||||
using static ImGuiNET.ImGuiColorEditFlags;
|
|
||||||
using static ImGuiNET.ImGuiInputTextFlags;
|
|
||||||
using static ImGuiNET.ImGuiTableColumnFlags;
|
|
||||||
using static ImGuiNET.ImGuiTableFlags;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
||||||
|
|
@ -266,7 +265,7 @@ internal unsafe partial class NineGridNodeTree
|
||||||
ImGui.Text("Ninegrid Offsets:");
|
ImGui.Text("Ninegrid Offsets:");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(150);
|
ImGui.SetNextItemWidth(150);
|
||||||
if (ImGui.DragFloat2($"##{(nint)this.Node:X}ngOffsetLR", ref lr, 1, 0))
|
if (ImGui.DragFloat2($"##{(nint)this.Node:X}ngOffsetLR", ref lr, 1f, 0f))
|
||||||
{
|
{
|
||||||
this.NgNode->LeftOffset = (short)Math.Max(0, lr.X);
|
this.NgNode->LeftOffset = (short)Math.Max(0, lr.X);
|
||||||
this.NgNode->RightOffset = (short)Math.Max(0, lr.Y);
|
this.NgNode->RightOffset = (short)Math.Max(0, lr.Y);
|
||||||
|
|
@ -278,7 +277,7 @@ internal unsafe partial class NineGridNodeTree
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(150);
|
ImGui.SetNextItemWidth(150);
|
||||||
if (ImGui.DragFloat2($"##{(nint)this.Node:X}ngOffsetTB", ref tb, 1, 0))
|
if (ImGui.DragFloat2($"##{(nint)this.Node:X}ngOffsetTB", ref tb, 1f, 0f))
|
||||||
{
|
{
|
||||||
this.NgNode->TopOffset = (short)Math.Max(0, tb.X);
|
this.NgNode->TopOffset = (short)Math.Max(0, tb.X);
|
||||||
this.NgNode->BottomOffset = (short)Math.Max(0, tb.Y);
|
this.NgNode->BottomOffset = (short)Math.Max(0, tb.Y);
|
||||||
|
|
@ -322,7 +321,7 @@ internal unsafe partial class TextNodeTree
|
||||||
ImGui.Text("Font:");
|
ImGui.Text("Font:");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(150);
|
ImGui.SetNextItemWidth(150);
|
||||||
if (ImGui.Combo($"##{(nint)this.Node:X}fontType", ref fontIndex, FontNames, FontList.Count))
|
if (ImGui.Combo($"##{(nint)this.Node:X}fontType", ref fontIndex, FontNames))
|
||||||
{
|
{
|
||||||
this.TxtNode->FontType = FontList[fontIndex];
|
this.TxtNode->FontType = FontList[fontIndex];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTableColumnFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTableFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTreeNodeFlags;
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
||||||
using static Dalamud.Utility.Util;
|
using static Dalamud.Utility.Util;
|
||||||
using static FFXIVClientStructs.FFXIV.Component.GUI.TextureType;
|
using static FFXIVClientStructs.FFXIV.Component.GUI.TextureType;
|
||||||
using static ImGuiNET.ImGuiTableColumnFlags;
|
|
||||||
using static ImGuiNET.ImGuiTableFlags;
|
|
||||||
using static ImGuiNET.ImGuiTreeNodeFlags;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
||||||
|
|
@ -227,13 +226,13 @@ internal unsafe partial class ImageNodeTree : ResNodeTree
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
||||||
ImGui.TextColored(!hiRes ? new(1) : new(0.6f, 0.6f, 0.6f, 1), "Standard:\t");
|
ImGui.TextColored(!hiRes ? new Vector4(1) : new(0.6f, 0.6f, 0.6f, 1), "Standard:\t");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
var cursX = ImGui.GetCursorPosX();
|
var cursX = ImGui.GetCursorPosX();
|
||||||
|
|
||||||
PrintPartCoords(u / 2f, v / 2f, width / 2f, height / 2f);
|
PrintPartCoords(u / 2f, v / 2f, width / 2f, height / 2f);
|
||||||
|
|
||||||
ImGui.TextColored(hiRes ? new(1) : new(0.6f, 0.6f, 0.6f, 1), "Hi-Res:\t");
|
ImGui.TextColored(hiRes ? new Vector4(1) : new(0.6f, 0.6f, 0.6f, 1), "Hi-Res:\t");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.SetCursorPosX(cursX);
|
ImGui.SetCursorPosX(cursX);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static Dalamud.Utility.Util;
|
using static Dalamud.Utility.Util;
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,14 @@ using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiCol;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTreeNodeFlags;
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static Dalamud.Interface.FontAwesomeIcon;
|
using static Dalamud.Interface.FontAwesomeIcon;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.Browsing.Events;
|
using static Dalamud.Interface.Internal.UiDebug2.Browsing.Events;
|
||||||
|
|
@ -18,9 +19,6 @@ using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
||||||
using static Dalamud.Utility.Util;
|
using static Dalamud.Utility.Util;
|
||||||
using static FFXIVClientStructs.FFXIV.Component.GUI.NodeFlags;
|
using static FFXIVClientStructs.FFXIV.Component.GUI.NodeFlags;
|
||||||
|
|
||||||
using static ImGuiNET.ImGuiCol;
|
|
||||||
using static ImGuiNET.ImGuiTreeNodeFlags;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface.ImGuiSeStringRenderer;
|
using Dalamud.Interface.ImGuiSeStringRenderer;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
||||||
|
|
@ -47,7 +47,7 @@ internal unsafe partial class TextNodeTree : ResNodeTree
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.TextColored(new(1), "Text:");
|
ImGui.TextColored(new Vector4(1), "Text:");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using ImGuiNET;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,19 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics;
|
using FFXIVClientStructs.FFXIV.Client.Graphics;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTableColumnFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTableFlags;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiTreeNodeFlags;
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
|
||||||
using static Dalamud.Utility.Util;
|
using static Dalamud.Utility.Util;
|
||||||
using static FFXIVClientStructs.FFXIV.Component.GUI.NodeType;
|
using static FFXIVClientStructs.FFXIV.Component.GUI.NodeType;
|
||||||
using static ImGuiNET.ImGuiTableColumnFlags;
|
|
||||||
using static ImGuiNET.ImGuiTableFlags;
|
|
||||||
using static ImGuiNET.ImGuiTreeNodeFlags;
|
|
||||||
|
|
||||||
// ReSharper disable SuggestBaseTypeForParameter
|
// ReSharper disable SuggestBaseTypeForParameter
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
|
|
@ -75,7 +74,7 @@ public readonly unsafe partial struct TimelineTree
|
||||||
("Frame Time", $"{this.NodeTimeline->FrameTime:F2} ({this.NodeTimeline->FrameTime * 30:F0})"));
|
("Frame Time", $"{this.NodeTimeline->FrameTime:F2} ({this.NodeTimeline->FrameTime * 30:F0})"));
|
||||||
|
|
||||||
PrintFieldValuePairs(("Active Label Id", $"{this.NodeTimeline->ActiveLabelId}"), ("Duration", $"{this.NodeTimeline->LabelFrameIdxDuration}"), ("End Frame", $"{this.NodeTimeline->LabelEndFrameIdx}"));
|
PrintFieldValuePairs(("Active Label Id", $"{this.NodeTimeline->ActiveLabelId}"), ("Duration", $"{this.NodeTimeline->LabelFrameIdxDuration}"), ("End Frame", $"{this.NodeTimeline->LabelEndFrameIdx}"));
|
||||||
ImGui.TextColored(new(0.6f, 0.6f, 0.6f, 1), "Animation List");
|
ImGui.TextColored(new Vector4(0.6f, 0.6f, 0.6f, 1), "Animation List");
|
||||||
|
|
||||||
for (var a = 0; a < animationCount; a++)
|
for (var a = 0; a < animationCount; a++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,23 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
using Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static System.Globalization.NumberFormatInfo;
|
using static System.Globalization.NumberFormatInfo;
|
||||||
|
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiCol;
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiWindowFlags;
|
||||||
using static Dalamud.Interface.FontAwesomeIcon;
|
using static Dalamud.Interface.FontAwesomeIcon;
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.UiDebug2;
|
using static Dalamud.Interface.Internal.UiDebug2.UiDebug2;
|
||||||
using static Dalamud.Interface.UiBuilder;
|
using static Dalamud.Interface.UiBuilder;
|
||||||
using static Dalamud.Interface.Utility.ImGuiHelpers;
|
using static Dalamud.Interface.Utility.ImGuiHelpers;
|
||||||
using static FFXIVClientStructs.FFXIV.Component.GUI.NodeFlags;
|
using static FFXIVClientStructs.FFXIV.Component.GUI.NodeFlags;
|
||||||
using static ImGuiNET.ImGuiCol;
|
|
||||||
using static ImGuiNET.ImGuiWindowFlags;
|
|
||||||
// ReSharper disable StructLacksIEquatable.Global
|
// ReSharper disable StructLacksIEquatable.Global
|
||||||
|
|
||||||
#pragma warning disable CS0659
|
#pragma warning disable CS0659
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2;
|
namespace Dalamud.Interface.Internal.UiDebug2;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static Dalamud.Interface.Internal.UiDebug2.UiDebug2;
|
using static Dalamud.Interface.Internal.UiDebug2.UiDebug2;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static System.StringComparison;
|
using static System.StringComparison;
|
||||||
|
|
||||||
using static Dalamud.Interface.FontAwesomeIcon;
|
using static Dalamud.Interface.FontAwesomeIcon;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2;
|
namespace Dalamud.Interface.Internal.UiDebug2;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Gui;
|
using Dalamud.Game.Gui;
|
||||||
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
using Dalamud.Interface.Internal.UiDebug2.Browsing;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Logging.Internal;
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
using ImGuiNET;
|
using static Dalamud.Bindings.ImGui.ImGuiWindowFlags;
|
||||||
|
|
||||||
using static ImGuiNET.ImGuiWindowFlags;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2;
|
namespace Dalamud.Interface.Internal.UiDebug2;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics;
|
using FFXIVClientStructs.FFXIV.Client.Graphics;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
|
using static Dalamud.Bindings.ImGui.ImGuiCol;
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
using static ImGuiNET.ImGuiCol;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Utility;
|
namespace Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
|
|
||||||
|
|
@ -29,7 +28,7 @@ internal static class Gui
|
||||||
var grey60 = new Vector4(0.6f, 0.6f, 0.6f, 1);
|
var grey60 = new Vector4(0.6f, 0.6f, 0.6f, 1);
|
||||||
if (copy)
|
if (copy)
|
||||||
{
|
{
|
||||||
ImGuiHelpers.ClickToCopyText(value, null, grey60);
|
ImGuiHelpers.ClickToCopyText(value, default, grey60);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using static System.MathF;
|
using static System.MathF;
|
||||||
|
|
||||||
using static Dalamud.Interface.ColorHelpers;
|
using static Dalamud.Interface.ColorHelpers;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.UiDebug2.Utility;
|
namespace Dalamud.Interface.Internal.UiDebug2.Utility;
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,12 @@ using System.Linq;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Networking.Http;
|
using Dalamud.Networking.Http;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.Windows;
|
namespace Dalamud.Interface.Internal.Windows;
|
||||||
|
|
@ -69,7 +68,7 @@ public class BranchSwitcherWindow : Window
|
||||||
var si = Service<Dalamud>.Get().StartInfo;
|
var si = Service<Dalamud>.Get().StartInfo;
|
||||||
|
|
||||||
var itemsArray = this.branches.Select(x => x.Key).ToArray();
|
var itemsArray = this.branches.Select(x => x.Key).ToArray();
|
||||||
ImGui.ListBox("Branch", ref this.selectedBranchIndex, itemsArray, itemsArray.Length);
|
ImGui.ListBox("Branch", ref this.selectedBranchIndex, itemsArray);
|
||||||
|
|
||||||
var pickedBranch = this.branches.ElementAt(this.selectedBranchIndex);
|
var pickedBranch = this.branches.ElementAt(this.selectedBranchIndex);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Gui;
|
using Dalamud.Game.Gui;
|
||||||
|
|
@ -22,11 +22,8 @@ using Dalamud.Plugin.Internal.AutoUpdate;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Storage.Assets;
|
using Dalamud.Storage.Assets;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.Windows;
|
namespace Dalamud.Interface.Internal.Windows;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -267,7 +264,7 @@ internal sealed class ChangelogWindow : Window, IDisposable
|
||||||
ImGui.SetCursorPos(new Vector2(logoContainerSize.X / 2 - logoSize.X / 2, logoContainerSize.Y / 2 - logoSize.Y / 2));
|
ImGui.SetCursorPos(new Vector2(logoContainerSize.X / 2 - logoSize.X / 2, logoContainerSize.Y / 2 - logoSize.Y / 2));
|
||||||
|
|
||||||
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, Math.Clamp(this.windowFade.EasedPoint.X - 0.5f, 0f, 1f)))
|
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, Math.Clamp(this.windowFade.EasedPoint.X - 0.5f, 0f, 1f)))
|
||||||
ImGui.Image(this.logoTexture.Value.ImGuiHandle, logoSize);
|
ImGui.Image(this.logoTexture.Value.Handle, logoSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
@ -383,7 +380,7 @@ internal sealed class ChangelogWindow : Window, IDisposable
|
||||||
|
|
||||||
ImGuiHelpers.CenterCursorFor(this.apiBumpExplainerTexture.Value.Width);
|
ImGuiHelpers.CenterCursorFor(this.apiBumpExplainerTexture.Value.Width);
|
||||||
ImGui.Image(
|
ImGui.Image(
|
||||||
this.apiBumpExplainerTexture.Value.ImGuiHandle,
|
this.apiBumpExplainerTexture.Value.Handle,
|
||||||
this.apiBumpExplainerTexture.Value.Size);
|
this.apiBumpExplainerTexture.Value.Size);
|
||||||
|
|
||||||
if (!this.currentFtueLevels.TryGetValue(FtueLevels.AutoUpdate.Name, out var autoUpdateLevel) || autoUpdateLevel < FtueLevels.AutoUpdate.AutoUpdateInitial)
|
if (!this.currentFtueLevels.TryGetValue(FtueLevels.AutoUpdate.Name, out var autoUpdateLevel) || autoUpdateLevel < FtueLevels.AutoUpdate.AutoUpdateInitial)
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.Windows;
|
namespace Dalamud.Interface.Internal.Windows;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface.Animation;
|
using Dalamud.Interface.Animation;
|
||||||
using Dalamud.Interface.Animation.EasingFunctions;
|
using Dalamud.Interface.Animation.EasingFunctions;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.Windows;
|
namespace Dalamud.Interface.Internal.Windows;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Console;
|
using Dalamud.Console;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
|
|
@ -21,9 +22,6 @@ using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin.Internal;
|
using Dalamud.Plugin.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
|
|
@ -114,10 +112,7 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
|
|
||||||
this.configuration.DalamudConfigurationSaved += this.OnDalamudConfigurationSaved;
|
this.configuration.DalamudConfigurationSaved += this.OnDalamudConfigurationSaved;
|
||||||
|
|
||||||
unsafe
|
this.clipperPtr = ImGui.ImGuiListClipper();
|
||||||
{
|
|
||||||
this.clipperPtr = new(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Gets the queue where log entries that are not processed yet are stored.</summary>
|
/// <summary>Gets the queue where log entries that are not processed yet are stored.</summary>
|
||||||
|
|
@ -840,11 +835,9 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe int CommandInputCallback(ImGuiInputTextCallbackData* data)
|
private int CommandInputCallback(ref ImGuiInputTextCallbackData data)
|
||||||
{
|
{
|
||||||
var ptr = new ImGuiInputTextCallbackDataPtr(data);
|
switch (data.EventFlag)
|
||||||
|
|
||||||
switch (data->EventFlag)
|
|
||||||
{
|
{
|
||||||
case ImGuiInputTextFlags.CallbackEdit:
|
case ImGuiInputTextFlags.CallbackEdit:
|
||||||
this.completionZipText = null;
|
this.completionZipText = null;
|
||||||
|
|
@ -852,9 +845,7 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ImGuiInputTextFlags.CallbackCompletion:
|
case ImGuiInputTextFlags.CallbackCompletion:
|
||||||
var textBytes = new byte[data->BufTextLen];
|
var text = Encoding.UTF8.GetString(data.BufTextSpan);
|
||||||
Marshal.Copy((IntPtr)data->Buf, textBytes, 0, data->BufTextLen);
|
|
||||||
var text = Encoding.UTF8.GetString(textBytes);
|
|
||||||
|
|
||||||
var words = text.Split();
|
var words = text.Split();
|
||||||
|
|
||||||
|
|
@ -899,8 +890,8 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
|
|
||||||
if (toComplete != null)
|
if (toComplete != null)
|
||||||
{
|
{
|
||||||
ptr.DeleteChars(0, ptr.BufTextLen);
|
data.DeleteChars(0, data.BufTextLen);
|
||||||
ptr.InsertChars(0, toComplete);
|
data.InsertChars(0, toComplete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -909,14 +900,14 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
case ImGuiInputTextFlags.CallbackHistory:
|
case ImGuiInputTextFlags.CallbackHistory:
|
||||||
var prevPos = this.historyPos;
|
var prevPos = this.historyPos;
|
||||||
|
|
||||||
if (ptr.EventKey == ImGuiKey.UpArrow)
|
if (data.EventKey == ImGuiKey.UpArrow)
|
||||||
{
|
{
|
||||||
if (this.historyPos == -1)
|
if (this.historyPos == -1)
|
||||||
this.historyPos = this.configuration.LogCommandHistory.Count - 1;
|
this.historyPos = this.configuration.LogCommandHistory.Count - 1;
|
||||||
else if (this.historyPos > 0)
|
else if (this.historyPos > 0)
|
||||||
this.historyPos--;
|
this.historyPos--;
|
||||||
}
|
}
|
||||||
else if (data->EventKey == ImGuiKey.DownArrow)
|
else if (data.EventKey == ImGuiKey.DownArrow)
|
||||||
{
|
{
|
||||||
if (this.historyPos != -1)
|
if (this.historyPos != -1)
|
||||||
{
|
{
|
||||||
|
|
@ -931,8 +922,8 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
{
|
{
|
||||||
var historyStr = this.historyPos >= 0 ? this.configuration.LogCommandHistory[this.historyPos] : string.Empty;
|
var historyStr = this.historyPos >= 0 ? this.configuration.LogCommandHistory[this.historyPos] : string.Empty;
|
||||||
|
|
||||||
ptr.DeleteChars(0, ptr.BufTextLen);
|
data.DeleteChars(0, data.BufTextLen);
|
||||||
ptr.InsertChars(0, historyStr);
|
data.InsertChars(0, historyStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -1121,7 +1112,7 @@ internal class ConsoleWindow : Window, IDisposable
|
||||||
charOffsets[charOffsetsIndex++] = line.Length;
|
charOffsets[charOffsetsIndex++] = line.Length;
|
||||||
|
|
||||||
var screenPos = ImGui.GetCursorScreenPos();
|
var screenPos = ImGui.GetCursorScreenPos();
|
||||||
var drawList = ImGui.GetWindowDrawList().NativePtr;
|
var drawList = ImGui.GetWindowDrawList().Handle;
|
||||||
var font = ImGui.GetFont();
|
var font = ImGui.GetFont();
|
||||||
var size = ImGui.GetFontSize();
|
var size = ImGui.GetFontSize();
|
||||||
var scale = size / font.FontSize;
|
var scale = size / font.FontSize;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue