diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index beb09f5..9426920 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -167,6 +167,7 @@ set(SWA_UI_CXX_SOURCES "ui/reddog/windows/counter_window.cpp" "ui/reddog/windows/exports_window.cpp" "ui/reddog/windows/view_window.cpp" + "ui/reddog/windows/welcome_window.cpp" "ui/reddog/windows/window_list.cpp" "ui/reddog/reddog_controls.cpp" "ui/reddog/reddog_manager.cpp" diff --git a/UnleashedRecomp/ui/reddog/reddog_window.cpp b/UnleashedRecomp/ui/reddog/reddog_window.cpp index efad1d8..471778a 100644 --- a/UnleashedRecomp/ui/reddog/reddog_window.cpp +++ b/UnleashedRecomp/ui/reddog/reddog_window.cpp @@ -231,85 +231,121 @@ void Reddog::Window::DrawFrame() drawList->AddText({ cmnIconMax.x + 5, windowPos.y + 4 }, colTitleText, Name); - ImVec2 closeButtonMin = { windowPos.x + windowSize.x - cmnSize - 4, windowPos.y + 3 }; + float controlsWidth = 0; + float controlsMargin = 4; + + ImVec2 closeButtonMin = { windowPos.x + windowSize.x - cmnSize - controlsMargin, windowPos.y + 3 }; ImVec2 closeButtonMax = { closeButtonMin.x + cmnSize, closeButtonMin.y + cmnSize }; - ImGui::SetCursorScreenPos(closeButtonMin); - ImGui::InvisibleButton("##CloseButton", { cmnSize, cmnSize }); - bool isCloseButtonActive = ImGui::IsItemActive(); - - if (isCloseButtonActive) + if (IsCloseVisible) { - drawList->AddImage(g_upButtonClose2.get(), closeButtonMin, closeButtonMax); - m_isCloseButtonPressed = true; - } - else - { - drawList->AddImage(g_upButtonClose1.get(), closeButtonMin, closeButtonMax); + controlsWidth += closeButtonMax.x - closeButtonMin.x + controlsMargin; - if (m_isCloseButtonPressed && m_pIsVisible) + ImGui::SetCursorScreenPos(closeButtonMin); + ImGui::InvisibleButton("##CloseButton", { cmnSize, cmnSize }); + bool isCloseButtonActive = ImGui::IsItemActive(); + + if (isCloseButtonActive) { - *m_pIsVisible = !*m_pIsVisible; - m_isCloseButtonPressed = false; + drawList->AddImage(g_upButtonClose2.get(), closeButtonMin, closeButtonMax); + m_isCloseButtonPressed = true; + } + else + { + drawList->AddImage(g_upButtonClose1.get(), closeButtonMin, closeButtonMax); + + if (m_isCloseButtonPressed && m_pIsVisible) + { + *m_pIsVisible = !*m_pIsVisible; + m_isCloseButtonPressed = false; + } } } - ImVec2 minimumButtonMin = { closeButtonMin.x - cmnSize - 4, windowPos.y + 3 }; + ImVec2 minimumButtonMin = { closeButtonMin.x - cmnSize - controlsMargin, windowPos.y + 3 }; ImVec2 minimumButtonMax = { minimumButtonMin.x + cmnSize, minimumButtonMin.y + cmnSize }; - ImGui::SetCursorScreenPos(minimumButtonMin); - ImGui::InvisibleButton("##MinimumButton", { cmnSize, cmnSize }); - bool isMinimumButtonActive = ImGui::IsItemActive(); - - if (isMinimumButtonActive) + if (IsMinimumVisible) { - drawList->AddImage(g_upButtonMinimum2.get(), minimumButtonMin, minimumButtonMax); - m_isMinimumButtonPressed = true; - } - else - { - drawList->AddImage(g_upButtonMinimum1.get(), minimumButtonMin, minimumButtonMax); + controlsWidth += minimumButtonMax.x - minimumButtonMin.x + controlsMargin; - if (m_isMinimumButtonPressed) + ImGui::SetCursorScreenPos(minimumButtonMin); + ImGui::InvisibleButton("##MinimumButton", { cmnSize, cmnSize }); + bool isMinimumButtonActive = ImGui::IsItemActive(); + + if (isMinimumButtonActive) { - IsMinimum = !IsMinimum; + drawList->AddImage(g_upButtonMinimum2.get(), minimumButtonMin, minimumButtonMax); + m_isMinimumButtonPressed = true; + } + else + { + drawList->AddImage(g_upButtonMinimum1.get(), minimumButtonMin, minimumButtonMax); - if (IsMinimum) + if (m_isMinimumButtonPressed) { - m_preMinimumWindowSize = windowSize; - ImGui::SetWindowSize(ImWindow, { windowSize.x, MIN_WINDOW_SIZE }); + SetMinimum(!IsMinimum); + m_isMinimumButtonPressed = false; } - else - { - ImGui::SetWindowSize(ImWindow, { windowSize.x, m_preMinimumWindowSize.y }); - } - - m_isMinimumButtonPressed = false; } } - ImVec2 pinButtonMin = { minimumButtonMin.x - cmnSize - 4, windowPos.y + 3 }; + ImVec2 pinButtonMin = { minimumButtonMin.x - cmnSize - controlsMargin, windowPos.y + 3 }; ImVec2 pinButtonMax = { pinButtonMin.x + cmnSize, pinButtonMin.y + cmnSize }; - ImGui::SetCursorScreenPos(pinButtonMin); - ImGui::InvisibleButton("##PinButton", { cmnSize, cmnSize }); - bool isPinButtonActive = ImGui::IsItemActive(); - - if (isPinButtonActive) + if (IsPinVisible) { - drawList->AddImage(g_upButtonPin2.get(), pinButtonMin, pinButtonMax); - m_isPinButtonPressed = true; - } - else - { - drawList->AddImage(g_upButtonPin1.get(), pinButtonMin, pinButtonMax); + controlsWidth += pinButtonMax.x - pinButtonMin.x + controlsMargin; - if (m_isPinButtonPressed) + ImGui::SetCursorScreenPos(pinButtonMin); + ImGui::InvisibleButton("##PinButton", { cmnSize, cmnSize }); + bool isPinButtonActive = ImGui::IsItemActive(); + + if (isPinButtonActive) { - IsPinned = !IsPinned; - m_isPinButtonPressed = false; + drawList->AddImage(g_upButtonPin2.get(), pinButtonMin, pinButtonMax); + m_isPinButtonPressed = true; + } + else + { + drawList->AddImage(g_upButtonPin1.get(), pinButtonMin, pinButtonMax); + + if (m_isPinButtonPressed) + { + IsPinned = !IsPinned; + m_isPinButtonPressed = false; + } } } + + ImVec2 titleBarMin = { windowPos.x, windowPos.y }; + ImVec2 titleBarMax = { windowPos.x + windowSize.x - controlsWidth, windowPos.y + titleBarHeight }; + + if (ImGui::IsMouseHoveringRect(titleBarMin, titleBarMax, false)) + { + if (IsMinimumVisible && ImGui::IsMouseDoubleClicked(0)) + SetMinimum(!IsMinimum); + } + } +} + +void Reddog::Window::SetMinimum(bool isMinimum) +{ + IsMinimum = isMinimum; + + if (!ImWindow) + return; + + auto windowSize = ImWindow->Size; + + if (IsMinimum) + { + m_preMinimumWindowSize = windowSize; + ImGui::SetWindowSize(ImWindow, { windowSize.x, MIN_WINDOW_SIZE }); + } + else + { + ImGui::SetWindowSize(ImWindow, { windowSize.x, m_preMinimumWindowSize.y }); } } @@ -338,13 +374,32 @@ bool Reddog::Window::Begin(bool* pIsVisible) if ((Flags & eWindowFlags_NoResize) != 0) flags |= ImGuiWindowFlags_NoResize; + if (m_preBegin) + m_preBegin(); + bool result = ImGui::Begin(Name, m_pIsVisible, flags); + if (m_postBegin) + m_postBegin(); + if (result && *m_pIsVisible) { ImWindow = ImGui::GetCurrentWindow(); IsFocused = ImGui::IsWindowFocused(); + if ((Flags & eWindowFlags_Centre) != 0 && !m_isSetCentre) + { + auto viewport = ImGui::GetMainViewport(); + auto windowPos = ImGui::GetWindowPos(); + auto pos = ImVec2((viewport->Size.x / 2) - (ImWindow->Size.x / 2), (viewport->Size.y / 2) - (ImWindow->Size.y / 2)); + + ImGui::SetWindowPos(pos); + } + + // Keep centring window until it has been moved. + if (ImGui::IsMouseDragging(0) && ImGui::IsWindowHovered()) + m_isSetCentre = true; + if (m_isSetVisible) { ImGui::SetWindowFocus(); @@ -361,6 +416,13 @@ bool Reddog::Window::Begin(bool* pIsVisible) void Reddog::Window::End() { + if (m_preEnd) + m_preEnd(); + ImGui::End(); + + if (m_postEnd) + m_postEnd(); + EndStyle(); } diff --git a/UnleashedRecomp/ui/reddog/reddog_window.h b/UnleashedRecomp/ui/reddog/reddog_window.h index 41cf2b9..0c9235f 100644 --- a/UnleashedRecomp/ui/reddog/reddog_window.h +++ b/UnleashedRecomp/ui/reddog/reddog_window.h @@ -6,10 +6,11 @@ namespace Reddog { enum EWindowFlags : uint32_t { - eWindowFlags_None = 0, - eWindowFlags_NoTitleBar = 1 << 0, - eWindowFlags_NoResize = 1 << 1, - eWindowFlags_NoListEntry = 1 << 2 + eWindowFlags_None = 0, + eWindowFlags_NoTitleBar = 1 << 0, + eWindowFlags_NoResize = 1 << 1, + eWindowFlags_NoListEntry = 1 << 2, + eWindowFlags_Centre = 1 << 3 }; class IWindow @@ -27,7 +28,9 @@ namespace Reddog private: bool* m_pIsVisible{ nullptr }; + bool m_isSetCentre{}; bool m_isSetVisible{}; + bool m_isCloseButtonPressed{}; bool m_isMinimumButtonPressed{}; bool m_isPinButtonPressed{}; @@ -46,10 +49,18 @@ namespace Reddog float m_maxWidth{ FLT_MAX }; float m_maxHeight{ FLT_MAX }; + std::function m_preBegin{ nullptr }; + std::function m_postBegin{ nullptr }; + std::function m_preEnd{ nullptr }; + std::function m_postEnd{ nullptr }; + public: const char* Name{ "(null)" }; EWindowFlags Flags{ eWindowFlags_None }; bool IsFocused{ true }; + bool IsCloseVisible{ true }; + bool IsMinimumVisible{ true }; + bool IsPinVisible{ true }; bool IsMinimum{}; bool IsPinned{ true }; bool IsVisible{}; @@ -78,6 +89,7 @@ namespace Reddog End(); } + void SetMinimum(bool isMinimum); void SetVisible(bool isVisible = true); bool Begin(bool* pIsVisible = nullptr); void End(); diff --git a/UnleashedRecomp/ui/reddog/windows/exports_window.cpp b/UnleashedRecomp/ui/reddog/windows/exports_window.cpp index cda15a0..f6e7fd4 100644 --- a/UnleashedRecomp/ui/reddog/windows/exports_window.cpp +++ b/UnleashedRecomp/ui/reddog/windows/exports_window.cpp @@ -2,7 +2,7 @@ #include #include -static ExportsWindow g_window{ "Exports" }; +static ExportsWindow g_window; void ExportsWindow::Draw() { diff --git a/UnleashedRecomp/ui/reddog/windows/exports_window.h b/UnleashedRecomp/ui/reddog/windows/exports_window.h index db8ceab..2a5acbe 100644 --- a/UnleashedRecomp/ui/reddog/windows/exports_window.h +++ b/UnleashedRecomp/ui/reddog/windows/exports_window.h @@ -5,7 +5,11 @@ class ExportsWindow : public Reddog::Window { public: - using Reddog::Window::Window; + ExportsWindow() : Window() + { + Name = "Exports"; + Flags = Reddog::eWindowFlags_NoResize; + } void Draw() override; }; diff --git a/UnleashedRecomp/ui/reddog/windows/view_window.cpp b/UnleashedRecomp/ui/reddog/windows/view_window.cpp index cb8424c..391e294 100644 --- a/UnleashedRecomp/ui/reddog/windows/view_window.cpp +++ b/UnleashedRecomp/ui/reddog/windows/view_window.cpp @@ -2,12 +2,12 @@ #include #include #include -#include #include +#include #include #include -static ViewWindow g_window{ "View" }; +static ViewWindow g_window; void ViewWindow::Draw() { @@ -46,6 +46,7 @@ void ViewWindow::Draw() Reddog::Checkbox("Render Event Collision", SWA::SGlobals::ms_IsTriggerRender); Reddog::Checkbox("Render Object Collision", SWA::SGlobals::ms_IsObjectCollisionRender); Reddog::Checkbox("Render Stage Collision", SWA::SGlobals::ms_IsCollisionRender); + ImGui::TextColored({ 1, 0, 0, 1 }, "* Requires stage restart."); Reddog::Separator(); diff --git a/UnleashedRecomp/ui/reddog/windows/view_window.h b/UnleashedRecomp/ui/reddog/windows/view_window.h index 2eb3ff2..ec5a0c8 100644 --- a/UnleashedRecomp/ui/reddog/windows/view_window.h +++ b/UnleashedRecomp/ui/reddog/windows/view_window.h @@ -5,7 +5,11 @@ class ViewWindow : public Reddog::Window { public: - using Reddog::Window::Window; + ViewWindow() : Window() + { + Name = "View"; + Flags = Reddog::eWindowFlags_NoResize; + } void Draw() override; }; diff --git a/UnleashedRecomp/ui/reddog/windows/welcome_window.cpp b/UnleashedRecomp/ui/reddog/windows/welcome_window.cpp new file mode 100644 index 0000000..486be41 --- /dev/null +++ b/UnleashedRecomp/ui/reddog/windows/welcome_window.cpp @@ -0,0 +1,13 @@ +#include "welcome_window.h" + +static WelcomeWindow g_window; + +void WelcomeWindow::Draw() +{ + if (Begin()) + { + ImGui::TextColored({ 1, 0, 0, 1 }, "!!! ATTENTION !!!"); + ImGui::Text("For development use only.\nAny changes made here may cause unexpected behaviour.\nUse at your own risk!"); + } + End(); +} diff --git a/UnleashedRecomp/ui/reddog/windows/welcome_window.h b/UnleashedRecomp/ui/reddog/windows/welcome_window.h new file mode 100644 index 0000000..88482a0 --- /dev/null +++ b/UnleashedRecomp/ui/reddog/windows/welcome_window.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +class WelcomeWindow : public Reddog::Window +{ +public: + WelcomeWindow() : Window() + { + Name = "Welcome"; + Flags = (Reddog::EWindowFlags)(Reddog::eWindowFlags_NoResize | Reddog::eWindowFlags_NoListEntry | Reddog::eWindowFlags_Centre); + IsMinimumVisible = false; + IsPinVisible = false; + IsPinned = false; + IsVisible = true; + } + + void Draw() override; +};