Skip to content

Commit 1b0e63d

Browse files
authored
Add animation support for particle spawning (#7416)
* Add particle during animation * cleanup
1 parent 811b412 commit 1b0e63d

3 files changed

Lines changed: 138 additions & 0 deletions

File tree

code/model/animation/modelanimation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,6 +1816,7 @@ namespace animation {
18161816
{"$Axis Rotation:", ModelAnimationSegmentAxisRotation::parser},
18171817
{"$Translation:", ModelAnimationSegmentTranslation::parser},
18181818
{"$Sound During:", ModelAnimationSegmentSoundDuring::parser},
1819+
{"$Particles During:", ModelAnimationSegmentParticlesDuring::parser},
18191820
{"$Inverse Kinematics:", ModelAnimationSegmentIK::parser}
18201821
};
18211822

code/model/animation/modelanimation_segments.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
#include <utility>
44

55
#include "render/3d.h"
6+
#include "particle/ParticleManager.h"
7+
#include "particle/hosts/EffectHostObject.h"
8+
#include "particle/hosts/EffectHostSubmodel.h"
9+
#include "particle/hosts/EffectHostVector.h"
610

711
namespace animation {
812

@@ -1287,6 +1291,8 @@ namespace animation {
12871291
instance.interruptableSound = false;
12881292
instance.currentlyPlaying = sound_handle::invalid();
12891293
}
1294+
1295+
m_segment->forceStopAnimation(pmi_id);
12901296
}
12911297

12921298
void ModelAnimationSegmentSoundDuring::playLoopSnd(polymodel_instance* pmi) {
@@ -1381,6 +1387,108 @@ namespace animation {
13811387
}
13821388

13831389

1390+
ModelAnimationSegmentParticlesDuring::ModelAnimationSegmentParticlesDuring(std::shared_ptr<ModelAnimationSegment> segment, particle::ParticleEffectHandle effect, float atTime, std::shared_ptr<ModelAnimationSubmodel> submodel, std::optional<vec3d> position, std::optional<matrix> orientation) :
1391+
m_segment(std::move(segment)), m_submodel(std::move(submodel)), m_position(std::move(position)), m_orientation(std::move(orientation)), m_effect(effect), m_atTime(atTime) { }
1392+
1393+
ModelAnimationSegment* ModelAnimationSegmentParticlesDuring::copy() const {
1394+
auto newCopy = new ModelAnimationSegmentParticlesDuring(*this);
1395+
newCopy->m_segment = std::shared_ptr<ModelAnimationSegment>(newCopy->m_segment->copy());
1396+
return newCopy;
1397+
}
1398+
1399+
void ModelAnimationSegmentParticlesDuring::recalculate(ModelAnimationSubmodelBuffer& base, ModelAnimationSubmodelBuffer& currentAnimDelta, polymodel_instance* pmi) {
1400+
m_segment->recalculate(base, currentAnimDelta, pmi);
1401+
m_duration[pmi->id] = m_segment->getDuration(pmi->id);
1402+
}
1403+
1404+
void ModelAnimationSegmentParticlesDuring::calculateAnimation(ModelAnimationSubmodelBuffer& base, float time, int pmi_id) const {
1405+
m_segment->calculateAnimation(base, time, pmi_id);
1406+
}
1407+
1408+
void ModelAnimationSegmentParticlesDuring::executeAnimation(const ModelAnimationSubmodelBuffer& state, float timeboundLower, float timeboundUpper, ModelAnimationDirection direction, int pmi_id) {
1409+
float atTime = fminf(fmaxf(m_atTime, 0.0f), m_duration.at(pmi_id));
1410+
if (timeboundLower <= atTime && atTime <= timeboundUpper) {
1411+
createParticleSource(model_get_instance(pmi_id));
1412+
}
1413+
m_segment->executeAnimation(state, timeboundLower, timeboundUpper, direction, pmi_id);
1414+
}
1415+
1416+
void ModelAnimationSegmentParticlesDuring::exchangeSubmodelPointers(ModelAnimationSet& replaceWith) {
1417+
m_segment->exchangeSubmodelPointers(replaceWith);
1418+
}
1419+
1420+
void ModelAnimationSegmentParticlesDuring::forceStopAnimation(int pmi_id) {
1421+
m_segment->forceStopAnimation(pmi_id);
1422+
}
1423+
1424+
void ModelAnimationSegmentParticlesDuring::createParticleSource(polymodel_instance* pmi) const {
1425+
if (!m_effect.isValid())
1426+
return;
1427+
1428+
auto source = particle::ParticleManager::get()->createSource(m_effect);
1429+
if (!source)
1430+
return;
1431+
1432+
matrix orient = m_orientation.value_or(vmd_identity_matrix);
1433+
vec3d pos = m_position.value_or(vmd_zero_vector);
1434+
1435+
std::unique_ptr<EffectHost> host;
1436+
1437+
if (m_submodel != nullptr && pmi->objnum >= 0) {
1438+
auto submodel = m_submodel->findSubmodel(pmi);
1439+
if (submodel.first != nullptr) {
1440+
host = std::make_unique<EffectHostSubmodel>(&Objects[pmi->objnum], static_cast<int>(submodel.first - pmi->submodel), pos, orient);
1441+
}
1442+
}
1443+
1444+
if (!host && pmi->objnum >= 0) {
1445+
host = std::make_unique<EffectHostObject>(&Objects[pmi->objnum], pos, orient);
1446+
}
1447+
1448+
if (!host) {
1449+
host = std::make_unique<EffectHostVector>(pos, orient, vmd_zero_vector);
1450+
}
1451+
1452+
source->setHost(std::move(host));
1453+
source->finishCreation();
1454+
}
1455+
1456+
std::shared_ptr<ModelAnimationSegment> ModelAnimationSegmentParticlesDuring::parser(ModelAnimationParseHelper* data) {
1457+
auto submodel = ModelAnimationParseHelper::parseSubmodel();
1458+
if (!submodel) {
1459+
if (data->parentSubmodel)
1460+
submodel = data->parentSubmodel;
1461+
}
1462+
1463+
required_string("+Effect:");
1464+
auto effect = particle::util::parseEffect(data->m_animationName);
1465+
1466+
required_string("+At Time:");
1467+
float atTime = 0.0f;
1468+
stuff_float(&atTime);
1469+
1470+
std::optional<vec3d> position = std::nullopt;
1471+
if (optional_string("+Position:")) {
1472+
vec3d parse;
1473+
stuff_vec3d(&parse);
1474+
position = std::move(parse);
1475+
}
1476+
1477+
std::optional<matrix> orientation = std::nullopt;
1478+
if (optional_string("+Orientation:")) {
1479+
angles angle;
1480+
stuff_angles_deg_phb(&angle);
1481+
matrix mat;
1482+
vm_angles_2_matrix(&mat, &angle);
1483+
orientation = std::move(mat);
1484+
}
1485+
1486+
auto segment = std::make_shared<ModelAnimationSegmentParticlesDuring>(data->parseSegment(), effect, atTime, submodel, position, orientation);
1487+
1488+
return segment;
1489+
}
1490+
1491+
13841492
ModelAnimationSegmentIK::ModelAnimationSegmentIK(const vec3d& targetPosition, const std::optional<matrix>& targetRotation)
13851493
: m_targetPosition(targetPosition), m_targetRotation(targetRotation) { }
13861494

code/model/animation/modelanimation_segments.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "math/ik_solver.h"
44
#include "model/animation/modelanimation.h"
5+
#include "particle/particle.h"
56

67
namespace animation {
78

@@ -290,6 +291,34 @@ namespace animation {
290291

291292
};
292293

294+
class ModelAnimationSegmentParticlesDuring : public ModelAnimationSegment {
295+
std::shared_ptr<ModelAnimationSegment> m_segment;
296+
297+
std::shared_ptr<ModelAnimationSubmodel> m_submodel;
298+
std::optional<vec3d> m_position;
299+
std::optional<matrix> m_orientation;
300+
301+
//configurables:
302+
public:
303+
particle::ParticleEffectHandle m_effect;
304+
float m_atTime;
305+
306+
private:
307+
ModelAnimationSegment* copy() const override;
308+
void recalculate(ModelAnimationSubmodelBuffer& base, ModelAnimationSubmodelBuffer& currentAnimDelta, polymodel_instance* pmi) override;
309+
void calculateAnimation(ModelAnimationSubmodelBuffer& base, float time, int pmi_id) const override;
310+
void executeAnimation(const ModelAnimationSubmodelBuffer& state, float timeboundLower, float timeboundUpper, ModelAnimationDirection direction, int pmi_id) override;
311+
void exchangeSubmodelPointers(ModelAnimationSet& replaceWith) override;
312+
void forceStopAnimation(int pmi_id) override;
313+
314+
void createParticleSource(polymodel_instance* pmi) const;
315+
316+
public:
317+
static std::shared_ptr<ModelAnimationSegment> parser(ModelAnimationParseHelper* data);
318+
ModelAnimationSegmentParticlesDuring(std::shared_ptr<ModelAnimationSegment> segment, particle::ParticleEffectHandle effect, float atTime, std::shared_ptr<ModelAnimationSubmodel> submodel = nullptr, std::optional<vec3d> position = std::nullopt, std::optional<matrix> orientation = std::nullopt);
319+
320+
};
321+
293322
class ModelAnimationSegmentIK : public ModelAnimationSegment {
294323
struct instance_data {
295324

0 commit comments

Comments
 (0)