|
3 | 3 | #include <utility> |
4 | 4 |
|
5 | 5 | #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" |
6 | 10 |
|
7 | 11 | namespace animation { |
8 | 12 |
|
@@ -1287,6 +1291,8 @@ namespace animation { |
1287 | 1291 | instance.interruptableSound = false; |
1288 | 1292 | instance.currentlyPlaying = sound_handle::invalid(); |
1289 | 1293 | } |
| 1294 | + |
| 1295 | + m_segment->forceStopAnimation(pmi_id); |
1290 | 1296 | } |
1291 | 1297 |
|
1292 | 1298 | void ModelAnimationSegmentSoundDuring::playLoopSnd(polymodel_instance* pmi) { |
@@ -1381,6 +1387,108 @@ namespace animation { |
1381 | 1387 | } |
1382 | 1388 |
|
1383 | 1389 |
|
| 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 | + |
1384 | 1492 | ModelAnimationSegmentIK::ModelAnimationSegmentIK(const vec3d& targetPosition, const std::optional<matrix>& targetRotation) |
1385 | 1493 | : m_targetPosition(targetPosition), m_targetRotation(targetRotation) { } |
1386 | 1494 |
|
|
0 commit comments