- added a TStaticArray class that allows safe access to resizable static data (like the sectors, linedefs, etc.) for the VM.

- used this to replace the line list in Sector because that gets already used and implemented proper bounds checks for this type of array.
This commit is contained in:
Christoph Oelckers 2017-01-02 21:40:52 +01:00
parent b31b6589e7
commit 1a16f664e4
24 changed files with 456 additions and 233 deletions

View file

@ -560,6 +560,7 @@ void PType::StaticInit()
RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PClassPointer);
RUNTIME_CLASS(PEnum)->TypeTableType = RUNTIME_CLASS(PEnum);
RUNTIME_CLASS(PArray)->TypeTableType = RUNTIME_CLASS(PArray);
RUNTIME_CLASS(PResizableArray)->TypeTableType = RUNTIME_CLASS(PResizableArray);
RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray);
RUNTIME_CLASS(PMap)->TypeTableType = RUNTIME_CLASS(PMap);
RUNTIME_CLASS(PStruct)->TypeTableType = RUNTIME_CLASS(PStruct);
@ -2050,6 +2051,80 @@ PArray *NewArray(PType *type, unsigned int count)
return (PArray *)atype;
}
/* PArray *****************************************************************/
IMPLEMENT_CLASS(PResizableArray, false, false)
//==========================================================================
//
// PArray - Default Constructor
//
//==========================================================================
PResizableArray::PResizableArray()
{
mDescriptiveName = "ResizableArray";
}
//==========================================================================
//
// PArray - Parameterized Constructor
//
//==========================================================================
PResizableArray::PResizableArray(PType *etype)
: PArray(etype, 0)
{
mDescriptiveName.Format("ResizableArray<%s>", etype->DescriptiveName());
}
//==========================================================================
//
// PArray :: IsMatch
//
//==========================================================================
bool PResizableArray::IsMatch(intptr_t id1, intptr_t id2) const
{
const PType *elemtype = (const PType *)id1;
unsigned int count = (unsigned int)(intptr_t)id2;
return elemtype == ElementType && count == 0;
}
//==========================================================================
//
// PArray :: GetTypeIDs
//
//==========================================================================
void PResizableArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
{
id1 = (intptr_t)ElementType;
id2 = 0;
}
//==========================================================================
//
// NewResizableArray
//
// Returns a PArray for the given type and size, making sure not to create
// duplicates.
//
//==========================================================================
PResizableArray *NewResizableArray(PType *type)
{
size_t bucket;
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PResizableArray), (intptr_t)type, 0, &bucket);
if (atype == NULL)
{
atype = new PResizableArray(type);
TypeTable.AddType(atype, RUNTIME_CLASS(PResizableArray), (intptr_t)type, 0, bucket);
}
return (PResizableArray *)atype;
}
/* PDynArray **************************************************************/
IMPLEMENT_CLASS(PDynArray, false, true)

View file

