Merge pull request #1797 from asarium/fix/particleEffectHandles

Use type-safe handles for particle effects
This commit is contained in:
m!m authored and GitHub committed 2018-07-15 16:37:31 +02:00
commit 7f03ac31ae
10 files changed
+65 -61

No files matched your search

+1 -1
View File
@@ -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 );
}
}
+17 -12
View File
@@ -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) {
+16 -13
View File
@@ -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 = "");
}
}
+1 -1
View File
@@ -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) {
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+7 -6
View File
@@ -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];
+7 -7
View File
@@ -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
View File
@@ -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;