Skip to content

Commit

Permalink
Merge pull request scp-fs2open#1797 from asarium/fix/particleEffectHa…
Browse files Browse the repository at this point in the history
…ndles

Use type-safe handles for particle effects
  • Loading branch information
asarium authored Jul 15, 2018
2 parents 25b396f + c6e2f94 commit 7f03ac3
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 61 deletions.
2 changes: 1 addition & 1 deletion code/asteroid/asteroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
}
Expand Down
29 changes: 17 additions & 12 deletions code/particle/ParticleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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) {
Expand Down Expand Up @@ -210,15 +211,16 @@ void ParticleManager::doFrame(float) {
}
}

ParticleEffectIndex ParticleManager::addEffect(ParticleEffectPtr effect) {
ParticleEffectHandle ParticleManager::addEffect(ParticleEffectPtr effect)
{
Assertion(effect, "Invalid effect pointer passed!");

#ifndef NDEBUG
if (!effect->getName().empty()) {
// 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;
}
Expand All @@ -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() {
Expand All @@ -236,7 +238,8 @@ void ParticleManager::pageIn() {
}
}

ParticleSourceWrapper ParticleManager::createSource(ParticleEffectIndex index) {
ParticleSourceWrapper ParticleManager::createSource(ParticleEffectHandle index)
{
ParticleEffectPtr eff = this->getEffect(index);
ParticleSourceWrapper wrapper;

Expand Down Expand Up @@ -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 {
Expand All @@ -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) {
Expand Down
29 changes: 16 additions & 13 deletions code/particle/ParticleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}

/**
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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 = "");
}
}

Expand Down
2 changes: 1 addition & 1 deletion code/particle/effects/CompositeEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions code/particle/effects/GenericShapeEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions code/ship/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion code/ship/ship.h
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ class ship_info
particle_effect knossos_end_particles;
particle_effect regular_end_particles;

particle::ParticleEffectIndex death_effect;
particle::ParticleEffectHandle death_effect;

//Debris stuff
float debris_min_lifetime;
Expand Down
13 changes: 7 additions & 6 deletions code/weapon/beam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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];
Expand Down
14 changes: 7 additions & 7 deletions code/weapon/weapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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::ParticleEffectHandle dinky_impact_weapon_expl_effect; // Dinky impact particle effect

particle::ParticleEffectIndex flash_impact_weapon_expl_effect;
particle::ParticleEffectHandle flash_impact_weapon_expl_effect;

particle::ParticleEffectIndex piercing_impact_effect;
particle::ParticleEffectIndex piercing_impact_secondary_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
Expand Down
27 changes: 11 additions & 16 deletions code/weapon/weapons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 7f03ac3

Please sign in to comment.