@ -660,6 +660,20 @@ protected:
PArray();
};
class PResizableArray : public PArray
{
DECLARE_CLASS(PResizableArray, PArray);
HAS_OBJECT_POINTERS;
public:
PResizableArray(PType *etype);
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PResizableArray();
};
class PDynArray : public PCompoundType
{
DECLARE_CLASS(PDynArray, PCompoundType);
@ -919,6 +933,7 @@ extern FTypeTable TypeTable;
// Returns a type from the TypeTable. Will create one if it isn't present.
PMap *NewMap(PType *keytype, PType *valuetype);
PArray *NewArray(PType *type, unsigned int count);
PResizableArray *NewResizableArray(PType *type);
PDynArray *NewDynArray(PType *type);
PPointer *NewPointer(PType *type, bool isconst = false);
PClassPointer *NewClassPointer(PClass *restrict);

View file

@ -305,7 +305,6 @@ static void PrepareTransparentDoors(sector_t * sector)
int notextures=0;
int nobtextures=0;
int selfref=0;
int i;
sector_t * nextsec=NULL;
#ifdef _DEBUG
@ -323,15 +322,15 @@ static void PrepareTransparentDoors(sector_t * sector)
if (sector->transdoor)
{
for (i=0; i<sector->linecount; i++)
for (auto ln : sector->Lines)
{
if (sector->lines[i]->frontsector==sector->lines[i]->backsector)
if (ln->frontsector == ln->backsector)
{
selfref++;
continue;
}
sector_t * sec=getNextSector(sector->lines[i], sector);
sector_t * sec=getNextSector(ln, sector);
if (sec==NULL)
{
solidwall=true;
@ -341,15 +340,15 @@ static void PrepareTransparentDoors(sector_t * sector)
{
nextsec=sec;
int side = sector->lines[i]->sidedef[0]->sector == sec;
int side = ln->sidedef[0]->sector == sec;
if (sector->GetPlaneTexZ(sector_t::floor)!=sec->GetPlaneTexZ(sector_t::floor)+1. || sec->floorplane.isSlope())
{
sector->transdoor=false;
return;
}
if (!sector->lines[i]->sidedef[1-side]->GetTexture(side_t::top).isValid()) notextures++;
if (!sector->lines[i]->sidedef[1-side]->GetTexture(side_t::bottom).isValid()) nobtextures++;
if (!ln->sidedef[1-side]->GetTexture(side_t::top).isValid()) notextures++;
if (!ln->sidedef[1-side]->GetTexture(side_t::bottom).isValid()) nobtextures++;
}
}
if (sector->GetTexture(sector_t::ceiling)==skyflatnum)
@ -358,19 +357,19 @@ static void PrepareTransparentDoors(sector_t * sector)
return;
}
if (selfref+nobtextures!=sector->linecount)
if (selfref+nobtextures!=sector->Lines.Size())
{
sector->transdoor=false;
}
if (selfref+notextures!=sector->linecount)
if (selfref+notextures!=sector->Lines.Size())
{
// This is a crude attempt to fix an incorrect transparent door effect I found in some
// WolfenDoom maps but considering the amount of code required to handle it I left it in.
// Do this only if the sector only contains one-sided walls or ones with no lower texture.
if (solidwall)
{
if (solidwall+nobtextures+selfref==sector->linecount && nextsec)
if (solidwall+nobtextures+selfref==sector->Lines.Size() && nextsec)
{
sector->heightsec=nextsec;
sector->heightsec->MoreFlags=0;
@ -604,9 +603,8 @@ void gl_PreprocessLevel()
PrepareTransparentDoors(&sectors[i]);
// This ignores vertices only used for seg splitting because those aren't needed here
for(int j = 0; j < sectors[i].linecount; j++)
for(auto l : sectors[i].Lines)
{
line_t *l = sectors[i].lines[j];
if (l->sidedef[0]->Flags & WALLF_POLYOBJ) continue; // don't bother with polyobjects
int vtnum1 = int(l->v1 - vertexes);

View file

@ -320,9 +320,8 @@ void GLFlat::DrawSkyboxSector(int pass, bool processlights)
float minx = FLT_MAX, miny = FLT_MAX;
float maxx = -FLT_MAX, maxy = -FLT_MAX;
for (int i = 0; i < sector->linecount; i++)
for (auto ln : sector->Lines)
{
line_t *ln = sector->lines[i];
float x = ln->v1->fX();
float y = ln->v1->fY();
if (x < minx) minx = x;

View file

@ -756,6 +756,7 @@ xx(ResolveState)
xx(DamageFunction)
xx(Length)
xx(Unit)
xx(Size)
xx(StateLabel)
xx(SpriteID)
xx(TextureID)

View file

@ -216,7 +216,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
//==========================================================================
static int P_Set3DFloor(line_t * line, int param, int param2, int alpha)
{
int s, i;
int s;
int flags;
int tag = line->args[0];
sector_t * sec = line->frontsector, *ss;
@ -230,10 +230,8 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha)
{
flags = FF_EXISTS | FF_RENDERALL | FF_SOLID | FF_INVERTSECTOR;
alpha = 255;
for (i = 0; i < sec->linecount; i++)
for (auto l: sec->Lines)
{
line_t * l = sec->lines[i];
if (l->special == Sector_SetContents && l->frontsector == sec)
{
alpha = clamp<int>(l->args[1], 0, 100);

View file

@ -167,10 +167,8 @@ void P_Attach3dMidtexLinesToSector(sector_t *sector, int lineid, int tag, bool c
int sec;
while ((sec = it.Next()) >= 0)
{
for (int line = 0; line < sectors[sec].linecount; line ++)
for (auto ln : sectors[sec].Lines)
{
line_t *ln = sectors[sec].lines[line];
if (lineid != 0 && !tagManager.LineHasID(ln, lineid)) continue;
if (ln->frontsector == NULL || ln->backsector == NULL || !(ln->flags & ML_3DMIDTEX))

View file

@ -242,7 +242,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
// new door thinker
DCeiling *ceiling = new DCeiling (sec, speed, speed2, silent & ~4);
vertex_t *spot = sec->lines[0]->v1;
vertex_t *spot = sec->Lines[0]->v1;
switch (type)
{

View file

@ -286,10 +286,9 @@ void DDoor::DoorSound(bool raise, DSeqNode *curseq) const
// Search the front top textures of 2-sided lines on the door sector
// for a door sound to use.
for (int i = 0; i < m_Sector->linecount; ++i)
for (auto line : m_Sector->Lines)
{
const char *texname;
line_t *line = m_Sector->lines[i];
if (line->backsector == NULL)
continue;
@ -694,14 +693,14 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay,
m_Line1 = line;
m_Line2 = line;
for (int i = 0; i < sec->linecount; ++i)
for (auto l : sec->Lines)
{
if (sec->lines[i] == line)
if (l == line)
continue;
if (sec->lines[i]->sidedef[0]->GetTexture(side_t::top) == line->sidedef[0]->GetTexture(side_t::top))
if (l->sidedef[0]->GetTexture(side_t::top) == line->sidedef[0]->GetTexture(side_t::top))
{
m_Line2 = sec->lines[i];
m_Line2 = l;
break;
}
}
@ -789,9 +788,8 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay)
continue;
}
for (int i = 0; tag != 0 && i < sec->linecount; ++i)
for (auto line : sec->Lines)
{
line = sec->lines[i];
if (line->backsector == NULL)
{
continue;

View file

@ -161,10 +161,8 @@ static void P_RecursiveSound(sector_t *sec, AActor *soundtarget, bool splash, AA
bool checkabove = !sec->PortalBlocksSound(sector_t::ceiling);
bool checkbelow = !sec->PortalBlocksSound(sector_t::floor);
for (int i = 0; i < sec->linecount; i++)
for (auto check : sec->Lines)
{
line_t *check = sec->lines[i];
// check sector portals
// I wish there was a better method to do this than randomly looking through the portal at a few places...
if (checkabove)

View file

@ -578,7 +578,6 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
int osecnum; //jff 3/4/98 save old loop index
double height;
double stairstep;
int i;
int newsecnum = -1;
FTextureID texture;
int ok;
@ -669,18 +668,18 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
}
else
{
for (i = 0; i < sec->linecount; i++)
for (auto line : sec->Lines)
{
if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
if ( !(line->flags & ML_TWOSIDED) )
continue;
tsec = (sec->lines[i])->frontsector;
tsec = line->frontsector;
newsecnum = (int)(tsec-sectors);
if (secnum != newsecnum)
continue;
tsec = (sec->lines[i])->backsector;
tsec = line->backsector;
if (!tsec) continue; //jff 5/7/98 if no backside, continue
newsecnum = (int)(tsec - sectors);
@ -765,7 +764,6 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed)
sector_t* s3;
int secnum;
bool rtn;
int i;
DFloor* floor;
vertex_t* spot;
double height;
@ -782,19 +780,19 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed)
continue; // safe now, because we check that tag is non-0 in the looping condition [fdari]
rtn = true;
s2 = getNextSector (s1->lines[0], s1); // s2 is pool's sector
s2 = getNextSector (s1->Lines[0], s1); // s2 is pool's sector
if (!s2) // note lowest numbered line around
continue; // pillar must be two-sided
if (s2->PlaneMoving(sector_t::floor))
continue;
for (i = 0; i < s2->linecount; i++)
for (auto ln : s2->Lines)
{
if (!(s2->lines[i]->flags & ML_TWOSIDED) ||
(s2->lines[i]->backsector == s1))
if (!(ln->flags & ML_TWOSIDED) ||
(ln->backsector == s1))
continue;
s3 = s2->lines[i]->backsector;
s3 = ln->backsector;
// Spawn rising slime
floor = new DFloor (s2);

View file

@ -540,9 +540,9 @@ void EV_TurnTagLightsOff (int tag)
sector_t *sector = sectors + secnum;
int min = sector->lightlevel;
for (int i = 0; i < sector->linecount; i++)
for (auto ln : sector->Lines)
{
sector_t *tsec = getNextSector (sector->lines[i],sector);
sector_t *tsec = getNextSector (ln, sector);
if (!tsec)
continue;
if (tsec->lightlevel < min)
@ -574,11 +574,9 @@ void EV_LightTurnOn (int tag, int bright)
// surrounding sector
if (bright < 0)
{
int j;
for (j = 0; j < sector->linecount; j++)
for (auto ln : sector->Lines)
{
sector_t *temp = getNextSector (sector->lines[j], sector);
sector_t *temp = getNextSector(ln, sector);
if (!temp)
continue;
@ -622,11 +620,11 @@ void EV_LightTurnOnPartway (int tag, double frac)
while ((secnum = it.Next()) >= 0)
{
sector_t *temp, *sector = &sectors[secnum];
int j, bright = 0, min = sector->lightlevel;
int bright = 0, min = sector->lightlevel;
for (j = 0; j < sector->linecount; ++j)
for (auto ln : sector->Lines)
{
if ((temp = getNextSector (sector->lines[j], sector)) != NULL)
if ((temp = getNextSector (ln, sector)) != nullptr)
{
if (temp->lightlevel > bright)
{

View file

@ -45,12 +45,8 @@
sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const
{
sector_t *tsec;
int i;
for (i = 0; i < linecount; i++)
for (auto ln : Lines)
{
line_t *ln = lines[i];
if (NULL != (tsec = getNextSector (ln, this)) &&
tsec != nogood &&
tsec->special == type)
@ -67,21 +63,18 @@ sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const
//
double sector_t::FindLowestFloorSurrounding (vertex_t **v) const
{
int i;
sector_t *other;
line_t *check;
double floor;
double ofloor;
vertex_t *spot;
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
spot = lines[0]->v1;
spot = Lines[0]->v1;
floor = floorplane.ZatPoint(spot);
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
ofloor = other->floorplane.ZatPoint (check->v1);
@ -111,21 +104,18 @@ double sector_t::FindLowestFloorSurrounding (vertex_t **v) const
//
double sector_t::FindHighestFloorSurrounding (vertex_t **v) const
{
int i;
line_t *check;
sector_t *other;
double floor;
double ofloor;
vertex_t *spot;
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
spot = lines[0]->v1;
spot = Lines[0]->v1;
floor = -FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
ofloor = other->floorplane.ZatPoint (check->v1);
@ -166,18 +156,15 @@ double sector_t::FindNextHighestFloor (vertex_t **v) const
double ofloor, floor;
sector_t *other;
vertex_t *spot;
line_t *check;
int i;
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
spot = lines[0]->v1;
spot = Lines[0]->v1;
height = floorplane.ZatPoint(spot);
heightdiff = FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
ofloor = other->floorplane.ZatPoint (check->v1);
@ -221,18 +208,15 @@ double sector_t::FindNextLowestFloor (vertex_t **v) const
double ofloor, floor;
sector_t *other;
vertex_t *spot;
line_t *check;
int i;
if (linecount == 0) return GetPlaneTexZ(sector_t::floor);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
spot = lines[0]->v1;
spot = Lines[0]->v1;
height = floorplane.ZatPoint (spot);
heightdiff = FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
ofloor = other->floorplane.ZatPoint (check->v1);
@ -275,19 +259,15 @@ double sector_t::FindNextLowestCeiling (vertex_t **v) const
double oceil, ceil;
sector_t *other;
vertex_t *spot;
line_t *check;
int i;
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::floor);
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
spot = lines[0]->v1;
spot = Lines[0]->v1;
height = ceilingplane.ZatPoint(spot);
heightdiff = FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
oceil = other->ceilingplane.ZatPoint(check->v1);
@ -330,18 +310,15 @@ double sector_t::FindNextHighestCeiling (vertex_t **v) const
double oceil, ceil;
sector_t *other;
vertex_t *spot;
line_t *check;
int i;
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::ceiling);
spot = lines[0]->v1;
spot = Lines[0]->v1;
height = ceilingplane.ZatPoint(spot);
heightdiff = FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
oceil = other->ceilingplane.ZatPoint(check->v1);
@ -376,17 +353,14 @@ double sector_t::FindLowestCeilingSurrounding (vertex_t **v) const
double oceil;
sector_t *other;
vertex_t *spot;
line_t *check;
int i;
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::ceiling);
spot = lines[0]->v1;
spot = Lines[0]->v1;
height = FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
oceil = other->ceilingplane.ZatPoint(check->v1);
@ -418,17 +392,14 @@ double sector_t::FindHighestCeilingSurrounding (vertex_t **v) const
double oceil;
sector_t *other;
vertex_t *spot;
line_t *check;
int i;
if (linecount == 0) return GetPlaneTexZ(sector_t::ceiling);
if (Lines.Size() == 0) return GetPlaneTexZ(sector_t::ceiling);
spot = lines[0]->v1;
spot = Lines[0]->v1;
height = -FLT_MAX;
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
check = lines[i];
if (NULL != (other = getNextSector (check, this)))
{
oceil = other->ceilingplane.ZatPoint(check->v1);
@ -479,12 +450,12 @@ double sector_t::FindShortestTextureAround () const
{
double minsize = FLT_MAX;
for (int i = 0; i < linecount; i++)
for (auto check : Lines)
{
if (lines[i]->flags & ML_TWOSIDED)
if (check->flags & ML_TWOSIDED)
{
CheckShortestTex (lines[i]->sidedef[0]->GetTexture(side_t::bottom), minsize);
CheckShortestTex (lines[i]->sidedef[1]->GetTexture(side_t::bottom), minsize);
CheckShortestTex (check->sidedef[0]->GetTexture(side_t::bottom), minsize);
CheckShortestTex (check->sidedef[1]->GetTexture(side_t::bottom), minsize);
}
}
return minsize < FLT_MAX ? minsize : TexMan[0]->GetHeight();
@ -505,12 +476,12 @@ double sector_t::FindShortestUpperAround () const
{
double minsize = FLT_MAX;
for (int i = 0; i < linecount; i++)
for (auto check : Lines)
{
if (lines[i]->flags & ML_TWOSIDED)
if (check->flags & ML_TWOSIDED)
{
CheckShortestTex (lines[i]->sidedef[0]->GetTexture(side_t::top), minsize);
CheckShortestTex (lines[i]->sidedef[1]->GetTexture(side_t::top), minsize);
CheckShortestTex (check->sidedef[0]->GetTexture(side_t::top), minsize);
CheckShortestTex (check->sidedef[1]->GetTexture(side_t::top), minsize);
}
}
return minsize < FLT_MAX ? minsize : TexMan[0]->GetHeight();
@ -533,17 +504,14 @@ double sector_t::FindShortestUpperAround () const
//
sector_t *sector_t::FindModelFloorSector (double floordestheight) const
{
int i;
sector_t *sec;
//jff 5/23/98 don't disturb sec->linecount while searching
// but allow early exit in old demos
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
sec = getNextSector (lines[i], this);
sec = getNextSector (check, this);
if (sec != NULL &&
(sec->floorplane.ZatPoint(lines[i]->v1) == floordestheight ||
sec->floorplane.ZatPoint(lines[i]->v2) == floordestheight))
(sec->floorplane.ZatPoint(check->v1) == floordestheight ||
sec->floorplane.ZatPoint(check->v2) == floordestheight))
{
return sec;
}
@ -569,17 +537,14 @@ sector_t *sector_t::FindModelFloorSector (double floordestheight) const
//
sector_t *sector_t::FindModelCeilingSector (double floordestheight) const
{
int i;
sector_t *sec;
//jff 5/23/98 don't disturb sec->linecount while searching
// but allow early exit in old demos
for (i = 0; i < linecount; i++)
for (auto check : Lines)
{
sec = getNextSector (lines[i], this);
sec = getNextSector (check, this);
if (sec != NULL &&
(sec->ceilingplane.ZatPoint(lines[i]->v1) == floordestheight ||
sec->ceilingplane.ZatPoint(lines[i]->v2) == floordestheight))
(sec->ceilingplane.ZatPoint(check->v1) == floordestheight ||
sec->ceilingplane.ZatPoint(check->v2) == floordestheight))
{
return sec;
}
@ -592,13 +557,10 @@ sector_t *sector_t::FindModelCeilingSector (double floordestheight) const
//
int sector_t::FindMinSurroundingLight (int min) const
{
int i;
line_t* line;
sector_t* check;
for (i = 0; i < linecount; i++)
for (auto line : Lines)
{
line = lines[i];
if (NULL != (check = getNextSector (line, this)) &&
check->lightlevel < min)
{
@ -613,8 +575,6 @@ int sector_t::FindMinSurroundingLight (int min) const
//
double sector_t::FindHighestFloorPoint (vertex_t **v) const
{
int i;
line_t *line;
double height = -FLT_MAX;
double probeheight;
vertex_t *spot = NULL;
@ -623,15 +583,14 @@ double sector_t::FindHighestFloorPoint (vertex_t **v) const
{
if (v != NULL)
{
if (linecount == 0) *v = &vertexes[0];
else *v = lines[0]->v1;
if (Lines.Size() == 0) *v = &vertexes[0];
else *v = Lines[0]->v1;
}
return -floorplane.fD();
}
for (i = 0; i < linecount; i++)
for (auto line : Lines)
{
line = lines[i];
probeheight = floorplane.ZatPoint(line->v1);
if (probeheight > height)
{
@ -655,8 +614,6 @@ double sector_t::FindHighestFloorPoint (vertex_t **v) const
//
double sector_t::FindLowestCeilingPoint (vertex_t **v) const
{
int i;
line_t *line;
double height = FLT_MAX;
double probeheight;
vertex_t *spot = NULL;
@ -665,15 +622,14 @@ double sector_t::FindLowestCeilingPoint (vertex_t **v) const
{
if (v != NULL)
{
if (linecount == 0) *v = &vertexes[0];
else *v = lines[0]->v1;
if (Lines.Size() == 0) *v = &vertexes[0];
else *v = Lines[0]->v1;
}
return ceilingplane.fD();
}
for (i = 0; i < linecount; i++)
for (auto line : Lines)
{
line = lines[i];
probeheight = ceilingplane.ZatPoint(line->v1);
if (probeheight < height)
{
@ -738,15 +694,14 @@ DEFINE_ACTION_FUNCTION(_Sector, SetFade)
void sector_t::ClosestPoint(const DVector2 &in, DVector2 &out) const
{
int i;
double x = in.X, y = in.Y;
double bestdist = HUGE_VAL;
double bestx = 0, besty = 0;
for (i = 0; i < linecount; ++i)
for (auto check : Lines)
{
vertex_t *v1 = lines[i]->v1;
vertex_t *v2 = lines[i]->v2;
vertex_t *v1 = check->v1;
vertex_t *v2 = check->v2;
double a = v2->fX() - v1->fX();
double b = v2->fY() - v1->fY();
double den = a*a + b*b;
@ -1133,9 +1088,8 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
void sector_t::RemoveForceField()
{
for (int i = 0; i < linecount; ++i)
for (auto line : Lines)
{
line_t *line = lines[i];
if (line->backsector != NULL && line->special == ForceField)
{
line->flags &= ~(ML_BLOCKING | ML_BLOCKEVERYTHING);
@ -1377,8 +1331,7 @@ DEFINE_FIELD_X(Sector, sector_t, soundtraversed)
DEFINE_FIELD_X(Sector, sector_t, stairlock)
DEFINE_FIELD_X(Sector, sector_t, prevsec)
DEFINE_FIELD_X(Sector, sector_t, nextsec)
DEFINE_FIELD_X(Sector, sector_t, linecount)
DEFINE_FIELD_X(Sector, sector_t, lines)
DEFINE_FIELD_X(Sector, sector_t, Lines)
DEFINE_FIELD_X(Sector, sector_t, heightsec)
DEFINE_FIELD_X(Sector, sector_t, bottommap)
DEFINE_FIELD_X(Sector, sector_t, midmap)

View file

@ -775,16 +775,13 @@ static void SetTextureNoErr (side_t *side, int position, DWORD *color, const cha
void P_FloodZone (sector_t *sec, int zonenum)
{
int i;
if (sec->ZoneNumber == zonenum)
return;
sec->ZoneNumber = zonenum;
for (i = 0; i < sec->linecount; ++i)
for (auto check : sec->Lines)
{
line_t *check = sec->lines[i];
sector_t *other;
if (check->sidedef[1] == NULL || (check->flags & ML_ZONEBOUNDARY))
@ -3093,7 +3090,6 @@ static void P_GroupLines (bool buildmap)
cycle_t times[16];
int* linesDoneInEachSector;
int i;
int j;
int total;
line_t* li;
sector_t* sector;
@ -3140,13 +3136,13 @@ static void P_GroupLines (bool buildmap)
}
else
{
li->frontsector->linecount++;
li->frontsector->Lines.Count++;
total++;
}
if (li->backsector && li->backsector != li->frontsector)
{
li->backsector->linecount++;
li->backsector->Lines.Count++;
total++;
}
}
@ -3165,7 +3161,7 @@ static void P_GroupLines (bool buildmap)
for (sector = sectors, i = 0; i < numsectors; i++, sector++)
{
if (sector->linecount == 0)
if (sector->Lines.Count == 0)
{
Printf ("Sector %i (tag %i) has no lines\n", i, tagManager.GetFirstSectorTag(sector));
// 0 the sector's tag so that no specials can use it
@ -3173,8 +3169,8 @@ static void P_GroupLines (bool buildmap)
}
else
{
sector->lines = lineb_p;
lineb_p += sector->linecount;
sector->Lines.Array = lineb_p;
lineb_p += sector->Lines.Count;
}
}
@ -3182,26 +3178,25 @@ static void P_GroupLines (bool buildmap)
{
if (li->frontsector != NULL)
{
li->frontsector->lines[linesDoneInEachSector[li->frontsector - sectors]++] = li;
li->frontsector->Lines[linesDoneInEachSector[li->frontsector - sectors]++] = li;
}
if (li->backsector != NULL && li->backsector != li->frontsector)
{
li->backsector->lines[linesDoneInEachSector[li->backsector - sectors]++] = li;
li->backsector->Lines[linesDoneInEachSector[li->backsector - sectors]++] = li;
}
}
for (i = 0, sector = sectors; i < numsectors; ++i, ++sector)
{
if (linesDoneInEachSector[i] != sector->linecount)
if (linesDoneInEachSector[i] != sector->Lines.Size())
{
I_Error("P_GroupLines: miscounted");
}
if (sector->linecount > 3)
if (sector->Lines.Size() > 3)
{
bbox.ClearBox();
for (j = 0; j < sector->linecount; ++j)
for (auto li : sector->Lines)
{
li = sector->lines[j];
bbox.AddToBox(li->v1->fPos());
bbox.AddToBox(li->v2->fPos());
}
@ -3210,15 +3205,15 @@ static void P_GroupLines (bool buildmap)
sector->centerspot.X = (bbox.Right() + bbox.Left()) / 2;
sector->centerspot.Y = (bbox.Top() + bbox.Bottom()) / 2;
}
else if (sector->linecount > 0)
else if (sector->Lines.Size() > 0)
{
// For triangular sectors the above does not calculate good points unless the longest of the triangle's lines is perfectly horizontal and vertical
DVector2 pos = { 0,0 };
for (int i = 0; i < sector->linecount; i++)
for (auto ln : sector->Lines)
{
pos += sector->lines[i]->v1->fPos() + sector->lines[i]->v2->fPos();
pos += ln->v1->fPos() + ln->v2->fPos();
}
sector->centerspot = pos / (2 * sector->linecount);
sector->centerspot = pos / (2 * sector->Lines.Size());
}
}
delete[] linesDoneInEachSector;

View file

@ -201,10 +201,8 @@ void P_SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi, const D
void P_VavoomSlope(sector_t * sec, int id, const DVector3 &pos, int which)
{
for (int i=0;i<sec->linecount;i++)
for(auto l : sec->Lines)
{
line_t * l=sec->lines[i];
if (l->args[0]==id)
{
DVector3 v1, v2, cross;
@ -306,16 +304,16 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
for (int i = 0; i < numsectors; i++)
{
sector_t *sec = &sectors[i];
if (sec->linecount != 3) continue; // only works with triangular sectors
if (sec->Lines.Size() != 3) continue; // only works with triangular sectors
DVector3 vt1, vt2, vt3, cross;
DVector3 vec1, vec2;
int vi1, vi2, vi3;
vi1 = int(sec->lines[0]->v1 - vertexes);
vi2 = int(sec->lines[0]->v2 - vertexes);
vi3 = (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2)?
int(sec->lines[1]->v2 - vertexes) : int(sec->lines[1]->v1 - vertexes);
vi1 = int(sec->Lines[0]->v1 - vertexes);
vi2 = int(sec->Lines[0]->v2 - vertexes);
vi3 = (sec->Lines[1]->v1 == sec->Lines[0]->v1 || sec->Lines[1]->v1 == sec->Lines[0]->v2)?
int(sec->Lines[1]->v2 - vertexes) : int(sec->Lines[1]->v1 - vertexes);
vt1 = DVector3(vertexes[vi1].fPos(), 0);
vt2 = DVector3(vertexes[vi2].fPos(), 0);
@ -332,7 +330,7 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
vt2.Z = h2? *h2 : j==0? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
vt3.Z = h3? *h3 : j==0? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
if (P_PointOnLineSidePrecise(vertexes[vi3].fX(), vertexes[vi3].fY(), sec->lines[0]) == 0)
if (P_PointOnLineSidePrecise(vertexes[vi3].fX(), vertexes[vi3].fY(), sec->Lines[0]) == 0)
{
vec1 = vt2 - vt3;
vec2 = vt1 - vt3;
@ -451,9 +449,7 @@ static void P_AlignPlane(sector_t *sec, line_t *line, int which)
{
sector_t *refsec;
double bestdist;
vertex_t *refvert = (*sec->lines)->v1; // Shut up, GCC
int i;
line_t **probe;
vertex_t *refvert = sec->Lines[0]->v1; // Shut up, GCC
if (line->backsector == NULL)
return;
@ -461,22 +457,22 @@ static void P_AlignPlane(sector_t *sec, line_t *line, int which)
// Find furthest vertex from the reference line. It, along with the two ends
// of the line, will define the plane.
bestdist = 0;
for (i = sec->linecount * 2, probe = sec->lines; i > 0; i--)
for (auto ln : sec->Lines)
{
double dist;
vertex_t *vert;
if (i & 1)
vert = (*probe++)->v2;
else
vert = (*probe)->v1;
dist = fabs((line->v1->fY() - vert->fY()) * line->Delta().X -
(line->v1->fX() - vert->fX()) * line->Delta().Y);
if (dist > bestdist)
for (int i = 0; i < 2; i++)
{
bestdist = dist;
refvert = vert;
double dist;
vertex_t *vert;
vert = i == 0 ? ln->v1 : ln->v2;
dist = fabs((line->v1->fY() - vert->fY()) * line->Delta().X -
(line->v1->fX() - vert->fX()) * line->Delta().Y);
if (dist > bestdist)
{
bestdist = dist;
refvert = vert;
}
}
}

View file

@ -1038,10 +1038,8 @@ void P_SpawnSkybox(ASkyViewpoint *origin)
}
if (Sector)
{
line_t * refline = NULL;
for (short i = 0; i < Sector->linecount; i++)
for(auto refline : Sector->Lines)
{
refline = Sector->lines[i];
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
{
// We found the setup linedef for this skybox, so let's use it for our init.

View file

@ -801,9 +801,8 @@ static bool CollectSectors(int groupid, sector_t *origin)
{
sector_t *sec = list[i];
for (int j = 0; j < sec->linecount; j++)
for (auto line : sec->Lines)
{
line_t *line = sec->lines[j];
sector_t *other = line->frontsector == sec ? line->backsector : line->frontsector;
if (other != NULL && other != sec && other->PortalGroup != groupid)
{
@ -1096,9 +1095,9 @@ void P_CreateLinkedPortals()
// set a flag on each line connecting to a plane portal sector. This is used to reduce the amount of checks in P_CheckSight.
if (sectors[i].PortalIsLinked(sector_t::floor) || sectors[i].PortalIsLinked(sector_t::ceiling))
{
for (int j = 0; j < sectors[i].linecount; j++)
for(auto ln : sectors[i].Lines)
{
sectors[i].lines[j]->flags |= ML_PORTALCONNECT;
ln->flags |= ML_PORTALCONNECT;
}
}
if (sectors[i].PortalIsLinked(sector_t::ceiling) && sectors[i].PortalIsLinked(sector_t::floor))

View file

@ -1037,8 +1037,7 @@ public:
// jff 2/26/98 lockout machinery for stairbuilding
SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally
short linecount;
struct line_t **lines; // [linecount] size
TStaticPointedArray<line_t *> Lines;
// killough 3/7/98: support flat heights drawn at another sector's heights
sector_t *heightsec; // other sector, or NULL if no other sector

View file

@ -6620,6 +6620,7 @@ FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index)
index = _index;
AddressRequested = false;
AddressWritable = false;
SizeAddr = ~0u;
}
//==========================================================================
@ -6691,10 +6692,31 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
arraytype = static_cast<PArray*>(ptype->PointedType);
arrayispointer = true;
}
if (index->isConstant())
if (Array->IsResizableArray())
{
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
{
auto parentfield = static_cast<FxStructMember *>(Array)->membervar;
SizeAddr = unsigned(parentfield->Offset + parentfield->Type->Align);
}
else if (Array->ExprType == EFX_GlobalVariable)
{
auto parentfield = static_cast<FxGlobalVariable *>(Array)->membervar;
SizeAddr = unsigned(parentfield->Offset + parentfield->Type->Align);
}
else
{
ScriptPosition.Message(MSG_ERROR, "Invalid resizable array");
delete this;
return nullptr;
}
}
else if (index->isConstant())
{
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
if (indexval >= arraytype->ElementCount)
if (indexval >= arraytype->ElementCount && !Array->IsResizableArray())
{
ScriptPosition.Message(MSG_ERROR, "Array index out of bounds");
delete this;
@ -6767,21 +6789,40 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
arraytype = static_cast<PArray*>(Array->ValueType);
}
ExpEmit start = Array->Emit(build);
ExpEmit bound;
/* what was this for?
if (start.Konst)
// For resizable arrays we even need to check the bounds if if the index is constant.
if (SizeAddr != ~0u)
{
ExpEmit tmpstart(build, REGT_POINTER);
build->Emit(OP_LKP, tmpstart.RegNum, start.RegNum);
start.Free(build);
start = tmpstart;
auto f = new PField(NAME_None, TypeUInt32, 0, SizeAddr);
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
{
static_cast<FxStructMember *>(Array)->membervar = f;
static_cast<FxStructMember *>(Array)->AddressRequested = false;
}
else if (Array->ExprType == EFX_GlobalVariable)
{
static_cast<FxGlobalVariable *>(Array)->membervar = f;
static_cast<FxGlobalVariable *>(Array)->AddressRequested = false;
}
Array->ValueType = TypeUInt32;
bound = Array->Emit(build);
}
*/
if (index->isConstant())
{
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
assert(indexval < arraytype->ElementCount && "Array index out of bounds");
assert(SizeAddr != ~0u || (indexval < arraytype->ElementCount && "Array index out of bounds"));
if (SizeAddr != ~0u)
{
ExpEmit indexreg(build, REGT_INT);
build->EmitLoadInt(indexreg.RegNum, indexval);
build->Emit(OP_BOUND_R, indexreg.RegNum, bound.RegNum);
indexreg.Free(build);
bound.Free(build);
}
if (AddressRequested)
{
if (indexval != 0)
@ -6821,9 +6862,12 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
else
{
ExpEmit indexv(index->Emit(build));
// Todo: For dynamically allocated arrays (like global sector and linedef tables) we need to get the bound value in here somehow.
// Right now their bounds are not properly checked for.
if (arraytype->ElementCount > 65535)
if (SizeAddr != ~0u)
{
build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum);
bound.Free(build);
}
else if (arraytype->ElementCount > 65535)
{
build->Emit(OP_BOUND_K, indexv.RegNum, build->GetConstantInt(arraytype->ElementCount));
}
@ -7347,7 +7391,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
// Note: These builtins would better be relegated to the actual type objects, instead of polluting this file, but that's a task for later.
// Texture builtins.
if (Self->ValueType == TypeTextureID)
else if (Self->ValueType == TypeTextureID)
{
if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull)
{
@ -7390,7 +7434,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
}
}
if (Self->IsVector())
else if (Self->IsVector())
{
// handle builtins: Vectors got 2: Length and Unit.
if (MethodName == NAME_Length || MethodName == NAME_Unit)
@ -7408,11 +7452,63 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
}
}
if (Self->ValueType == TypeString)
else if (Self->ValueType == TypeString)
{
// same for String methods. It also uses a hidden struct type to define them.
Self->ValueType = TypeStringStruct;
}
else if (Self->IsArray())
{
if (MethodName == NAME_Size)
{
if (ArgList.Size() > 0)
{
ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars());
delete this;
return nullptr;
}
if (!Self->IsResizableArray())
{
auto atype = Self->ValueType;
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) atype = static_cast<PPointer*>(ValueType)->PointedType;
auto size = static_cast<PArray*>(atype)->ElementCount;
auto x = new FxConstant(size, ScriptPosition);
delete this;
return x;
}
else
{
// Resizable arrays can only be defined in C code and they can only exist in pointer form to reduce their impact on the code generator.
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember)
{
auto member = static_cast<FxStructMember*>(Self);
auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer.
member->membervar = newfield;
Self = nullptr;
delete this;
member->ValueType = TypeUInt32;
return member;
}
else if (Self->ExprType == EFX_GlobalVariable)
{
auto member = static_cast<FxGlobalVariable*>(Self);
auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer.
member->membervar = newfield;
Self = nullptr;
delete this;
member->ValueType = TypeUInt32;
return member;
}
else
{
// This should never happen because resizable arrays cannot be defined in scripts.
ScriptPosition.Message(MSG_ERROR, "Cannot retrieve size of array");
delete this;
return nullptr;
}
}
}
}
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{

View file

@ -326,6 +326,8 @@ public:
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); }
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); }
bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PResizableArray))); } // can only exist in pointer form.
virtual ExpEmit Emit(VMFunctionBuilder *build);
void EmitStatement(VMFunctionBuilder *build);
@ -426,6 +428,13 @@ public:
isresolved = true;
}
FxConstant(unsigned int val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos)
{
ValueType = value.Type = TypeUInt32;
value.Int = val;
isresolved = true;
}
FxConstant(double val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos)
{
ValueType = value.Type = TypeFloat64;
@ -1427,6 +1436,7 @@ class FxArrayElement : public FxExpression
public:
FxExpression *Array;
FxExpression *index;
unsigned SizeAddr;
bool AddressRequested;
bool AddressWritable;
bool arrayispointer = false;

View file

@ -710,12 +710,8 @@ static int fieldcmp(const void * a, const void * b)
void InitThingdef()
{
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
// Create all global variables here because this cannot be done on the script side and really isn't worth adding support for.
PStruct *sstruct = NewNativeStruct("Sector", nullptr);
auto sptr = NewPointer(sstruct);
sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget));
// expose the global validcount variable.
PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount);
GlobalSymbols.AddSymbol(vcf);
@ -746,7 +742,7 @@ void InitThingdef()
// set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well...
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
pstruct = NewNativeStruct("Sector", nullptr);
pstruct->AddNativeField("lines", NewPointer(NewArray(NewPointer(NewNativeStruct("line", nullptr), false), 0x40000), false), myoffsetof(sector_t, lines), VARF_Native);
pstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(NewNativeStruct("line", nullptr), false)), false), myoffsetof(sector_t, Lines), VARF_Native);
parray = NewArray(TypeBool, MAXPLAYERS);
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);

View file

@ -467,6 +467,112 @@ 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 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
{
public:
typedef TIterator<T> iterator;
typedef TIterator<const T> const_iterator;
iterator begin()
{
return &Array[0];
}
const_iterator begin() const
{
return &Array[0];
}
const_iterator cbegin() const
{
return &Array[0];
}
iterator end()
{
return &Array[Count];
}
const_iterator end() const
{
return &Array[Count];
}
const_iterator cend() const
{
return &Array[Count];
}
void Init(T *ptr, unsigned cnt)
{
Array = ptr;
Count = cnt;
}
// Return a reference to an element
T &operator[] (size_t index) const
{
return Array[index];
}
unsigned int Size() const
{
return Count;
}
// Some code needs to access these directly so they cannot be private.
T *Array;
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()
{
Count = 0;
Array = NULL;
}
// This is not supposed to be copyable.
TStaticArray(const TStaticArray<T> &other) = delete;
~TStaticArray()
{
Clear();
}
void Clear()
{
if (Array) delete[] Array;
}
void Alloc(unsigned int amount)
{
Clear();
Array = new T[amount];
Count = Amount;
}
};
// 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

View file

@ -273,8 +273,7 @@ struct Sector native
native int prevsec;
native int nextsec;
native readonly int16 linecount;
//line_t **lines; // this is defined internally to avoid exposing some overly complicated type to the parser
//TStaticPointedArray<line_t *> Lines; // this is defined internally to avoid exposing some overly complicated type to the parser
native readonly Sector heightsec;

View file

@ -58,7 +58,7 @@ class LittleFly : Actor
return fallback;
}
// Try neighboring sectors
for (int i = 0; i < sec.linecount; ++i)
for (int i = 0; i < sec.lines.Size(); ++i)
{
line ln = sec.lines[i];
sector sec2 = (ln.frontsector == sec) ? ln.backsector : ln.frontsector;