Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
cf19f33
redone from scratch for dev
davo0411 Dec 8, 2025
60078df
better custom weather system, md writeups, fixes
davo0411 Dec 8, 2025
69381ea
moar fix
davo0411 Dec 8, 2025
f93c395
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 8, 2025
4b35846
heaps of fixes
davo0411 Dec 8, 2025
68ba2f2
DRY
davo0411 Dec 8, 2025
441f152
Merge branch 'weather-editor-updated' of https://github.com/davo0411/…
davo0411 Dec 8, 2025
014c33a
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 8, 2025
5a092b9
updates
davo0411 Dec 9, 2025
72e9162
Merge branch 'weather-editor-updated' of https://github.com/davo0411/…
davo0411 Dec 9, 2025
33ca26b
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 9, 2025
a823ae1
Undo function, extra safeguards, fixes
davo0411 Dec 10, 2025
d1a62db
Merge branch 'weather-editor-updated' of https://github.com/davo0411/…
davo0411 Dec 10, 2025
cd86446
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 10, 2025
f31eb1d
fixes
davo0411 Dec 10, 2025
6ed12bb
Merge branch 'weather-editor-updated' of https://github.com/davo0411/…
davo0411 Dec 10, 2025
a8a2670
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 10, 2025
d07fb2d
white
davo0411 Dec 10, 2025
a40fec2
Merge branch 'weather-editor-updated' of https://github.com/davo0411/…
davo0411 Dec 10, 2025
fe676f7
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 10, 2025
8d94c87
Update docs/weather-system-docs/WeatherVariableRegistration.md
davo0411 Dec 10, 2025
6589589
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 10, 2025
dfe27a8
fixes for ai rabbit
davo0411 Dec 10, 2025
d530790
fixes
davo0411 Dec 11, 2025
aa8e941
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 11, 2025
aa7d468
Merge branch 'dev' into weather-editor-updated
davo0411 Dec 18, 2025
72e83b8
fix
davo0411 Dec 18, 2025
8978320
ai and dev updates
davo0411 Dec 18, 2025
d71d265
updated to new theme stuff (UNTESTED)
davo0411 Dec 18, 2025
f4a0cc3
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 18, 2025
a977f18
fix
davo0411 Dec 18, 2025
51855e4
Merge branch 'weather-editor-updated' of https://github.com/davo0411/…
davo0411 Dec 18, 2025
c837087
Update UI.cpp
davo0411 Dec 20, 2025
b27f473
refactor, cut line count
davo0411 Dec 20, 2025
176c761
fix: alandtse comments
davo0411 Dec 30, 2025
e95a8a1
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Dec 30, 2025
4a7d38f
fix: widget declaration for build failure
davo0411 Jan 4, 2026
39e164d
Merge branch 'doodlum:dev' into weather-editor-updated
davo0411 Jan 4, 2026
c61179c
Merge branch 'dev' into weather-editor-updated
davo0411 Jan 11, 2026
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
273 changes: 273 additions & 0 deletions docs/weather-system-docs/WeatherVariableRegistration.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just because claude loves making verbose documentation in response to queries doesn't mean it's useful. Please read and make sure it actually is valuable. This is just another maintenance point particularly if the code will be changing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i got it to generate up the how to just to make it easier for other devs to see how to create a weather-specific setting. I can rewrite it as doxygen or something but this should not change much. If i have to change the weather settings at all i will update this in accordance, but the system should work as is.

Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
# Weather Variable Registration System

## Overview

The weather variable registration system provides a centralized way for features to support per-weather settings. Features register their variables once during initialization, and the weather system automatically handles serialization, interpolation, and state management.

## Architecture

### Core Components

**WeatherVariableRegistry.h** contains:

- **`IWeatherVariable`**: Base interface for all weather variables
- **`WeatherVariable<T>`**: Templated variable with type-safe serialization and interpolation
- **`FloatVariable`, `Float3Variable`, `Float4Variable`**: Specialized types with range support
- **`FeatureWeatherRegistry`**: Manages all variables for a single feature
- **`GlobalWeatherRegistry`**: Singleton coordinating all features

### Data Flow

```
Feature Registration → Global Registry → Weather Manager
↓ ↓ ↓
RegisterWeatherVariables Tracks Support Detects Changes
↓ ↓ ↓
Variable Metadata Per-Feature Loads JSON
Registry ↓
Interpolates
Updates Variables
```

## Usage Guide

### Implementing Weather Support in Features

#### Step 1: Define Your Settings Structure

In your feature class, override `RegisterWeatherVariables()`:

```cpp
class MyFeature : public Feature
{
struct Settings
{
float intensity = 1.0f;
float3 color = { 1.0f, 1.0f, 1.0f };
bool enabled = true;
} settings;

void RegisterWeatherVariables() override
{
// ... rest of feature implementation
};
```

