openclonk/src/landscape/C4PXS.cpp

531 lines
14 KiB
C++
Raw Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, Matthes Bender
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
2009-05-08 13:28:41 +00:00
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
2009-05-08 13:28:41 +00:00
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
2009-05-08 13:28:41 +00:00
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
2009-05-08 13:28:41 +00:00
*/
/* Pixel Sprite system for tiny bits of moving material */
#include <C4Include.h>
#include <C4PXS.h>
#include <C4Components.h>
#include <C4Config.h>
2009-05-08 13:28:41 +00:00
#include <C4Physics.h>
#include <C4Random.h>
2009-06-11 19:59:35 +00:00
#include <C4Weather.h>
2009-08-25 15:50:51 +00:00
#include <C4Record.h>
2009-05-08 13:28:41 +00:00
static const C4Real WindDrift_Factor = itofix(1, 800);
2009-05-08 13:28:41 +00:00
void C4PXS::Execute()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
#ifdef DEBUGREC_PXS
if (Config.General.DebugRec)
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
C4RCExecPXS rc;
rc.x=x; rc.y=y; rc.iMat=Mat;
rc.pos = 0;
AddDbgRec(RCT_ExecPXS, &rc, sizeof(rc));
2009-05-08 13:28:41 +00:00
}
#endif
int32_t inmat;
// Safety
if (!MatValid(Mat))
{ Deactivate(); return; }
// Out of bounds
if ((x<0) || (x>=GBackWdt) || (y<-10) || (y>=GBackHgt))
{ Deactivate(); return; }
// Material conversion
int32_t iX = fixtoi(x), iY = fixtoi(y);
inmat=GBackMat(iX,iY);
2009-06-05 18:46:03 +00:00
C4MaterialReaction *pReact = ::MaterialMap.GetReactionUnsafe(Mat, inmat);
2009-05-08 13:28:41 +00:00
if (pReact && (*pReact->pFunc)(pReact, iX,iY, iX,iY, xdir,ydir, Mat,inmat, meePXSPos, NULL))
{ Deactivate(); return; }
// Gravity
ydir+=GravAccel;
2010-03-28 18:58:01 +00:00
if (GBackDensity(iX, iY + 1) < ::MaterialMap.Map[Mat].Density)
{
2009-05-08 13:28:41 +00:00
// Air speed: Wind plus some random
int32_t iWind = Weather.GetWind(iX, iY);
C4Real txdir = itofix(iWind, 15) + C4REAL256(Random(1200) - 600);
C4Real tydir = C4REAL256(Random(1200) - 600);
2009-05-08 13:28:41 +00:00
// Air friction, based on WindDrift. MaxSpeed is ignored.
int32_t iWindDrift = std::max(::MaterialMap.Map[Mat].WindDrift - 20, 0);
2009-05-08 13:28:41 +00:00
xdir += ((txdir - xdir) * iWindDrift) * WindDrift_Factor;
ydir += ((tydir - ydir) * iWindDrift) * WindDrift_Factor;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Real ctcox = x + xdir;
C4Real ctcoy = y + ydir;
2009-05-08 13:28:41 +00:00
int32_t iToX = fixtoi(ctcox), iToY = fixtoi(ctcoy);
// In bounds?
2010-03-28 18:58:01 +00:00
if (Inside<int32_t>(iToX, 0, GBackWdt-1) && Inside<int32_t>(iToY, 0, GBackHgt-1))
2009-05-08 13:28:41 +00:00
// Check path
2010-03-28 18:58:01 +00:00
if (::Landscape._PathFree(iX, iY, iToX, iToY))
{
2009-05-08 13:28:41 +00:00
x=ctcox; y=ctcoy;
return;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Test path to target position
int32_t iX0 = iX, iY0 = iY;
2009-05-08 13:28:41 +00:00
bool fStopMovement = false;
do
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Step
int32_t inX = iX + Sign(iToX - iX), inY = iY + Sign(iToY - iY);
// Contact?
inmat = GBackMat(inX, inY);
2009-06-05 18:46:03 +00:00
C4MaterialReaction *pReact = ::MaterialMap.GetReactionUnsafe(Mat, inmat);
2009-05-08 13:28:41 +00:00
if (pReact)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ((*pReact->pFunc)(pReact, iX,iY, inX,inY, xdir,ydir, Mat,inmat, meePXSMove, &fStopMovement))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// destructive contact
Deactivate();
return;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no destructive contact, but speed or position changed: Stop moving for now
if (fStopMovement)
2010-03-28 18:58:01 +00:00
{
// But keep fractional positions to allow proper movement on moving ground
if (iX != iX0) x = itofix(iX);
if (iY != iY0) y = itofix(iY);
2009-05-08 13:28:41 +00:00
return;
}
2010-03-28 18:58:01 +00:00
// there was a reaction func, but it didn't do anything - continue movement
2010-01-25 04:00:59 +00:00
}
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
iX = inX; iY = inY;
}
2009-05-08 13:28:41 +00:00
while (iX != iToX || iY != iToY);
// No contact? Free movement
x=ctcox; y=ctcoy;
#ifdef DEBUGREC_PXS
if (Config.General.DebugRec)
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
C4RCExecPXS rc;
rc.x=x; rc.y=y; rc.iMat=Mat;
rc.pos = 1;
AddDbgRec(RCT_ExecPXS, &rc, sizeof(rc));
2009-05-08 13:28:41 +00:00
}
#endif
return;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXS::Deactivate()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
#ifdef DEBUGREC_PXS
if (Config.General.DebugRec)
{
C4RCExecPXS rc;
rc.x=x; rc.y=y; rc.iMat=Mat;
rc.pos = 2;
AddDbgRec(RCT_ExecPXS, &rc, sizeof(rc));
}
2009-05-08 13:28:41 +00:00
#endif
Mat=MNone;
2009-06-05 15:20:27 +00:00
::PXS.Delete(this);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PXSSystem::C4PXSSystem()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Default();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PXSSystem::~C4PXSSystem()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Clear();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Default()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Count=0;
for (unsigned int cnt=0; cnt<PXSMaxChunk; cnt++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Chunk[cnt]=NULL;
iChunkPXS[cnt]=0;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Clear()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for (unsigned int cnt=0; cnt<PXSMaxChunk; cnt++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (Chunk[cnt]) delete [] Chunk[cnt];
Chunk[cnt]=NULL;
iChunkPXS[cnt]=0;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PXS* C4PXSSystem::New()
2010-03-28 18:58:01 +00:00
{
unsigned int cnt,cnt2;
C4PXS *pxp;
// Check chunks for available space
for (cnt=0; cnt<PXSMaxChunk; cnt++)
2010-03-28 18:58:01 +00:00
{
// Create new chunk if necessary
if (!Chunk[cnt])
2010-03-28 18:58:01 +00:00
{
if (!(Chunk[cnt]=new C4PXS[PXSChunkSize])) return NULL;
2009-05-08 13:28:41 +00:00
iChunkPXS[cnt] = 0;
2010-03-28 18:58:01 +00:00
}
// Check this chunk for space
2010-03-28 18:58:01 +00:00
if (iChunkPXS[cnt] < PXSChunkSize)
2009-05-08 13:28:41 +00:00
for (cnt2=0,pxp=Chunk[cnt]; cnt2<PXSChunkSize; cnt2++,pxp++)
if (pxp->Mat==MNone)
{
// count theam
iChunkPXS[cnt]++;
return pxp;
}
}
2010-03-28 18:58:01 +00:00
return NULL;
}
2009-05-08 13:28:41 +00:00
bool C4PXSSystem::Create(int32_t mat, C4Real ix, C4Real iy, C4Real ixdir, C4Real iydir)
2010-03-28 18:58:01 +00:00
{
C4PXS *pxp;
if (!MatValid(mat)) return false;
if (!(pxp=New())) return false;
pxp->Mat=mat;
pxp->x=ix; pxp->y=iy;
pxp->xdir=ixdir; pxp->ydir=iydir;
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Execute()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Execute all chunks
Count=0;
for (unsigned int cchunk=0; cchunk<PXSMaxChunk; cchunk++)
if (Chunk[cchunk])
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// empty chunk?
2010-03-28 18:58:01 +00:00
if (!iChunkPXS[cchunk])
2009-05-08 13:28:41 +00:00
{ delete [] Chunk[cchunk]; Chunk[cchunk]=NULL; }
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Execute chunk pxs, check for empty
C4PXS *pxp = Chunk[cchunk];
for (unsigned int cnt2=0; cnt2<PXSChunkSize; cnt2++,pxp++)
if (pxp->Mat!=MNone)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pxp->Execute();
Count++;
2010-03-28 18:58:01 +00:00
}
2010-01-25 04:00:59 +00:00
}
2010-03-28 18:58:01 +00:00
}
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Draw(C4TargetFacet &cgo)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Draw PXS in this region
C4Rect VisibleRect(cgo.TargetX, cgo.TargetY, cgo.Wdt, cgo.Hgt);
VisibleRect.Enlarge(20);
2014-10-08 17:36:15 +00:00
// Go through all PXS and build vertex arrays. The vertex arrays are
// then submitted to the GL in one go.
std::vector<C4BltVertex> pixVtx;
std::vector<C4BltVertex> lineVtx;
std::map<int, std::vector<C4BltVertex> > bltVtx;
// TODO: reserve some space to avoid too many allocations
// TODO: keep vertex mem allocated between draw invocations
2011-05-26 13:03:51 +00:00
float cgox = cgo.X - cgo.TargetX, cgoy = cgo.Y - cgo.TargetY;
2014-10-08 17:36:15 +00:00
// First pass: draw simple PXS (lines/pixels)
2009-05-08 13:28:41 +00:00
unsigned int cnt;
2011-05-26 13:03:51 +00:00
for (cnt=0; cnt < PXSMaxChunk; cnt++)
2014-10-08 17:36:15 +00:00
{
2009-05-08 13:28:41 +00:00
if (Chunk[cnt] && iChunkPXS[cnt])
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PXS *pxp = Chunk[cnt];
2011-05-26 13:03:51 +00:00
for (unsigned int cnt2 = 0; cnt2 < PXSChunkSize; cnt2++, pxp++)
2009-05-08 13:28:41 +00:00
if (pxp->Mat != MNone && VisibleRect.Contains(fixtoi(pxp->x), fixtoi(pxp->y)))
2010-03-28 18:58:01 +00:00
{
2014-10-08 17:36:15 +00:00
C4Material *pMat = &::MaterialMap.Map[pxp->Mat];
const DWORD dwMatClr = ::Landscape.GetPal()->GetClr((BYTE) (Mat2PixColDefault(pxp->Mat)));
if(pMat->PXSFace.Surface)
2010-03-28 18:58:01 +00:00
{
2014-10-08 17:36:15 +00:00
int32_t pnx, pny;
pMat->PXSFace.GetPhaseNum(pnx, pny);
int32_t fcWdt = pMat->PXSFace.Wdt;
int32_t fcHgt = pMat->PXSFace.Hgt;
// calculate draw width and tile to use (random-ish)
uint32_t size = (1103515245 * (cnt * PXSChunkSize + cnt2) + 12345) >> 3;
float z = pMat->PXSGfxSize * (0.625f + 0.05f * int(size % 16));
pny = (cnt2 / pnx) % pny; pnx = cnt2 % pnx;
const float w = z;
const float h = z * fcHgt / fcWdt;
const float x1 = fixtof(pxp->x) + cgox + z * pMat->PXSGfxRt.tx / fcWdt;
const float y1 = fixtof(pxp->y) + cgoy + z * pMat->PXSGfxRt.ty / fcHgt;
2014-10-08 17:36:15 +00:00
const float x2 = x1 + w;
const float y2 = y1 + h;
const float sfcWdt = pMat->PXSFace.Surface->Wdt;
const float sfcHgt = pMat->PXSFace.Surface->Hgt;
2014-10-08 17:36:15 +00:00
C4BltVertex vtx[6];
vtx[0].tx = (pnx + 0.f) * fcWdt / sfcWdt; vtx[0].ty = (pny + 0.f) * fcHgt / sfcHgt;
vtx[0].ftx = x1; vtx[0].fty = y1;
vtx[1].tx = (pnx + 1.f) * fcWdt / sfcWdt; vtx[1].ty = (pny + 0.f) * fcHgt / sfcHgt;
vtx[1].ftx = x2; vtx[1].fty = y1;
vtx[2].tx = (pnx + 1.f) * fcWdt / sfcWdt; vtx[2].ty = (pny + 1.f) * fcHgt / sfcHgt;
vtx[2].ftx = x2; vtx[2].fty = y2;
vtx[3].tx = (pnx + 0.f) * fcWdt / sfcWdt; vtx[3].ty = (pny + 1.f) * fcHgt / sfcHgt;
vtx[3].ftx = x1; vtx[3].fty = y2;
DwTo4UB(0xFFFFFFFF, vtx[0].color);
DwTo4UB(0xFFFFFFFF, vtx[1].color);
DwTo4UB(0xFFFFFFFF, vtx[2].color);
DwTo4UB(0xFFFFFFFF, vtx[3].color);
vtx[4] = vtx[2];
vtx[5] = vtx[0];
std::vector<C4BltVertex>& vec = bltVtx[pxp->Mat];
vec.push_back(vtx[0]);
vec.push_back(vtx[1]);
vec.push_back(vtx[2]);
vec.push_back(vtx[3]);
vec.push_back(vtx[4]);
vec.push_back(vtx[5]);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2014-10-08 17:36:15 +00:00
{
// old-style: unicolored pixels or lines
if (fixtoi(pxp->xdir) || fixtoi(pxp->ydir))
{
// lines for stuff that goes whooosh!
int len = fixtoi(Abs(pxp->xdir) + Abs(pxp->ydir));
const DWORD dwMatClrLen = uint32_t(std::max<int>(dwMatClr >> 24, 195 - (195 - (dwMatClr >> 24)) / len)) << 24 | (dwMatClr & 0xffffff);
2014-10-08 17:36:15 +00:00
C4BltVertex begin, end;
begin.ftx = fixtof(pxp->x - pxp->xdir) + cgox; begin.fty = fixtof(pxp->y - pxp->ydir) + cgoy;
end.ftx = fixtof(pxp->x) + cgox; end.fty = fixtof(pxp->y) + cgoy;
DwTo4UB(dwMatClrLen, begin.color);
DwTo4UB(dwMatClrLen, end.color);
lineVtx.push_back(begin);
lineVtx.push_back(end);
}
else
{
// single pixels for slow stuff
C4BltVertex vtx;
vtx.ftx = fixtof(pxp->x) + cgox;
vtx.fty = fixtof(pxp->y) + cgoy;
DwTo4UB(dwMatClr, vtx.color);
pixVtx.push_back(vtx);
}
}
2010-03-28 18:58:01 +00:00
}
}
2014-10-08 17:36:15 +00:00
}
if(!pixVtx.empty()) pDraw->PerformMultiPix(cgo.Surface, &pixVtx[0], pixVtx.size(), NULL);
if(!lineVtx.empty()) pDraw->PerformMultiLines(cgo.Surface, &lineVtx[0], lineVtx.size(), 1.0f, NULL);
2009-05-08 13:28:41 +00:00
// PXS graphics disabled?
2010-03-28 18:58:01 +00:00
if (!Config.Graphics.PXSGfx)
2009-05-08 13:28:41 +00:00
return;
2014-10-08 17:36:15 +00:00
for(std::map<int, std::vector<C4BltVertex> >::const_iterator iter = bltVtx.begin(); iter != bltVtx.end(); ++iter)
{
C4Material *pMat = &::MaterialMap.Map[iter->first];
pDraw->PerformMultiTris(cgo.Surface, &iter->second[0], iter->second.size(), NULL, &pMat->PXSFace.Surface->textures[0], NULL, NULL, 0, NULL);
2014-10-08 17:36:15 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Cast(int32_t mat, int32_t num, int32_t tx, int32_t ty, int32_t level)
2010-03-28 18:58:01 +00:00
{
int32_t cnt;
for (cnt=0; cnt<num; cnt++)
{
// Must do these calculation steps separately, because the order of
// invokations of Random() is not defined if they're used as parameters
C4Real xdir = itofix(Random(level+1)-level/2); xdir/=10;
C4Real ydir = itofix(Random(level+1)-level); ydir/=10;
Create(mat,
2010-03-28 18:58:01 +00:00
itofix(tx),itofix(ty),
xdir,
ydir);
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PXSSystem::Save(C4Group &hGroup)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
unsigned int cnt;
// Check used chunk count
int32_t iChunks=0;
for (cnt=0; cnt<PXSMaxChunk; cnt++)
if (Chunk[cnt] && iChunkPXS[cnt])
iChunks++;
if (!iChunks)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
hGroup.Delete(C4CFN_PXS);
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Save chunks to temp file
CStdFile hTempFile;
if (!hTempFile.Create(Config.AtTempPath(C4CFN_TempPXS)))
return false;
#ifdef C4REAL_USE_FIXNUM
2009-05-08 13:28:41 +00:00
int32_t iNumFormat = 1;
#else
int32_t iNumFormat = 2;
#endif
2010-03-28 18:58:01 +00:00
if (!hTempFile.Write(&iNumFormat, sizeof (iNumFormat)))
return false;
2009-05-08 13:28:41 +00:00
for (cnt=0; cnt<PXSMaxChunk; cnt++)
if (Chunk[cnt]) // must save all chunks in order to keep order consistent on all clients
if (!hTempFile.Write(Chunk[cnt],PXSChunkSize * sizeof(C4PXS)))
return false;
2009-05-08 13:28:41 +00:00
if (!hTempFile.Close())
return false;
2009-05-08 13:28:41 +00:00
// Move temp file to group
if (!hGroup.Move( Config.AtTempPath(C4CFN_TempPXS),
2010-03-28 18:58:01 +00:00
C4CFN_PXS ))
return false;
2009-05-08 13:28:41 +00:00
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PXSSystem::Load(C4Group &hGroup)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// load new
size_t iBinSize,iChunkNum,cnt2;
size_t iChunkSize = PXSChunkSize * sizeof(C4PXS);
if (!hGroup.AccessEntry(C4CFN_PXS,&iBinSize)) return false;
2009-05-08 13:28:41 +00:00
// clear previous
Clear();
// using C4Real or float?
2009-05-08 13:28:41 +00:00
int32_t iNumForm = 1;
2010-03-28 18:58:01 +00:00
if (iBinSize % iChunkSize == 4)
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
if (!hGroup.Read(&iNumForm, sizeof (iNumForm))) return false;
if (!Inside<int32_t>(iNumForm, 1, 2)) return false;
2009-05-08 13:28:41 +00:00
iBinSize -= 4;
}
// old pxs-files have no tag for the number format
2010-03-28 18:58:01 +00:00
else if (iBinSize % iChunkSize != 0) return false;
2009-05-08 13:28:41 +00:00
// calc chunk count
iChunkNum = iBinSize / iChunkSize;
2010-03-28 18:58:01 +00:00
if (iChunkNum > PXSMaxChunk) return false;
2009-05-08 13:28:41 +00:00
for (uint32_t cnt=0; cnt<iChunkNum; cnt++)
2010-03-28 18:58:01 +00:00
{
if (!(Chunk[cnt]=new C4PXS[PXSChunkSize])) return false;
if (!hGroup.Read(Chunk[cnt],iChunkSize)) return false;
2009-05-08 13:28:41 +00:00
// count the PXS, Peter!
// convert num format, if neccessary
C4PXS *pxp; iChunkPXS[cnt]=0;
for (cnt2=0,pxp=Chunk[cnt]; cnt2<PXSChunkSize; cnt2++,pxp++)
if (pxp->Mat != MNone)
{
++iChunkPXS[cnt];
// convert number format
#ifdef C4REAL_USE_FIXNUM
2010-03-28 18:58:01 +00:00
if (iNumForm == 2) { FLOAT_TO_FIXED(&pxp->x); FLOAT_TO_FIXED(&pxp->y); FLOAT_TO_FIXED(&pxp->xdir); FLOAT_TO_FIXED(&pxp->ydir); }
2009-05-08 13:28:41 +00:00
#else
2010-03-28 18:58:01 +00:00
if (iNumForm == 1) { FIXED_TO_FLOAT(&pxp->x); FIXED_TO_FLOAT(&pxp->y); FIXED_TO_FLOAT(&pxp->xdir); FIXED_TO_FLOAT(&pxp->ydir); }
2009-05-08 13:28:41 +00:00
#endif
}
}
2010-03-28 18:58:01 +00:00
return true;
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Synchronize()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Count=0;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::SyncClearance()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// consolidate chunks; remove empty chunks
C4PXS **pDestChunk = Chunk;
int32_t iDestChunk = 0;
for (unsigned int cnt=0; cnt<PXSMaxChunk; cnt++)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (Chunk[cnt])
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (iChunkPXS[cnt])
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
*pDestChunk++ = Chunk[cnt];
iChunkPXS[iDestChunk++] = iChunkPXS[cnt];
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete [] Chunk[cnt];
Chunk[cnt] = NULL;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PXSSystem::Delete(C4PXS *pPXS)
{
// find chunk
unsigned int cnt;
2010-03-28 18:58:01 +00:00
for (cnt = 0; cnt < PXSMaxChunk; cnt++)
if (Chunk[cnt] && iChunkPXS[cnt])
if (pPXS >= Chunk[cnt] && pPXS < Chunk[cnt] + PXSChunkSize)
2009-05-08 13:28:41 +00:00
break;
// decrease pxs counter
2010-03-28 18:58:01 +00:00
if (cnt < PXSMaxChunk)
2009-05-08 13:28:41 +00:00
iChunkPXS[cnt]--;
}
2009-06-05 15:20:27 +00:00
int32_t C4PXSSystem::GetCount(int32_t mat) const
{
// count PXS of given material
int32_t result = 0;
for (size_t cnt = 0; cnt < PXSMaxChunk; cnt++) if (Chunk[cnt] && iChunkPXS[cnt])
{
C4PXS *pxp = Chunk[cnt];
for (size_t cnt2 = 0; cnt2 < PXSChunkSize; cnt2++, pxp++) if (pxp->Mat == mat) ++result;
}
return result;
}
int32_t C4PXSSystem::GetCount(int32_t mat, int32_t x, int32_t y, int32_t wdt, int32_t hgt) const
{
// count PXS of given material in given area
int32_t result = 0;
for (size_t cnt = 0; cnt < PXSMaxChunk; cnt++) if (Chunk[cnt] && iChunkPXS[cnt])
{
C4PXS *pxp = Chunk[cnt];
for (size_t cnt2 = 0; cnt2 < PXSChunkSize; cnt2++, pxp++)
if (pxp->Mat != MNone)
if (pxp->Mat == mat || mat == MNone)
if (Inside(pxp->x, x, x + wdt - 1) && Inside(pxp->y, y, y + hgt - 1)) ++result;
}
return result;
}
2009-06-05 15:20:27 +00:00
C4PXSSystem PXS;