// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Content/BinaryAsset.h" #include "Engine/Core/Math/Color32.h" #include "Engine/Core/Types/Pair.h" #include "ParticleEmitter.h" /// /// Particle system contains a composition of particle emitters and playback information. /// API_CLASS(NoSpawn) class FLAXENGINE_API ParticleSystem : public BinaryAsset { DECLARE_BINARY_ASSET_HEADER(ParticleSystem, 1); public: /// /// The particle system timeline track data. /// struct Track { enum class Types { Emitter = 0, Folder = 1, }; enum class Flags { None = 0, Mute = 1, }; /// /// The type of the track. /// Types Type; /// /// The flags of the track. /// Flags Flag; /// /// The parent track index or -1 for root tracks. /// int32 ParentIndex; /// /// The amount of child tracks (stored in the sequence after this track). /// int32 ChildrenCount; /// /// The name of the track. /// String Name; /// /// True if track is disabled, otherwise false (cached on load based on the flags and parent flags). /// bool Disabled; /// /// The track color. /// Color32 Color; union { struct { /// /// The index of the emitter (from particle system emitters collection). /// int32 Index; /// /// The start frame of the emitter play begin. /// int32 StartFrame; /// /// The total duration of the emitter playback in the timeline sequence frames amount. /// int32 DurationFrames; } AsEmitter; struct { } AsFolder; }; Track() { } }; typedef Pair EmitterParameterOverrideKey; private: #if !BUILD_RELEASE String _debugName; #endif public: /// /// The asset data version number. Used to sync the data with the instances state. Incremented each time asset gets loaded. /// uint32 Version = 0; /// /// The frames amount per second of the timeline animation. /// API_FIELD(ReadOnly) float FramesPerSecond; /// /// The animation duration (in frames). /// API_FIELD(ReadOnly) int32 DurationFrames; /// /// The animation duration (in seconds). /// API_PROPERTY() float GetDuration() const { return static_cast(DurationFrames) / FramesPerSecond; } /// /// The emitters used by this system. /// Array> Emitters; /// /// The overriden values for the emitters parameters. Key is pair of emitter index and parameter ID, value is the custom value. /// Dictionary EmittersParametersOverrides; /// /// The tracks on the system timeline. /// Array Tracks; public: /// /// Initializes the particle system that plays a single particles emitter. This can be used only for virtual assets. /// /// The emitter to playback. /// The timeline animation duration in seconds. /// The amount of frames per second of the timeline animation. API_FUNCTION() void Init(ParticleEmitter* emitter, float duration, float fps = 60.0f); /// /// Loads the serialized timeline data. /// /// The output surface data, or empty if failed to load. API_FUNCTION() BytesContainer LoadTimeline(); #if USE_EDITOR /// /// Saves the serialized timeline data to the asset. /// /// The timeline data container. /// true failed to save data; otherwise, false. API_FUNCTION() bool SaveTimeline(BytesContainer& data); #endif public: /// /// Spawns the particles at the given location. /// /// The spawn position. /// If set to true effect be auto-destroyed after duration. /// The spawned effect. API_FUNCTION() ParticleEffect* Spawn(const Vector3& position, bool autoDestroy = false) { return Spawn(nullptr, Transform(position), autoDestroy); } /// /// Spawns the particles at the given location. /// /// The spawn position. /// The spawn rotation. /// If set to true effect be auto-destroyed after duration. /// The spawned effect. API_FUNCTION() ParticleEffect* Spawn(const Vector3& position, const Quaternion& rotation, bool autoDestroy = false) { return Spawn(nullptr, Transform(position, rotation), autoDestroy); } /// /// Spawns the particles at the given location. /// /// The spawn transform. /// If set to true effect be auto-destroyed after duration. /// The spawned effect. API_FUNCTION() ParticleEffect* Spawn(const Transform& transform, bool autoDestroy = false) { return Spawn(nullptr, transform, autoDestroy); } /// /// Spawns the particles at the given location. /// /// The parent actor (can be null to link it to the first loaded scene). /// The spawn position. /// If set to true effect be auto-destroyed after duration. /// The spawned effect. API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Vector3& position, bool autoDestroy = false) { return Spawn(parent, Transform(position), autoDestroy); } /// /// Spawns the particles at the given location. /// /// The parent actor (can be null to link it to the first loaded scene). /// The spawn position. /// The spawn rotation. /// If set to true effect be auto-destroyed after duration. /// The spawned effect. API_FUNCTION() ParticleEffect* Spawn(Actor* parent, Vector3 position, Quaternion rotation, bool autoDestroy = false) { return Spawn(parent, Transform(position, rotation), autoDestroy); } /// /// Spawns the particles at the given location. /// /// The parent actor (can be null to link it to the first loaded scene). /// The spawn transform. /// If set to true effect be auto-destroyed after duration. /// The spawned effect. API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Transform& transform, bool autoDestroy = false); public: // [BinaryAsset] void InitAsVirtual() override; #if USE_EDITOR void GetReferences(Array& assets, Array& files) const override; #endif protected: // [ParticleSystemBase] LoadResult load() override; void unload(bool isReloading) override; AssetChunksFlag getChunksToPreload() const override; };