Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/Features/PerformanceOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,56 @@ void PerformanceOverlay::DrawSettings()
if (ImGui::Button("Reset Position")) {
this->settings.PositionSet = false;
}
ImGui::SameLine();
if (ImGui::Button("Restore Defaults")) {
RestoreDefaultSettings();
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::TextUnformatted("Restores Performance Overlay settings to defaults, including graphs, appearance, and update intervals.");
}

ImGui::Unindent();
}
ImGui::Unindent();
}
}

void PerformanceOverlay::SaveSettings(json& j)
{
// Persist all overlay settings to JSON
j = this->settings; // uses NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
}

void PerformanceOverlay::LoadSettings(json& j)
{
try {
// Load all settings from JSON (missing fields use defaults)
this->settings = j.get<PerformanceOverlay::Settings>();
} catch (...) {
// Fallback to defaults if JSON is invalid
this->settings = PerformanceOverlay::Settings{};
}
// Ensure history buffers match loaded size
this->state.frameTimeHistory.Resize(this->settings.FrameHistorySize);
this->state.postFGFrameTimeHistory.Resize(this->settings.FrameHistorySize);
}

void PerformanceOverlay::RestoreDefaultSettings()
{
this->settings = PerformanceOverlay::Settings{};
// Reset runtime buffers/state to match defaults
this->state.frameTimeHistory.Resize(this->settings.FrameHistorySize);
this->state.postFGFrameTimeHistory.Resize(this->settings.FrameHistorySize);
this->state.smoothFps = 0.0f;
this->state.smoothFrameTimeMs = 0.0f;
this->state.postFGSmoothFps = 0.0f;
this->state.postFGSmoothFrameTimeMs = 0.0f;
this->state.minFrameTime = 1000.0f;
this->state.maxFrameTime = 0.0f;
this->state.smoothedMinFrameTime = 0.0f;
this->state.smoothedMaxFrameTime = 50.0f;
}

void PerformanceOverlay::DataLoaded()
{
// Initialize performance overlay state
Expand Down
4 changes: 4 additions & 0 deletions src/Features/PerformanceOverlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ struct PerformanceOverlay : OverlayFeature
virtual void DrawSettings() override;
virtual void DataLoaded() override;
void DrawOverlay() override;
// Settings persistence and defaults
void SaveSettings(json& j) override;
void LoadSettings(json& j) override;
void RestoreDefaultSettings() override;

// ============================================================================
// CORE PERFORMANCE DISPLAY FUNCTIONS
Expand Down
18 changes: 6 additions & 12 deletions src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,8 @@ void Menu::Init()
DXGI_SWAP_CHAIN_DESC desc{};
globals::d3d::swapChain->GetDesc(&desc);

float fontSize = settings.Theme.FontSize;

if (std::round(fontSize) != std::round(ThemeManager::Constants::DEFAULT_FONT_SIZE)) {
if (globals::state->screenSize.y > 0) {
fontSize = globals::state->screenSize.y * ThemeManager::Constants::DEFAULT_FONT_RATIO;
} else {
logger::warn("Menu::Init() - Failed to get game resolution from globals::state->screenSize.");
}
}

fontSize = std::clamp(fontSize, ThemeManager::Constants::MIN_FONT_SIZE, ThemeManager::Constants::MAX_FONT_SIZE);
// Determine effective font size: user setting when >0, otherwise dynamic default by resolution
float fontSize = ThemeManager::ResolveFontSize(*this);

auto fontPath = Util::PathHelpers::GetFontsPath() / "Jost-Regular.ttf";
if (!imgui_io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(),
Expand All @@ -197,6 +188,9 @@ void Menu::Init()

imgui_io.FontGlobalScale = exp2(settings.Theme.GlobalScale);

// Initialize cached font size to effective size to prevent redundant reload on first frame
cachedFontSize = fontSize;

// Setup Platform/Renderer backends
ImGui_ImplWin32_Init(desc.OutputWindow);
ImGui_ImplDX11_Init(globals::d3d::device, globals::d3d::context);
Expand Down Expand Up @@ -423,7 +417,7 @@ void Menu::DrawOverlay()
[this]() { DrawSettings(); },
[](uint32_t key) { return Util::Input::KeyIdToString(key); },
cachedFontSize,
settings.Theme.FontSize);
ThemeManager::ResolveFontSize(*this));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class Menu

