diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.cpp b/src/WeatherEditor/Weather/PrecipitationWidget.cpp index ba0cfaae85..a7624d8592 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.cpp +++ b/src/WeatherEditor/Weather/PrecipitationWidget.cpp @@ -98,10 +98,6 @@ void PrecipitationWidget::DrawWidget() ImGui::EndTabBar(); } - - if (changed && EditorWindow::GetSingleton()->settings.autoApplyChanges) { - ApplyChanges(); - } } ImGui::End(); } @@ -226,6 +222,7 @@ void PrecipitationWidget::ApplyChanges() runtime.data[(uint32_t)RE::BGSShaderParticleGeometryData::DataID::kParticleDensity].f = settings.particleDensity; runtime.particleTexture.textureName = settings.particleTexture.c_str(); ApplyLiveParticleTexture(settings.particleTexture); + Widget::ForceCurrentWeatherReinit(); } void PrecipitationWidget::ApplyLiveParticleTexture(const std::string& path) diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.h b/src/WeatherEditor/Weather/PrecipitationWidget.h index 5c0bbbdff5..cbfbc988e0 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.h +++ b/src/WeatherEditor/Weather/PrecipitationWidget.h @@ -21,6 +21,7 @@ class PrecipitationWidget : public Widget void DrawWidget() override; const char* GetWidgetTypeName() const override { return "Precipitation"; } + bool RequiresManualApply() const override { return true; } void LoadSettings() override; void SaveSettings() override; void ApplyChanges() override; diff --git a/src/WeatherEditor/Weather/ReferenceEffectWidget.cpp b/src/WeatherEditor/Weather/ReferenceEffectWidget.cpp index 1f6e8bd374..c607e0519b 100644 --- a/src/WeatherEditor/Weather/ReferenceEffectWidget.cpp +++ b/src/WeatherEditor/Weather/ReferenceEffectWidget.cpp @@ -35,11 +35,6 @@ void ReferenceEffectWidget::DrawWidget() changed = true; if (ImGui::Checkbox("Inherit Rotation", &settings.inheritRotation)) changed = true; - - if (changed && editorWindow->settings.autoApplyChanges) { - editorWindow->PushUndoState(this); - ApplyChanges(); - } } EndScrollableContent(); } @@ -126,6 +121,8 @@ void ReferenceEffectWidget::ApplyChanges() referenceEffect->data.flags.set(RE::BGSReferenceEffect::Flag::kAttachToCamera); if (settings.inheritRotation) referenceEffect->data.flags.set(RE::BGSReferenceEffect::Flag::kInheritRotation); + + Widget::ForceCurrentWeatherReinit(); } void ReferenceEffectWidget::RevertChanges() diff --git a/src/WeatherEditor/Weather/ReferenceEffectWidget.h b/src/WeatherEditor/Weather/ReferenceEffectWidget.h index b3b72e11b0..40144c3a10 100644 --- a/src/WeatherEditor/Weather/ReferenceEffectWidget.h +++ b/src/WeatherEditor/Weather/ReferenceEffectWidget.h @@ -20,6 +20,7 @@ class ReferenceEffectWidget : public Widget void DrawWidget() override; const char* GetWidgetTypeName() const override { return "Visual Effect"; } + bool RequiresManualApply() const override { return true; } void LoadSettings() override; void SaveSettings() override; void ApplyChanges() override; diff --git a/src/WeatherEditor/Weather/WeatherWidget.cpp b/src/WeatherEditor/Weather/WeatherWidget.cpp index 1b25cf7b37..8c1d8368c6 100644 --- a/src/WeatherEditor/Weather/WeatherWidget.cpp +++ b/src/WeatherEditor/Weather/WeatherWidget.cpp @@ -224,7 +224,6 @@ void WeatherWidget::DrawWidget() ImGui::Spacing(); auto* editorWindow = EditorWindow::GetSingleton(); - bool recordChanged = false; bool hasParent = editorWindow->settings.enableInheritFromParent && HasParent(); WeatherWidget* parentWidget = hasParent ? GetParent() : nullptr; const float todLabelOffset = (hasParent ? 120.0f : 100.0f) * scale; @@ -245,7 +244,7 @@ void WeatherWidget::DrawWidget() if (inheritFlag && parentWidget) { if (settings.imageSpaceRefs[i] != parentWidget->settings.imageSpaceRefs[i]) { settings.imageSpaceRefs[i] = parentWidget->settings.imageSpaceRefs[i]; - recordChanged = true; + pendingReinit = true; } } if (ImGui::IsItemHovered()) { @@ -257,7 +256,7 @@ void WeatherWidget::DrawWidget() ImGui::Text("%s:", label.c_str()); ImGui::SameLine(todLabelOffset); if (WeatherUtils::DrawFormPickerCached("##ImageSpace", settings.imageSpaceRefs[i], editorWindow->imageSpaceWidgets, false, true, pickerWidth)) { - recordChanged = true; + pendingReinit = true; } // Add "Open" button if (settings.imageSpaceRefs[i]) { ImGui::SameLine(); @@ -293,7 +292,7 @@ void WeatherWidget::DrawWidget() if (inheritFlag && parentWidget) { if (settings.volumetricLightingRefs[i] != parentWidget->settings.volumetricLightingRefs[i]) { settings.volumetricLightingRefs[i] = parentWidget->settings.volumetricLightingRefs[i]; - recordChanged = true; + pendingReinit = true; } } if (ImGui::IsItemHovered()) { @@ -305,7 +304,7 @@ void WeatherWidget::DrawWidget() ImGui::Text("%s:", label.c_str()); ImGui::SameLine(todLabelOffset); if (WeatherUtils::DrawFormPickerCached("##VolumetricLighting", settings.volumetricLightingRefs[i], editorWindow->volumetricLightingWidgets, false, true, pickerWidth)) { - recordChanged = true; + pendingReinit = true; } // Add "Open" button if (settings.volumetricLightingRefs[i]) { ImGui::SameLine(); @@ -336,7 +335,7 @@ void WeatherWidget::DrawWidget() if (inheritFlag && parentWidget) { if (settings.precipitationData != parentWidget->settings.precipitationData) { settings.precipitationData = parentWidget->settings.precipitationData; - recordChanged = true; + pendingReinit = true; } } if (ImGui::IsItemHovered()) { @@ -348,7 +347,7 @@ void WeatherWidget::DrawWidget() ImGui::Text("Particle Shader:"); ImGui::SameLine(formLabelOffset); if (WeatherUtils::DrawFormPickerCached("##Precipitation", settings.precipitationData, editorWindow->precipitationWidgets, false, true, pickerWidth)) { - recordChanged = true; + pendingReinit = true; } // Add "Open" button if (settings.precipitationData) { ImGui::SameLine(); @@ -377,7 +376,7 @@ void WeatherWidget::DrawWidget() if (inheritFlag && parentWidget) { if (settings.referenceEffect != parentWidget->settings.referenceEffect) { settings.referenceEffect = parentWidget->settings.referenceEffect; - recordChanged = true; + pendingReinit = true; } } if (ImGui::IsItemHovered()) { @@ -389,7 +388,7 @@ void WeatherWidget::DrawWidget() ImGui::Text("Reference Effect:"); ImGui::SameLine(formLabelOffset); if (WeatherUtils::DrawFormPickerCached("##ReferenceEffect", settings.referenceEffect, editorWindow->referenceEffectWidgets, false, true, pickerWidth)) { - recordChanged = true; + pendingReinit = true; } // Add "Open" button if (settings.referenceEffect) { ImGui::SameLine(); @@ -409,7 +408,7 @@ void WeatherWidget::DrawWidget() ImGui::Spacing(); } - if (recordChanged && EditorWindow::GetSingleton()->settings.autoApplyChanges) { + if (pendingReinit) { ApplyChanges(); } @@ -495,6 +494,7 @@ void WeatherWidget::LoadSettings() LoadFeatureSettings(); } originalSettings = settings; + pendingReinit = true; ApplyChanges(); } @@ -1175,12 +1175,8 @@ void WeatherWidget::DrawCloudSettings() if (enableChanged) { // Apply enable/disable immediately for instant feedback, regardless of autoApplyChanges. editorWindow->PushUndoState(this); + pendingReinit = true; ApplyChanges(); - if (editorWindow->IsWeatherLocked() && editorWindow->GetLockedWeather() == weather) { - if (auto sky = RE::Sky::GetSingleton()) { - sky->ForceWeather(weather, true); // override=true for immediate application; matches "instant feedback" intent above - } - } } else if (changed && editorWindow->settings.autoApplyChanges) { editorWindow->PushUndoState(this); ApplyChanges(); @@ -1535,7 +1531,8 @@ void WeatherWidget::InheritAllFromParent() settings.inheritFlags["Precipitation"] = true; settings.inheritFlags["ReferenceEffect"] = true; - // Apply the changes + // Apply the changes — form references require a weather reinit to propagate + pendingReinit = true; if (EditorWindow::GetSingleton()->settings.autoApplyChanges) { ApplyChanges(); } @@ -1657,6 +1654,10 @@ void WeatherWidget::LoadFeatureSettings() void WeatherWidget::ApplyChanges() { SetWeatherValues(); + if (pendingReinit) { + Widget::ForceWeatherReinit(weather); + pendingReinit = false; + } } void WeatherWidget::RevertChanges() @@ -1684,6 +1685,7 @@ void WeatherWidget::RevertChanges() weatherManager->ClearAllFeatureSettingsForWeather(weather); settings = vanillaSettings; + pendingReinit = true; ApplyChanges(); } diff --git a/src/WeatherEditor/Weather/WeatherWidget.h b/src/WeatherEditor/Weather/WeatherWidget.h index 302ab1b6c7..a58c01c7c3 100644 --- a/src/WeatherEditor/Weather/WeatherWidget.h +++ b/src/WeatherEditor/Weather/WeatherWidget.h @@ -152,4 +152,5 @@ class WeatherWidget : public Widget void DrawProperties(std::string category, std::map properties); void InheritFromParent(const std::string& property); void InheritAllFromParent(); + bool pendingReinit = false; }; \ No newline at end of file diff --git a/src/WeatherEditor/Widget.cpp b/src/WeatherEditor/Widget.cpp index 789b88689a..1db02aa8ea 100644 --- a/src/WeatherEditor/Widget.cpp +++ b/src/WeatherEditor/Widget.cpp @@ -276,6 +276,20 @@ bool Widget::BeginWidgetWindow() return result; } +void Widget::ForceWeatherReinit(RE::TESWeather* weather) +{ + auto* sky = globals::game::sky; + if (weather && sky && sky->currentWeather == weather) + sky->ForceWeather(weather, true); +} + +void Widget::ForceCurrentWeatherReinit() +{ + auto* sky = globals::game::sky; + if (sky && sky->currentWeather) + sky->ForceWeather(sky->currentWeather, true); +} + void Widget::DrawWidgetHeader(const char* searchId, bool showApply, bool showSaveLoadRevert, bool showForceWeather, RE::TESWeather* weather) { auto editorWindow = EditorWindow::GetSingleton(); @@ -348,8 +362,17 @@ void Widget::DrawWidgetHeader(const char* searchId, bool showApply, bool showSav }; // Apply button - if (showApply && !editorWindow->settings.autoApplyChanges) - iconButton("_Apply", menu->uiIcons.applyToGame.texture, "Apply changes to the game", [&]() { ApplyChanges(); }); + if (showApply && (!editorWindow->settings.autoApplyChanges || RequiresManualApply())) { + if (menu->uiIcons.applyToGame.texture) { + iconButton("_Apply", menu->uiIcons.applyToGame.texture, "Apply changes to the game", [&]() { ApplyChanges(); }); + } else { + ImGui::SameLine(); + if (ImGui::Button("Apply")) + ApplyChanges(); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Apply changes to the game"); + } + } // Save/Load/Revert/Delete group if (showSaveLoadRevert) { @@ -415,7 +438,7 @@ void Widget::DrawWidgetHeader(const char* searchId, bool showApply, bool showSav }; // Apply button - if (showApply && !editorWindow->settings.autoApplyChanges) + if (showApply && (!editorWindow->settings.autoApplyChanges || RequiresManualApply())) styledTextButton("Apply", palette.SuccessColor, "Apply changes to the game", [&]() { ApplyChanges(); }); // Save/Load/Revert/Delete group @@ -433,5 +456,12 @@ void Widget::DrawWidgetHeader(const char* searchId, bool showApply, bool showSav DrawDeleteConfirmationModal(); + if (showApply && RequiresManualApply() && editorWindow->settings.autoApplyChanges && menu) { + ImGui::SameLine(); + ImGui::TextColored(menu->GetTheme().StatusPalette.Warning, "(Changes require manual apply)"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("This form type is only re-read by the engine on weather reinit.\nAuto-apply is disabled - use the Apply button."); + } + ImGui::Separator(); } diff --git a/src/WeatherEditor/Widget.h b/src/WeatherEditor/Widget.h index 27dc1a0fe8..a46e70fa90 100644 --- a/src/WeatherEditor/Widget.h +++ b/src/WeatherEditor/Widget.h @@ -146,6 +146,14 @@ class Widget virtual void RevertChanges() { LoadSettings(); } virtual bool HasUnsavedChanges() const { return false; } + // Reinitialize weather to apply form refs that are only read at load time. + static void ForceWeatherReinit(RE::TESWeather* weather); + // Reinitialize the current sky weather (use when the specific weather is unknown). + static void ForceCurrentWeatherReinit(); + + // Override to suppress per-frame auto-apply and show a manual-apply warning in the header. + virtual bool RequiresManualApply() const { return false; } + // Draw common header with search bar and action buttons void DrawWidgetHeader(const char* searchId, bool showApply = true, bool showSaveLoadRevert = false, bool showForceWeather = false, RE::TESWeather* weather = nullptr);