#pragma once #include #include #include #include #include #include #include "DynamicValue.h" #include "Effect.h" #include "Material.h" #include "Model.h" #include "Types.h" #include "UserSetting.h" #include "WallpaperEngine/Data/Utils/TypeCaster.h" #include namespace WallpaperEngine::Data::Model { using namespace WallpaperEngine::Data::Utils; struct ObjectData { int id; std::string name; std::vector dependencies; std::optional parent; /** Name of a named attachment point on the parent's puppet rig to follow, if any */ std::optional attachment; /** Explicit paint-order override (scene.json's "sortorder") - lower draws first (further back). * Falls back to this object's array position when absent. */ std::optional sortOrder; UserSettingUniquePtr origin; /** Transform fields for generic scene/group objects. Typed objects keep their own transform fields. */ UserSettingUniquePtr groupScale; UserSettingUniquePtr groupAngles; UserSettingUniquePtr groupVisible; UserSettingUniquePtr groupParallaxDepth; }; class Object : public TypeCaster, public ObjectData { public: explicit Object (ObjectData data) noexcept : TypeCaster (), ObjectData (std::move (data)) { }; ~Object () override = default; }; struct ImageEffectPassOverride { int id; ComboMap combos; ShaderConstantMap constants; TextureMap textures; TextureMap usertextures; std::optional shaderOverride; // Overrides MaterialPass::shader when set }; struct ImageEffect { /** Not sure what it's used for */ int id; /** Effect's name for the editor */ std::string name; UserSettingUniquePtr visible; std::vector passOverrides; EffectUniquePtr effect; }; struct ImageAnimationLayer { int id; /** Matches the name of a baked animation clip stored in the puppet .mdl's MDLA section */ std::string name; UserSettingUniquePtr rate; UserSettingUniquePtr visible; UserSettingUniquePtr blend; UserSettingUniquePtr animation; }; enum ImageAlignment { ImageAlignment_Center = 0, ImageAlignment_Top = 1, ImageAlignment_Bottom = 2, ImageAlignment_Left = 4, ImageAlignment_Right = 8, }; struct ImageData { UserSettingUniquePtr scale; UserSettingUniquePtr angles; UserSettingUniquePtr visible; UserSettingUniquePtr alpha; UserSettingUniquePtr color; uint32_t alignment; /** In pixels */ glm::vec2 size; UserSettingUniquePtr parallaxDepth; UserSettingUniquePtr colorBlendMode; UserSettingUniquePtr brightness; /** Forces UV clamping on this object's composite buffers regardless of the base texture's own flags */ bool clampUVs; ModelUniquePtr model; /** Applied after the material is rendered */ std::vector effects; std::vector animationLayers; }; class Image : public Object, public ImageData { public: explicit Image (ObjectData data, ImageData imageData) noexcept : Object (std::move (data)), ImageData (std::move (imageData)) { }; ~Image () override = default; }; enum SoundPlaybackMode { PlaybackMode_Single = 0, PlaybackMode_Loop = 1, PlaybackMode_Random = 2 }; struct SoundData { SoundPlaybackMode playbackmode; std::vector sounds; /** Per-object volume (0-1), independent of the global volume - lets a wallpaper with several * Sound objects (e.g. alternate music tracks) mute all but one via --set-property */ UserSettingUniquePtr volume; /** Sound stays muted until a script calls play() on its layer */ std::optional startsilent; }; class Sound : public Object, public SoundData { public: explicit Sound (ObjectData data, SoundData soundData) noexcept : Object (std::move (data)), SoundData (std::move (soundData)) { }; ~Sound () override = default; }; /** * Particle control points for forces and positions */ struct ParticleControlPoint { int id; uint32_t flags; glm::vec3 offset; bool lockToPointer; }; /** * Particle emitter configuration */ struct ParticleEmitter { int id; std::string name; glm::vec3 directions; glm::vec3 distanceMin; glm::vec3 distanceMax; glm::vec3 origin; glm::ivec3 sign; uint32_t instantaneous; float speedMin; float speedMax; float rate; int controlPoint; uint32_t flags; float cone; float delay; float duration; glm::vec2 audioProcessingBounds; float audioProcessingExponent; int audioProcessingFrequencyStart; int audioProcessingFrequencyEnd; int audioProcessingMode; float minPeriodicDelay; float maxPeriodicDelay; float minPeriodicDuration; float maxPeriodicDuration; }; /** * Particle initializer base and implementations */ class ParticleInitializerBase : public TypeCaster { public: virtual ~ParticleInitializerBase () = default; }; class ColorRandomInitializer : public ParticleInitializerBase { public: ColorRandomInitializer (UserSettingUniquePtr min, UserSettingUniquePtr max) : min (std::move (min)), max (std::move (max)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; }; class SizeRandomInitializer : public ParticleInitializerBase { public: SizeRandomInitializer (UserSettingUniquePtr min, UserSettingUniquePtr max, UserSettingUniquePtr exponent) : min (std::move (min)), max (std::move (max)), exponent (std::move (exponent)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; UserSettingUniquePtr exponent; }; class AlphaRandomInitializer : public ParticleInitializerBase { public: AlphaRandomInitializer (UserSettingUniquePtr min, UserSettingUniquePtr max) : min (std::move (min)), max (std::move (max)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; }; class LifetimeRandomInitializer : public ParticleInitializerBase { public: LifetimeRandomInitializer (UserSettingUniquePtr min, UserSettingUniquePtr max) : min (std::move (min)), max (std::move (max)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; }; class VelocityRandomInitializer : public ParticleInitializerBase { public: VelocityRandomInitializer (UserSettingUniquePtr min, UserSettingUniquePtr max) : min (std::move (min)), max (std::move (max)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; }; class RotationRandomInitializer : public ParticleInitializerBase { public: RotationRandomInitializer (UserSettingUniquePtr min, UserSettingUniquePtr max) : min (std::move (min)), max (std::move (max)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; }; class AngularVelocityRandomInitializer : public ParticleInitializerBase { public: AngularVelocityRandomInitializer ( UserSettingUniquePtr min, UserSettingUniquePtr max, UserSettingUniquePtr exponent ) : min (std::move (min)), max (std::move (max)), exponent (std::move (exponent)) { } UserSettingUniquePtr min; UserSettingUniquePtr max; UserSettingUniquePtr exponent; }; class TurbulentVelocityRandomInitializer : public ParticleInitializerBase { public: TurbulentVelocityRandomInitializer ( UserSettingUniquePtr speedMin, UserSettingUniquePtr speedMax, UserSettingUniquePtr scale, UserSettingUniquePtr offset, UserSettingUniquePtr forward, UserSettingUniquePtr timeScale, UserSettingUniquePtr phaseMin, UserSettingUniquePtr phaseMax, UserSettingUniquePtr right, UserSettingUniquePtr audioProcessingMode, UserSettingUniquePtr audioProcessingBounds, UserSettingUniquePtr audioProcessingExponent, UserSettingUniquePtr audioProcessingFrequencyStart, UserSettingUniquePtr audioProcessingFrequencyEnd ) : speedMin (std::move (speedMin)), speedMax (std::move (speedMax)), scale (std::move (scale)), offset (std::move (offset)), forward (std::move (forward)), timeScale (std::move (timeScale)), phaseMin (std::move (phaseMin)), phaseMax (std::move (phaseMax)), right (std::move (right)), audioProcessingMode (std::move (audioProcessingMode)), audioProcessingBounds (std::move (audioProcessingBounds)), audioProcessingExponent (std::move (audioProcessingExponent)), audioProcessingFrequencyStart (std::move (audioProcessingFrequencyStart)), audioProcessingFrequencyEnd (std::move (audioProcessingFrequencyEnd)) { } UserSettingUniquePtr speedMin; UserSettingUniquePtr speedMax; UserSettingUniquePtr scale; UserSettingUniquePtr offset; UserSettingUniquePtr forward; UserSettingUniquePtr timeScale; UserSettingUniquePtr phaseMin; UserSettingUniquePtr phaseMax; UserSettingUniquePtr right; UserSettingUniquePtr audioProcessingMode; UserSettingUniquePtr audioProcessingBounds; UserSettingUniquePtr audioProcessingExponent; UserSettingUniquePtr audioProcessingFrequencyStart; UserSettingUniquePtr audioProcessingFrequencyEnd; }; class MapSequenceAroundControlPointInitializer : public ParticleInitializerBase { public: MapSequenceAroundControlPointInitializer ( UserSettingUniquePtr controlPoint, UserSettingUniquePtr count, UserSettingUniquePtr speedMin, UserSettingUniquePtr speedMax ) : controlPoint (std::move (controlPoint)), count (std::move (count)), speedMin (std::move (speedMin)), speedMax (std::move (speedMax)) { } UserSettingUniquePtr controlPoint; UserSettingUniquePtr count; UserSettingUniquePtr speedMin; UserSettingUniquePtr speedMax; }; using ParticleInitializerUniquePtr = std::unique_ptr; /** * Particle operator base and implementations */ class ParticleOperatorBase : public TypeCaster { public: virtual ~ParticleOperatorBase () = default; }; class MovementOperator : public ParticleOperatorBase { public: MovementOperator (UserSettingUniquePtr drag, UserSettingUniquePtr gravity) : drag (std::move (drag)), gravity (std::move (gravity)) { } UserSettingUniquePtr drag; UserSettingUniquePtr gravity; }; class AngularMovementOperator : public ParticleOperatorBase { public: AngularMovementOperator (UserSettingUniquePtr drag, UserSettingUniquePtr force) : drag (std::move (drag)), force (std::move (force)) { } UserSettingUniquePtr drag; UserSettingUniquePtr force; }; class AlphaFadeOperator : public ParticleOperatorBase { public: AlphaFadeOperator (UserSettingUniquePtr fadeInTime, UserSettingUniquePtr fadeOutTime) : fadeInTime (std::move (fadeInTime)), fadeOutTime (std::move (fadeOutTime)) { } UserSettingUniquePtr fadeInTime; UserSettingUniquePtr fadeOutTime; }; class SizeChangeOperator : public ParticleOperatorBase { public: SizeChangeOperator ( UserSettingUniquePtr startTime, UserSettingUniquePtr endTime, UserSettingUniquePtr startValue, UserSettingUniquePtr endValue ) : startTime (std::move (startTime)), endTime (std::move (endTime)), startValue (std::move (startValue)), endValue (std::move (endValue)) { } UserSettingUniquePtr startTime; UserSettingUniquePtr endTime; UserSettingUniquePtr startValue; UserSettingUniquePtr endValue; }; class AlphaChangeOperator : public ParticleOperatorBase { public: AlphaChangeOperator ( UserSettingUniquePtr startTime, UserSettingUniquePtr endTime, UserSettingUniquePtr startValue, UserSettingUniquePtr endValue ) : startTime (std::move (startTime)), endTime (std::move (endTime)), startValue (std::move (startValue)), endValue (std::move (endValue)) { } UserSettingUniquePtr startTime; UserSettingUniquePtr endTime; UserSettingUniquePtr startValue; UserSettingUniquePtr endValue; }; class ColorChangeOperator : public ParticleOperatorBase { public: ColorChangeOperator ( UserSettingUniquePtr startTime, UserSettingUniquePtr endTime, UserSettingUniquePtr startValue, UserSettingUniquePtr endValue ) : startTime (std::move (startTime)), endTime (std::move (endTime)), startValue (std::move (startValue)), endValue (std::move (endValue)) { } UserSettingUniquePtr startTime; UserSettingUniquePtr endTime; UserSettingUniquePtr startValue; UserSettingUniquePtr endValue; }; class TurbulenceOperator : public ParticleOperatorBase { public: TurbulenceOperator ( UserSettingUniquePtr scale, UserSettingUniquePtr speedMin, UserSettingUniquePtr speedMax, UserSettingUniquePtr timeScale, UserSettingUniquePtr mask, UserSettingUniquePtr phaseMin, UserSettingUniquePtr phaseMax, UserSettingUniquePtr audioProcessingMode, UserSettingUniquePtr audioProcessingBounds, UserSettingUniquePtr audioProcessingExponent, UserSettingUniquePtr audioProcessingFrequencyStart, UserSettingUniquePtr audioProcessingFrequencyEnd ) : scale (std::move (scale)), speedMin (std::move (speedMin)), speedMax (std::move (speedMax)), timeScale (std::move (timeScale)), mask (std::move (mask)), phaseMin (std::move (phaseMin)), phaseMax (std::move (phaseMax)), audioProcessingMode (std::move (audioProcessingMode)), audioProcessingBounds (std::move (audioProcessingBounds)), audioProcessingExponent (std::move (audioProcessingExponent)), audioProcessingFrequencyStart (std::move (audioProcessingFrequencyStart)), audioProcessingFrequencyEnd (std::move (audioProcessingFrequencyEnd)) { } UserSettingUniquePtr scale; UserSettingUniquePtr speedMin; UserSettingUniquePtr speedMax; UserSettingUniquePtr timeScale; UserSettingUniquePtr mask; UserSettingUniquePtr phaseMin; UserSettingUniquePtr phaseMax; UserSettingUniquePtr audioProcessingMode; UserSettingUniquePtr audioProcessingBounds; UserSettingUniquePtr audioProcessingExponent; UserSettingUniquePtr audioProcessingFrequencyStart; UserSettingUniquePtr audioProcessingFrequencyEnd; }; class VortexOperator : public ParticleOperatorBase { public: VortexOperator ( int controlPoint, int flags, UserSettingUniquePtr axis, UserSettingUniquePtr offset, UserSettingUniquePtr distanceInner, UserSettingUniquePtr distanceOuter, UserSettingUniquePtr speedInner, UserSettingUniquePtr speedOuter, UserSettingUniquePtr centerForce, UserSettingUniquePtr ringRadius, UserSettingUniquePtr ringWidth, UserSettingUniquePtr ringPullDistance, UserSettingUniquePtr ringPullForce, UserSettingUniquePtr audioProcessingMode, UserSettingUniquePtr audioProcessingBounds, UserSettingUniquePtr audioProcessingExponent, UserSettingUniquePtr audioProcessingFrequencyStart, UserSettingUniquePtr audioProcessingFrequencyEnd ) : controlPoint (controlPoint), flags (flags), axis (std::move (axis)), offset (std::move (offset)), distanceInner (std::move (distanceInner)), distanceOuter (std::move (distanceOuter)), speedInner (std::move (speedInner)), speedOuter (std::move (speedOuter)), centerForce (std::move (centerForce)), ringRadius (std::move (ringRadius)), ringWidth (std::move (ringWidth)), ringPullDistance (std::move (ringPullDistance)), ringPullForce (std::move (ringPullForce)), audioProcessingMode (std::move (audioProcessingMode)), audioProcessingBounds (std::move (audioProcessingBounds)), audioProcessingExponent (std::move (audioProcessingExponent)), audioProcessingFrequencyStart (std::move (audioProcessingFrequencyStart)), audioProcessingFrequencyEnd (std::move (audioProcessingFrequencyEnd)) { } int controlPoint; int flags; // 1 = infinite axis, 2 = maintain distance to center, 4 = ring shape UserSettingUniquePtr axis; UserSettingUniquePtr offset; UserSettingUniquePtr distanceInner; // Standard vortex inner radius UserSettingUniquePtr distanceOuter; // Standard vortex outer radius UserSettingUniquePtr speedInner; UserSettingUniquePtr speedOuter; UserSettingUniquePtr centerForce; // Strength to pull particles toward center UserSettingUniquePtr ringRadius; // Ring mode: radius of the ring UserSettingUniquePtr ringWidth; // Ring mode: width of the ring UserSettingUniquePtr ringPullDistance; // Ring mode: distance at which ring attracts particles UserSettingUniquePtr ringPullForce; // Ring mode: strength of ring attraction UserSettingUniquePtr audioProcessingMode; UserSettingUniquePtr audioProcessingBounds; UserSettingUniquePtr audioProcessingExponent; UserSettingUniquePtr audioProcessingFrequencyStart; UserSettingUniquePtr audioProcessingFrequencyEnd; }; class ControlPointAttractOperator : public ParticleOperatorBase { public: ControlPointAttractOperator ( int controlPoint, UserSettingUniquePtr origin, UserSettingUniquePtr scale, UserSettingUniquePtr threshold ) : controlPoint (controlPoint), origin (std::move (origin)), scale (std::move (scale)), threshold (std::move (threshold)) { } int controlPoint; UserSettingUniquePtr origin; UserSettingUniquePtr scale; UserSettingUniquePtr threshold; }; class OscillateAlphaOperator : public ParticleOperatorBase { public: OscillateAlphaOperator ( UserSettingUniquePtr frequencyMin, UserSettingUniquePtr frequencyMax, UserSettingUniquePtr scaleMin, UserSettingUniquePtr scaleMax, UserSettingUniquePtr phaseMin, UserSettingUniquePtr phaseMax ) : frequencyMin (std::move (frequencyMin)), frequencyMax (std::move (frequencyMax)), scaleMin (std::move (scaleMin)), scaleMax (std::move (scaleMax)), phaseMin (std::move (phaseMin)), phaseMax (std::move (phaseMax)) { } UserSettingUniquePtr frequencyMin; UserSettingUniquePtr frequencyMax; UserSettingUniquePtr scaleMin; UserSettingUniquePtr scaleMax; UserSettingUniquePtr phaseMin; UserSettingUniquePtr phaseMax; }; class OscillateSizeOperator : public ParticleOperatorBase { public: OscillateSizeOperator ( UserSettingUniquePtr frequencyMin, UserSettingUniquePtr frequencyMax, UserSettingUniquePtr scaleMin, UserSettingUniquePtr scaleMax, UserSettingUniquePtr phaseMin, UserSettingUniquePtr phaseMax ) : frequencyMin (std::move (frequencyMin)), frequencyMax (std::move (frequencyMax)), scaleMin (std::move (scaleMin)), scaleMax (std::move (scaleMax)), phaseMin (std::move (phaseMin)), phaseMax (std::move (phaseMax)) { } UserSettingUniquePtr frequencyMin; UserSettingUniquePtr frequencyMax; UserSettingUniquePtr scaleMin; UserSettingUniquePtr scaleMax; UserSettingUniquePtr phaseMin; UserSettingUniquePtr phaseMax; }; class OscillatePositionOperator : public ParticleOperatorBase { public: OscillatePositionOperator ( UserSettingUniquePtr frequencyMin, UserSettingUniquePtr frequencyMax, UserSettingUniquePtr scaleMin, UserSettingUniquePtr scaleMax, UserSettingUniquePtr phaseMin, UserSettingUniquePtr phaseMax, UserSettingUniquePtr mask ) : frequencyMin (std::move (frequencyMin)), frequencyMax (std::move (frequencyMax)), scaleMin (std::move (scaleMin)), scaleMax (std::move (scaleMax)), phaseMin (std::move (phaseMin)), phaseMax (std::move (phaseMax)), mask (std::move (mask)) { } UserSettingUniquePtr frequencyMin; UserSettingUniquePtr frequencyMax; UserSettingUniquePtr scaleMin; UserSettingUniquePtr scaleMax; UserSettingUniquePtr phaseMin; UserSettingUniquePtr phaseMax; UserSettingUniquePtr mask; }; using ParticleOperatorUniquePtr = std::unique_ptr; /** * Particle renderer configuration */ struct ParticleRenderer { std::string name; float length; float maxLength; float minLength; float subdivision; float segments; // ropetrail: number of history segments per particle float uvScale; bool uvScrolling; bool uvSmoothing; // rope only: reduces flickering when lifetimes are identical bool fadeAlpha; // ropetrail: fade alpha along trail bool fadeSize; // ropetrail: fade size along trail }; /** * Child particle system */ struct ParticleChild { std::string type; std::string name; int maxCount; int controlPointStartIndex; float probability; glm::vec3 angles; glm::vec3 origin; glm::vec3 scale; std::string particleFile; }; /** * Instance override values */ struct ParticleInstanceOverride { UserSettingUniquePtr enabled; UserSettingUniquePtr alpha; UserSettingUniquePtr size; UserSettingUniquePtr lifetime; UserSettingUniquePtr rate; UserSettingUniquePtr speed; UserSettingUniquePtr count; UserSettingUniquePtr color; // Replaces particle color UserSettingUniquePtr colorn; // Multiplies particle color }; struct ParticleData { UserSettingUniquePtr scale; UserSettingUniquePtr angles; UserSettingUniquePtr visible; UserSettingUniquePtr parallaxDepth; std::string particleFile; std::string animationMode; float sequenceMultiplier; uint32_t maxCount; float startTime; uint32_t flags; ModelUniquePtr material; std::vector emitters; std::vector initializers; std::vector operators; std::vector renderers; std::vector controlPoints; std::vector children; ParticleInstanceOverride instanceOverride; }; class Particle : public Object, public ParticleData { public: explicit Particle (ObjectData data, ParticleData particleData) noexcept : Object (std::move (data)), ParticleData (std::move (particleData)) { }; ~Particle () override = default; }; /** * Text object data. Phase 1 of text support covers only static text; * dynamic (script-driven) text captures the script source for a future * pass but renders whatever initial value the scene provides. */ struct TextData { /** Initial text content to render (for scripted text, this is the `value` placeholder) */ UserSettingUniquePtr text; /** Font reference from scene (e.g. "fonts/VCR_OSD_MONO.ttf" or "systemfont_arial") */ std::string font; /** Font size in points, optionally bound to a user setting or script */ UserSettingUniquePtr pointSize; /** Bounding box size */ glm::vec2 size; /** Scale (x, y, z) */ UserSettingUniquePtr scale; /** Text color as linear-space RGB */ UserSettingUniquePtr color; UserSettingUniquePtr alpha; UserSettingUniquePtr visible; UserSettingUniquePtr parallaxDepth; /** Horizontal alignment: "left", "center", "right" */ std::string alignment; /** Vertical alignment: "top", "center", "bottom" */ std::string verticalalign; /** Padding inside the bounding box (x = horizontal, y = vertical) */ glm::vec2 padding; /** Applied after the glyphs are rendered */ std::vector effects; /** Wrap lines wider than maxWidth (layout pixels, before the object's scale) */ UserSettingUniquePtr limitWidth; UserSettingUniquePtr maxWidth; /** Cut the text after maxRows lines, optionally marking the cut with an ellipsis */ UserSettingUniquePtr limitRows; UserSettingUniquePtr maxRows; UserSettingUniquePtr limitUseEllipsis; }; class Text : public Object, public TextData { public: explicit Text (ObjectData data, TextData textData) noexcept : Object (std::move (data)), TextData (std::move (textData)) { }; ~Text () override = default; }; } // namespace WallpaperEngine::Data::Model