diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index adc5d5e0d2..36a8eea9aa 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -314,8 +314,6 @@ static void MarkRoot() if (playeringame[i]) players[i].PropagateMark(); } - // Mark sound sequences. - DSeqNode::StaticMarkHead(); // Mark sectors. if (SectorMarker == nullptr && level.sectors.Size() > 0) { diff --git a/src/g_level.cpp b/src/g_level.cpp index aee49e878a..8668140719 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1981,6 +1981,8 @@ void FLevelLocals::Mark() GC::Mark(FraggleScriptThinker); GC::Mark(ACSThinker); GC::Mark(interpolator.Head); + GC::Mark(SequenceListHead); + canvasTextureInfo.Mark(); for (auto &c : CorpseQueue) { diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 0ac845d1c2..0ad5546724 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -53,6 +53,7 @@ class DACSThinker; class DFraggleThinker; class DSpotState; +class DSeqNode; struct FStrifeDialogueNode; typedef TMap FDialogueIDMap; // maps dialogue IDs to dialogue array index (for ACS) @@ -224,6 +225,9 @@ struct FLevelLocals : public FLevelData FInterpolator interpolator; + int ActiveSequences; + DSeqNode *SequenceListHead; + TArray Scrolls; // NULL if no DScrollers in this level int8_t WallVertLight; // Light diffs for vert/horiz walls diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 95918faa73..8922f4bcd8 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -545,7 +545,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, zone_t &z, zone_t *def void P_SerializeSounds(FSerializer &arc) { S_SerializeSounds(arc, &level); - DSeqNode::SerializeSequences (arc); const char *name = NULL; uint8_t order; float musvol = level.MusicVolume; @@ -984,7 +983,9 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) ("acsthinker", Level->ACSThinker) ("impactdecalcount", Level->ImpactDecalCount) ("freeze", Level->freeze) - ("changefreeze", Level->changefreeze); + ("changefreeze", Level->changefreeze) + ("sndseqlisthead", Level->SequenceListHead); + // Hub transitions must keep the current total time if (!hubload) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ceb62855d7..4c0aec72ef 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -262,6 +262,8 @@ void FLevelLocals::ClearLevelData() killed_monsters = found_items = found_secrets = wminfo.maxfrags = 0; + SN_StopAllSequences(this); + FStrifeDialogueNode *node; while (StrifeDialogues.Pop (node)) @@ -352,8 +354,6 @@ void P_FreeLevelData () R_FreePastViewers(); P_ClearUDMFKeys(); - SN_StopAllSequences (); - level.ClearLevelData(); } diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index d08a26732d..18e65e9396 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -219,8 +219,6 @@ static bool TwiddleSeqNum (int &sequence, seqtype_t type); // PUBLIC DATA DEFINITIONS ------------------------------------------------- FSoundSequencePtrArray Sequences; -int ActiveSequences; -DSeqNode *DSeqNode::SequenceListHead; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -289,11 +287,6 @@ static FRandom pr_sndseq ("SndSeq"); // CODE -------------------------------------------------------------------- -void DSeqNode::SerializeSequences (FSerializer &arc) -{ - arc("sndseqlisthead", SequenceListHead); -} - IMPLEMENT_CLASS(DSeqNode, false, true) IMPLEMENT_POINTERS_START(DSeqNode) @@ -361,6 +354,7 @@ void DSeqNode::Serialize(FSerializer &arc) } else { + Level = &level; // temporary solution seqnum = FindSequence (seqName); if (seqnum >= 0) { @@ -397,9 +391,9 @@ void DSeqNode::OnDestroy() m_ParentSeqNode->m_ChildSeqNode = nullptr; m_ParentSeqNode = nullptr; } - if (SequenceListHead == this) + if (Level->SequenceListHead == this) { - SequenceListHead = m_Next; + Level->SequenceListHead = m_Next; GC::WriteBarrier(m_Next); } if (m_Prev) @@ -412,7 +406,7 @@ void DSeqNode::OnDestroy() m_Next->m_Prev = m_Prev; GC::WriteBarrier(m_Next, m_Prev); } - ActiveSequences--; + Level->ActiveSequences--; Super::OnDestroy(); } @@ -803,20 +797,21 @@ static void AddSequence (int curseq, FName seqname, FName slot, int stopsound, c Sequences[curseq]->Script[ScriptTemp.Size()] = MakeCommand(SS_CMD_END, 0); } -DSeqNode::DSeqNode (int sequence, int modenum) +DSeqNode::DSeqNode (FLevelLocals *l, int sequence, int modenum) : m_ModeNum(modenum), m_SequenceChoices(0) { + Level = l; ActivateSequence (sequence); - if (!SequenceListHead) + if (!Level->SequenceListHead) { - SequenceListHead = this; + Level->SequenceListHead = this; m_Next = m_Prev = NULL; } else { - SequenceListHead->m_Prev = this; GC::WriteBarrier(SequenceListHead->m_Prev, this); - m_Next = SequenceListHead; GC::WriteBarrier(this, SequenceListHead); - SequenceListHead = this; + Level->SequenceListHead->m_Prev = this; GC::WriteBarrier(Level->SequenceListHead->m_Prev, this); + m_Next = Level->SequenceListHead; GC::WriteBarrier(this, Level->SequenceListHead); + Level->SequenceListHead = this; m_Prev = NULL; } GC::WriteBarrier(this); @@ -832,24 +827,23 @@ void DSeqNode::ActivateSequence (int sequence) m_CurrentSoundID = 0; m_Volume = 1; // Start at max volume... m_Atten = ATTN_IDLE; // ...and idle attenuation - - ActiveSequences++; + Level->ActiveSequences++; } DSeqActorNode::DSeqActorNode (AActor *actor, int sequence, int modenum) - : DSeqNode (sequence, modenum), + : DSeqNode (actor->Level, sequence, modenum), m_Actor (actor) { } DSeqPolyNode::DSeqPolyNode (FPolyObj *poly, int sequence, int modenum) - : DSeqNode (sequence, modenum), + : DSeqNode (poly->GetLevel(), sequence, modenum), m_Poly (poly) { } DSeqSectorNode::DSeqSectorNode (sector_t *sec, int chan, int sequence, int modenum) - : DSeqNode (sequence, modenum), + : DSeqNode (sec->Level, sequence, modenum), Channel (chan), m_Sector (sec) { @@ -1048,7 +1042,8 @@ static int FindSequence (FName seqname) DSeqNode *SN_CheckSequence(sector_t *sector, int chan) { - for (DSeqNode *node = DSeqNode::FirstSequence(); node; ) + auto Level = sector->Level; + for (DSeqNode *node = Level->SequenceListHead; node; ) { DSeqNode *next = node->NextSequence(); if (node->Source() == sector) @@ -1079,7 +1074,7 @@ DEFINE_ACTION_FUNCTION(_Sector, CheckSoundSequence) void SN_StopSequence (AActor *actor) { - SN_DoStop (actor); + SN_DoStop (actor->Level, actor); } DEFINE_ACTION_FUNCTION(AActor, StopSoundSequence) @@ -1109,14 +1104,14 @@ DEFINE_ACTION_FUNCTION(_Sector, StopSoundSequence) void SN_StopSequence (FPolyObj *poly) { - SN_DoStop (poly); + SN_DoStop (poly->GetLevel(), poly); } -void SN_DoStop (void *source) +void SN_DoStop (FLevelLocals *Level, void *source) { DSeqNode *node; - for (node = DSeqNode::FirstSequence(); node; ) + for (node = Level->SequenceListHead; node; ) { DSeqNode *next = node->NextSequence(); if (node->Source() == source) @@ -1164,7 +1159,7 @@ bool SN_IsMakingLoopingSound (sector_t *sector) { DSeqNode *node; - for (node = DSeqNode::FirstSequence (); node; ) + for (node = sector->Level->SequenceListHead; node; ) { DSeqNode *next = node->NextSequence(); if (node->Source() == (void *)sector) @@ -1328,7 +1323,7 @@ void DSeqNode::Tick () int seqnum = FindSequence (ENamedName(m_SequencePtr[i*2+1])); if (seqnum >= 0) { // Found a match, and it's a good one too. - ActiveSequences--; + Level->ActiveSequences--; ActivateSequence (seqnum); break; } @@ -1359,15 +1354,15 @@ void DSeqNode::Tick () } } -void SN_UpdateActiveSequences (void) +void SN_UpdateActiveSequences (FLevelLocals *Level) { DSeqNode *node; - if (!ActiveSequences || paused) + if (!Level->ActiveSequences || paused) { // No sequences currently playing/game is paused return; } - for (node = DSeqNode::FirstSequence(); node; node = node->NextSequence()) + for (node =Level->SequenceListHead; node; node = node->NextSequence()) { node->Tick (); } @@ -1379,11 +1374,11 @@ void SN_UpdateActiveSequences (void) // //========================================================================== -void SN_StopAllSequences (void) +void SN_StopAllSequences (FLevelLocals *Level) { DSeqNode *node; - for (node = DSeqNode::FirstSequence(); node; ) + for (node = Level->SequenceListHead; node; ) { DSeqNode *next = node->NextSequence(); node->m_StopSound = 0; // don't play any stop sounds @@ -1470,14 +1465,14 @@ DEFINE_ACTION_FUNCTION(DSeqNode, MarkPrecacheSounds) // nodeNum zero is the first node //========================================================================== -void SN_ChangeNodeData (int nodeNum, int seqOffset, int delayTics, float volume, +void SN_ChangeNodeData (FLevelLocals *Level, int nodeNum, int seqOffset, int delayTics, float volume, int currentSoundID) { int i; DSeqNode *node; i = 0; - node = DSeqNode::FirstSequence(); + node = Level->SequenceListHead; while (node && i < nodeNum) { node = node->NextSequence(); diff --git a/src/s_sndseq.h b/src/s_sndseq.h index 83b0475bef..17e4284d26 100644 --- a/src/s_sndseq.h +++ b/src/s_sndseq.h @@ -28,21 +28,18 @@ public: void AddChoice (int seqnum, seqtype_t type); int GetModeNum() const { return m_ModeNum; } FName GetSequenceName() const; - static void StaticMarkHead() { GC::Mark(SequenceListHead); } virtual void MakeSound (int loop, FSoundID id) {} virtual void *Source () { return NULL; } virtual bool IsPlaying () { return false; } virtual DSeqNode *SpawnChild (int seqnum) { return NULL; } - inline static DSeqNode *FirstSequence() { return SequenceListHead; } inline DSeqNode *NextSequence() const { return m_Next; } - static void SerializeSequences (FSerializer &arc); protected: DSeqNode (); - DSeqNode (int sequence, int modenum); + DSeqNode (FLevelLocals *l, int sequence, int modenum); int32_t *m_SequencePtr; int m_Sequence; @@ -54,20 +51,20 @@ protected: float m_Atten; int m_ModeNum; + FLevelLocals *Level; TArray m_SequenceChoices; TObjPtr m_ChildSeqNode; TObjPtr m_ParentSeqNode; private: - static DSeqNode *SequenceListHead; DSeqNode *m_Next, *m_Prev; void ActivateSequence (int sequence); - friend void SN_StopAllSequences (void); + friend void SN_StopAllSequences (FLevelLocals *Level); }; -void SN_StopAllSequences (void); +void SN_StopAllSequences (FLevelLocals *Level); struct FSoundSequence { @@ -92,11 +89,10 @@ void SN_StopSequence (sector_t *sector, int chan); void SN_StopSequence (FPolyObj *poly); bool SN_AreModesSame(int sequence, seqtype_t type, int mode1, int mode2); bool SN_AreModesSame(FName name, int mode1, int mode2); -void SN_UpdateActiveSequences (void); +void SN_UpdateActiveSequences (FLevelLocals *Level); ptrdiff_t SN_GetSequenceOffset (int sequence, int32_t *sequencePtr); -void SN_DoStop (void *); -void SN_ChangeNodeData (int nodeNum, int seqOffset, int delayTics, - float volume, int currentSoundID); +void SN_DoStop (FLevelLocals *Level, void *); +void SN_ChangeNodeData (FLevelLocals *Level, int nodeNum, int seqOffset, int delayTics, float volume, int currentSoundID); FName SN_GetSequenceSlot (int sequence, seqtype_t type); void SN_MarkPrecacheSounds (int sequence, seqtype_t type); bool SN_IsMakingLoopingSound (sector_t *sector); diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 4f6b4c66c8..9d3599bcd2 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1768,7 +1768,7 @@ void S_StopSound (const FPolyObj *poly, int channel) void S_StopAllChannels () { - SN_StopAllSequences(); + ForAllLevels(SN_StopAllSequences); FSoundChan *chan = Channels; while (chan != NULL) @@ -2195,7 +2195,7 @@ void S_UpdateSounds (AActor *listenactor) chan->ChanFlags &= ~CHAN_JUSTSTARTED; } - SN_UpdateActiveSequences(); + ForAllLevels(SN_UpdateActiveSequences); GSnd->UpdateListener(&listener); diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index fe1c994ebb..c8f418faaa 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -769,7 +769,7 @@ void WI_Start(wbstartstruct_t *wbstartstruct) else wbstartstruct->nextname = info->LookupLevelName(); V_SetBlend(0, 0, 0, 0); S_StopAllChannels(); - SN_StopAllSequences(); + ForAllLevels(SN_StopAllSequences); WI_Screen = cls->CreateNew(); IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Start) {