struct ThemeSettings
{
float FontSize = ThemeManager::Constants::DEFAULT_FONT_SIZE;
float FontSize = 0.0f; // When 0, dynamic default (resolution-based) is used
float GlobalScale = REL::Module::IsVR() ? -0.5f : 0.f; // exponential

bool UseSimplePalette = true; // simple palette or full customization
Expand Down
2 changes: 1 addition & 1 deletion src/Menu/OverlayRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void OverlayRenderer::RenderOverlay(
const std::function<void()>& processInputEventQueue,
const std::function<void()>& drawSettings,
const std::function<const char*(uint32_t)>& keyIdToString,
float cachedFontSize,
float& cachedFontSize,
float currentFontSize)
{
HandleVRSetup();
Expand Down
2 changes: 1 addition & 1 deletion src/Menu/OverlayRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class OverlayRenderer
const std::function<void()>& processInputEventQueue,
const std::function<void()>& drawSettings,
const std::function<const char*(uint32_t)>& keyIdToString,
float cachedFontSize,
float& cachedFontSize,
float currentFontSize);

private:
Expand Down
36 changes: 36 additions & 0 deletions src/Menu/SettingsTabRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "Globals.h"
#include "Menu.h"
#include "ShaderCache.h"
#include "ThemeManager.h"
#include "Util.h"

void SettingsTabRenderer::RenderGeneralSettings(
Expand Down Expand Up @@ -141,6 +142,17 @@ void SettingsTabRenderer::RenderKeybindingsTab(
void SettingsTabRenderer::RenderInterfaceTab()
{
if (ImGui::BeginTabItem("Interface")) {
// Restore theme defaults button
if (ImGui::Button("Restore Theme Defaults")) {
auto& settings = globals::menu->GetSettings();
settings.Theme = Menu::ThemeSettings{}; // reset to default-initialized theme
// Apply global font scale immediately
ImGui::GetIO().FontGlobalScale = exp2(settings.Theme.GlobalScale);
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::TextUnformatted("Resets UI sizes, colors and options to their defaults (including resolution-based font size).");
}

if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None)) {
RenderUIOptionsTab();
RenderSizesTab();
Expand Down Expand Up @@ -186,7 +198,31 @@ void SettingsTabRenderer::RenderSizesTab()
auto& io = ImGui::GetIO();
io.FontGlobalScale = trueScale;
}
// Font size controls: Auto (resolution-based) or Manual
bool useAutoFont = (themeSettings.FontSize <= 0.0f);
if (ImGui::Checkbox("Use resolution-based font size", &useAutoFont)) {
if (useAutoFont) {
// Enable auto: set sentinel 0.0f
themeSettings.FontSize = 0.0f;
} else {
// Disable auto: seed manual size with current effective (what user sees now)
float effective = ThemeManager::ResolveFontSize(*globals::menu);
themeSettings.FontSize = std::clamp(effective, ThemeManager::Constants::MIN_FONT_SIZE, ThemeManager::Constants::MAX_FONT_SIZE);
}
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::TextUnformatted("When enabled, the UI font size scales with your screen resolution. Disable to set a fixed size.");
}

// Show current effective size for clarity
float effectiveNow = ThemeManager::ResolveFontSize(*globals::menu);
ImGui::Text("Effective size: %.0f px", std::round(effectiveNow));

// Manual font size slider (disabled in auto mode)
ImGui::BeginDisabled(useAutoFont);
ImGui::SliderFloat("Font Size", &themeSettings.FontSize, ThemeManager::Constants::MIN_FONT_SIZE, ThemeManager::Constants::MAX_FONT_SIZE, "%.0f");
ImGui::EndDisabled();

ImGui::SliderFloat2("Window Padding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("Frame Padding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("Item Spacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
Expand Down
28 changes: 25 additions & 3 deletions src/Menu/ThemeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <imgui_impl_dx11.h>

#include "RE/Skyrim.h"
#include "State.h"
#include "Util.h"

void ThemeManager::SetupImGuiStyle(const Menu& menu)
Expand Down Expand Up @@ -124,8 +125,8 @@ void ThemeManager::ReloadFont(const Menu& menu, float& cachedFontSize)
font_config.PixelSnapH = Constants::FCONF_PIXELSNAP_H;
font_config.RasterizerMultiply = Constants::FCONF_RASTERIZER_MULTIPLY;

float fontSize = themeSettings.FontSize;
fontSize = std::clamp(fontSize, Constants::MIN_FONT_SIZE, Constants::MAX_FONT_SIZE);
// Compute effective font size (user value or dynamic default)
float fontSize = ResolveFontSize(menu);

auto fontPath = Util::PathHelpers::GetFontsPath() / "Jost-Regular.ttf";
if (!io.Fonts->AddFontFromFileTTF(fontPath.string().c_str(),
Expand All @@ -140,5 +141,26 @@ void ThemeManager::ReloadFont(const Menu& menu, float& cachedFontSize)

io.FontGlobalScale = exp2(themeSettings.GlobalScale);

cachedFontSize = themeSettings.FontSize;
// Cache the effective size so we can detect changes accurately
cachedFontSize = fontSize;
}

float ThemeManager::ResolveFontSize(const Menu& menu)
{
const auto& themeSettings = menu.GetTheme();
float configured = themeSettings.FontSize;

// If user configured a positive size, use it (clamped)
if (std::round(configured) > 0) {
return std::clamp(configured, Constants::MIN_FONT_SIZE, Constants::MAX_FONT_SIZE);
}

// Otherwise, compute dynamic default based on current screen resolution
float dynamicSize = Constants::DEFAULT_FONT_SIZE;
if (globals::state && globals::state->screenSize.y > 0) {
dynamicSize = globals::state->screenSize.y * Constants::DEFAULT_FONT_RATIO;
} else {
logger::warn("ThemeManager::ResolveFontSize() - Falling back to DEFAULT_FONT_SIZE due to missing screen height.");
}
return std::clamp(dynamicSize, Constants::MIN_FONT_SIZE, Constants::MAX_FONT_SIZE);
}
3 changes: 3 additions & 0 deletions src/Menu/ThemeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class ThemeManager
public:
static void SetupImGuiStyle(const class Menu& menu);
static void ReloadFont(const class Menu& menu, float& cachedFontSize);
// Returns the effective font size to use. If the user setting is <= 0, a dynamic
// default based on current screen resolution is returned; otherwise the user value.
static float ResolveFontSize(const class Menu& menu);

struct Constants
{
Expand Down