From ae57bc71d4a99c1a18390aa425ae3bc9b9e5df14 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 18 Aug 2019 13:48:52 +0200 Subject: [PATCH] - fixed attached dynamic light setup. This was only run on a state change and missed every external light change. Any place which wants to flag a light change now only will set a flag and at the end of the thinker loop all flagged actors will be processed. For performance reasons this was merged with the P_RunEffects iterator loop. --- src/p_tick.cpp | 19 +++++++++++++++++-- src/playsim/a_dynlight.cpp | 19 ++++++++----------- src/playsim/actor.h | 3 ++- src/playsim/p_effect.cpp | 19 ------------------- src/playsim/p_effect.h | 1 - src/playsim/p_mobj.cpp | 4 ++-- 6 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 0407ba81b..42b18224f 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -134,7 +134,6 @@ void P_Ticker (void) for (auto Level : AllLevels()) { // todo: set up a sandbox for secondary levels here. - auto it = Level->GetThinkerIterator(); AActor *ac; @@ -142,6 +141,7 @@ void P_Ticker (void) { ac->ClearInterpolation(); } + P_ThinkParticles(Level); // [RH] make the particles think for (i = 0; i < MAXPLAYERS; i++) @@ -157,7 +157,22 @@ void P_Ticker (void) if (!Level->isFrozen()) { P_UpdateSpecials(Level); - P_RunEffects(Level); // [RH] Run particle effects + } + it = Level->GetThinkerIterator(); + + // Set dynamic lights at the end of the tick, so that this catches all changes being made through the last frame. + while ((ac = it.Next())) + { + if (ac->flags8 & MF8_RECREATELIGHTS) + { + ac->flags8 &= ~MF8_RECREATELIGHTS; + ac->SetDynamicLights(); + } + // This was merged from P_RunEffects to eliminate the costly duplicate ThinkerIterator loop. + if ((ac->effects || ac->fountaincolor) && !Level->isFrozen()) + { + P_RunEffect(ac, ac->effects); + } } // for par times diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 6332bf83d..9aea2689a 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -764,17 +764,11 @@ void AActor::SetDynamicLights() AttachLight(count++, def); } - if (LightAssociations.Size() > 0) + for (const auto asso : LightAssociations) { - unsigned int i; - - for (i = 0; i < LightAssociations.Size(); i++) + if (asso->Sprite() == sprite && (asso->Frame() == frame || asso->Frame() == -1)) { - if (LightAssociations[i]->Sprite() == sprite && - (LightAssociations[i]->Frame()==frame || LightAssociations[i]->Frame()==-1)) - { - AttachLight(count++, LightAssociations[i]->Light()); - } + AttachLight(count++, asso->Light()); } } if (count == 0 && state->Light > 0) @@ -850,6 +844,7 @@ int AttachLightDef(AActor *self, int _lightid, int _lightname) { auto userlight = self->UserLights[FindUserLight(self, lightid, true)]; userlight->CopyFrom(*LightDefaults[lightdef]); + self->flags8 |= MF8_RECREATELIGHTS; return 1; } return 0; @@ -893,7 +888,7 @@ int AttachLightDirect(AActor *self, int _lightid, int type, int color, int radiu { userlight->UnsetSpotPitch(); } - + self->flags8 |= MF8_RECREATELIGHTS; return 1; } @@ -930,8 +925,10 @@ int RemoveLight(AActor *self, int _lightid) { delete self->UserLights[userlight]; self->UserLights.Delete(userlight); + self->flags8 |= MF8_RECREATELIGHTS; + return 1; } - return 1; + return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_RemoveLight, RemoveLight) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index e2114d109..0b76592e2 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -409,7 +409,8 @@ enum ActorFlag8 MF8_HITOWNER = 0x00000010, // projectile can hit the actor that fired it MF8_NOFRICTION = 0x00000020, // friction doesn't apply to the actor at all MF8_NOFRICTIONBOUNCE = 0x00000040, // don't bounce off walls when on icy floors - MF8_RETARGETAFTERSLAM = 0x00000080 // Forces jumping to the idle state after slamming into something + MF8_RETARGETAFTERSLAM = 0x00000080, // Forces jumping to the idle state after slamming into something + MF8_RECREATELIGHTS = 0x00000100, // Internal flag that signifies that the light attachments need to be recreated at the }; // --- mobj.renderflags --- diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 54f362347..1e9d8e1d1 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -299,25 +299,6 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v } } -// -// P_RunEffects -// -// Run effects on all actors in the world -// -void P_RunEffects (FLevelLocals *Level) -{ - AActor *actor; - auto iterator = Level->GetThinkerIterator(); - - while ( (actor = iterator.Next ()) ) - { - if (actor->effects || actor->fountaincolor) - { - P_RunEffect (actor, actor->effects); - } - } -} - // // JitterParticle // diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 22a9ab823..a2aeacbec 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -78,7 +78,6 @@ particle_t *JitterParticle (FLevelLocals *Level, int ttl, double drift); void P_ThinkParticles (FLevelLocals *Level); void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double sizestep, int flags = 0); void P_InitEffects (void); -void P_RunEffects (FLevelLocals *Level); void P_RunEffect (AActor *actor, int effects); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 6fce5d039..590c95fea 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -577,7 +577,7 @@ bool AActor::SetState (FState *newstate, bool nofunction) newstate = newstate->GetNextState(); } while (tics == 0); - SetDynamicLights(); + flags8 |= MF8_RECREATELIGHTS; return true; } @@ -4702,9 +4702,9 @@ void AActor::CallBeginPlay() void AActor::PostBeginPlay () { - SetDynamicLights(); PrevAngles = Angles; flags7 |= MF7_HANDLENODELAY; + flags8 |= MF8_RECREATELIGHTS; } void AActor::CallPostBeginPlay()