1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#include "EffectTiming.h"
namespace particle {
namespace util {
EffectTiming::EffectTiming() : m_duration(Duration::Onetime) {
}
void EffectTiming::applyToSource(ParticleSource* source) const
{
if (m_duration == Duration::Range || m_duration == Duration::Always) {
int duration = -1;
int delay = static_cast<int>(m_delayRange.next() * 1000.f);
// Make the timestamp invalid if there is no delay
if (delay == 0) {
delay = -1;
}
if (m_duration == Duration::Range) {
duration = static_cast<int>(m_durationRange.next() * 1000.f);
}
if (delay != -1 && duration != -1) {
// Need to adjust the duration because setLifetime expects a timestamp for the end
duration = delay + duration;
}
source->getTiming()->setLifetime(timestamp(delay), timestamp(duration));
}
}
bool EffectTiming::continueProcessing(const ParticleSource* source) const
{
switch (m_duration) {
case Duration::Onetime:
if (source->getProcessingCount() > 0) {
// Only process on the first frame
return false;
}
break;
default:
// Everything else is handled elsewhere
return true;
}
return true;
}
int EffectTiming::shouldCreateEffect(ParticleSource* source, EffectTiming::TimingState& localState) const
{
if (m_particlesPerSecond.min() < 0.0f) {
// If this is not specified then on every frame we will create exactly one effect
if (localState.initial) {
localState.initial = false;
return 0;
} else {
return -1;
}
}
// We have a valid particles per second value so we use the next creation timestamp in the particle source for
// deciding if we can create an effect
if (source->getTiming()->nextCreationTimeExpired())
{
// Invert this so we can compute the time difference between effect creations
auto secondsPerParticle = 1.0f / m_particlesPerSecond.next();
// we need to clamp this to 1 because a spawn delay of 0 means we try to spawn infinite particles
auto time_diff_ms = std::max(fl2i(secondsPerParticle * MILLISECONDS_PER_SECOND), 1);
int creation_time = source->getTiming()->getNextCreationTime();
source->getTiming()->incrementNextCreationTime(time_diff_ms);
return timestamp_since(creation_time);
}
return -1;
}
EffectTiming EffectTiming::parseTiming() {
EffectTiming timing;
if (optional_string("+Duration:")) {
if (optional_string("Onetime")) {
timing.m_duration = Duration::Onetime;
}
else if (optional_string("Always")) {
timing.m_duration = Duration::Always;
}
else {
timing.m_duration = Duration::Range;
timing.m_durationRange = ::util::ParsedRandomFloatRange::parseRandomRange(0.0f);
}
}
if (optional_string("+Delay:")) {
if (timing.m_duration == Duration::Onetime) {
error_display(0, "+Delay is not valid for one-time effects!");
}
else {
timing.m_delayRange = ::util::ParsedRandomFloatRange::parseRandomRange(0.0f);
}
}
if (optional_string("+Effects per second:")) {
timing.m_particlesPerSecond = ::util::ParsedRandomFloatRange::parseRandomRange();
if (timing.m_particlesPerSecond.min() < 0.001f) {
error_display(0, "Invalid effects per second minimum %f. Setting was disabled.", timing.m_particlesPerSecond.min());
timing.m_particlesPerSecond = ::util::UniformFloatRange(-1.f);
}
if (timing.m_particlesPerSecond.max() > 1000.0f) {
error_display(0, "Effects per second maximum %f is above 1000. Delay between effects will be clamped to 1 millisecond.", timing.m_particlesPerSecond.max());
}
}
return timing;
}
}
}
|