diff --git a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.cpp b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.cpp index f0cf76ce4..8dae724ab 100644 --- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.cpp +++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.cpp @@ -505,7 +505,8 @@ void ParticleEmitterGraphCPUExecutor::Update(ParticleEmitter* emitter, ParticleE } // Spawn particles - int32 spawnCount = 0; + int32 spawnCount = data.CustomSpawnCount; + data.CustomSpawnCount = 0; if (canSpawn) { PROFILE_CPU_NAMED("Spawn"); @@ -573,7 +574,8 @@ int32 ParticleEmitterGraphCPUExecutor::UpdateSpawn(ParticleEmitter* emitter, Par Init(emitter, effect, data, dt); // Spawn particles - int32 spawnCount = 0; + int32 spawnCount = data.CustomSpawnCount; + data.CustomSpawnCount = 0; for (int32 i = 0; i < _graph.SpawnModules.Count(); i++) { spawnCount += ProcessSpawnModule(i); diff --git a/Source/Engine/Particles/ParticleEffect.cpp b/Source/Engine/Particles/ParticleEffect.cpp index ab3066372..9b033641c 100644 --- a/Source/Engine/Particles/ParticleEffect.cpp +++ b/Source/Engine/Particles/ParticleEffect.cpp @@ -281,6 +281,34 @@ void ParticleEffect::UpdateSimulation(bool singleFrame) Particles::UpdateEffect(this); } +void ParticleEffect::SpawnParticles(int32 count, const StringView& emitterTrackName) +{ + auto system = ParticleSystem.Get(); + if (!system) + return; + if (emitterTrackName.IsEmpty()) + { + for (auto& e : Instance.Emitters) + e.CustomSpawnCount += count; + } + else + { + for (int32 i = 0; i < system->Tracks.Count(); i++) + { + auto& track = system->Tracks[i]; + if (track.Type == ParticleSystem::Track::Types::Emitter && track.Name == emitterTrackName) + { + const int32 emitterIndex = track.AsEmitter.Index; + if (Instance.Emitters.IsValidIndex(emitterIndex)) + { + Instance.Emitters.Get()[emitterIndex].CustomSpawnCount += count; + break; + } + } + } + } +} + void ParticleEffect::Play() { _isPlaying = true; diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h index 5e2770f89..2b32b3ca2 100644 --- a/Source/Engine/Particles/ParticleEffect.h +++ b/Source/Engine/Particles/ParticleEffect.h @@ -350,6 +350,13 @@ public: /// True if update animation by a single frame only (time time since last engine update), otherwise will update simulation with delta time since last update. API_FUNCTION() void UpdateSimulation(bool singleFrame = false); + /// + /// Manually spawns additional particles into the simulation. + /// + /// Amount of particles to spawn. + /// Name of the emitter track to spawn particles in. Empty if spawn particles into all tracks. + API_FUNCTION() void SpawnParticles(int32 count, const StringView& emitterTrackName = String::Empty); + /// /// Plays the simulation. /// diff --git a/Source/Engine/Particles/ParticlesSimulation.cpp b/Source/Engine/Particles/ParticlesSimulation.cpp index 880f6389d..3fafc8ad6 100644 --- a/Source/Engine/Particles/ParticlesSimulation.cpp +++ b/Source/Engine/Particles/ParticlesSimulation.cpp @@ -26,6 +26,7 @@ void ParticleEmitterInstance::ClearState() Time = 0; SpawnModulesData.Clear(); CustomData.Clear(); + CustomSpawnCount = 0; #if COMPILE_WITH_GPU_PARTICLES GPU.DeltaTime = 0.0f; GPU.SpawnCount = 0; diff --git a/Source/Engine/Particles/ParticlesSimulation.h b/Source/Engine/Particles/ParticlesSimulation.h index 19303b971..ec2bd5e05 100644 --- a/Source/Engine/Particles/ParticlesSimulation.h +++ b/Source/Engine/Particles/ParticlesSimulation.h @@ -84,6 +84,11 @@ public: /// Array CustomData; + /// + /// The external amount of the particles to spawn. + /// + int32 CustomSpawnCount = 0; + struct { ///