mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
Merge pull request #1797 from asarium/fix/particleEffectHandles
Use type-safe handles for particle effects
This commit is contained in:
10 files changed
+65
-61
No files matched your search
@@ -1387,7 +1387,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
|
||||
weapon_info *wip;
|
||||
wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
|
||||
// If the weapon didn't play any impact animation, play custom asteroid impact animation
|
||||
if ( wip->impact_weapon_expl_effect < 0 ) {
|
||||
if (!wip->impact_weapon_expl_effect.isValid()) {
|
||||
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, particle::PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,10 +155,11 @@ ParticleSource* ParticleManager::createSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
ParticleEffectIndex ParticleManager::getEffectByName(const SCP_string& name) {
|
||||
ParticleEffectHandle ParticleManager::getEffectByName(const SCP_string& name)
|
||||
{
|
||||
if (name.empty()) {
|
||||
// Don't allow empty names, it's a special case for effects that should not be referenced.
|
||||
return -1;
|
||||
return ParticleEffectHandle::invalid();
|
||||
}
|
||||
|
||||
auto foundIterator = find_if(m_effects.begin(), m_effects.end(),
|
||||
@@ -167,10 +168,10 @@ ParticleEffectIndex ParticleManager::getEffectByName(const SCP_string& name) {
|
||||
});
|
||||
|
||||
if (foundIterator == m_effects.end()) {
|
||||
return -1;
|
||||
return ParticleEffectHandle::invalid();
|
||||
}
|
||||
|
||||
return distance(m_effects.begin(), foundIterator);
|
||||
return ParticleEffectHandle(distance(m_effects.begin(), foundIterator));
|
||||
}
|
||||
|
||||
void ParticleManager::doFrame(float) {
|
||||
@@ -210,7 +211,8 @@ void ParticleManager::doFrame(float) {
|
||||
}
|
||||
}
|
||||
|
||||
ParticleEffectIndex ParticleManager::addEffect(ParticleEffectPtr effect) {
|
||||
ParticleEffectHandle ParticleManager::addEffect(ParticleEffectPtr effect)
|
||||
{
|
||||
Assertion(effect, "Invalid effect pointer passed!");
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -218,7 +220,7 @@ ParticleEffectIndex ParticleManager::addEffect(ParticleEffectPtr effect) {
|
||||
// This check is a bit expensive and will only be used in debug
|
||||
auto index = getEffectByName(effect->getName());
|
||||
|
||||
if (index >= 0) {
|
||||
if (index.isValid()) {
|
||||
Warning(LOCATION, "Effect with name '%s' already exists!", effect->getName().c_str());
|
||||
return index;
|
||||
}
|
||||
@@ -227,7 +229,7 @@ ParticleEffectIndex ParticleManager::addEffect(ParticleEffectPtr effect) {
|
||||
|
||||
m_effects.push_back(std::shared_ptr<ParticleEffect>(effect));
|
||||
|
||||
return static_cast<ParticleEffectIndex>(m_effects.size() - 1);
|
||||
return ParticleEffectHandle(static_cast<ParticleEffectHandle::impl_type>(m_effects.size() - 1));
|
||||
}
|
||||
|
||||
void ParticleManager::pageIn() {
|
||||
@@ -236,7 +238,8 @@ void ParticleManager::pageIn() {
|
||||
}
|
||||
}
|
||||
|
||||
ParticleSourceWrapper ParticleManager::createSource(ParticleEffectIndex index) {
|
||||
ParticleSourceWrapper ParticleManager::createSource(ParticleEffectHandle index)
|
||||
{
|
||||
ParticleEffectPtr eff = this->getEffect(index);
|
||||
ParticleSourceWrapper wrapper;
|
||||
|
||||
@@ -277,13 +280,14 @@ void ParticleManager::clearSources() {
|
||||
}
|
||||
|
||||
namespace util {
|
||||
ParticleEffectIndex parseEffect(const SCP_string& objectName) {
|
||||
ParticleEffectHandle parseEffect(const SCP_string& objectName)
|
||||
{
|
||||
SCP_string name;
|
||||
stuff_string(name, F_NAME);
|
||||
|
||||
auto idx = ParticleManager::get()->getEffectByName(name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!idx.isValid()) {
|
||||
if (objectName.empty()) {
|
||||
error_display(0, "Unknown particle effect name '%s' encountered!", name.c_str());
|
||||
} else {
|
||||
@@ -297,14 +301,15 @@ ParticleEffectIndex parseEffect(const SCP_string& objectName) {
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
ParticleEffectIndex parseEffectElement(EffectType forcedType, const SCP_string& name) {
|
||||
ParticleEffectHandle parseEffectElement(EffectType forcedType, const SCP_string& name)
|
||||
{
|
||||
if (!optional_string("$New Effect")) {
|
||||
SCP_string newName;
|
||||
stuff_string(newName, F_NAME);
|
||||
|
||||
auto index = ParticleManager::get()->getEffectByName(newName);
|
||||
|
||||
if (index < 0) {
|
||||
if (!index.isValid()) {
|
||||
error_display(0, "Unknown particle effect name '%s' encountered!", newName.c_str());
|
||||
}
|
||||
if (forcedType != EffectType::Invalid) {
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
#include "particle/ParticleEffect.h"
|
||||
#include "particle/ParticleSource.h"
|
||||
#include "particle/ParticleSourceWrapper.h"
|
||||
#include "utils/id.h"
|
||||
|
||||
namespace particle {
|
||||
// typedef this to make usages of particle effects clearer
|
||||
struct particle_effect_tag {
|
||||
};
|
||||
/**
|
||||
* The particle index type. Use this in place of int or ptrdiff_t.
|
||||
* The particle index type.
|
||||
*/
|
||||
typedef ptrdiff_t ParticleEffectIndex;
|
||||
using ParticleEffectHandle = ::util::ID<particle_effect_tag, ptrdiff_t, -1>;
|
||||
|
||||
/**
|
||||
* @brief Manages high-level particle effects and sources
|
||||
@@ -79,11 +81,13 @@ class ParticleManager {
|
||||
* @param effectID The id of the effect to retrieve
|
||||
* @return The particle effect pointer, will not be @c nullptr
|
||||
*/
|
||||
inline ParticleEffectPtr getEffect(ParticleEffectIndex effectID) {
|
||||
Assertion(effectID >= 0 && effectID < static_cast<ParticleEffectIndex>(m_effects.size()),
|
||||
"Particle effect index " PTRDIFF_T_ARG " is invalid!", effectID);
|
||||
inline ParticleEffectPtr getEffect(ParticleEffectHandle effectID)
|
||||
{
|
||||
Assertion(effectID.value() >= 0 &&
|
||||
effectID.value() < static_cast<ParticleEffectHandle::impl_type>(m_effects.size()),
|
||||
"Particle effect index " PTRDIFF_T_ARG " is invalid!", effectID.value());
|
||||
|
||||
return m_effects[effectID].get();
|
||||
return m_effects[effectID.value()].get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,14 +99,14 @@ class ParticleManager {
|
||||
* @param name The name of the effect that is being searchd, may not be empty
|
||||
* @return The index of the effect
|
||||
*/
|
||||
ParticleEffectIndex getEffectByName(const SCP_string& name);
|
||||
ParticleEffectHandle getEffectByName(const SCP_string& name);
|
||||
|
||||
/**
|
||||
* @brief Adds an effect
|
||||
* @param effect The effect to add
|
||||
* @return The index of the added effect
|
||||
*/
|
||||
ParticleEffectIndex addEffect(ParticleEffectPtr effect);
|
||||
ParticleEffectHandle addEffect(ParticleEffectPtr effect);
|
||||
|
||||
/**
|
||||
* @brief Does one processing step of the particle manager
|
||||
@@ -128,7 +132,7 @@ class ParticleManager {
|
||||
* @param index The index of the effect
|
||||
* @return A wrapper class which allows access to the created sources
|
||||
*/
|
||||
ParticleSourceWrapper createSource(ParticleEffectIndex index);
|
||||
ParticleSourceWrapper createSource(ParticleEffectHandle index);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
@@ -142,8 +146,7 @@ namespace internal {
|
||||
* @param name The name of the created effect, an empty string means no special name
|
||||
* @return The index of the added effect
|
||||
*/
|
||||
ParticleEffectIndex parseEffectElement(EffectType forcedType = EffectType::Invalid,
|
||||
const SCP_string& name = "");
|
||||
ParticleEffectHandle parseEffectElement(EffectType forcedType = EffectType::Invalid, const SCP_string& name = "");
|
||||
|
||||
/**
|
||||
* @brief Utility function for required_string
|
||||
@@ -178,7 +181,7 @@ namespace util {
|
||||
* @param objectName Can be optionally specified so the error message is a bit more specific
|
||||
* @return The index
|
||||
*/
|
||||
ParticleEffectIndex parseEffect(const SCP_string& objectName = "");
|
||||
ParticleEffectHandle parseEffect(const SCP_string& objectName = "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ bool CompositeEffect::processSource(const ParticleSource*) {
|
||||
void CompositeEffect::parseValues(bool) {
|
||||
while (optional_string("+Child effect:")) {
|
||||
auto effectId = internal::parseEffectElement();
|
||||
if (effectId >= 0) {
|
||||
if (effectId.isValid()) {
|
||||
ParticleEffectPtr effect = ParticleManager::get()->getEffect(effectId);
|
||||
|
||||
if (effect->getType() == EffectType::Composite) {
|
||||
|
||||
@@ -32,7 +32,7 @@ class GenericShapeEffect : public ParticleEffect {
|
||||
::util::UniformFloatRange m_velocity;
|
||||
::util::UniformUIntRange m_particleNum;
|
||||
|
||||
ParticleEffectIndex m_particleTrail = -1;
|
||||
ParticleEffectHandle m_particleTrail = ParticleEffectHandle::invalid();
|
||||
|
||||
util::EffectTiming m_timing;
|
||||
|
||||
@@ -113,7 +113,7 @@ class GenericShapeEffect : public ParticleEffect {
|
||||
}
|
||||
vm_vec_scale(&info.vel, m_velocity.next());
|
||||
|
||||
if (m_particleTrail >= 0) {
|
||||
if (m_particleTrail.isValid()) {
|
||||
auto part = m_particleProperties.createPersistentParticle(info);
|
||||
|
||||
auto trailSource = ParticleManager::get()->createSource(m_particleTrail);
|
||||
|
||||
+2
-2
@@ -1593,7 +1593,7 @@ ship_info::ship_info()
|
||||
regular_end_particles.min_vel = 0.0f;
|
||||
regular_end_particles.variance = 2.0f;
|
||||
|
||||
death_effect = -1;
|
||||
death_effect = particle::ParticleEffectHandle::invalid();
|
||||
|
||||
debris_min_lifetime = -1.0f;
|
||||
debris_max_lifetime = -1.0f;
|
||||
@@ -7999,7 +7999,7 @@ static void ship_dying_frame(object *objp, int ship_num)
|
||||
}
|
||||
|
||||
if (!knossos_ship){
|
||||
if (sip->death_effect > 0) {
|
||||
if (sip->death_effect.isValid()) {
|
||||
// Use the new particle effect
|
||||
auto source = particle::ParticleManager::get()->createSource(sip->death_effect);
|
||||
|
||||
|
||||
+1
-1
@@ -1015,7 +1015,7 @@ public:
|
||||
particle_effect knossos_end_particles;
|
||||
particle_effect regular_end_particles;
|
||||
|
||||
particle::ParticleEffectIndex death_effect;
|
||||
particle::ParticleEffectHandle death_effect;
|
||||
|
||||
//Debris stuff
|
||||
float debris_min_lifetime;
|
||||
|
||||
@@ -3079,10 +3079,11 @@ void beam_handle_collisions(beam *b)
|
||||
// KOMET_EXT -->
|
||||
|
||||
// draw flash, explosion
|
||||
if (draw_effects && ((wi->piercing_impact_effect >= 0) || (wi->flash_impact_weapon_expl_effect >= 0))) {
|
||||
if (draw_effects &&
|
||||
((wi->piercing_impact_effect.isValid()) || (wi->flash_impact_weapon_expl_effect.isValid()))) {
|
||||
float rnd = frand();
|
||||
int do_expl = 0;
|
||||
if((rnd < 0.2f || apply_beam_physics) && wi->impact_weapon_expl_effect >= 0){
|
||||
if ((rnd < 0.2f || apply_beam_physics) && wi->impact_weapon_expl_effect.isValid()) {
|
||||
do_expl = 1;
|
||||
}
|
||||
vec3d temp_pos, temp_local_pos;
|
||||
@@ -3103,7 +3104,7 @@ void beam_handle_collisions(beam *b)
|
||||
vm_vec_unrotate(&worldNormal, &b->f_collisions[idx].cinfo.hit_normal, &Objects[target].orient);
|
||||
}
|
||||
|
||||
if (wi->flash_impact_weapon_expl_effect >= 0) {
|
||||
if (wi->flash_impact_weapon_expl_effect.isValid()) {
|
||||
auto particleSource = particle::ParticleManager::get()->createSource(wi->flash_impact_weapon_expl_effect);
|
||||
particleSource.moveToObject(&Objects[target], &temp_local_pos);
|
||||
particleSource.setOrientationNormal(&worldNormal);
|
||||
@@ -3132,8 +3133,8 @@ void beam_handle_collisions(beam *b)
|
||||
|
||||
particleSource.finish();
|
||||
}
|
||||
|
||||
if (wi->piercing_impact_effect > 0) {
|
||||
|
||||
if (wi->piercing_impact_effect.isValid()) {
|
||||
vec3d fvec;
|
||||
vm_vec_sub(&fvec, &b->last_shot, &b->last_start);
|
||||
|
||||
@@ -3200,7 +3201,7 @@ void beam_handle_collisions(beam *b)
|
||||
} else {
|
||||
if(draw_effects && apply_beam_physics && !physics_paused){
|
||||
// maybe draw an explosion, if we aren't hitting shields
|
||||
if ( (wi->impact_weapon_expl_effect >= 0) && (b->f_collisions[idx].quadrant < 0) ) {
|
||||
if ((wi->impact_weapon_expl_effect.isValid()) && (b->f_collisions[idx].quadrant < 0)) {
|
||||
vec3d worldNormal;
|
||||
if (Objects[target].type == OBJ_SHIP) {
|
||||
auto shipp = &Ships[Objects[target].instance];
|
||||
|
||||
@@ -337,17 +337,17 @@ typedef struct weapon_info {
|
||||
|
||||
float shield_impact_explosion_radius;
|
||||
|
||||
particle::ParticleEffectIndex impact_weapon_expl_effect; // Impact particle effect
|
||||
|
||||
particle::ParticleEffectIndex dinky_impact_weapon_expl_effect; // Dinky impact particle effect
|
||||
particle::ParticleEffectHandle impact_weapon_expl_effect; // Impact particle effect
|
||||
|
||||
particle::ParticleEffectIndex flash_impact_weapon_expl_effect;
|
||||
particle::ParticleEffectHandle dinky_impact_weapon_expl_effect; // Dinky impact particle effect
|
||||
|
||||
particle::ParticleEffectIndex piercing_impact_effect;
|
||||
particle::ParticleEffectIndex piercing_impact_secondary_effect;
|
||||
particle::ParticleEffectHandle flash_impact_weapon_expl_effect;
|
||||
|
||||
particle::ParticleEffectHandle piercing_impact_effect;
|
||||
particle::ParticleEffectHandle piercing_impact_secondary_effect;
|
||||
|
||||
// Particle effect for the various states, WeaponState::NORMAL is the state for the whole lifetime, even for missiles
|
||||
SCP_unordered_map<WeaponState, particle::ParticleEffectIndex, WeaponStateHash> state_effects;
|
||||
SCP_unordered_map<WeaponState, particle::ParticleEffectHandle, WeaponStateHash> state_effects;
|
||||
|
||||
// EMP effect
|
||||
float emp_intensity; // intensity of the EMP effect
|
||||
|
||||
+11
-16
@@ -1668,8 +1668,7 @@ int parse_weapon(int subtype, bool replace, const char *filename)
|
||||
|
||||
// Default value
|
||||
wip->shield_impact_explosion_radius = 1.0f;
|
||||
if (wip->impact_weapon_expl_effect >= 0)
|
||||
{
|
||||
if (wip->impact_weapon_expl_effect.isValid()) {
|
||||
auto singleEffect = dynamic_cast<effects::SingleParticleEffect*>(ParticleManager::get()->getEffect(wip->impact_weapon_expl_effect));
|
||||
|
||||
if (singleEffect)
|
||||
@@ -1743,7 +1742,7 @@ int parse_weapon(int subtype, bool replace, const char *filename)
|
||||
if (first_time)
|
||||
{
|
||||
// The secondary effect is only needed if the old effect got parsed
|
||||
wip->piercing_impact_secondary_effect = -1;
|
||||
wip->piercing_impact_secondary_effect = particle::ParticleEffectHandle::invalid();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -6142,8 +6141,7 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu
|
||||
weapon_hit_do_sound(other_obj, wip, hitpos, armed_weapon, quadrant);
|
||||
}
|
||||
|
||||
if ( wip->impact_weapon_expl_effect >= 0 && armed_weapon)
|
||||
{
|
||||
if (wip->impact_weapon_expl_effect.isValid() && armed_weapon) {
|
||||
auto particleSource = particle::ParticleManager::get()->createSource(wip->impact_weapon_expl_effect);
|
||||
particleSource.moveTo(hitpos);
|
||||
particleSource.setOrientationFromVec(&weapon_obj->phys_info.vel);
|
||||
@@ -6154,9 +6152,7 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu
|
||||
}
|
||||
|
||||
particleSource.finish();
|
||||
}
|
||||
else if(wip->dinky_impact_weapon_expl_effect >= 0 && !armed_weapon)
|
||||
{
|
||||
} else if (wip->dinky_impact_weapon_expl_effect.isValid() && !armed_weapon) {
|
||||
auto particleSource = particle::ParticleManager::get()->createSource(wip->dinky_impact_weapon_expl_effect);
|
||||
particleSource.moveTo(hitpos);
|
||||
particleSource.setOrientationFromVec(&weapon_obj->phys_info.vel);
|
||||
@@ -6169,7 +6165,7 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu
|
||||
particleSource.finish();
|
||||
}
|
||||
|
||||
if((other_obj != NULL) && (quadrant == -1) && (wip->piercing_impact_effect > -1 && armed_weapon)) {
|
||||
if ((other_obj != nullptr) && (quadrant == -1) && (wip->piercing_impact_effect.isValid() && armed_weapon)) {
|
||||
if ((other_obj->type == OBJ_SHIP) || (other_obj->type == OBJ_DEBRIS)) {
|
||||
|
||||
int ok_to_draw = 1;
|
||||
@@ -6211,8 +6207,7 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu
|
||||
|
||||
primarySource.finish();
|
||||
|
||||
if (wip->piercing_impact_secondary_effect >= 0)
|
||||
{
|
||||
if (wip->piercing_impact_secondary_effect.isValid()) {
|
||||
auto secondarySource = ParticleManager::get()->createSource(wip->piercing_impact_secondary_effect);
|
||||
secondarySource.moveTo(&weapon_obj->pos);
|
||||
secondarySource.setOrientationMatrix(&weapon_obj->last_orient);
|
||||
@@ -7676,14 +7671,14 @@ void weapon_info::reset()
|
||||
|
||||
this->shield_impact_explosion_radius = 1.0f;
|
||||
|
||||
this->impact_weapon_expl_effect = -1;
|
||||
this->impact_weapon_expl_effect = particle::ParticleEffectHandle::invalid();
|
||||
|
||||
this->dinky_impact_weapon_expl_effect = -1;
|
||||
this->dinky_impact_weapon_expl_effect = particle::ParticleEffectHandle::invalid();
|
||||
|
||||
this->flash_impact_weapon_expl_effect = -1;
|
||||
this->flash_impact_weapon_expl_effect = particle::ParticleEffectHandle::invalid();
|
||||
|
||||
this->piercing_impact_effect = -1;
|
||||
this->piercing_impact_secondary_effect = -1;
|
||||
this->piercing_impact_effect = particle::ParticleEffectHandle::invalid();
|
||||
this->piercing_impact_secondary_effect = particle::ParticleEffectHandle::invalid();
|
||||
|
||||
this->muzzle_flash = -1;
|
||||
|
||||
|
||||
Reference in new issue
Block a user