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
23 changes: 13 additions & 10 deletions package/Shaders/Menu/BackgroundBlurComposite.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
cbuffer WindowBuffer : register(b1)
{
float4 WindowRect; // x = minX, y = minY, z = maxX, w = maxY (in pixels)
float4 WindowParams; // x = cornerRadius, y = screenWidth, z = screenHeight, w = unused
float4 WindowParams; // x = cornerRadius, y = screenWidth, z = screenHeight, w = fullscreen (1.0 = skip SDF)
};

SamplerState LinearSampler : register(s0);
Expand Down Expand Up @@ -102,17 +102,20 @@ float4 PS_Main(VS_OUTPUT input) :
float2 rectMax = WindowRect.zw;
float cornerRadius = WindowParams.x;

// Calculate signed distance to rounded rectangle
float sdf = RoundedRectSDF(pixelPos, rectMin, rectMax, cornerRadius);
float alpha = 1.0f;
if (WindowParams.w < 0.5f) {
// Calculate signed distance to rounded rectangle
float sdf = RoundedRectSDF(pixelPos, rectMin, rectMax, cornerRadius);

// Create smooth edge (anti-aliased)
// Negative = inside, positive outside
// Use 1.0 pixel transition for smooth edge
float alpha = saturate(-sdf);
// Create smooth edge (anti-aliased)
// Negative = inside, positive outside
// Use 1.0 pixel transition for smooth edge
alpha = saturate(-sdf);

// Early out if completely outside
if (alpha <= 0.0f) {
discard;
// Early out if completely outside
if (alpha <= 0.0f) {
discard;
}
}

float2 blurTexelSize = DOWNSAMPLE_FACTOR / float2(WindowParams.y, WindowParams.z);
Expand Down
8 changes: 3 additions & 5 deletions src/Features/WeatherEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,10 @@ void LerpDirectional(RE::BGSDirectionalAmbientLightingColors::Directional& oldCo

void WeatherEditor::DrawSettings()
{
auto player = RE::PlayerCharacter::GetSingleton();
bool hasCell = player && player->parentCell;
ImGui::BeginDisabled(!hasCell);
if (ImGui::Button(hasCell ? "Open Editor" : "Open Editor (no active cell)", { -1, 0 })) {
bool canOpen = EditorWindow::CanBeOpen();
ImGui::BeginDisabled(!canOpen);
if (ImGui::Button("Open Editor", { -1, 0 }))
EditorWindow::GetSingleton()->open = true;
}
ImGui::EndDisabled();

// Time controls
Expand Down
2 changes: 2 additions & 0 deletions src/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ namespace globals
float* cameraFar = nullptr;
float* deltaTime = nullptr;
RE::BSUtilityShader* utilityShader = nullptr;
RE::PlayerCharacter* player = nullptr;
RE::Sky* sky = nullptr;
RE::UI* ui = nullptr;
RE::Calendar* calendar = nullptr;
Expand Down Expand Up @@ -204,6 +205,7 @@ namespace globals
void OnDataLoaded()
{
using namespace game;
player = RE::PlayerCharacter::GetSingleton();
sky = RE::Sky::GetSingleton();
utilityShader = RE::BSUtilityShader::GetSingleton();
waterSystem = RE::TESWaterSystem::GetSingleton();
Expand Down
1 change: 1 addition & 0 deletions src/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ namespace globals
extern float* cameraFar;
extern float* deltaTime;
extern RE::BSUtilityShader* utilityShader;
extern RE::PlayerCharacter* player;
extern RE::Sky* sky;
extern RE::UI* ui;
extern RE::Calendar* calendar;
Expand Down
6 changes: 2 additions & 4 deletions src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,10 +1080,8 @@ void Menu::ProcessInputEventQueue()
} else if (ew->IsInPreviewMode()) {
// Locked or PlayMode → fully exit preview
ew->ExitPreviewMode();
} else {
auto p = RE::PlayerCharacter::GetSingleton();
if (p && p->parentCell)
ew->open = !ew->open;
} else if (EditorWindow::CanBeOpen()) {
ew->open = !ew->open;
}
} },
};
Expand Down
21 changes: 20 additions & 1 deletion src/Menu/BackgroundBlur.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace BackgroundBlur
{
std::mutex resourceMutex;
bool enabled = false;
bool weatherEditorActive = false;

// DirectX resources (RAII managed)
winrt::com_ptr<ID3D11VertexShader> vertexShader;
Expand Down Expand Up @@ -411,7 +412,7 @@ namespace BackgroundBlur
windowConstants.windowParams[0] = cornerRadius;
windowConstants.windowParams[1] = static_cast<float>(sourceDesc.Width);
windowConstants.windowParams[2] = static_cast<float>(sourceDesc.Height);
windowConstants.windowParams[3] = 0.0f;
windowConstants.windowParams[3] = weatherEditorActive ? 1.0f : 0.0f;
context->UpdateSubresource(windowConstantBuffer.get(), 0, nullptr, &windowConstants, 0, 0);
auto windowConstantBufferPtr = windowConstantBuffer.get();
context->PSSetConstantBuffers(1, 1, &windowConstantBufferPtr);
Expand Down Expand Up @@ -484,6 +485,16 @@ namespace BackgroundBlur
enabled = enable;
}

