diff --git a/docs/weather-system-docs/WeatherVariableRegistration.md b/docs/weather-system-docs/WeatherVariableRegistration.md index 04671712d6..4e39e25fdd 100644 --- a/docs/weather-system-docs/WeatherVariableRegistration.md +++ b/docs/weather-system-docs/WeatherVariableRegistration.md @@ -126,6 +126,91 @@ public: }; ``` +### Array and Vector Types + +The weather system supports `std::array` and `std::vector` for complex data structures: + +#### Using ArrayVariable for Fixed-Size Arrays + +```cpp +void RegisterWeatherVariables() override +{ + auto* registry = WeatherVariables::GlobalWeatherRegistry::GetSingleton() + ->GetOrCreateFeatureRegistry(GetShortName()); + + // Array of primitive types (floats) + registry->RegisterVariable(std::make_shared>( + "weights", + "Weight Values", + "Array of weight coefficients", + &settings.weights, + std::array{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f } + // elementLerpFunc optional for float types - uses default std::lerp + )); + + // Array of complex types with custom interpolation + registry->RegisterVariable(std::make_shared>( + "profiles", + "Color Profiles", + "Array of color profile configurations", + &settings.profiles, + defaultProfiles, + [](const ColorProfile& from, const ColorProfile& to, float factor) { + ColorProfile result; + result.hue = std::lerp(from.hue, to.hue, factor); + result.saturation = std::lerp(from.saturation, to.saturation, factor); + result.brightness = std::lerp(from.brightness, to.brightness, factor); + // interpolate other fields... + return result; + } + )); +} +``` + +#### Using VectorVariable for Dynamic Arrays + +```cpp +void RegisterWeatherVariables() override +{ + auto* registry = WeatherVariables::GlobalWeatherRegistry::GetSingleton() + ->GetOrCreateFeatureRegistry(GetShortName()); + + // Vector of floats with default interpolation + registry->RegisterVariable(std::make_shared>( + "coefficients", + "Dynamic Coefficients", + "Variable-length coefficient array", + &settings.coefficients, + std::vector{ 1.0f, 0.5f, 0.25f } + )); + + // Vector of complex types with custom interpolation + registry->RegisterVariable(std::make_shared>( + "lights", + "Light Configurations", + "Dynamic array of light settings", + &settings.lights, + defaultLights, + [](const LightConfig& from, const LightConfig& to, float factor) { + LightConfig result; + result.intensity = std::lerp(from.intensity, to.intensity, factor); + result.color = float3{ + std::lerp(from.color.x, to.color.x, factor), + std::lerp(from.color.y, to.color.y, factor), + std::lerp(from.color.z, to.color.z, factor) + }; + return result; + } + )); +} +``` + +**Notes on Vector Interpolation:** + +- When vectors have different sizes, interpolation uses the maximum size +- Missing elements from shorter vectors are default-initialized (T{}) +- This allows smooth transitions when adding/removing elements between weathers + ## System Integration ### How Weather Manager Uses the Registry @@ -236,7 +321,25 @@ 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 +- **std::array** - Fixed-size arrays serialized as JSON arrays +- **std::vector** - Dynamic arrays serialized as JSON arrays +- Custom types require NLOHMANN*DEFINE_TYPE*\* macros or custom serialization functions + +Example JSON with array/vector types: + +```json +{ + "MyFeature": { + "intensity": 1.5, + "weights": [1.0, 0.8, 0.6, 0.4, 0.2, 0.1, 0.05, 0.025], + "coefficients": [1.0, 0.5, 0.25], + "profiles": [ + { "hue": 0.5, "saturation": 1.0, "brightness": 1.0 }, + { "hue": 0.7, "saturation": 0.8, "brightness": 0.9 } + ] + } +} +``` ### Error Handling diff --git a/src/WeatherVariableRegistry.h b/src/WeatherVariableRegistry.h index 03a6260039..0f902fff45 100644 --- a/src/WeatherVariableRegistry.h +++ b/src/WeatherVariableRegistry.h @@ -10,6 +10,23 @@ using json = nlohmann::json; // Weather variable system - features register variables which are automatically handled by weather system +// Supports primitive types (float, float3, float4), std::array, and std::vector +// +// Usage examples: +// - FloatVariable: Single float values with min/max bounds +// - Float3Variable/Float4Variable: Vector types (colors, positions, etc.) +// - ArrayVariable: Fixed-size arrays (e.g., std::array) +// - VectorVariable: Dynamic arrays (e.g., std::vector) +// +// Custom element types require providing an element lerp function: +// auto arrayVar = std::make_shared>( +// "profiles", "Color Profiles", "Array of color profiles", +// &settings.profiles, defaultProfiles, +// [](const ColorProfile& from, const ColorProfile& to, float factor) { +// ColorProfile result; +// // Implement per-field interpolation +// return result; +// }); namespace WeatherVariables { // Base class for weather-controllable variables @@ -169,6 +186,73 @@ namespace WeatherVariables } }; + // Specialized weather variable for std::array types + template + class ArrayVariable : public WeatherVariable> + { + public: + ArrayVariable(const std::string& name, const std::string& displayName, const std::string& tooltip, + std::array* valuePtr, std::array defaultValue, + std::function elementLerpFunc) : + WeatherVariable>(name, displayName, tooltip, valuePtr, defaultValue, + [elementLerpFunc](const std::array& from, const std::array& to, float factor) { + std::array result; + for (size_t i = 0; i < N; ++i) { + result[i] = elementLerpFunc(from[i], to[i], factor); + } + return result; + }) + { + } + + // Helper constructor for float element types with default lerp + template >> + ArrayVariable(const std::string& name, const std::string& displayName, const std::string& tooltip, + std::array* valuePtr, std::array defaultValue) : + ArrayVariable(name, displayName, tooltip, valuePtr, defaultValue, + [](const T& from, const T& to, float factor) { + return static_cast(std::lerp(from, to, factor)); + }) + { + } + }; + + // Specialized weather variable for std::vector types + template + class VectorVariable : public WeatherVariable> + { + public: + VectorVariable(const std::string& name, const std::string& displayName, const std::string& tooltip, + std::vector* valuePtr, std::vector defaultValue, + std::function elementLerpFunc) : + WeatherVariable>(name, displayName, tooltip, valuePtr, defaultValue, + [elementLerpFunc](const std::vector& from, const std::vector& to, float factor) { + size_t maxSize = std::max(from.size(), to.size()); + std::vector result; + result.reserve(maxSize); + + for (size_t i = 0; i < maxSize; ++i) { + T fromVal = (i < from.size()) ? from[i] : T{}; + T toVal = (i < to.size()) ? to[i] : T{}; + result.push_back(elementLerpFunc(fromVal, toVal, factor)); + } + return result; + }) + { + } + + // Helper constructor for float element types with default lerp + template >> + VectorVariable(const std::string& name, const std::string& displayName, const std::string& tooltip, + std::vector* valuePtr, std::vector defaultValue) : + VectorVariable(name, displayName, tooltip, valuePtr, defaultValue, + [](const T& from, const T& to, float factor) { + return static_cast(std::lerp(from, to, factor)); + }) + { + } + }; + // Registry for a feature's weather variables class FeatureWeatherRegistry {