Skip to content

Commit

Permalink
Merge pull request #3 from ffarrell17/ImGuiNative
Browse files Browse the repository at this point in the history
Converted UI from reshade to native imgui
  • Loading branch information
doodlum authored May 14, 2023
2 parents 0448b5e + f4ce09e commit d516afa
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 3,608 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ include(XSEPlugin)
find_package(magic_enum CONFIG REQUIRED)
find_package(xbyak CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(imgui CONFIG REQUIRED)


target_link_libraries(
${PROJECT_NAME}
Expand All @@ -22,4 +24,5 @@ target_link_libraries(
magic_enum::magic_enum
xbyak::xbyak
nlohmann_json::nlohmann_json
imgui::imgui
)
2 changes: 0 additions & 2 deletions include/PCH.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ namespace DX

#include <CLIBUtil/simpleINI.hpp>

#define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
#include "imgui.h"
#include "reshade/reshade.hpp"

#include <nlohmann/json.hpp>
using json = nlohmann::json;
Expand Down
3,564 changes: 0 additions & 3,564 deletions include/imgui.h

This file was deleted.

4 changes: 4 additions & 0 deletions src/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "ShaderCache.h"
#include "State.h"
#include "Menu.h"

#include "Features/Clustered.h"
#include "ShaderTools/BSShaderHooks.h"
Expand Down Expand Up @@ -45,6 +46,7 @@ decltype(&ID3D11DeviceContext::DrawIndexedInstanced) ptrDrawIndexedInstanced;
HRESULT WINAPI hk_IDXGISwapChain_Present(IDXGISwapChain* This, UINT SyncInterval, UINT Flags)
{
State::GetSingleton()->Reset();
Menu::GetSingleton()->DrawOverlay();
return (This->*ptrPresent)(SyncInterval, Flags);
}

Expand Down Expand Up @@ -80,6 +82,7 @@ namespace Hooks

auto context = manager->GetRuntimeData().context;
auto swapchain = manager->GetRuntimeData().swapChain;
auto device = manager->GetRuntimeData().forwarder;

logger::info("Detouring virtual function tables");

Expand All @@ -88,6 +91,7 @@ namespace Hooks
*(uintptr_t*)&ptrDrawIndexedInstanced = Detours::X64::DetourClassVTable(*(uintptr_t*)context, &hk_ID3D11DeviceContext_DrawIndexedInstanced, 20);

State::GetSingleton()->Setup();
Menu::GetSingleton()->Init(swapchain, device, context);
}
static inline REL::Relocation<decltype(thunk)> func;
};
Expand Down
210 changes: 186 additions & 24 deletions src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ void SetupImGuiStyle()
}
bool IsEnabled = false;

Menu::~Menu()
{
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}