#### Step 2: Override RegisterWeatherVariables()

```cpp
void MyFeature::RegisterWeatherVariables() override
{
auto* registry = WeatherVariables::GlobalWeatherRegistry::GetSingleton()
->GetOrCreateFeatureRegistry(GetShortName());

// Register a float with range constraints
registry->RegisterVariable(std::make_shared<WeatherVariables::FloatVariable>(
"Intensity", // JSON key
"Effect Intensity", // Display name
"Controls the strength", // Tooltip
&settings.intensity, // Pointer to variable
1.0f, // Default value
0.0f, 2.0f // Min/max range
));

// Register a float3 (color or vector)
registry->RegisterVariable(std::make_shared<WeatherVariables::Float3Variable>(
"Color",
"Effect Color",
"RGB color values",
&settings.color,
float3{ 1.0f, 1.0f, 1.0f }
));

// Register bool with custom interpolation
registry->RegisterVariable(std::make_shared<WeatherVariables::WeatherVariable<bool>>(
"Enabled",
"Enable Effect",
"Toggle the effect",
&settings.enabled,
true,
[](const bool& from, const bool& to, float factor) {
return factor > 0.5f ? to : from; // Switch at midpoint
}
));
}
```

#### Step 3: Implementation Complete

The system now automatically:

- Saves/loads weather-specific settings to JSON
- Interpolates variables during weather transitions
- Appears in the weather editor UI
- Handles default values and missing dataanced Usage

### Custom Variable Types

Create custom weather variable types for complex data:

```cpp
class CustomTypeVariable : public WeatherVariables::WeatherVariable<MyCustomType>
{
public:
CustomTypeVariable(const std::string& name, MyCustomType* valuePtr, MyCustomType defaultValue) :
WeatherVariable<MyCustomType>(name, name, "", valuePtr, defaultValue,
[](const MyCustomType& from, const MyCustomType& to, float factor) {
// Custom interpolation logic
MyCustomType result;
result.field1 = std::lerp(from.field1, to.field1, factor);
result.field2 = from.field2; // No lerp for this field
return result;
})
{
}
};
```

## System Integration

### How Weather Manager Uses the Registry

The weather manager detects and updates features automatically:

```cpp
// Detection
if (globalRegistry->HasWeatherSupport(featureName)) {
// Feature has registered variables
}

// Loading
json currWeatherSettings, nextWeatherSettings;
LoadSettingsFromWeather(weather, featureName, currWeatherSettings);
LoadSettingsFromWeather(lastWeather, featureName, nextWeatherSettings);

// Interpolation during weather transitions
globalRegistry->UpdateFeatureFromWeathers(
featureName,
currWeatherSettings,
nextWeatherSettings,
lerpFactor // 0.0 to 1.0
);
```

### File Structure

Weather-specific settings are stored in:

```
Data/SKSE/Plugins/CommunityShaders/Weathers/
WeatherEditorID_FormID.json
```

Each file contains settings for all features:

```json
{
"FeatureName1": {
"Intensity": 1.5,
"Color": [1.0, 0.8, 0.6]
},
"FeatureName2": {
"Enabled": true
}
}
```

## Advanced Patterns

### Conditional Registration

Register variables based on feature state:

```cpp
void RegisterWeatherVariables() override
{
auto* registry = WeatherVariables::GlobalWeatherRegistry::GetSingleton()
->GetOrCreateFeatureRegistry(GetShortName());

// Core variables
registry->RegisterVariable(std::make_shared<FloatVariable>(
"intensity", "Intensity", "Main intensity",
&settings.intensity, 1.0f, 0.0f, 2.0f
));

// Advanced variables (conditional)
if (settings.enableAdvancedMode) {
registry->RegisterVariable(std::make_shared<Float3Variable>(
"advancedColor", "Advanced Color", "Color tuning",
&settings.advancedColor, float3{ 1.0f, 1.0f, 1.0f }
));
}
}
```

### Runtime Queries

Access registered variables for debugging or dynamic UI:

```cpp
auto* registry = WeatherVariables::GlobalWeatherRegistry::GetSingleton()
->GetFeatureRegistry("MyFeature");

if (registry) {
for (const auto& var : registry->GetVariables()) {
logger::info("{}: {}", var->GetDisplayName(), var->GetName());
}
}
```

## Implementation Notes

### Memory Management

- Registry uses `std::shared_ptr` for variable lifetime
- Variables store raw pointers to feature data (safe as features outlive registry)
- No copying - variables are modified in-place

### Thread Safety

Current implementation is single-threaded (main game thread). Variables are accessed and modified on the same thread that updates weather.

### JSON Serialization

Uses nlohmann::json for type conversion. Built-in support for:

- Primitive types (float, int, bool)
- float2, float3, float4 (see `Utils/Serialize.h`)
- Custom types require NLOHMANN*DEFINE_TYPE*\* macros