void SetWeatherEditorActive(bool active)
{
weatherEditorActive = active;
}

bool IsWeatherEditorActive()
{
return weatherEditorActive;
}

void RenderBackgroundBlur()
{
if (!enabled) {
Expand Down Expand Up @@ -575,6 +586,14 @@ namespace BackgroundBlur
CreateBlurTextures(texDesc.Width, texDesc.Height, texDesc.Format);
}

// Weather editor mode: single fullscreen blur pass (better perf than per-window)
if (weatherEditorActive) {
ImVec2 screenMin = { 0, 0 };
ImVec2 screenMax = { static_cast<float>(texDesc.Width), static_cast<float>(texDesc.Height) };
PerformBlur(currentTexture.get(), sourceSRV, currentRTV.get(), screenMin, screenMax, 0.0f, uiBufferSRV, uiBufferRTV);
return;
}

// Find ImGui windows that need blur
ImGuiContext* ctx = ImGui::GetCurrentContext();
if (!ctx || ctx->Windows.Size == 0) {
Expand Down
4 changes: 4 additions & 0 deletions src/Menu/BackgroundBlur.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ namespace BackgroundBlur

void SetEnabled(bool enable);

/// When true, a single fullscreen blur replaces per-window blur (weather editor mode)
void SetWeatherEditorActive(bool active);
bool IsWeatherEditorActive();

} // namespace BackgroundBlur
6 changes: 2 additions & 4 deletions src/Menu/OverlayRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,13 @@ void OverlayRenderer::RenderOverlay(
RenderShaderCompilationStatus(keyIdToString);
RenderShaderBlockingStatus();

// Draw weather editor independently of main menu state
// Auto-close editor if player leaves valid game space (e.g., loading screen)
auto* editorWindow = EditorWindow::GetSingleton();
auto player = RE::PlayerCharacter::GetSingleton();
if (editorWindow->open && !(player && player->parentCell)) {
if (editorWindow->open && !EditorWindow::CanBeOpen()) {
editorWindow->open = false;
if (editorWindow->IsInPreviewMode())
editorWindow->ExitPreviewMode();
}
editorWindow->UpdateOpenState();
if (editorWindow->open) {
bool flying = editorWindow->IsPreviewFlying();
auto& io = ImGui::GetIO();
Expand Down
53 changes: 48 additions & 5 deletions src/WeatherEditor/EditorWindow.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "EditorWindow.h"

#include "Features/Upscaling.h"
#include "Features/WeatherEditor.h"
#include "InteriorOnlyPanel.h"
#include "Menu.h"
#include "Menu/BackgroundBlur.h"
#include "PaletteWindow.h"
#include "State.h"
#include "Utils/UI.h"
Expand Down Expand Up @@ -877,7 +879,6 @@ void EditorWindow::RenderUI()
ImGui::GetStyle().FontScaleMain = settings.editorUIScale;

if (settings.showViewport) {
// Dim the game scene using the theme's modal dim background color
ImGui::GetBackgroundDrawList()->AddRectFilled({ 0, 0 }, io.DisplaySize, ImGui::GetColorU32(ImGuiCol_ModalWindowDimBg));
}

Expand Down Expand Up @@ -1010,6 +1011,7 @@ void EditorWindow::RenderUI()
}
if (ImGui::BeginMenu("Window")) {
if (ImGui::Checkbox("Viewport", &settings.showViewport)) {
BackgroundBlur::SetWeatherEditorActive(settings.showViewport);
Save();
}
if (ImGui::Checkbox("Palette", &PaletteWindow::GetSingleton()->open)) {
Expand Down Expand Up @@ -1388,6 +1390,7 @@ void EditorWindow::OpenWeatherFeatureSetting(RE::TESWeather* weather, const std:

EditorWindow::~EditorWindow()
{
ShowGameMenus();
delete tempTexture;
weatherWidgets.clear();
lightingTemplateWidgets.clear();
Expand Down Expand Up @@ -1420,23 +1423,27 @@ void EditorWindow::SetupResources()
WidgetFactory::PopulateSimpleWidgets<RE::TESEffectShader>(effectShaderWidgets);
}

void EditorWindow::Draw()
void EditorWindow::UpdateOpenState()
{
// Track editor open state for vanity camera management
static bool wasOpen = false;

if (open && !wasOpen) {
// Editor just opened - disable vanity camera and restore session
DisableVanityCamera();
HideGameMenus();
BackgroundBlur::SetWeatherEditorActive(settings.showViewport);
RestoreSessionWidgets();
} else if (!open && wasOpen) {
// Editor just closed - restore vanity camera and save session
RestoreVanityCamera();
ShowGameMenus();
BackgroundBlur::SetWeatherEditorActive(false);
SaveSessionWidgets();
}

wasOpen = open;
}

void EditorWindow::Draw()
{
// Re-enforce weather lock if active (handles time changes)
if (weatherLockActive && lockedWeather) {
auto sky = RE::Sky::GetSingleton();
Expand Down Expand Up @@ -1914,6 +1921,13 @@ void EditorWindow::DrawTimeControls()
ImGui::Text("Adjust how fast time passes (vanilla: %.1fx)", kVanillaTimeScale);
}

bool EditorWindow::CanBeOpen()
{
auto* player = globals::game::player;
auto* state = globals::state;
return player && player->parentCell && !state->isLoadingMenuOpen && !state->isMainMenuOpen;
}

void EditorWindow::DisableVanityCamera()
{
if (vanityCameraDisabled)
Expand Down Expand Up @@ -1941,6 +1955,35 @@ void EditorWindow::RestoreVanityCamera()
}
}

void EditorWindow::HideGameMenus()
{
if (gameMenusHidden)
return;

// ShowMenus(false) stops the game from rendering to the back buffer.
// Without d3d12SwapChain, blur reads directly from that buffer and would freeze.
if (!globals::features::upscaling.d3d12SwapChainActive)
return;

if (auto ui = RE::UI::GetSingleton()) {
ui->ShowMenus(false);
gameMenusHidden = true;
logger::info("Game menus hidden for weather editor");
}
}

void EditorWindow::ShowGameMenus()
{
if (!gameMenusHidden)
return;

if (auto ui = RE::UI::GetSingleton()) {
ui->ShowMenus(true);
gameMenusHidden = false;
logger::info("Game menus restored after weather editor");
}
}

void EditorWindow::EnterPreviewMode(PreviewMode mode)
{
if (mode == PreviewMode::None)
Expand Down
9 changes: 9 additions & 0 deletions src/WeatherEditor/EditorWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ class EditorWindow
bool vanityCameraDisabled = false;
float savedVanityCameraDelay = 180.0f;

// Game HUD hiding (tm equivalent)
bool gameMenusHidden = false;

void ShowObjectsWindow();

void ShowViewportWindow();
Expand Down Expand Up @@ -132,8 +135,14 @@ class EditorWindow
// Check if ESC key should close the editor (no popups open)
bool ShouldHandleEscapeKey() const;

static bool CanBeOpen();
void DisableVanityCamera();
void RestoreVanityCamera();
void HideGameMenus();
void ShowGameMenus();

/// Call every frame from the overlay renderer to track open/close transitions.
void UpdateOpenState();

// Undo system
struct UndoState
Expand Down
Loading