void Menu::Load(json& o_json)
{
if (o_json[SETTING_MENU_TOGGLEKEY].is_number_unsigned()) {
Expand All @@ -36,7 +43,7 @@ void Menu::Save(json& o_json)

RE::BSEventNotifyControl Menu::ProcessEvent(RE::InputEvent* const* a_event, RE::BSTEventSource<RE::InputEvent*>* a_eventSource)
{
if (!a_event || !a_eventSource)
if (!a_event || !a_eventSource)
return RE::BSEventNotifyControl::kContinue;

for (auto event = *a_event; event; event = event->next) {
Expand Down Expand Up @@ -132,22 +139,40 @@ RE::BSEventNotifyControl Menu::ProcessEvent(RE::InputEvent* const* a_event, RE::
break;
}

switch (button->device.get()) {
auto& io = ImGui::GetIO();
switch (button->device.get())
{
case RE::INPUT_DEVICE::kKeyboard:
if (key == toggleKey && !button->IsPressed()) {

// Avoid closing menu when setting the toggle key
if (settingToggleKey) {
if (!button->IsPressed())
{
if (settingToggleKey)
{
toggleKey = key;
settingToggleKey = false;
break;
}

IsEnabled = !IsEnabled;
if (const auto controlMap = RE::ControlMap::GetSingleton()) {
controlMap->ignoreKeyboardMouse = IsEnabled;
}
else if (key == toggleKey)
{
IsEnabled = !IsEnabled;
if (const auto controlMap = RE::ControlMap::GetSingleton())
{
controlMap->ignoreKeyboardMouse = IsEnabled;
}
}
else
{
io.AddKeyEvent(VirtualKeyToImGuiKey(key), button->IsPressed());
}
}
break;
case RE::INPUT_DEVICE::kMouse:
if (scan_code > 7) // middle scroll
io.AddMouseWheelEvent(0, button->Value() * (scan_code == 8 ? 1 : -1));
else {
if (scan_code > 5)
scan_code = 5;
io.AddMouseButtonEvent(scan_code, button->IsPressed());
}
break;
default:
continue;
}
Expand All @@ -157,12 +182,36 @@ RE::BSEventNotifyControl Menu::ProcessEvent(RE::InputEvent* const* a_event, RE::
return RE::BSEventNotifyControl::kContinue;
}

void Menu::Init(IDXGISwapChain* swapchain, ID3D11Device* device, ID3D11DeviceContext* context)
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
auto& imgui_io = ImGui::GetIO();

imgui_io.ConfigFlags = ImGuiConfigFlags_NavEnableKeyboard;
imgui_io.BackendFlags = ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_RendererHasVtxOffset;

DXGI_SWAP_CHAIN_DESC desc;
swapchain->GetDesc(&desc);

// Setup Platform/Renderer backends
ImGui_ImplWin32_Init(desc.OutputWindow);
ImGui_ImplDX11_Init(device, context);

}

void Menu::DrawSettings()
{
ImGuiStyle oldStyle = ImGui::GetStyle();
SetupImGuiStyle();
static bool visible = false;

// Start the Dear ImGui frame
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::SetNextWindowSize({ 1024, 1024 }, ImGuiCond_Once);
ImGui::Begin(std::format("Skyrim Community Shaders {}", Plugin::VERSION.string(".")).c_str(), &IsEnabled);

Expand Down Expand Up @@ -212,17 +261,6 @@ void Menu::DrawSettings()

if (ImGui::CollapsingHeader("Menu", ImGuiTreeNodeFlags_DefaultOpen)) {

// Check if we're waiting for input
if (settingToggleKey) {
// Loop over all the keys and check if any of them are pressed
for (int i = 0; i < IM_ARRAYSIZE(ImGui::GetIO().KeysDown); i++) {
if (ImGui::IsKeyPressed(i)) {
// If a key is pressed, set the selected key code and break out of the loop
toggleKey = i;
break;
}
}
}
if (settingToggleKey)
{
ImGui::Text("Press any key to set as toggle key...");
Expand Down Expand Up @@ -297,6 +335,9 @@ void Menu::DrawSettings()
ImGui::End();
ImGuiStyle& style = ImGui::GetStyle();
style = oldStyle;

ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}

void Menu::DrawOverlay()
Expand All @@ -309,7 +350,12 @@ void Menu::DrawOverlay()
compiledShaders = shaderCache.GetCompletedTasks();
totalShaders = shaderCache.GetTotalTasks();

if (compiledShaders != totalShaders) {
if (compiledShaders != totalShaders)
{
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::SetNextWindowBgAlpha(1);
ImGui::SetNextWindowPos(ImVec2(10, 10));
if (!ImGui::Begin("ShaderCompilationInfo", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings)) {
Expand All @@ -320,6 +366,9 @@ void Menu::DrawOverlay()
ImGui::Text("Compiling Shaders: %d / %d", compiledShaders, totalShaders);

ImGui::End();

ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}

if (IsEnabled)
Expand Down Expand Up @@ -355,3 +404,116 @@ const char* Menu::KeyIdToString(uint32_t key)

return keyboard_keys_international[key];
}

#define IM_VK_KEYPAD_ENTER (VK_RETURN + 256)
const ImGuiKey Menu::VirtualKeyToImGuiKey(WPARAM vkKey)
{
switch (vkKey) {
case VK_TAB: return ImGuiKey_Tab;
case VK_LEFT: return ImGuiKey_LeftArrow;
case VK_RIGHT: return ImGuiKey_RightArrow;
case VK_UP: return ImGuiKey_UpArrow;
case VK_DOWN: return ImGuiKey_DownArrow;
case VK_PRIOR: return ImGuiKey_PageUp;
case VK_NEXT: return ImGuiKey_PageDown;
case VK_HOME: return ImGuiKey_Home;
case VK_END: return ImGuiKey_End;
case VK_INSERT: return ImGuiKey_Insert;
case VK_DELETE: return ImGuiKey_Delete;
case VK_BACK: return ImGuiKey_Backspace;
case VK_SPACE: return ImGuiKey_Space;
case VK_RETURN: return ImGuiKey_Enter;
case VK_ESCAPE: return ImGuiKey_Escape;
case VK_OEM_7: return ImGuiKey_Apostrophe;
case VK_OEM_COMMA: return ImGuiKey_Comma;
case VK_OEM_MINUS: return ImGuiKey_Minus;
case VK_OEM_PERIOD: return ImGuiKey_Period;
case VK_OEM_2: return ImGuiKey_Slash;
case VK_OEM_1: return ImGuiKey_Semicolon;
case VK_OEM_PLUS: return ImGuiKey_Equal;
case VK_OEM_4: return ImGuiKey_LeftBracket;
case VK_OEM_5: return ImGuiKey_Backslash;
case VK_OEM_6: return ImGuiKey_RightBracket;
case VK_OEM_3: return ImGuiKey_GraveAccent;
case VK_CAPITAL: return ImGuiKey_CapsLock;
case VK_SCROLL: return ImGuiKey_ScrollLock;
case VK_NUMLOCK: return ImGuiKey_NumLock;
case VK_SNAPSHOT: return ImGuiKey_PrintScreen;
case VK_PAUSE: return ImGuiKey_Pause;
case VK_NUMPAD0: return ImGuiKey_Keypad0;
case VK_NUMPAD1: return ImGuiKey_Keypad1;
case VK_NUMPAD2: return ImGuiKey_Keypad2;
case VK_NUMPAD3: return ImGuiKey_Keypad3;
case VK_NUMPAD4: return ImGuiKey_Keypad4;
case VK_NUMPAD5: return ImGuiKey_Keypad5;
case VK_NUMPAD6: return ImGuiKey_Keypad6;
case VK_NUMPAD7: return ImGuiKey_Keypad7;
case VK_NUMPAD8: return ImGuiKey_Keypad8;
case VK_NUMPAD9: return ImGuiKey_Keypad9;
case VK_DECIMAL: return ImGuiKey_KeypadDecimal;
case VK_DIVIDE: return ImGuiKey_KeypadDivide;
case VK_MULTIPLY: return ImGuiKey_KeypadMultiply;
case VK_SUBTRACT: return ImGuiKey_KeypadSubtract;
case VK_ADD: return ImGuiKey_KeypadAdd;
case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter;
case VK_LSHIFT: return ImGuiKey_LeftShift;
case VK_LCONTROL: return ImGuiKey_LeftCtrl;
case VK_LMENU: return ImGuiKey_LeftAlt;
case VK_LWIN: return ImGuiKey_LeftSuper;
case VK_RSHIFT: return ImGuiKey_RightShift;
case VK_RCONTROL: return ImGuiKey_RightCtrl;
case VK_RMENU: return ImGuiKey_RightAlt;
case VK_RWIN: return ImGuiKey_RightSuper;
case VK_APPS: return ImGuiKey_Menu;
case '0': return ImGuiKey_0;
case '1': return ImGuiKey_1;
case '2': return ImGuiKey_2;
case '3': return ImGuiKey_3;
case '4': return ImGuiKey_4;
case '5': return ImGuiKey_5;
case '6': return ImGuiKey_6;
case '7': return ImGuiKey_7;
case '8': return ImGuiKey_8;
case '9': return ImGuiKey_9;
case 'A': return ImGuiKey_A;
case 'B': return ImGuiKey_B;
case 'C': return ImGuiKey_C;
case 'D': return ImGuiKey_D;
case 'E': return ImGuiKey_E;
case 'F': return ImGuiKey_F;
case 'G': return ImGuiKey_G;
case 'H': return ImGuiKey_H;
case 'I': return ImGuiKey_I;
case 'J': return ImGuiKey_J;
case 'K': return ImGuiKey_K;
case 'L': return ImGuiKey_L;
case 'M': return ImGuiKey_M;
case 'N': return ImGuiKey_N;
case 'O': return ImGuiKey_O;
case 'P': return ImGuiKey_P;
case 'Q': return ImGuiKey_Q;
case 'R': return ImGuiKey_R;
case 'S': return ImGuiKey_S;
case 'T': return ImGuiKey_T;
case 'U': return ImGuiKey_U;
case 'V': return ImGuiKey_V;
case 'W': return ImGuiKey_W;
case 'X': return ImGuiKey_X;
case 'Y': return ImGuiKey_Y;
case 'Z': return ImGuiKey_Z;
case VK_F1: return ImGuiKey_F1;
case VK_F2: return ImGuiKey_F2;
case VK_F3: return ImGuiKey_F3;
case VK_F4: return ImGuiKey_F4;
case VK_F5: return ImGuiKey_F5;
case VK_F6: return ImGuiKey_F6;
case VK_F7: return ImGuiKey_F7;
case VK_F8: return ImGuiKey_F8;
case VK_F9: return ImGuiKey_F9;
case VK_F10: return ImGuiKey_F10;
case VK_F11: return ImGuiKey_F11;
case VK_F12: return ImGuiKey_F12;
default:
return ImGuiKey_None;
};
}
11 changes: 8 additions & 3 deletions src/Menu.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#pragma once

#define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
#include "imgui.h"
#include "reshade/reshade.hpp"
#include "imgui_impl_dx11.h"
#include "imgui_impl_win32.h"

class Menu : public RE::BSTEventSink<RE::InputEvent*>
{
public:
~Menu();

static Menu* GetSingleton()
{
static Menu menu;
Expand All @@ -19,6 +21,8 @@ class Menu : public RE::BSTEventSink<RE::InputEvent*>
RE::BSEventNotifyControl ProcessEvent(RE::InputEvent* const* a_event,
RE::BSTEventSource<RE::InputEvent*>* a_eventSource) override;


void Init(IDXGISwapChain* swapchain, ID3D11Device* device, ID3D11DeviceContext* context);
void DrawSettings();
void DrawOverlay();

Expand All @@ -29,4 +33,5 @@ class Menu : public RE::BSTEventSink<RE::InputEvent*>

Menu() { }
const char* KeyIdToString(uint32_t key);
};
const ImGuiKey VirtualKeyToImGuiKey(WPARAM vkKey);
};
12 changes: 0 additions & 12 deletions src/XSEPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID)
return TRUE;
}

void DrawOverlayCallback(reshade::api::effect_runtime*)
{
Menu::GetSingleton()->DrawOverlay();
}

void MessageHandler(SKSE::MessagingInterface::Message* message)
{
switch (message->type) {
Expand All @@ -40,13 +35,6 @@ void MessageHandler(SKSE::MessagingInterface::Message* message)

shaderCache.ValidateDiskCache();

if (reshade::register_addon(m_hModule)) {
logger::info("ReShade: Registered add-on");
reshade::register_event<reshade::addon_event::reshade_overlay>(DrawOverlayCallback);
} else {
logger::info("ReShade: Could not register add-on");
}

break;
}
case SKSE::MessagingInterface::kDataLoaded:
Expand Down
Loading

0 comments on commit d516afa

Please sign in to comment.