### Error Handling

- Missing JSON keys use default values
- Type mismatches caught by json exceptions
- Invalid weather files are logged but do not crash the system

## Architecture Benefits

### Separation of Concerns

- **Features**: Focus on rendering logic and effect implementation
- **Weather System**: Handles persistence, interpolation, and state management
- **UI Layer**: Automatically discovers registered variables for editor display

### Future Enhancements

The centralized registry enables:

- Weather template inheritance (parent weather settings override children)
- Automatic UI generation for weather variable editing
- Bulk operations (reset all weathers to defaults, copy settings, etc.)
- Variable validation and constraints
- Change tracking and undo/redo support

### Performance

- Variables are directly modified in place (no copying)
- Interpolation only happens during weather transitions
- Registration is one-time during feature initialization

```

```
115 changes: 115 additions & 0 deletions docs/weather-system-docs/examples/ExampleWeatherFeature.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Example Feature: Demonstrates the Weather Variable Registration Pattern
//
// This is a minimal example showing how features can support per-weather settings.
// Simply register your variables once during RegisterWeatherVariables() and the weather system handles the rest.

#include "ExampleWeatherFeature.h"
#include "WeatherVariableRegistry.h"

void ExampleWeatherFeature::RegisterWeatherVariables()
{
// Get or create the registry for this feature
auto* registry = WeatherVariables::GlobalWeatherRegistry::GetSingleton()
->GetOrCreateFeatureRegistry(GetShortName());

// Register a simple float variable
registry->RegisterVariable(std::make_shared<WeatherVariables::FloatVariable>(
"Intensity", // JSON key name
"Effect Intensity", // Display name for UI
"Controls how strong the effect is", // Tooltip/description
&settings.intensity, // Pointer to the actual variable
1.0f, // Default value
0.0f, 2.0f // Min/max range (optional)
));

// Register a float3 color variable
registry->RegisterVariable(std::make_shared<WeatherVariables::Float3Variable>(
"Color",
"Effect Color",
"RGB color values for the effect",
&settings.color,
float3{ 1.0f, 0.5f, 0.2f } // Default orange color
));

// Register a float4 variable (could be RGBA color or other 4-component data)
registry->RegisterVariable(std::make_shared<WeatherVariables::Float4Variable>(
"TintColor",
"Tint Color",
"RGBA tint color with alpha",
&settings.tintColor,
float4{ 1.0f, 1.0f, 1.0f, 1.0f } // Default white with full opacity
));

// Register a custom type with manual lerp function
// This example shows a bool that transitions at the halfway point
registry->RegisterVariable(std::make_shared<WeatherVariables::WeatherVariable<bool>>(
"Enabled",
"Enable Effect",
"Toggle the effect on/off",
&settings.enabled,
true, // Default enabled
[](const bool& from, const bool& to, float factor) {
// Custom lerp: switch to target value when more than halfway through transition
return factor > 0.5f ? to : from;
}));

// That's it! No need to override:
// - SupportsWeather() - automatically detected via HasWeatherSupport()
// - UpdateSettingsFromWeathers() - handled by registry
// - SaveSettings() / LoadSettings() for weather data - automatic
}

void ExampleWeatherFeature::DrawSettings()
{
ImGui::TextWrapped("This is an example feature demonstrating the weather variable registration system.");
ImGui::Spacing();

// Draw regular feature settings UI
if (ImGui::SliderFloat("Intensity", &settings.intensity, 0.0f, 2.0f)) {
// Settings changed - if you want to save immediately, call:
// State::GetSingleton()->Save();
}

if (ImGui::ColorEdit3("Color", &settings.color.x)) {
// Color changed
}

if (ImGui::ColorEdit4("Tint Color", &settings.tintColor.x)) {
// Tint changed
}

if (ImGui::Checkbox("Enabled", &settings.enabled)) {
// Enabled state changed
}

ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();

ImGui::TextWrapped(
"Note: When weather-specific settings exist for the current weather, "
"they will automatically override these base settings. The weather system "
"handles all interpolation during weather transitions.");
}

void ExampleWeatherFeature::LoadSettings(json& o_json)
{
// Load base settings (non-weather-specific)
if (o_json.contains("Intensity"))
settings.intensity = o_json["Intensity"];
if (o_json.contains("Color"))
settings.color = o_json["Color"];
if (o_json.contains("TintColor"))
settings.tintColor = o_json["TintColor"];
if (o_json.contains("Enabled"))
settings.enabled = o_json["Enabled"];
}

void ExampleWeatherFeature::SaveSettings(json& o_json)
{
// Save base settings (non-weather-specific)
o_json["Intensity"] = settings.intensity;
o_json["Color"] = settings.color;
o_json["TintColor"] = settings.tintColor;
o_json["Enabled"] = settings.enabled;
}
Loading
Loading