mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- moved the Zones array into FLevelLocals.
- replaced TStaticArray with regular TArrays. They had incomplete implementations preventing proper cleanup of the level loading code. It makes more sense to add the missing methods to the regular TArray and use that. This also makes some changes to how the game nodes are used to avoid creating a copy: If the head node's pointer is stored in a separate variable, no code needs to check which of the two arrays gets used.
This commit is contained in:
parent
c1b774e809
commit
ea1d6634f7
11 changed files with 80 additions and 243 deletions
|
@ -29,17 +29,25 @@ struct FLevelLocals
|
|||
FString F1Pic;
|
||||
EMapType maptype;
|
||||
|
||||
TStaticArray<vertex_t> vertexes;
|
||||
TStaticArray<sector_t> sectors;
|
||||
TStaticArray<line_t> lines;
|
||||
TStaticArray<side_t> sides;
|
||||
TStaticArray<seg_t> segs;
|
||||
TStaticPointableArray<subsector_t> subsectors;
|
||||
TStaticPointableArray<subsector_t> gamesubsectors;
|
||||
TStaticPointableArray<node_t> nodes;
|
||||
TStaticPointableArray<node_t> gamenodes;
|
||||
TArray<vertex_t> vertexes;
|
||||
TArray<sector_t> sectors;
|
||||
TArray<line_t> lines;
|
||||
TArray<side_t> sides;
|
||||
TArray<seg_t> segs;
|
||||
TArray<subsector_t> subsectors;
|
||||
TArray<node_t> nodes;
|
||||
TArray<subsector_t> gamesubsectors;
|
||||
TArray<node_t> gamenodes;
|
||||
node_t *headgamenode;
|
||||
|
||||
TArray<FSectorPortal> sectorPortals;
|
||||
TArray<zone_t> Zones;
|
||||
|
||||
// These are copies of the loaded map data that get used by the savegame code to skip unaltered fields
|
||||
// Without such a mechanism the savegame format would become too slow and large because more than 80-90% are normally still unaltered.
|
||||
TArray<sector_t> loadsectors;
|
||||
TArray<line_t> loadlines;
|
||||
TArray<side_t> loadsides;
|
||||
|
||||
|
||||
uint32_t flags;
|
||||
|
@ -102,7 +110,7 @@ struct FLevelLocals
|
|||
}
|
||||
node_t *HeadGamenode() const
|
||||
{
|
||||
return &gamenodes[gamenodes.Size() - 1];
|
||||
return headgamenode;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ class ClipNode
|
|||
class Clipper
|
||||
{
|
||||
unsigned starttime;
|
||||
TStaticArray<angle_t> anglecache;
|
||||
FMemArena nodearena;
|
||||
ClipNode * freelist = nullptr;
|
||||
|
||||
|
|
|
@ -247,15 +247,14 @@ static bool LoadGLVertexes(FileReader * lump)
|
|||
mapglvertex_t* mgl = (mapglvertex_t *)(gldata + GL_VERT_OFFSET);
|
||||
unsigned numvertexes = firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t);
|
||||
|
||||
TStaticArray<vertex_t> oldvertexes = std::move(level.vertexes);
|
||||
level.vertexes.Alloc(numvertexes);
|
||||
auto oldvertexes = &level.vertexes[0];
|
||||
level.vertexes.Resize(numvertexes);
|
||||
|
||||
memcpy(&level.vertexes[0], &oldvertexes[0], firstglvertex * sizeof(vertex_t));
|
||||
for(auto &line : level.lines)
|
||||
{
|
||||
// Remap vertex pointers in linedefs
|
||||
line.v1 = &level.vertexes[line.v1 - &oldvertexes[0]];
|
||||
line.v2 = &level.vertexes[line.v2 - &oldvertexes[0]];
|
||||
line.v1 = &level.vertexes[line.v1 - oldvertexes];
|
||||
line.v2 = &level.vertexes[line.v2 - oldvertexes];
|
||||
}
|
||||
|
||||
for (i = firstglvertex; i < (int)numvertexes; i++)
|
||||
|
@ -940,13 +939,14 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime)
|
|||
if (!rebuilt && !P_CheckForGLNodes())
|
||||
{
|
||||
ret = true; // we are not using the level's original nodes if we get here.
|
||||
for (auto &sub : level.gamesubsectors)
|
||||
for (auto &sub : level.subsectors)
|
||||
{
|
||||
sub.sector = sub.firstline->sidedef->sector;
|
||||
}
|
||||
|
||||
level.nodes.Clear();
|
||||
level.subsectors.Clear();
|
||||
// The nodes and subsectors need to be preserved for gameplay related purposes.
|
||||
level.gamenodes = std::move(level.nodes);
|
||||
level.gamesubsectors = std::move(level.subsectors);
|
||||
level.segs.Clear();
|
||||
|
||||
// Try to load GL nodes (cached or GWA)
|
||||
|
@ -992,12 +992,6 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime)
|
|||
DPrintf(DMSG_NOTIFY, "Not caching nodes (time = %f)\n", buildtime/1000.f);
|
||||
}
|
||||
}
|
||||
|
||||
if (level.gamenodes.Size() == 0)
|
||||
{
|
||||
level.gamenodes.Point(level.nodes);
|
||||
level.gamesubsectors.Point(level.subsectors);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2101,14 +2101,10 @@ int P_VanillaPointOnLineSide(double x, double y, const line_t* line)
|
|||
|
||||
subsector_t *P_PointInSubsector(double x, double y)
|
||||
{
|
||||
node_t *node;
|
||||
int side;
|
||||
|
||||
// single subsector is a special case
|
||||
if (level.gamenodes.Size() == 0)
|
||||
return &level.gamesubsectors[0];
|
||||
|
||||
node = level.HeadGamenode();
|
||||
auto node = level.HeadGamenode();
|
||||
if (node == nullptr) return &level.subsectors[0];
|
||||
|
||||
fixed_t xx = FLOAT2FIXED(x);
|
||||
fixed_t yy = FLOAT2FIXED(y);
|
||||
|
@ -2131,11 +2127,8 @@ subsector_t *P_PointInSubsector(double x, double y)
|
|||
sector_t *P_PointInSectorBuggy(double x, double y)
|
||||
{
|
||||
// single subsector is a special case
|
||||
if (level.gamenodes.Size() == 0)
|
||||
return level.gamesubsectors[0].sector;
|
||||
|
||||
auto node = level.HeadGamenode();
|
||||
|
||||
if (node == nullptr) return level.subsectors[0].sector;
|
||||
do
|
||||
{
|
||||
// Use original buggy point-on-side test when spawning
|
||||
|
|
|
@ -65,11 +65,6 @@
|
|||
#include "g_levellocals.h"
|
||||
#include "events.h"
|
||||
|
||||
static TStaticArray<sector_t> loadsectors;
|
||||
static TStaticArray<line_t> loadlines;
|
||||
static TStaticArray<side_t> loadsides;
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -991,10 +986,10 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
|
|||
|
||||
FBehavior::StaticSerializeModuleStates(arc);
|
||||
// The order here is important: First world state, then portal state, then thinkers, and last polyobjects.
|
||||
arc.Array("linedefs", &level.lines[0], &loadlines[0], level.lines.Size());
|
||||
arc.Array("sidedefs", &level.sides[0], &loadsides[0], level.sides.Size());
|
||||
arc.Array("sectors", &level.sectors[0], &loadsectors[0], level.sectors.Size());
|
||||
arc("zones", Zones);
|
||||
arc("linedefs", level.lines, level.loadlines);
|
||||
arc("sidedefs", level.sides, level.loadsides);
|
||||
arc("sectors", level.sectors, level.loadsectors);
|
||||
arc("zones", level.Zones);
|
||||
arc("lineportals", linePortals);
|
||||
arc("sectorportals", level.sectorPortals);
|
||||
if (arc.isReading()) P_CollectLinkedPortals();
|
||||
|
@ -1029,19 +1024,3 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
|
|||
Renderer->EndSerialize(arc);
|
||||
|
||||
}
|
||||
|
||||
// Create a backup of the map data so the savegame code can toss out all fields that haven't changed in order to reduce processing time and file size.
|
||||
|
||||
void P_BackupMapData()
|
||||
{
|
||||
loadsectors = level.sectors;
|
||||
loadlines = level.lines;
|
||||
loadsides = level.sides;
|
||||
}
|
||||
|
||||
void P_FreeMapDataBackup()
|
||||
{
|
||||
loadsectors.Clear();
|
||||
loadlines.Clear();
|
||||
loadsides.Clear();
|
||||
}
|
||||
|
|
|
@ -46,7 +46,4 @@ void P_WriteACSDefereds (FSerializer &);
|
|||
|
||||
void G_SerializeLevel(FSerializer &arc, bool hubLoad);
|
||||
|
||||
void P_BackupMapData();
|
||||
void P_FreeMapDataBackup();
|
||||
|
||||
#endif // __P_SAVEG_H__
|
||||
|
|
|
@ -1879,18 +1879,18 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(_Sector, SetEnvironmentID)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||
PARAM_INT(envnum);
|
||||
Zones[self->ZoneNumber].Environment = S_FindEnvironment(envnum);
|
||||
return 0;
|
||||
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||
PARAM_INT(envnum);
|
||||
level.Zones[self->ZoneNumber].Environment = S_FindEnvironment(envnum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Sector, SetEnvironment)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||
PARAM_STRING(env);
|
||||
Zones[self->ZoneNumber].Environment = S_FindEnvironment(env);
|
||||
return 0;
|
||||
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||
PARAM_STRING(env);
|
||||
level.Zones[self->ZoneNumber].Environment = S_FindEnvironment(env);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Sector, GetGlowHeight)
|
||||
|
|
|
@ -125,14 +125,6 @@ inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int
|
|||
//
|
||||
TArray<vertexdata_t> vertexdatas;
|
||||
|
||||
//int numnodes;
|
||||
//node_t* nodes;
|
||||
|
||||
TArray<zone_t> Zones;
|
||||
|
||||
//node_t * gamenodes;
|
||||
//int numgamenodes;
|
||||
|
||||
bool hasglnodes;
|
||||
|
||||
TArray<FMapThing> MapThingsConverted;
|
||||
|
@ -799,7 +791,7 @@ void P_FloodZones ()
|
|||
P_FloodZone (&sec, z++);
|
||||
}
|
||||
}
|
||||
Zones.Resize(z);
|
||||
level.Zones.Resize(z);
|
||||
reverb = S_FindEnvironment(level.DefaultEnvironment);
|
||||
if (reverb == NULL)
|
||||
{
|
||||
|
@ -808,7 +800,7 @@ void P_FloodZones ()
|
|||
}
|
||||
for (i = 0; i < z; ++i)
|
||||
{
|
||||
Zones[i].Environment = reverb;
|
||||
level.Zones[i].Environment = reverb;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -961,7 +953,6 @@ void LoadZNodes(FileReaderBase &data, int glnodes)
|
|||
{
|
||||
// Read extra vertices added during node building
|
||||
uint32_t orgVerts, newVerts;
|
||||
TStaticArray<vertex_t> newvertarray;
|
||||
unsigned int i;
|
||||
|
||||
data >> orgVerts >> newVerts;
|
||||
|
@ -970,35 +961,26 @@ void LoadZNodes(FileReaderBase &data, int glnodes)
|
|||
// We can't use them.
|
||||
throw CRecoverableError("Incorrect number of vertexes in nodes.\n");
|
||||
}
|
||||
bool fix;
|
||||
if (orgVerts + newVerts == level.vertexes.Size())
|
||||
auto oldvertexes = &level.vertexes[0];
|
||||
if (orgVerts + newVerts != level.vertexes.Size())
|
||||
{
|
||||
newvertarray = std::move(level.vertexes);
|
||||
fix = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
newvertarray.Alloc(orgVerts + newVerts);
|
||||
memcpy (&newvertarray[0], &level.vertexes[0], orgVerts * sizeof(vertex_t));
|
||||
fix = true;
|
||||
level.vertexes.Reserve(newVerts);
|
||||
}
|
||||
for (i = 0; i < newVerts; ++i)
|
||||
{
|
||||
fixed_t x, y;
|
||||
data >> x >> y;
|
||||
newvertarray[i + orgVerts].set(x, y);
|
||||
level.vertexes[i + orgVerts].set(x, y);
|
||||
}
|
||||
if (fix)
|
||||
if (oldvertexes != &level.vertexes[0])
|
||||
{
|
||||
for (auto &line : level.lines)
|
||||
{
|
||||
line.v1 = line.v1 - &level.vertexes[0] + &newvertarray[0];
|
||||
line.v2 = line.v2 - &level.vertexes[0] + &newvertarray[0];
|
||||
line.v1 = line.v1 - oldvertexes + &level.vertexes[0];
|
||||
line.v2 = line.v2 - oldvertexes + &level.vertexes[0];
|
||||
}
|
||||
}
|
||||
|
||||
level.vertexes = std::move(newvertarray);
|
||||
|
||||
// Read the subsectors
|
||||
uint32_t numSubs, currSeg;
|
||||
|
||||
|
@ -3424,7 +3406,6 @@ void P_FreeLevelData ()
|
|||
// [RH] Clear all ThingID hash chains.
|
||||
AActor::ClearTIDHashes();
|
||||
|
||||
P_FreeMapDataBackup();
|
||||
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
|
||||
Renderer->CleanLevelData();
|
||||
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
|
||||
|
@ -3450,11 +3431,14 @@ void P_FreeLevelData ()
|
|||
level.sectors.Clear();
|
||||
level.lines.Clear();
|
||||
level.sides.Clear();
|
||||
level.loadsectors.Clear();
|
||||
level.loadlines.Clear();
|
||||
level.loadsides.Clear();
|
||||
level.vertexes.Clear();
|
||||
level.nodes.Clear();
|
||||
level.gamenodes.Clear();
|
||||
level.gamenodes.Reset();
|
||||
level.subsectors.Clear();
|
||||
level.gamesubsectors.Clear();
|
||||
level.gamesubsectors.Reset();
|
||||
|
||||
if (blockmaplump != NULL)
|
||||
{
|
||||
|
@ -3497,7 +3481,7 @@ void P_FreeLevelData ()
|
|||
polyobjs = NULL;
|
||||
}
|
||||
po_NumPolyobjs = 0;
|
||||
Zones.Clear();
|
||||
level.Zones.Clear();
|
||||
P_FreeStrifeConversations ();
|
||||
level.Scrolls.Clear();
|
||||
P_ClearUDMFKeys();
|
||||
|
@ -3895,13 +3879,6 @@ void P_SetupLevel (const char *lumpname, int position)
|
|||
}
|
||||
}
|
||||
|
||||
// duplicate the nodes in the game* arrays so that replacement nodes do not overwrite them.
|
||||
// let the game data take ownership, because that is guaranteed to remain intact after here.
|
||||
level.gamesubsectors = std::move(level.subsectors);
|
||||
level.subsectors.Point(level.gamesubsectors);
|
||||
level.gamenodes = std::move(level.nodes);
|
||||
level.nodes.Point(level.gamenodes);
|
||||
|
||||
if (RequireGLNodes)
|
||||
{
|
||||
// Build GL nodes if we want a textured automap or GL nodes are forced to be built.
|
||||
|
@ -3916,6 +3893,9 @@ void P_SetupLevel (const char *lumpname, int position)
|
|||
hasglnodes = P_CheckForGLNodes();
|
||||
}
|
||||
|
||||
// set the head node for gameplay purposes. If the separate gamenodes array is not empty, use that, otherwise use the render nodes.
|
||||
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : &level.nodes[level.nodes.Size() - 1];
|
||||
|
||||
times[10].Clock();
|
||||
P_LoadBlockMap (map);
|
||||
times[10].Unclock();
|
||||
|
@ -4119,7 +4099,10 @@ void P_SetupLevel (const char *lumpname, int position)
|
|||
MapThingsUserDataIndex.Clear();
|
||||
MapThingsUserData.Clear();
|
||||
|
||||
P_BackupMapData();
|
||||
// Create a backup of the map data so the savegame code can toss out all fields that haven't changed in order to reduce processing time and file size.
|
||||
level.loadsectors = level.sectors;
|
||||
level.loadlines = level.lines;
|
||||
level.loadsides = level.sides;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,15 +46,6 @@ extern uint32_t NumStdSprites;
|
|||
|
||||
extern TArray<vertexdata_t> vertexdatas;
|
||||
|
||||
//extern int numnodes;
|
||||
//extern node_t* nodes;
|
||||
|
||||
extern TArray<zone_t> Zones;
|
||||
|
||||
//extern node_t * gamenodes;
|
||||
//extern int numgamenodes;
|
||||
|
||||
|
||||
//
|
||||
// POV data.
|
||||
//
|
||||
|
|
|
@ -2109,8 +2109,8 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor)
|
|||
listener.velocity.Zero();
|
||||
listener.position = listenactor->SoundPos();
|
||||
listener.underwater = listenactor->waterlevel == 3;
|
||||
assert(Zones.Size() > listenactor->Sector->ZoneNumber);
|
||||
listener.Environment = Zones[listenactor->Sector->ZoneNumber].Environment;
|
||||
assert(level.Zones.Size() > listenactor->Sector->ZoneNumber);
|
||||
listener.Environment = level.Zones[listenactor->Sector->ZoneNumber].Environment;
|
||||
listener.valid = true;
|
||||
}
|
||||
else
|
||||
|
|
137
src/tarray.h
137
src/tarray.h
|
@ -366,6 +366,14 @@ public:
|
|||
}
|
||||
Count = amount;
|
||||
}
|
||||
void Alloc(unsigned int amount)
|
||||
{
|
||||
// first destroys all content and then rebuilds the array.
|
||||
if (Count > 0) DoDelete(0, Count - 1);
|
||||
Count = 0;
|
||||
Resize(amount);
|
||||
ShrinkToFit();
|
||||
}
|
||||
// Reserves amount entries at the end of the array, but does nothing
|
||||
// with them.
|
||||
unsigned int Reserve (unsigned int amount)
|
||||
|
@ -395,6 +403,11 @@ public:
|
|||
Count = 0;
|
||||
}
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
Clear();
|
||||
ShrinkToFit();
|
||||
}
|
||||
private:
|
||||
T *Array;
|
||||
unsigned int Count;
|
||||
|
@ -466,13 +479,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// A non-resizable array
|
||||
// This is meant for data that can be replaced but is otherwise static as long as it exists.
|
||||
// The reason for it is to replace any global pointer/counter pairs with something that can
|
||||
// be reliably accessed by the scripting VM and which can use 'for' iterator syntax.
|
||||
// This is not a real dynamic array but just a wrapper around a pointer reference.
|
||||
// Used for wrapping some memory allocated elsewhere into a VM compatible data structure.
|
||||
|
||||
// This is split into two, so that it also can be used to wrap arrays that are not directly allocated.
|
||||
// This first class only gets a reference to some data but won't own it.
|
||||
template <class T>
|
||||
class TStaticPointedArray
|
||||
{
|
||||
|
@ -526,122 +535,6 @@ public:
|
|||
unsigned int Count;
|
||||
};
|
||||
|
||||
// This second type owns its data, it can delete and reallocate it, but it cannot
|
||||
// resize the array or repurpose its old contents if new ones are about to be created.
|
||||
template <class T>
|
||||
class TStaticArray : public TStaticPointedArray<T>
|
||||
{
|
||||
public:
|
||||
|
||||
////////
|
||||
// This is a dummy constructor that does nothing. The purpose of this
|
||||
// is so you can create a global TArray in the data segment that gets
|
||||
// used by code before startup without worrying about the constructor
|
||||
// resetting it after it's already been used. You MUST NOT use it for
|
||||
// heap- or stack-allocated TArrays.
|
||||
enum ENoInit
|
||||
{
|
||||
NoInit
|
||||
};
|
||||
TStaticArray(ENoInit dummy)
|
||||
{
|
||||
}
|
||||
////////
|
||||
TStaticArray()
|
||||
{
|
||||
this->Count = 0;
|
||||
this->Array = NULL;
|
||||
}
|
||||
TStaticArray(TStaticArray<T> &&other)
|
||||
{
|
||||
this->Array = other.Array;
|
||||
this->Count = other.Count;
|
||||
other.Array = nullptr;
|
||||
other.Count = 0;
|
||||
}
|
||||
// This is not supposed to be copyable.
|
||||
TStaticArray(const TStaticArray<T> &other) = delete;
|
||||
|
||||
~TStaticArray()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
if (this->Array) delete[] this->Array;
|
||||
this->Count = 0;
|
||||
this->Array = nullptr;
|
||||
}
|
||||
void Alloc(unsigned int amount)
|
||||
{
|
||||
// intentionally first deletes and then reallocates.
|
||||
if (this->Array) delete[] this->Array;
|
||||
this->Array = new T[amount];
|
||||
this->Count = amount;
|
||||
}
|
||||
TStaticArray &operator=(const TStaticArray &other)
|
||||
{
|
||||
Alloc(other.Size());
|
||||
memcpy(this->Array, other.Array, this->Count * sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
TStaticArray &operator=(TStaticArray &&other)
|
||||
{
|
||||
if (this->Array) delete[] this->Array;
|
||||
this->Array = other.Array;
|
||||
this->Count = other.Count;
|
||||
other.Array = nullptr;
|
||||
other.Count = 0;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class TStaticPointableArray : public TStaticArray<T>
|
||||
{
|
||||
bool pointed = false;
|
||||
public:
|
||||
|
||||
////////
|
||||
TStaticPointableArray()
|
||||
{
|
||||
}
|
||||
// This is not supposed to be copyable.
|
||||
TStaticPointableArray(const TStaticArray<T> &other) = delete;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if (!pointed && this->Array) delete[] this->Array;
|
||||
this->Count = 0;
|
||||
this->Array = nullptr;
|
||||
}
|
||||
void Alloc(unsigned int amount)
|
||||
{
|
||||
// intentionally first deletes and then reallocates.
|
||||
if (!pointed && this->Array) delete[] this->Array;
|
||||
this->Array = new T[amount];
|
||||
this->Count = amount;
|
||||
pointed = false;
|
||||
}
|
||||
void Point(TStaticArray<T> & other)
|
||||
{
|
||||
if (!pointed && this->Array) delete[] this->Array;
|
||||
this->Array = other.Array;
|
||||
this->Count = other.Count;
|
||||
pointed = true;
|
||||
}
|
||||
TStaticPointableArray &operator=(TStaticArray<T> &&other)
|
||||
{
|
||||
if (!pointed && this->Array) delete[] this->Array;
|
||||
this->Array = other.Array;
|
||||
this->Count = other.Count;
|
||||
other.Array = nullptr;
|
||||
other.Count = 0;
|
||||
pointed = false;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// TAutoGrowArray -----------------------------------------------------------
|
||||
// An array with accessors that automatically grow the array as needed.
|
||||
// It can still be used as a normal TArray if needed. ACS uses this for
|
||||
|
|
Loading…
Reference in a new issue