From f33823f9758c72766a1f8d44b0e9311f208cf9c6 Mon Sep 17 00:00:00 2001 From: ParticleTroned <248299730+ParticleTroned@users.noreply.github.com> Date: Sun, 26 Apr 2026 09:36:22 +0100 Subject: [PATCH 1/6] fix(weather-editor): write VR precipitation settings through VR runtime data --- .../Weather/PrecipitationWidget.cpp | 68 ++++++++++++++----- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.cpp b/src/WeatherEditor/Weather/PrecipitationWidget.cpp index 35042d8af2..a2baf49506 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.cpp +++ b/src/WeatherEditor/Weather/PrecipitationWidget.cpp @@ -4,6 +4,40 @@ #include "Globals.h" #include "RE/B/BSShaderManager.h" #include "RE/N/NiSourceTexture.h" +#include "Utils/Game.h" + +namespace +{ + using PrecipitationData = RE::BGSShaderParticleGeometryData; + using DataID = PrecipitationData::DataID; + using SettingValue = PrecipitationData::SETTING_VALUE; + + void SetSettingValue(PrecipitationData* precipitation, DataID id, SettingValue value) + { + const auto index = static_cast(id); + if (REL::Module::IsVR()) { + precipitation->GetVRRuntimeData().data[index].value = value; + return; + } + + precipitation->GetRuntimeData().data[index] = value; + } + + void SetSetting(PrecipitationData* precipitation, DataID id, float value) + { + SettingValue setting{}; + setting.f = value; + SetSettingValue(precipitation, id, setting); + } + + void SetSetting(PrecipitationData* precipitation, DataID id, uint32_t value) + { + SettingValue setting{}; + setting.i = value; + SetSettingValue(precipitation, id, setting); + } + +} void PrecipitationWidget::DrawWidget() { @@ -166,8 +200,6 @@ void PrecipitationWidget::LoadFromGameSettings() if (!precipitation) return; - auto& runtime = precipitation->GetRuntimeData(); - settings.gravityVelocity = precipitation->GetSettingValue(RE::BGSShaderParticleGeometryData::DataID::kGravityVelocity).f; settings.rotationVelocity = precipitation->GetSettingValue(RE::BGSShaderParticleGeometryData::DataID::kRotationVelocity).f; settings.particleSizeX = precipitation->GetSettingValue(RE::BGSShaderParticleGeometryData::DataID::kParticleSizeX).f; @@ -180,7 +212,8 @@ void PrecipitationWidget::LoadFromGameSettings() settings.particleType = precipitation->GetSettingValue(RE::BGSShaderParticleGeometryData::DataID::kParticleType).i; settings.boxSize = precipitation->GetSettingValue(RE::BGSShaderParticleGeometryData::DataID::kBoxSize).f; settings.particleDensity = precipitation->GetSettingValue(RE::BGSShaderParticleGeometryData::DataID::kParticleDensity).f; - settings.particleTexture = runtime.particleTexture.textureName.c_str(); + GET_INSTANCE_MEMBER(particleTexture, precipitation) + settings.particleTexture = particleTexture.textureName.c_str(); } void PrecipitationWidget::SaveSettings() @@ -206,21 +239,20 @@ void PrecipitationWidget::ApplyChanges() if (!precipitation) return; - auto& runtime = precipitation->GetRuntimeData(); - - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kGravityVelocity)].f = settings.gravityVelocity; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kRotationVelocity)].f = settings.rotationVelocity; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kParticleSizeX)].f = settings.particleSizeX; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kParticleSizeY)].f = settings.particleSizeY; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kCenterOffsetMin)].f = settings.centerOffsetMin; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kCenterOffsetMax)].f = settings.centerOffsetMax; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kStartRotationRange)].f = settings.startRotationRange; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kNumSubtexturesX)].i = settings.numSubtexturesX; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kNumSubtexturesY)].i = settings.numSubtexturesY; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kParticleType)].i = settings.particleType; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kBoxSize)].f = settings.boxSize; - runtime.data[static_cast(RE::BGSShaderParticleGeometryData::DataID::kParticleDensity)].f = settings.particleDensity; - runtime.particleTexture.textureName = settings.particleTexture.c_str(); + SetSetting(precipitation, DataID::kGravityVelocity, settings.gravityVelocity); + SetSetting(precipitation, DataID::kRotationVelocity, settings.rotationVelocity); + SetSetting(precipitation, DataID::kParticleSizeX, settings.particleSizeX); + SetSetting(precipitation, DataID::kParticleSizeY, settings.particleSizeY); + SetSetting(precipitation, DataID::kCenterOffsetMin, settings.centerOffsetMin); + SetSetting(precipitation, DataID::kCenterOffsetMax, settings.centerOffsetMax); + SetSetting(precipitation, DataID::kStartRotationRange, settings.startRotationRange); + SetSetting(precipitation, DataID::kNumSubtexturesX, settings.numSubtexturesX); + SetSetting(precipitation, DataID::kNumSubtexturesY, settings.numSubtexturesY); + SetSetting(precipitation, DataID::kParticleType, settings.particleType); + SetSetting(precipitation, DataID::kBoxSize, settings.boxSize); + SetSetting(precipitation, DataID::kParticleDensity, settings.particleDensity); + GET_INSTANCE_MEMBER(particleTexture, precipitation) + particleTexture.textureName = settings.particleTexture.c_str(); ApplyLiveParticleTexture(settings.particleTexture); Widget::ForceCurrentWeatherReinit(); } From df6944a29822fdfc6306bee250b357e21b5f8fbe Mon Sep 17 00:00:00 2001 From: ParticleTroned <248299730+ParticleTroned@users.noreply.github.com> Date: Sun, 26 Apr 2026 17:09:22 +0100 Subject: [PATCH 2/6] refactor(weather-editor): use shared VR particle setting helper --- src/Utils/Game.h | 20 ++++++ .../Weather/PrecipitationWidget.cpp | 71 +++++++------------ 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/Utils/Game.h b/src/Utils/Game.h index 83f620cdc7..7dd7bd924e 100644 --- a/src/Utils/Game.h +++ b/src/Utils/Game.h @@ -2,6 +2,11 @@ #pragma once +namespace globals::game +{ + extern bool isVR; +} + /** @def GET_INSTANCE_MEMBER @brief Set variable in current namespace based on instance member from GetRuntimeData or GetVRRuntimeData. @@ -28,6 +33,21 @@ #define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ &(!REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) +/** + @def GET_SHADER_PARTICLE_SETTING + @brief Set variable in current namespace to a shader particle setting, using the correct flat/VR storage. + + @warning Only for RE::BGSShaderParticleGeometryData. In VR, particle settings are stored in + data[id].value instead of directly in data[id]. + + @param a_value The local variable name to create. + @param a_source The BGSShaderParticleGeometryData instance. + @param a_id The BGSShaderParticleGeometryData::DataID setting. + @result The a_value will be set as a variable in the current namespace. + */ +#define GET_SHADER_PARTICLE_SETTING(a_value, a_source, a_id) \ + auto& a_value = !globals::game::isVR ? (a_source)->GetRuntimeData().data[static_cast(a_id)] : (a_source)->GetVRRuntimeData().data[static_cast(a_id)].value; + namespace Util { void StoreTransform3x4NoScale(DirectX::XMFLOAT3X4& Dest, const RE::NiTransform& Source); diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.cpp b/src/WeatherEditor/Weather/PrecipitationWidget.cpp index a2baf49506..07444bbf6a 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.cpp +++ b/src/WeatherEditor/Weather/PrecipitationWidget.cpp @@ -6,39 +6,6 @@ #include "RE/N/NiSourceTexture.h" #include "Utils/Game.h" -namespace -{ - using PrecipitationData = RE::BGSShaderParticleGeometryData; - using DataID = PrecipitationData::DataID; - using SettingValue = PrecipitationData::SETTING_VALUE; - - void SetSettingValue(PrecipitationData* precipitation, DataID id, SettingValue value) - { - const auto index = static_cast(id); - if (REL::Module::IsVR()) { - precipitation->GetVRRuntimeData().data[index].value = value; - return; - } - - precipitation->GetRuntimeData().data[index] = value; - } - - void SetSetting(PrecipitationData* precipitation, DataID id, float value) - { - SettingValue setting{}; - setting.f = value; - SetSettingValue(precipitation, id, setting); - } - - void SetSetting(PrecipitationData* precipitation, DataID id, uint32_t value) - { - SettingValue setting{}; - setting.i = value; - SetSettingValue(precipitation, id, setting); - } - -} - void PrecipitationWidget::DrawWidget() { WeatherUtils::SetCurrentWidget(this); @@ -239,18 +206,32 @@ void PrecipitationWidget::ApplyChanges() if (!precipitation) return; - SetSetting(precipitation, DataID::kGravityVelocity, settings.gravityVelocity); - SetSetting(precipitation, DataID::kRotationVelocity, settings.rotationVelocity); - SetSetting(precipitation, DataID::kParticleSizeX, settings.particleSizeX); - SetSetting(precipitation, DataID::kParticleSizeY, settings.particleSizeY); - SetSetting(precipitation, DataID::kCenterOffsetMin, settings.centerOffsetMin); - SetSetting(precipitation, DataID::kCenterOffsetMax, settings.centerOffsetMax); - SetSetting(precipitation, DataID::kStartRotationRange, settings.startRotationRange); - SetSetting(precipitation, DataID::kNumSubtexturesX, settings.numSubtexturesX); - SetSetting(precipitation, DataID::kNumSubtexturesY, settings.numSubtexturesY); - SetSetting(precipitation, DataID::kParticleType, settings.particleType); - SetSetting(precipitation, DataID::kBoxSize, settings.boxSize); - SetSetting(precipitation, DataID::kParticleDensity, settings.particleDensity); + using DataID = RE::BGSShaderParticleGeometryData::DataID; + + GET_SHADER_PARTICLE_SETTING(gravityVelocity, precipitation, DataID::kGravityVelocity) + gravityVelocity.f = settings.gravityVelocity; + GET_SHADER_PARTICLE_SETTING(rotationVelocity, precipitation, DataID::kRotationVelocity) + rotationVelocity.f = settings.rotationVelocity; + GET_SHADER_PARTICLE_SETTING(particleSizeX, precipitation, DataID::kParticleSizeX) + particleSizeX.f = settings.particleSizeX; + GET_SHADER_PARTICLE_SETTING(particleSizeY, precipitation, DataID::kParticleSizeY) + particleSizeY.f = settings.particleSizeY; + GET_SHADER_PARTICLE_SETTING(centerOffsetMin, precipitation, DataID::kCenterOffsetMin) + centerOffsetMin.f = settings.centerOffsetMin; + GET_SHADER_PARTICLE_SETTING(centerOffsetMax, precipitation, DataID::kCenterOffsetMax) + centerOffsetMax.f = settings.centerOffsetMax; + GET_SHADER_PARTICLE_SETTING(startRotationRange, precipitation, DataID::kStartRotationRange) + startRotationRange.f = settings.startRotationRange; + GET_SHADER_PARTICLE_SETTING(numSubtexturesX, precipitation, DataID::kNumSubtexturesX) + numSubtexturesX.i = settings.numSubtexturesX; + GET_SHADER_PARTICLE_SETTING(numSubtexturesY, precipitation, DataID::kNumSubtexturesY) + numSubtexturesY.i = settings.numSubtexturesY; + GET_SHADER_PARTICLE_SETTING(particleType, precipitation, DataID::kParticleType) + particleType.i = settings.particleType; + GET_SHADER_PARTICLE_SETTING(boxSize, precipitation, DataID::kBoxSize) + boxSize.f = settings.boxSize; + GET_SHADER_PARTICLE_SETTING(particleDensity, precipitation, DataID::kParticleDensity) + particleDensity.f = settings.particleDensity; GET_INSTANCE_MEMBER(particleTexture, precipitation) particleTexture.textureName = settings.particleTexture.c_str(); ApplyLiveParticleTexture(settings.particleTexture); From 0cdfde61ca57d80cb34efdb7c7717897e04dd7cb Mon Sep 17 00:00:00 2001 From: ParticleTroned <248299730+ParticleTroned@users.noreply.github.com> Date: Sun, 26 Apr 2026 18:05:54 +0100 Subject: [PATCH 3/6] refactor(utils): use cached VR flag in game macros --- src/Utils/Game.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utils/Game.h b/src/Utils/Game.h index 7dd7bd924e..690f1d9fd4 100644 --- a/src/Utils/Game.h +++ b/src/Utils/Game.h @@ -18,7 +18,7 @@ namespace globals::game @result The a_value will be set as a variable in the current namespace. (e.g., auto& renderTargets = state->renderTargets;) */ #define GET_INSTANCE_MEMBER(a_value, a_source) \ - auto& a_value = !REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; + auto& a_value = !globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; /** @def GET_INSTANCE_MEMBER_PTR @@ -31,7 +31,7 @@ namespace globals::game @result The a_value will be returned as a refptr. (e.g., &state->renderTargets;) */ #define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ - &(!REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) + &(!globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) /** @def GET_SHADER_PARTICLE_SETTING From 6cf2719e534e940254a9f16256cd416a645720a2 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 26 Apr 2026 16:40:08 -0700 Subject: [PATCH 4/6] refactor(weather-editor): replace particle macro with GetSettingRef Add GetSettingRef(DataID) to BGSShaderParticleGeometryData as a writable companion to GetSettingValue(DataID), mirroring its VR-aware dispatch. This removes the need for the particle-only GET_SHADER_PARTICLE_SETTING macro. Revert GET_INSTANCE_MEMBER/GET_INSTANCE_MEMBER_PTR to REL::Module::IsVR() and drop the globals::game::isVR forward declaration from Game.h. Co-Authored-By: Claude Sonnet 4.6 --- extern/CommonLibSSE-NG | 2 +- src/Utils/Game.h | 24 ++----------- .../Weather/PrecipitationWidget.cpp | 36 +++++++------------ 3 files changed, 15 insertions(+), 47 deletions(-) diff --git a/extern/CommonLibSSE-NG b/extern/CommonLibSSE-NG index 5ec15342d1..42c65076f4 160000 --- a/extern/CommonLibSSE-NG +++ b/extern/CommonLibSSE-NG @@ -1 +1 @@ -Subproject commit 5ec15342d1cb92914fe1b9300944bb371e214697 +Subproject commit 42c65076f49b482f8febf67eb1901337e2f760b6 diff --git a/src/Utils/Game.h b/src/Utils/Game.h index 690f1d9fd4..83f620cdc7 100644 --- a/src/Utils/Game.h +++ b/src/Utils/Game.h @@ -2,11 +2,6 @@ #pragma once -namespace globals::game -{ - extern bool isVR; -} - /** @def GET_INSTANCE_MEMBER @brief Set variable in current namespace based on instance member from GetRuntimeData or GetVRRuntimeData. @@ -18,7 +13,7 @@ namespace globals::game @result The a_value will be set as a variable in the current namespace. (e.g., auto& renderTargets = state->renderTargets;) */ #define GET_INSTANCE_MEMBER(a_value, a_source) \ - auto& a_value = !globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; + auto& a_value = !REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; /** @def GET_INSTANCE_MEMBER_PTR @@ -31,22 +26,7 @@ namespace globals::game @result The a_value will be returned as a refptr. (e.g., &state->renderTargets;) */ #define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ - &(!globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) - -/** - @def GET_SHADER_PARTICLE_SETTING - @brief Set variable in current namespace to a shader particle setting, using the correct flat/VR storage. - - @warning Only for RE::BGSShaderParticleGeometryData. In VR, particle settings are stored in - data[id].value instead of directly in data[id]. - - @param a_value The local variable name to create. - @param a_source The BGSShaderParticleGeometryData instance. - @param a_id The BGSShaderParticleGeometryData::DataID setting. - @result The a_value will be set as a variable in the current namespace. - */ -#define GET_SHADER_PARTICLE_SETTING(a_value, a_source, a_id) \ - auto& a_value = !globals::game::isVR ? (a_source)->GetRuntimeData().data[static_cast(a_id)] : (a_source)->GetVRRuntimeData().data[static_cast(a_id)].value; + &(!REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) namespace Util { diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.cpp b/src/WeatherEditor/Weather/PrecipitationWidget.cpp index 07444bbf6a..2bed7a1c12 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.cpp +++ b/src/WeatherEditor/Weather/PrecipitationWidget.cpp @@ -208,30 +208,18 @@ void PrecipitationWidget::ApplyChanges() using DataID = RE::BGSShaderParticleGeometryData::DataID; - GET_SHADER_PARTICLE_SETTING(gravityVelocity, precipitation, DataID::kGravityVelocity) - gravityVelocity.f = settings.gravityVelocity; - GET_SHADER_PARTICLE_SETTING(rotationVelocity, precipitation, DataID::kRotationVelocity) - rotationVelocity.f = settings.rotationVelocity; - GET_SHADER_PARTICLE_SETTING(particleSizeX, precipitation, DataID::kParticleSizeX) - particleSizeX.f = settings.particleSizeX; - GET_SHADER_PARTICLE_SETTING(particleSizeY, precipitation, DataID::kParticleSizeY) - particleSizeY.f = settings.particleSizeY; - GET_SHADER_PARTICLE_SETTING(centerOffsetMin, precipitation, DataID::kCenterOffsetMin) - centerOffsetMin.f = settings.centerOffsetMin; - GET_SHADER_PARTICLE_SETTING(centerOffsetMax, precipitation, DataID::kCenterOffsetMax) - centerOffsetMax.f = settings.centerOffsetMax; - GET_SHADER_PARTICLE_SETTING(startRotationRange, precipitation, DataID::kStartRotationRange) - startRotationRange.f = settings.startRotationRange; - GET_SHADER_PARTICLE_SETTING(numSubtexturesX, precipitation, DataID::kNumSubtexturesX) - numSubtexturesX.i = settings.numSubtexturesX; - GET_SHADER_PARTICLE_SETTING(numSubtexturesY, precipitation, DataID::kNumSubtexturesY) - numSubtexturesY.i = settings.numSubtexturesY; - GET_SHADER_PARTICLE_SETTING(particleType, precipitation, DataID::kParticleType) - particleType.i = settings.particleType; - GET_SHADER_PARTICLE_SETTING(boxSize, precipitation, DataID::kBoxSize) - boxSize.f = settings.boxSize; - GET_SHADER_PARTICLE_SETTING(particleDensity, precipitation, DataID::kParticleDensity) - particleDensity.f = settings.particleDensity; + precipitation->GetSettingRef(DataID::kGravityVelocity).f = settings.gravityVelocity; + precipitation->GetSettingRef(DataID::kRotationVelocity).f = settings.rotationVelocity; + precipitation->GetSettingRef(DataID::kParticleSizeX).f = settings.particleSizeX; + precipitation->GetSettingRef(DataID::kParticleSizeY).f = settings.particleSizeY; + precipitation->GetSettingRef(DataID::kCenterOffsetMin).f = settings.centerOffsetMin; + precipitation->GetSettingRef(DataID::kCenterOffsetMax).f = settings.centerOffsetMax; + precipitation->GetSettingRef(DataID::kStartRotationRange).f = settings.startRotationRange; + precipitation->GetSettingRef(DataID::kNumSubtexturesX).i = settings.numSubtexturesX; + precipitation->GetSettingRef(DataID::kNumSubtexturesY).i = settings.numSubtexturesY; + precipitation->GetSettingRef(DataID::kParticleType).i = settings.particleType; + precipitation->GetSettingRef(DataID::kBoxSize).f = settings.boxSize; + precipitation->GetSettingRef(DataID::kParticleDensity).f = settings.particleDensity; GET_INSTANCE_MEMBER(particleTexture, precipitation) particleTexture.textureName = settings.particleTexture.c_str(); ApplyLiveParticleTexture(settings.particleTexture); From 9b1d292ad460ebd42b2ad2be7b8d7969bce5edb1 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 26 Apr 2026 16:41:59 -0700 Subject: [PATCH 5/6] Revert "refactor(weather-editor): replace particle macro with GetSettingRef" This reverts commit 6cf2719e534e940254a9f16256cd416a645720a2. --- extern/CommonLibSSE-NG | 2 +- src/Utils/Game.h | 24 +++++++++++-- .../Weather/PrecipitationWidget.cpp | 36 ++++++++++++------- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/extern/CommonLibSSE-NG b/extern/CommonLibSSE-NG index 42c65076f4..5ec15342d1 160000 --- a/extern/CommonLibSSE-NG +++ b/extern/CommonLibSSE-NG @@ -1 +1 @@ -Subproject commit 42c65076f49b482f8febf67eb1901337e2f760b6 +Subproject commit 5ec15342d1cb92914fe1b9300944bb371e214697 diff --git a/src/Utils/Game.h b/src/Utils/Game.h index 83f620cdc7..690f1d9fd4 100644 --- a/src/Utils/Game.h +++ b/src/Utils/Game.h @@ -2,6 +2,11 @@ #pragma once +namespace globals::game +{ + extern bool isVR; +} + /** @def GET_INSTANCE_MEMBER @brief Set variable in current namespace based on instance member from GetRuntimeData or GetVRRuntimeData. @@ -13,7 +18,7 @@ @result The a_value will be set as a variable in the current namespace. (e.g., auto& renderTargets = state->renderTargets;) */ #define GET_INSTANCE_MEMBER(a_value, a_source) \ - auto& a_value = !REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; + auto& a_value = !globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; /** @def GET_INSTANCE_MEMBER_PTR @@ -26,7 +31,22 @@ @result The a_value will be returned as a refptr. (e.g., &state->renderTargets;) */ #define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ - &(!REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) + &(!globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) + +/** + @def GET_SHADER_PARTICLE_SETTING + @brief Set variable in current namespace to a shader particle setting, using the correct flat/VR storage. + + @warning Only for RE::BGSShaderParticleGeometryData. In VR, particle settings are stored in + data[id].value instead of directly in data[id]. + + @param a_value The local variable name to create. + @param a_source The BGSShaderParticleGeometryData instance. + @param a_id The BGSShaderParticleGeometryData::DataID setting. + @result The a_value will be set as a variable in the current namespace. + */ +#define GET_SHADER_PARTICLE_SETTING(a_value, a_source, a_id) \ + auto& a_value = !globals::game::isVR ? (a_source)->GetRuntimeData().data[static_cast(a_id)] : (a_source)->GetVRRuntimeData().data[static_cast(a_id)].value; namespace Util { diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.cpp b/src/WeatherEditor/Weather/PrecipitationWidget.cpp index 2bed7a1c12..07444bbf6a 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.cpp +++ b/src/WeatherEditor/Weather/PrecipitationWidget.cpp @@ -208,18 +208,30 @@ void PrecipitationWidget::ApplyChanges() using DataID = RE::BGSShaderParticleGeometryData::DataID; - precipitation->GetSettingRef(DataID::kGravityVelocity).f = settings.gravityVelocity; - precipitation->GetSettingRef(DataID::kRotationVelocity).f = settings.rotationVelocity; - precipitation->GetSettingRef(DataID::kParticleSizeX).f = settings.particleSizeX; - precipitation->GetSettingRef(DataID::kParticleSizeY).f = settings.particleSizeY; - precipitation->GetSettingRef(DataID::kCenterOffsetMin).f = settings.centerOffsetMin; - precipitation->GetSettingRef(DataID::kCenterOffsetMax).f = settings.centerOffsetMax; - precipitation->GetSettingRef(DataID::kStartRotationRange).f = settings.startRotationRange; - precipitation->GetSettingRef(DataID::kNumSubtexturesX).i = settings.numSubtexturesX; - precipitation->GetSettingRef(DataID::kNumSubtexturesY).i = settings.numSubtexturesY; - precipitation->GetSettingRef(DataID::kParticleType).i = settings.particleType; - precipitation->GetSettingRef(DataID::kBoxSize).f = settings.boxSize; - precipitation->GetSettingRef(DataID::kParticleDensity).f = settings.particleDensity; + GET_SHADER_PARTICLE_SETTING(gravityVelocity, precipitation, DataID::kGravityVelocity) + gravityVelocity.f = settings.gravityVelocity; + GET_SHADER_PARTICLE_SETTING(rotationVelocity, precipitation, DataID::kRotationVelocity) + rotationVelocity.f = settings.rotationVelocity; + GET_SHADER_PARTICLE_SETTING(particleSizeX, precipitation, DataID::kParticleSizeX) + particleSizeX.f = settings.particleSizeX; + GET_SHADER_PARTICLE_SETTING(particleSizeY, precipitation, DataID::kParticleSizeY) + particleSizeY.f = settings.particleSizeY; + GET_SHADER_PARTICLE_SETTING(centerOffsetMin, precipitation, DataID::kCenterOffsetMin) + centerOffsetMin.f = settings.centerOffsetMin; + GET_SHADER_PARTICLE_SETTING(centerOffsetMax, precipitation, DataID::kCenterOffsetMax) + centerOffsetMax.f = settings.centerOffsetMax; + GET_SHADER_PARTICLE_SETTING(startRotationRange, precipitation, DataID::kStartRotationRange) + startRotationRange.f = settings.startRotationRange; + GET_SHADER_PARTICLE_SETTING(numSubtexturesX, precipitation, DataID::kNumSubtexturesX) + numSubtexturesX.i = settings.numSubtexturesX; + GET_SHADER_PARTICLE_SETTING(numSubtexturesY, precipitation, DataID::kNumSubtexturesY) + numSubtexturesY.i = settings.numSubtexturesY; + GET_SHADER_PARTICLE_SETTING(particleType, precipitation, DataID::kParticleType) + particleType.i = settings.particleType; + GET_SHADER_PARTICLE_SETTING(boxSize, precipitation, DataID::kBoxSize) + boxSize.f = settings.boxSize; + GET_SHADER_PARTICLE_SETTING(particleDensity, precipitation, DataID::kParticleDensity) + particleDensity.f = settings.particleDensity; GET_INSTANCE_MEMBER(particleTexture, precipitation) particleTexture.textureName = settings.particleTexture.c_str(); ApplyLiveParticleTexture(settings.particleTexture); From 0103a91e7be5b28bf41110c47a3b4a9255ee44bd Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 26 Apr 2026 18:08:34 -0700 Subject: [PATCH 6/6] refactor(weather-editor): use GetSettingRef for VR-aware writes Replace GET_SHADER_PARTICLE_SETTING macro with GetSettingRef() from CommonLib, which handles the flat/VR layout difference internally. Remove the particle-specific macro and the globals::game::isVR forward declaration. Revert GET_INSTANCE_MEMBER/GET_INSTANCE_MEMBER_PTR to REL::Module::IsVR(). Bump CommonLib to 4.15.0. Co-Authored-By: Claude Sonnet 4.6 --- extern/CommonLibSSE-NG | 2 +- src/Utils/Game.h | 24 ++----------- .../Weather/PrecipitationWidget.cpp | 36 +++++++------------ 3 files changed, 15 insertions(+), 47 deletions(-) diff --git a/extern/CommonLibSSE-NG b/extern/CommonLibSSE-NG index 5ec15342d1..530bbc73e5 160000 --- a/extern/CommonLibSSE-NG +++ b/extern/CommonLibSSE-NG @@ -1 +1 @@ -Subproject commit 5ec15342d1cb92914fe1b9300944bb371e214697 +Subproject commit 530bbc73e514251ce96be899375d59f6ccd9fe9f diff --git a/src/Utils/Game.h b/src/Utils/Game.h index 690f1d9fd4..83f620cdc7 100644 --- a/src/Utils/Game.h +++ b/src/Utils/Game.h @@ -2,11 +2,6 @@ #pragma once -namespace globals::game -{ - extern bool isVR; -} - /** @def GET_INSTANCE_MEMBER @brief Set variable in current namespace based on instance member from GetRuntimeData or GetVRRuntimeData. @@ -18,7 +13,7 @@ namespace globals::game @result The a_value will be set as a variable in the current namespace. (e.g., auto& renderTargets = state->renderTargets;) */ #define GET_INSTANCE_MEMBER(a_value, a_source) \ - auto& a_value = !globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; + auto& a_value = !REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; /** @def GET_INSTANCE_MEMBER_PTR @@ -31,22 +26,7 @@ namespace globals::game @result The a_value will be returned as a refptr. (e.g., &state->renderTargets;) */ #define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ - &(!globals::game::isVR ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) - -/** - @def GET_SHADER_PARTICLE_SETTING - @brief Set variable in current namespace to a shader particle setting, using the correct flat/VR storage. - - @warning Only for RE::BGSShaderParticleGeometryData. In VR, particle settings are stored in - data[id].value instead of directly in data[id]. - - @param a_value The local variable name to create. - @param a_source The BGSShaderParticleGeometryData instance. - @param a_id The BGSShaderParticleGeometryData::DataID setting. - @result The a_value will be set as a variable in the current namespace. - */ -#define GET_SHADER_PARTICLE_SETTING(a_value, a_source, a_id) \ - auto& a_value = !globals::game::isVR ? (a_source)->GetRuntimeData().data[static_cast(a_id)] : (a_source)->GetVRRuntimeData().data[static_cast(a_id)].value; + &(!REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) namespace Util { diff --git a/src/WeatherEditor/Weather/PrecipitationWidget.cpp b/src/WeatherEditor/Weather/PrecipitationWidget.cpp index 07444bbf6a..2bed7a1c12 100644 --- a/src/WeatherEditor/Weather/PrecipitationWidget.cpp +++ b/src/WeatherEditor/Weather/PrecipitationWidget.cpp @@ -208,30 +208,18 @@ void PrecipitationWidget::ApplyChanges() using DataID = RE::BGSShaderParticleGeometryData::DataID; - GET_SHADER_PARTICLE_SETTING(gravityVelocity, precipitation, DataID::kGravityVelocity) - gravityVelocity.f = settings.gravityVelocity; - GET_SHADER_PARTICLE_SETTING(rotationVelocity, precipitation, DataID::kRotationVelocity) - rotationVelocity.f = settings.rotationVelocity; - GET_SHADER_PARTICLE_SETTING(particleSizeX, precipitation, DataID::kParticleSizeX) - particleSizeX.f = settings.particleSizeX; - GET_SHADER_PARTICLE_SETTING(particleSizeY, precipitation, DataID::kParticleSizeY) - particleSizeY.f = settings.particleSizeY; - GET_SHADER_PARTICLE_SETTING(centerOffsetMin, precipitation, DataID::kCenterOffsetMin) - centerOffsetMin.f = settings.centerOffsetMin; - GET_SHADER_PARTICLE_SETTING(centerOffsetMax, precipitation, DataID::kCenterOffsetMax) - centerOffsetMax.f = settings.centerOffsetMax; - GET_SHADER_PARTICLE_SETTING(startRotationRange, precipitation, DataID::kStartRotationRange) - startRotationRange.f = settings.startRotationRange; - GET_SHADER_PARTICLE_SETTING(numSubtexturesX, precipitation, DataID::kNumSubtexturesX) - numSubtexturesX.i = settings.numSubtexturesX; - GET_SHADER_PARTICLE_SETTING(numSubtexturesY, precipitation, DataID::kNumSubtexturesY) - numSubtexturesY.i = settings.numSubtexturesY; - GET_SHADER_PARTICLE_SETTING(particleType, precipitation, DataID::kParticleType) - particleType.i = settings.particleType; - GET_SHADER_PARTICLE_SETTING(boxSize, precipitation, DataID::kBoxSize) - boxSize.f = settings.boxSize; - GET_SHADER_PARTICLE_SETTING(particleDensity, precipitation, DataID::kParticleDensity) - particleDensity.f = settings.particleDensity; + precipitation->GetSettingRef(DataID::kGravityVelocity).f = settings.gravityVelocity; + precipitation->GetSettingRef(DataID::kRotationVelocity).f = settings.rotationVelocity; + precipitation->GetSettingRef(DataID::kParticleSizeX).f = settings.particleSizeX; + precipitation->GetSettingRef(DataID::kParticleSizeY).f = settings.particleSizeY; + precipitation->GetSettingRef(DataID::kCenterOffsetMin).f = settings.centerOffsetMin; + precipitation->GetSettingRef(DataID::kCenterOffsetMax).f = settings.centerOffsetMax; + precipitation->GetSettingRef(DataID::kStartRotationRange).f = settings.startRotationRange; + precipitation->GetSettingRef(DataID::kNumSubtexturesX).i = settings.numSubtexturesX; + precipitation->GetSettingRef(DataID::kNumSubtexturesY).i = settings.numSubtexturesY; + precipitation->GetSettingRef(DataID::kParticleType).i = settings.particleType; + precipitation->GetSettingRef(DataID::kBoxSize).f = settings.boxSize; + precipitation->GetSettingRef(DataID::kParticleDensity).f = settings.particleDensity; GET_INSTANCE_MEMBER(particleTexture, precipitation) particleTexture.textureName = settings.particleTexture.c_str(); ApplyLiveParticleTexture(settings.particleTexture);