Files
FlaxEngine/Source/Engine/Particles/ParticleSystem.h
2022-01-14 13:31:12 +01:00

254 lines
8.1 KiB
C++

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