Particle source duration curve + life remaining input (#7231)

* Add curve to control the duration of a particle source

* Also add fractional Life Left curve input for sources

* Actually register new particle curve output
This commit is contained in:
BMagnu authored and GitHub committed 2026-02-17 12:09:13 +01:00
1 parent 4fbfa84c6e
commit e827011113
4 files changed
+22 -6

No files matched your search

+7 -3
View File
@@ -416,13 +416,17 @@ void ParticleEffect::pageIn() {
}
}
std::pair<TIMESTAMP, TIMESTAMP> ParticleEffect::getEffectDuration() const {
std::pair<TIMESTAMP, TIMESTAMP> ParticleEffect::getEffectDuration(float interp, const ParticleSource& source, size_t effectNumber) const {
std::pair<TIMESTAMP, TIMESTAMP> timing;
timing.first = _timestamp(fl2i(m_delayRange.next() * 1000.0f));
if (m_duration == Duration::ALWAYS)
timing.second = TIMESTAMP::never();
else
timing.second = timestamp_delta(timing.first, fl2i(m_durationRange.next() * 1000.0f));
else {
const auto& [pos, hostOrientation] = source.m_host->getPositionAndOrientation(m_parent_local, interp, m_manual_offset);
auto modularCurvesInput = std::forward_as_tuple(source, effectNumber, pos);
timing.second = timestamp_delta(timing.first, fl2i(m_durationRange.next() * 1000.0f * m_modular_curves.get_output(ParticleCurvesOutput::SOURCE_DURATION_MULT, modularCurvesInput)));
}
return timing;
}
+4 -1
View File
@@ -75,6 +75,7 @@ public:
RADIUS_MULT,
LENGTH_MULT,
LIFETIME_MULT,
SOURCE_DURATION_MULT,
VOLUME_VELOCITY_MULT,
INHERIT_VELOCITY_MULT,
POSITION_INHERIT_VELOCITY_MULT,
@@ -236,7 +237,7 @@ public:
const SCP_string& getName() const { return m_name; }
std::pair<TIMESTAMP, TIMESTAMP> getEffectDuration() const;
std::pair<TIMESTAMP, TIMESTAMP> getEffectDuration(float interp, const ParticleSource& source, size_t effectNumber) const;
float getNextSpawnDelay() const;
@@ -251,6 +252,7 @@ public:
std::pair {"Radius Mult", ParticleCurvesOutput::RADIUS_MULT},
std::pair {"Length Mult", ParticleCurvesOutput::LENGTH_MULT},
std::pair {"Lifetime Mult", ParticleCurvesOutput::LIFETIME_MULT},
std::pair {"Source Duration Mult", ParticleCurvesOutput::SOURCE_DURATION_MULT},
std::pair {"Velocity Volume Mult", ParticleCurvesOutput::VOLUME_VELOCITY_MULT},
std::pair {"Velocity Inherit Mult", ParticleCurvesOutput::INHERIT_VELOCITY_MULT},
std::pair {"Velocity Position Inherit Mult", ParticleCurvesOutput::POSITION_INHERIT_VELOCITY_MULT},
@@ -299,6 +301,7 @@ public:
std::pair {"Host Ship Time Until Explosion", modular_curves_submember_input<&ParticleSource::m_host, &EffectHost::getParentObjAndSig, 0, &Objects, &obj_get_instance_maybe<OBJ_SHIP>, &ship::final_death_time, static_cast<int (*)(int)>(&timestamp_until)>{}})
.derive_modular_curves_input_only_subset<size_t>( //Effect Number
std::pair {"Spawntime Left", modular_curves_functional_full_input<&ParticleSource::getEffectRemainingTime>{}},
std::pair {"Life Left", modular_curves_functional_full_input<&ParticleSource::getEffectRemainingLife>{}},
std::pair {"Time Running", modular_curves_functional_full_input<&ParticleSource::getEffectRunningTime>{}})
.derive_modular_curves_input_only_subset<vec3d>( //Sampled spawn position
std::pair {"Pixel Size At Emitter", modular_curves_functional_full_input<&ParticleSource::getEffectPixelSize>{}},
+9 -2
View File
@@ -34,8 +34,10 @@ void ParticleSource::finishCreation() {
m_host->setupProcessing();
for (const auto& effect : ParticleManager::get()->getEffect(m_effect)) {
const auto& [begin, end] = effect.getEffectDuration();
const auto& effectList = ParticleManager::get()->getEffect(m_effect);
for (size_t i = 0; i < effectList.size(); i++) {
const auto& effect = effectList[i];
const auto& [begin, end] = effect.getEffectDuration(0.0, *this, i);
m_timing.emplace_back(SourceTiming{timestamp_delta(begin, 0), begin, end});
}
}
@@ -111,6 +113,11 @@ float ParticleSource::getEffectRunningTime(const std::tuple<const ParticleSource
return i2fl(timestamp_get_delta(timing.m_startTimestamp, timing.m_nextCreation)) / i2fl(MILLISECONDS_PER_SECOND);
}
float ParticleSource::getEffectRemainingLife(const std::tuple<const ParticleSource&, const size_t&>& source) {
const auto& timing = std::get<0>(source).m_timing[std::get<1>(source)];
return i2fl(timestamp_get_delta(timing.m_nextCreation, timing.m_endTimestamp)) / i2fl(timestamp_get_delta(timing.m_startTimestamp, timing.m_endTimestamp)) ;
}
float ParticleSource::getEffectPixelSize(const std::tuple<const ParticleSource&, const size_t&, const vec3d&>& source) {
return std::get<0>(source).getEffect()[std::get<1>(source)].getApproximatePixelSize(std::get<2>(source));
}
+2
View File
@@ -75,6 +75,8 @@ class ParticleSource {
static float getEffectRunningTime(const std::tuple<const ParticleSource&, const size_t&>& source);
static float getEffectRemainingLife(const std::tuple<const ParticleSource&, const size_t&>& source);
static float getEffectPixelSize(const std::tuple<const ParticleSource&, const size_t&, const vec3d&>& source);
static float getEffectApparentSize(const std::tuple<const ParticleSource&, const size_t&, const vec3d&>& source);