From 64595abe60baaaa73cfa7e40d69d10022b36a283 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Dec 2018 10:08:39 +0100 Subject: [PATCH] - moved main polyobject array into FLevelLocals and simplified the setup process to not depend on P_SpawnMapThing. Since the SpawnedThings array is still available when polyobjects are spawned it makes no sense to create an expensive linked list in P_SpawnMapThing. This can be done far better by scanning through the array again and collect all matching items in a second array. --- src/am_map.cpp | 5 +- src/dobjgc.cpp | 28 ++------- src/g_levellocals.h | 2 + src/maploader/maploader.cpp | 2 + src/maploader/maploader.h | 3 +- src/p_mobj.cpp | 12 +--- src/p_saveg.cpp | 4 +- src/p_setup.cpp | 7 +-- src/po_man.cpp | 112 +++++++++++++++++------------------- src/po_man.h | 17 ------ src/serializer.cpp | 4 +- src/win32/i_main.cpp | 2 +- 12 files changed, 72 insertions(+), 126 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 8e39951b4a..95d9780542 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2333,10 +2333,9 @@ void AM_showSS() AM_drawSeg(sub->firstline + i, yellow); } - for (int i = 0; i subsectorlinks; + FPolyNode *pnode = poly.subsectorlinks; while (pnode != NULL) { diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 51e95313db..35ecaaf447 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -190,24 +190,6 @@ size_t PropagateMark() obj->GetClass()->Size; } -//========================================================================== -// -// PropagateAll -// -// Empties the gray list by propagating every single object in it. -// -//========================================================================== - -static size_t PropagateAll() -{ - size_t m = 0; - while (Gray != NULL) - { - m += PropagateMark(); - } - return m; -} - //========================================================================== // // SweepList @@ -668,14 +650,14 @@ size_t DSectorMarker::PropagateMark() moretodo = true; } - if (!moretodo && polyobjs != NULL) + if (!moretodo && level.Polyobjects.Size() > 0) { - for (i = 0; i < POLYSTEPSIZE && PolyNum + i < po_NumPolyobjs; ++i) + for (i = 0; i < POLYSTEPSIZE && PolyNum + i < (int)level.Polyobjects.Size(); ++i) { - GC::Mark(polyobjs[PolyNum + i].interpolation); + GC::Mark(level.Polyobjects[PolyNum + i].interpolation); } marked += i * sizeof(FPolyObj); - if (PolyNum + i < po_NumPolyobjs) + if (PolyNum + i < (int)level.Polyobjects.Size()) { PolyNum += i; moretodo = true; @@ -686,7 +668,7 @@ size_t DSectorMarker::PropagateMark() for (i = 0; i < SIDEDEFSTEPSIZE && SideNum + i < (int)level.sides.Size(); ++i) { side_t *side = &level.sides[SideNum + i]; - for(int j=0;j<3;j++) GC::Mark(side->textures[j].interpolation); + for (int j = 0; j < 3; j++) GC::Mark(side->textures[j].interpolation); } marked += i * sizeof(side_t); if (SideNum + i < (int)level.sides.Size()) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index a91db47ff2..05ed781600 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -42,6 +42,7 @@ #include "portal.h" #include "p_blockmap.h" #include "p_local.h" +#include "po_man.h" #include "p_destructible.h" #include "r_data/r_sections.h" #include "r_data/r_canvastexture.h" @@ -62,6 +63,7 @@ struct FLevelData node_t *headgamenode; TArray rejectmatrix; TArray Zones; + TArray Polyobjects; TArray sectorPortals; TArray linePortals; diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 157dd2c0db..649ed04329 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -108,6 +108,8 @@ TArray MapThingsConverted; bool ForceNodeBuild; +void PO_Init(); + #define MISSING_TEXTURE_WARN_LIMIT 20 void BloodCrypt (void *data, int key, int len); diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index bd6d6a0206..28631102ba 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -81,7 +81,7 @@ class MapLoader TMap MapThingsUserDataIndex; // from mapthing idx -> user data idx TArray MapThingsUserData; - int sidecount; + int sidecount = 0; TArray linemap; TMap EDLines; @@ -130,6 +130,7 @@ class MapLoader void ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex); void SetMapThingUserData(AActor *actor, unsigned udi); void CreateBlockMap(); + void PO_Init(void); public: void LoadMapinfoACSLump(); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index ca0a950097..e43dcb99be 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5251,17 +5251,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) case SMT_PolySpawn: case SMT_PolySpawnCrush: case SMT_PolySpawnHurt: - { - polyspawns_t *polyspawn = new polyspawns_t; - polyspawn->next = polyspawns; - polyspawn->pos = mthing->pos; - polyspawn->angle = mthing->angle; - polyspawn->type = mentry->Special; - polyspawns = polyspawn; - if (mentry->Special != SMT_PolyAnchor) - po_NumPolyobjs++; - return NULL; - } + return nullptr; case SMT_Player1Start: case SMT_Player2Start: diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 663b6b328e..3131a30875 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -935,7 +935,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) if (arc.GetSize("linedefs") != level.lines.Size() || arc.GetSize("sidedefs") != level.sides.Size() || arc.GetSize("sectors") != level.sectors.Size() || - arc.GetSize("polyobjs") != (unsigned)po_NumPolyobjs || + arc.GetSize("polyobjs") != level.Polyobjects.Size() || memcmp(chk, level.md5, 16)) { I_Error("Savegame is from a different level"); @@ -1007,7 +1007,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) // [ZZ] serialize events E_SerializeEvents(arc); DThinker::SerializeThinkers(arc, hubload); - arc.Array("polyobjs", polyobjs, po_NumPolyobjs); + arc("polyobjs", level.Polyobjects); SerializeSubsectors(arc, "subsectors"); StatusBar->SerializeMessages(arc); AM_SerializeMarkers(arc); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index cc6cd6b7b0..9e372b0594 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -285,6 +285,7 @@ void P_FreeLevelData () level.rejectmatrix.Clear(); level.Zones.Clear(); level.blockmap.Clear(); + level.Polyobjects.Clear(); if (PolyBlockMap != nullptr) { @@ -301,12 +302,6 @@ void P_FreeLevelData () delete[] PolyBlockMap; PolyBlockMap = nullptr; } - if (polyobjs != nullptr) - { - delete[] polyobjs; - polyobjs = nullptr; - } - po_NumPolyobjs = 0; level.deathmatchstarts.Clear(); level.AllPlayerStarts.Clear(); diff --git a/src/po_man.cpp b/src/po_man.cpp index fe34418af2..b366b7569e 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -40,6 +40,8 @@ #include "actorinlines.h" #include "v_text.h" +#include "maploader/maploader.h" + // MACROS ------------------------------------------------------------------ #define PO_MAXPOLYSEGS 64 @@ -146,9 +148,6 @@ static void ReleaseAllPolyNodes(); // PUBLIC DATA DEFINITIONS ------------------------------------------------- polyblock_t **PolyBlockMap; -FPolyObj *polyobjs; // list of all poly-objects on the level -int po_NumPolyobjs; -polyspawns_t *polyspawns; // [RH] Let P_SpawnMapThings() find our thingies for us // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -770,16 +769,14 @@ bool EV_StopPoly(int polynum) FPolyObj *PO_GetPolyobj (int polyNum) { - int i; - - for (i = 0; i < po_NumPolyobjs; i++) + for(auto &poly : level.Polyobjects) { - if (polyobjs[i].tag == polyNum) + if (poly.tag == polyNum) { - return &polyobjs[i]; + return &poly; } } - return NULL; + return nullptr; } @@ -1405,16 +1402,15 @@ void FPolyObj::ClosestPoint(const DVector2 &fpos, DVector2 &out, side_t **side) static void InitBlockMap (void) { - int i; int bmapwidth = level.blockmap.bmapwidth; int bmapheight = level.blockmap.bmapheight; PolyBlockMap = new polyblock_t *[bmapwidth*bmapheight]; memset (PolyBlockMap, 0, bmapwidth*bmapheight*sizeof(polyblock_t *)); - for (i = 0; i < po_NumPolyobjs; i++) + for(auto &poly : level.Polyobjects) { - polyobjs[i].LinkPolyobj(); + poly.LinkPolyobj(); } } @@ -1521,7 +1517,7 @@ static void SpawnPolyobj (int index, int tag, int type) { unsigned int ii; int i; - FPolyObj *po = &polyobjs[index]; + FPolyObj *po = &level.Polyobjects[index]; for (ii = 0; ii < KnownPolySides.Size(); ++ii) { @@ -1547,7 +1543,7 @@ static void SpawnPolyobj (int index, int tag, int type) { sd->linedef->special = 0; sd->linedef->args[0] = 0; - IterFindPolySides(&polyobjs[index], sd); + IterFindPolySides(&level.Polyobjects[index], sd); po->MirrorNum = sd->linedef->args[1]; po->crush = (type != SMT_PolySpawn) ? 3 : 0; po->bHurtOnTouch = (type == SMT_PolySpawnHurt); @@ -1652,16 +1648,8 @@ static void TranslateToStartSpot (int tag, const DVector2 &origin) FPolyObj *po; DVector2 delta; - po = NULL; - for (int i = 0; i < po_NumPolyobjs; i++) - { - if (polyobjs[i].tag == tag) - { - po = &polyobjs[i]; - break; - } - } - if (po == NULL) + po = PO_GetPolyobj(tag); + if (po == nullptr) { // didn't match the tag with a polyobj tag Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); return; @@ -1702,60 +1690,64 @@ static void TranslateToStartSpot (int tag, const DVector2 &origin) // //========================================================================== -void PO_Init (void) +void MapLoader::PO_Init (void) { - // [RH] Hexen found the polyobject-related things by reloading the map's - // THINGS lump here and scanning through it. I have P_SpawnMapThing() - // record those things instead, so that in here we simply need to - // look at the polyspawns list. - polyspawns_t *polyspawn, **prev; + int NumPolyobjs = 0; + TArray polythings; + for (auto &mthing : MapThingsConverted) + { + if (mthing.EdNum == 0 || mthing.EdNum == -1) continue; + + FDoomEdEntry *mentry = mthing.info; + switch (mentry->Special) + { + case SMT_PolyAnchor: + case SMT_PolySpawn: + case SMT_PolySpawnCrush: + case SMT_PolySpawnHurt: + polythings.Push(&mthing); + if (mentry->Special != SMT_PolyAnchor) + NumPolyobjs++; + } + } + int polyIndex; // [RH] Make this faster InitSideLists (); - polyobjs = new FPolyObj[po_NumPolyobjs]; + Level->Polyobjects.Resize(NumPolyobjs); polyIndex = 0; // index polyobj number // Find the startSpot points, and spawn each polyobj - for (polyspawn = polyspawns, prev = &polyspawns; polyspawn;) + for (int i=polythings.Size()-1; i >= 0; i--) { // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch - if (polyspawn->type >= SMT_PolySpawn && polyspawn->type <= SMT_PolySpawnHurt) + int type = polythings[i]->info->Special; + if (type >= SMT_PolySpawn && type <= SMT_PolySpawnHurt) { // Polyobj StartSpot Pt. - polyobjs[polyIndex].StartSpot.pos = polyspawn->pos; - SpawnPolyobj(polyIndex, polyspawn->angle, polyspawn->type); + Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos; + SpawnPolyobj(polyIndex, polythings[i]->angle, type); polyIndex++; - *prev = polyspawn->next; - delete polyspawn; - polyspawn = *prev; } - else - { - prev = &polyspawn->next; - polyspawn = polyspawn->next; - } } - for (polyspawn = polyspawns; polyspawn;) + for (int i = polythings.Size() - 1; i >= 0; i--) { - polyspawns_t *next = polyspawn->next; - if (polyspawn->type == SMT_PolyAnchor) + int type = polythings[i]->info->Special; + if (type == SMT_PolyAnchor) { // Polyobj Anchor Pt. - TranslateToStartSpot (polyspawn->angle, polyspawn->pos); + TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos); } - delete polyspawn; - polyspawn = next; } - polyspawns = NULL; // check for a startspot without an anchor point - for (polyIndex = 0; polyIndex < po_NumPolyobjs; polyIndex++) + for (auto &poly : Level->Polyobjects) { - if (polyobjs[polyIndex].OriginalPts.Size() == 0) + if (poly.OriginalPts.Size() == 0) { - Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", polyobjs[polyIndex].tag); + Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", poly.tag); } } InitBlockMap(); @@ -1765,7 +1757,7 @@ void PO_Init (void) // mark all subsectors which have a seg belonging to a polyobj // These ones should not be rendered on the textured automap. - for (auto &ss : level.subsectors) + for (auto &ss : Level->subsectors) { for(uint32_t j=0;jlines) { if (line.special == Polyobj_ExplicitLine || line.special == Polyobj_StartLine) { @@ -1847,9 +1839,9 @@ void FPolyObj::ClearSubsectorLinks() void FPolyObj::ClearAllSubsectorLinks() { - for (int i = 0; i < po_NumPolyobjs; i++) + for(auto &poly : level.Polyobjects) { - polyobjs[i].ClearSubsectorLinks(); + poly.ClearSubsectorLinks(); } ReleaseAllPolyNodes(); } @@ -2173,11 +2165,11 @@ void FPolyObj::CreateSubsectorLinks() void PO_LinkToSubsectors() { - for (int i = 0; i < po_NumPolyobjs; i++) + for(auto &poly : level.Polyobjects) { - if (polyobjs[i].subsectorlinks == NULL) + if (poly.subsectorlinks == nullptr) { - polyobjs[i].CreateSubsectorLinks(); + poly.CreateSubsectorLinks(); } } } diff --git a/src/po_man.h b/src/po_man.h index 4bf56a147d..7932032723 100644 --- a/src/po_man.h +++ b/src/po_man.h @@ -116,7 +116,6 @@ private: bool CheckMobjBlocking (side_t *sd); }; -extern FPolyObj *polyobjs; // list of all poly-objects on the level struct polyblock_t { @@ -144,22 +143,6 @@ bool EV_MovePolyTo (line_t *line, int polyNum, double speed, const DVector2 &pos bool EV_OpenPolyDoor (line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type); bool EV_StopPoly (int polyNum); - -// [RH] Data structure for P_SpawnMapThing() to keep track -// of polyobject-related things. -struct polyspawns_t -{ - polyspawns_t *next; - DVector2 pos; - short angle; - short type; -}; - -extern int po_NumPolyobjs; -extern polyspawns_t *polyspawns; // [RH] list of polyobject things to spawn - - -void PO_Init (); bool PO_Busy (int polyobj); FPolyObj *PO_GetPolyobj(int polyNum); diff --git a/src/serializer.cpp b/src/serializer.cpp index e4f9369167..5b740712be 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -1449,12 +1449,12 @@ FSerializer &SerializePointer(FSerializer &arc, const char *key, T *&value, T ** template<> FSerializer &Serialize(FSerializer &arc, const char *key, FPolyObj *&value, FPolyObj **defval) { - return SerializePointer(arc, key, value, defval, polyobjs); + return SerializePointer(arc, key, value, defval, level.Polyobjects.Data()); } template<> FSerializer &Serialize(FSerializer &arc, const char *key, const FPolyObj *&value, const FPolyObj **defval) { - return SerializePointer(arc, key, value, defval, polyobjs); + return SerializePointer(arc, key, value, defval, level.Polyobjects.Data()); } template<> FSerializer &Serialize(FSerializer &arc, const char *key, side_t *&value, side_t **defval) diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 8fa0869ae3..809deb43cb 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1343,7 +1343,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - _crtBreakAlloc = 227524; + //_crtBreakAlloc = 227524; #endif DoMain (hInstance);