2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 2003 , 2005 , 2008 Sven Eberhardt
* Copyright ( c ) 2007 Peter Wortmann
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2007 - 2010 G ü nther Brammer
* Copyright ( c ) 2010 Benjamin Herr
* Copyright ( c ) 2010 Nicolas Hake
2009-05-08 13:28:41 +00:00
* Copyright ( c ) 2001 - 2009 , RedWolf Design GmbH , http : //www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk .
*
* Permission to use , copy , modify , and / or distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
* See isc_license . txt for full license and disclaimer .
*
* " Clonk " is a registered trademark of Matthes Bender .
* See clonk_trademark_license . txt for full license .
*/
/* Solid areas of objects, put into the landscape */
# include <C4Include.h>
# include <C4SolidMask.h>
# include <C4Object.h>
2009-06-12 18:52:21 +00:00
# include <C4Landscape.h>
# include <C4Game.h>
2009-06-15 21:47:26 +00:00
# include <C4GameObjects.h>
2009-05-08 13:28:41 +00:00
void C4SolidMask : : Put ( bool fCauseInstability , C4TargetRect * pClipRect , bool fRestoreAttachment )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// If not put, put mask to background,
// storing background pixels in cSolidMask.
2010-03-27 16:05:02 +00:00
// No mask
if ( ! pSolidMask | | ! pSolidMaskMatBuff ) { iAttachingObjectsCount = 0 ; return ; }
// Contained
if ( pForObject - > Contained ) { iAttachingObjectsCount = 0 ; return ; }
// Mask is put
2009-05-08 13:28:41 +00:00
if ( fCauseInstability ) CheckConsistency ( ) ;
bool RegularPut ;
if ( ! pClipRect )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Regular Put: Update MaskPutRect and MaskPutRotation
MaskPutRotation = pForObject - > r ;
pClipRect = & MaskPutRect ;
RegularPut = true ;
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
// Reput by C4SolidMask::Remove
// Don't change MaskPutRotation or MaskPutRect
// Intersect ClipRect with the MaskPutRect
if ( ! pClipRect - > ClipBy ( MaskPutRect ) ) return ;
RegularPut = false ;
2010-03-28 18:58:01 +00:00
}
2010-03-27 16:05:02 +00:00
// Lock mask surface
int iPitch = pForObject - > SolidMask . Wdt ;
2009-05-08 13:28:41 +00:00
int xcnt , ycnt , iTx , iTy ;
// Put mask pixels
2010-03-27 16:05:02 +00:00
BYTE byPixel ;
2009-05-08 13:28:41 +00:00
// not rotated?
if ( ! MaskPutRotation )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// calc put rect
if ( RegularPut )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int ox , oy ;
ox = pForObject - > GetX ( ) + pForObject - > Def - > Shape . x + pForObject - > SolidMask . tx ;
oy = pForObject - > GetY ( ) + pForObject - > Def - > Shape . y + pForObject - > SolidMask . ty ;
MaskPutRect . x = ox ;
2010-03-28 18:58:01 +00:00
if ( MaskPutRect . x < 0 ) { MaskPutRect . tx = - MaskPutRect . x ; MaskPutRect . x = 0 ; }
else MaskPutRect . tx = 0 ;
2009-05-08 13:28:41 +00:00
MaskPutRect . y = oy ;
2010-03-28 18:58:01 +00:00
if ( MaskPutRect . y < 0 ) { MaskPutRect . ty = - MaskPutRect . y ; MaskPutRect . y = 0 ; }
else MaskPutRect . ty = 0 ;
2009-05-08 13:28:41 +00:00
MaskPutRect . Wdt = Min < int32_t > ( ox + pForObject - > SolidMask . Wdt , GBackWdt ) - MaskPutRect . x ;
MaskPutRect . Hgt = Min < int32_t > ( oy + pForObject - > SolidMask . Hgt , GBackHgt ) - MaskPutRect . y ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// fill rect with mask
for ( ycnt = 0 ; ycnt < pClipRect - > Hgt ; + + ycnt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
BYTE * pPix = pSolidMask + ( ycnt + pClipRect - > ty ) * pForObject - > SolidMask . Wdt + pClipRect - > tx ;
for ( xcnt = 0 ; xcnt < pClipRect - > Wdt ; + + xcnt , + + pPix )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( * pPix )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// solid mask present here
// calc position in landscape
iTx = pClipRect - > x + xcnt ; iTy = pClipRect - > y + ycnt ;
// is background mat to be stored? always do this in the given rect
if ( ! MaskPut )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get background pixel
byPixel = GBackPix ( iTx , iTy ) ;
// store it. If MCVehic, also store in initial put, but won't be used in restore
// do not overwrite current value in re-put issued by SolidMask-remover
if ( byPixel ! = MCVehic | | RegularPut )
pSolidMaskMatBuff [ ( ycnt + pClipRect - > ty ) * MatBuffPitch + xcnt + pClipRect - > tx ] = byPixel ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// and set mask
_SBackPix ( iTx , iTy , MCVehic ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
// no SolidMask: mark buffer as unused here
if ( ! MaskPut )
pSolidMaskMatBuff [ ( ycnt + pClipRect - > ty ) * MatBuffPitch + xcnt + pClipRect - > tx ] = MCVehic ;
}
}
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
// calc matrix for given rotation
2010-05-04 15:35:18 +00:00
C4Real Ma1 = Cos ( itofix ( - MaskPutRotation ) ) , Ma2 = - Sin ( itofix ( - MaskPutRotation ) ) ,
2010-03-28 18:58:01 +00:00
Mb1 = Sin ( itofix ( - MaskPutRotation ) ) , Mb2 = Cos ( itofix ( - MaskPutRotation ) ) ;
2009-05-08 13:28:41 +00:00
// get upper-left corner of landscape copy rect
int centerx = pForObject - > Def - > Shape . x + pForObject - > SolidMask . tx + pForObject - > SolidMask . Wdt / 2 ;
int centery = pForObject - > Def - > Shape . y + pForObject - > SolidMask . ty + pForObject - > SolidMask . Hgt / 2 ;
int xstart = pForObject - > GetX ( ) + fixtoi ( Ma1 * itofix ( centerx ) - Ma2 * itofix ( centery ) ) - MatBuffPitch / 2 ;
int ystart = pForObject - > GetY ( ) + fixtoi ( - Mb1 * itofix ( centerx ) + Mb2 * itofix ( centery ) ) - MatBuffPitch / 2 ;
// store put rect
if ( RegularPut )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
MaskPutRect . x = xstart ;
2010-03-28 18:58:01 +00:00
if ( MaskPutRect . x < 0 ) { MaskPutRect . tx = - MaskPutRect . x ; MaskPutRect . Wdt = MaskPutRect . x ; MaskPutRect . x = 0 ; }
else { MaskPutRect . tx = 0 ; MaskPutRect . Wdt = 0 ; }
2009-05-08 13:28:41 +00:00
MaskPutRect . y = ystart ;
2010-03-28 18:58:01 +00:00
if ( MaskPutRect . y < 0 ) { MaskPutRect . ty = - MaskPutRect . y ; MaskPutRect . Hgt = MaskPutRect . y ; MaskPutRect . y = 0 ; }
else { MaskPutRect . ty = 0 ; MaskPutRect . Hgt = 0 ; }
2009-05-08 13:28:41 +00:00
MaskPutRect . Wdt = Min < int32_t > ( xstart + MatBuffPitch , GBackWdt ) - MaskPutRect . x ;
MaskPutRect . Hgt = Min < int32_t > ( ystart + MatBuffPitch , GBackHgt ) - MaskPutRect . y ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// go through clipping rect
2010-05-04 15:35:18 +00:00
const C4Real y0 = itofix ( pClipRect - > ty - MatBuffPitch / 2 ) ;
const C4Real x0 = itofix ( pClipRect - > tx - MatBuffPitch / 2 ) ;
2009-05-08 13:28:41 +00:00
iTy = pClipRect - > y ;
int w = pForObject - > SolidMask . Wdt ;
int h = pForObject - > SolidMask . Hgt ;
2010-05-04 15:35:18 +00:00
C4Real ya = y0 * Ma2 ;
C4Real yb = y0 * Mb2 ;
2010-03-28 18:58:01 +00:00
for ( ycnt = 0 ; ycnt < pClipRect - > Hgt ; ycnt + + )
{
2009-05-08 13:28:41 +00:00
iTx = pClipRect - > x ;
int i = ( ycnt + pClipRect - > ty ) * MatBuffPitch + pClipRect - > tx ;
2010-05-04 15:35:18 +00:00
C4Real xa = x0 * Ma1 ;
C4Real xb = x0 * Mb1 ;
2010-03-28 18:58:01 +00:00
for ( xcnt = 0 ; xcnt < pClipRect - > Wdt ; xcnt + + )
{
2009-05-08 13:28:41 +00:00
// calc position in solidmask buffer
2009-09-19 21:20:32 +00:00
int iMx = fixtoi ( xa + ya ) + w / 2 ;
int iMy = fixtoi ( xb + yb ) + h / 2 ;
2009-05-08 13:28:41 +00:00
// in bounds? and solidmask?
2010-03-28 18:58:01 +00:00
if ( iMx > = 0 & & iMy > = 0 & & iMx < w & & iMy < h & & pSolidMask [ iMy * iPitch + iMx ] )
{
2009-05-08 13:28:41 +00:00
// is background mat to be stored?
if ( ! MaskPut )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get background pixel
byPixel = _GBackPix ( iTx , iTy ) ;
// store it. If MCVehic, also store in initial put, but won't be used in restore
// do not overwrite current value in re-put issued by SolidMask-remover
if ( byPixel ! = MCVehic | | RegularPut )
pSolidMaskMatBuff [ i + xcnt ] = byPixel ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// set mask pix
_SBackPix ( iTx , iTy , MCVehic ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if ( ! MaskPut )
// mark pix as unused in buf
pSolidMaskMatBuff [ i + xcnt ] = MCVehic ;
2009-09-19 21:20:32 +00:00
xa + = Ma1 ; xb + = Mb1 ;
2009-05-08 13:28:41 +00:00
+ + iTx ;
2010-03-28 18:58:01 +00:00
}
2009-09-19 21:20:32 +00:00
ya + = Ma2 ; yb + = Mb2 ;
2009-05-08 13:28:41 +00:00
+ + iTy ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Store mask put status
2009-08-15 18:50:32 +00:00
MaskPut = true ;
2009-05-08 13:28:41 +00:00
// restore attached object positions if moved
if ( fRestoreAttachment & & iAttachingObjectsCount )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t dx = pForObject - > GetX ( ) - MaskRemovalX ;
int32_t dy = pForObject - > GetY ( ) - MaskRemovalY ;
if ( dx | dy )
for ( int i = 0 ; i < iAttachingObjectsCount ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Object * pObj = ppAttachingObjects [ i ] ;
2011-01-03 22:54:17 +00:00
if ( pObj - > IsMoveableBySolidMask ( pForObject - > GetPlane ( ) ) )
2009-05-08 13:28:41 +00:00
if ( ! pObj - > Shape . ContactCheck ( pObj - > GetX ( ) + dx , pObj - > GetY ( ) + dy ) )
if ( pObj - > iLastAttachMovementFrame ! = Game . FrameCounter )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pObj - > iLastAttachMovementFrame = Game . FrameCounter ;
pObj - > MovePosition ( dx , dy ) ;
2010-03-28 18:58:01 +00:00
}
}
2009-05-08 13:28:41 +00:00
iAttachingObjectsCount = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( fCauseInstability ) CheckConsistency ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
int32_t C4SolidMask : : DensityProvider : : GetDensity ( int32_t x , int32_t y ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// outside SolidMask: free
x - = rSolidMaskData . MaskPutRect . x ;
y - = rSolidMaskData . MaskPutRect . y ;
if ( ! Inside < int32_t > ( x , 0 , rSolidMaskData . MaskPutRect . Wdt - 1 )
2010-03-28 18:58:01 +00:00
| | ! Inside < int32_t > ( y , 0 , rSolidMaskData . MaskPutRect . Hgt - 1 ) )
2009-05-08 13:28:41 +00:00
return 0 ;
// check put mask. Easy for unrotated
BYTE * pPix ;
if ( ! rSolidMaskData . MaskPutRotation )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pPix = rSolidMaskData . pSolidMask + ( y + rSolidMaskData . MaskPutRect . ty ) * rSolidMaskData . pForObject - > SolidMask . Wdt + rSolidMaskData . MaskPutRect . tx + x ;
if ( * pPix = = 0xff )
return C4M_Solid ;
else
return 0 ;
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
// Using put-buffer for rotated masks
// for SolidMask-pixels not put because there was another SolidMask already, this will not return solid
pPix = rSolidMaskData . pSolidMaskMatBuff + ( y + rSolidMaskData . MaskPutRect . ty ) * rSolidMaskData . MatBuffPitch + rSolidMaskData . MaskPutRect . tx + x ;
if ( * pPix = = MCVehic )
return 0 ;
else
return C4M_Solid ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-04-20 20:38:18 +00:00
void C4SolidMask : : Remove ( bool fBackupAttachment )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// If put, restore background pixels from buffer
// Not put
2010-03-27 16:05:02 +00:00
if ( ! MaskPut | | ! pSolidMask | | ! pSolidMaskMatBuff ) return ;
2009-05-08 13:28:41 +00:00
CheckConsistency ( ) ;
// reput background pixels
for ( int ycnt = 0 ; ycnt < MaskPutRect . Hgt ; + + ycnt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
BYTE * pPix = pSolidMaskMatBuff + ( ycnt + MaskPutRect . ty ) * MatBuffPitch + MaskPutRect . tx ;
for ( int xcnt = 0 ; xcnt < MaskPutRect . Wdt ; + + xcnt , + + pPix )
// only if mask was used here
if ( * pPix ! = MCVehic )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// calc position in landscape
int iTx = MaskPutRect . x + xcnt ; int iTy = MaskPutRect . y + ycnt ;
// restore pixel here
// The pPix-check ensures that only pixels that hads been overwritten by this SolidMask are restored
// Non-SolidMask-pixels should not happen here, because all relevant landscape change routines should
// temp remove SolidMasks before
assert ( _GBackPix ( iTx , iTy ) = = MCVehic ) ;
_SBackPixIfMask ( iTx , iTy , * pPix , MCVehic ) ;
// Instability
2010-04-20 20:38:18 +00:00
: : Landscape . CheckInstabilityRange ( iTx , iTy ) ;
2010-03-28 18:58:01 +00:00
}
}
2009-05-08 13:28:41 +00:00
// Mask not put flag
MaskPut = false ;
// update surrounding masks in that range
C4TargetRect ClipRect ;
for ( C4SolidMask * pSolid = C4SolidMask : : Last ; pSolid ; pSolid = pSolid - > Prev )
if ( pSolid - > MaskPut ) if ( pSolid - > MaskPutRect . Overlap ( MaskPutRect ) )
{
2010-03-28 18:58:01 +00:00
// set clipping rect for all calls, since they may modify it
ClipRect . Set ( MaskPutRect . x , MaskPutRect . y , MaskPutRect . Wdt , MaskPutRect . Hgt , 0 , 0 ) ;
// doubled solidmask-pixels have just been removed in the clipped area!
pSolid - > MaskPut = false ;
// re-put the solidmask
pSolid - > Put ( false , & ClipRect , false ) ;
2009-05-08 13:28:41 +00:00
}
// backup attachment if desired: Backup old pos and all objects that attach to or lie on the SolidMask
if ( fBackupAttachment )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
MaskRemovalX = pForObject - > GetX ( ) ;
MaskRemovalY = pForObject - > GetY ( ) ;
iAttachingObjectsCount = 0 ;
2009-06-15 21:47:26 +00:00
C4LArea SolidArea ( & : : Objects . Sectors , MaskPutRect . x - 1 , MaskPutRect . y - 1 , MaskPutRect . Wdt + 2 , MaskPutRect . Hgt + 2 ) ;
2009-05-08 13:28:41 +00:00
C4LSector * pSct ; C4Object * pObj ;
for ( C4ObjectList * pLst = SolidArea . FirstObjectShapes ( & pSct ) ; pLst ; pLst = SolidArea . NextObjectShapes ( pLst , & pSct ) )
for ( C4ObjectLink * clnk = pLst - > First ; clnk ; clnk = clnk - > Next )
2011-01-03 22:54:17 +00:00
if ( ( pObj = clnk - > Obj ) & & pObj ! = pForObject & & pObj - > IsMoveableBySolidMask ( pForObject - > GetPlane ( ) ) & & ! pObj - > Shape . CheckContact ( pObj - > GetX ( ) , pObj - > GetY ( ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check for any contact to own SolidMask - attach-directions, bottom - "stuck" (CNAT_Center) is ignored, because that causes problems with things being stuck in basements :(
int iVtx = 0 ;
for ( ; iVtx < pObj - > Shape . VtxNum ; + + iVtx )
if ( pObj - > Shape . GetVertexContact ( iVtx , pObj - > Action . t_attach | CNAT_Bottom , pObj - > GetX ( ) , pObj - > GetY ( ) , DensityProvider ( pForObject , * this ) ) )
if ( pObj - > Shape . GetVertexContact ( iVtx , pObj - > Action . t_attach | CNAT_Bottom , pObj - > GetX ( ) , pObj - > GetY ( ) , DensityProvider ( pForObject , * this ) ) )
break ;
if ( iVtx = = pObj - > Shape . VtxNum ) continue ; // no contact
// contact: Add object to list
if ( iAttachingObjectsCapacity = = iAttachingObjectsCount )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
iAttachingObjectsCapacity + = 4 ;
C4Object * * ppNewAttachingObjects = new C4Object * [ iAttachingObjectsCapacity ] ;
if ( iAttachingObjectsCount ) memcpy ( ppNewAttachingObjects , ppAttachingObjects , sizeof ( C4Object * ) * iAttachingObjectsCount ) ;
delete [ ] ppAttachingObjects ;
ppAttachingObjects = ppNewAttachingObjects ;
}
2010-03-28 18:58:01 +00:00
ppAttachingObjects [ iAttachingObjectsCount + + ] = pObj ;
}
}
2009-05-08 13:28:41 +00:00
CheckConsistency ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4SolidMask : : Draw ( C4TargetFacet & cgo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only if put
if ( ! MaskPut ) return ;
// set topface facet
C4Facet fct ; fct . Set ( pForObject - > GetGraphics ( ) - > GetBitmap ( ) , pForObject - > SolidMask . x , pForObject - > SolidMask . y , pForObject - > SolidMask . Wdt , pForObject - > SolidMask . Hgt ) ;
// draw it
if ( MaskPutRotation )
fct . DrawXR ( cgo . Surface , pForObject - > GetX ( ) + pForObject - > Shape . x + cgo . X - cgo . TargetX + pForObject - > SolidMask . tx , pForObject - > GetY ( ) + pForObject - > Shape . y + cgo . Y - cgo . TargetY + pForObject - > SolidMask . ty , fct . Wdt , fct . Hgt , 0 , 0 , MaskPutRotation ) ;
else
fct . DrawX ( cgo . Surface , pForObject - > GetX ( ) + pForObject - > Shape . x + cgo . X - cgo . TargetX + pForObject - > SolidMask . tx , pForObject - > GetY ( ) + pForObject - > Shape . y + cgo . Y - cgo . TargetY + pForObject - > SolidMask . ty , fct . Wdt , fct . Hgt , 0 , 0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4SolidMask : : RemoveTemporary ( C4Rect where )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! MaskPut | | ! pSolidMask | | ! pSolidMaskMatBuff ) return ;
where . Intersect ( MaskPutRect ) ;
// reput background pixels
for ( int y = where . y ; y < where . y + where . Hgt ; + + y )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( int x = where . x ; x < where . x + where . Wdt ; + + x )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
BYTE * pPix = pSolidMaskMatBuff + ( y - MaskPutRect . y + MaskPutRect . ty ) * MatBuffPitch + x - MaskPutRect . x + MaskPutRect . tx ;
// only if mask was used here
if ( * pPix ! = MCVehic )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// restore
assert ( GBackPix ( x , y ) = = MCVehic ) ;
_SBackPix ( x , y , * pPix ) ;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4SolidMask : : PutTemporary ( C4Rect where )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! MaskPut | | ! pSolidMask | | ! pSolidMaskMatBuff ) return ;
where . Intersect ( MaskPutRect ) ;
// reput vehicle pixels
for ( int y = where . y ; y < where . y + where . Hgt ; + + y )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( int x = where . x ; x < where . x + where . Wdt ; + + x )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
BYTE * pPix = pSolidMaskMatBuff + ( y - MaskPutRect . y + MaskPutRect . ty ) * MatBuffPitch + x - MaskPutRect . x + MaskPutRect . tx ;
// only if mask was used here
if ( * pPix ! = MCVehic )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// put
assert ( GBackPix ( x , y ) = = * pPix ) ;
_SBackPix ( x , y , MCVehic ) ;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4SolidMask : : Repair ( C4Rect where )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! MaskPut | | ! pSolidMask | | ! pSolidMaskMatBuff ) return ;
where . Intersect ( MaskPutRect ) ;
// reput vehicle pixels
for ( int y = where . y ; y < where . y + where . Hgt ; + + y )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( int x = where . x ; x < where . x + where . Wdt ; + + x )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
BYTE * pPix = pSolidMaskMatBuff + ( y - MaskPutRect . y + MaskPutRect . ty ) * MatBuffPitch + x - MaskPutRect . x + MaskPutRect . tx ;
// only if mask was used here
if ( * pPix ! = MCVehic )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// record changed landscape in MatBuff
* pPix = GBackPix ( x , y ) ;
// put
_SBackPix ( x , y , MCVehic ) ;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4SolidMask : : C4SolidMask ( C4Object * pForObject ) : pForObject ( pForObject )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// zero fields
MaskPut = false ;
MaskPutRotation = 0 ;
MaskRemovalX = MaskRemovalY = 0 ;
ppAttachingObjects = NULL ;
iAttachingObjectsCount = iAttachingObjectsCapacity = 0 ;
// Update linked list
Next = 0 ;
Prev = Last ;
Last = this ;
if ( Prev ) Prev - > Next = this ;
else First = this ;
// copy solid mask from bitmap
int iNeededBufSize = pForObject - > SolidMask . Wdt * pForObject - > SolidMask . Hgt ;
if ( ! ( pSolidMask = new BYTE [ iNeededBufSize ] ) ) return ;
SURFACE sfcBitmap = pForObject - > GetGraphics ( ) - > GetBitmap ( ) ;
if ( ! sfcBitmap - > Lock ( ) ) return ;
2011-09-04 22:35:01 +00:00
for ( int ycnt = 0 ; ycnt < pForObject - > SolidMask . Hgt ; ycnt + + )
for ( int xcnt = 0 ; xcnt < pForObject - > SolidMask . Wdt ; xcnt + + )
2010-03-28 18:58:01 +00:00
{
2011-09-04 22:35:01 +00:00
// Solid mask target x/y is relative to def bitmap top-left, not object center
int dx = sfcBitmap - > Scale * ( pForObject - > SolidMask . x + xcnt ) ;
int dy = sfcBitmap - > Scale * ( pForObject - > SolidMask . y + ycnt ) ;
pSolidMask [ xcnt + ycnt * pForObject - > SolidMask . Wdt ] = sfcBitmap - > IsPixTransparent ( dx , dy ) ? 0x00 : 0xff ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// create mat buff to store the material replaced by the solid mask
// the upper left corner is here the [objpos]+rot([shapexy]+[targetxy]+[realWH]/2)-maxWH/2
MatBuffPitch = ( int ) sqrt ( double ( pForObject - > SolidMask . Wdt * pForObject - > SolidMask . Wdt + pForObject - > SolidMask . Hgt * pForObject - > SolidMask . Hgt ) ) + 1 ;
if ( ! ( pSolidMaskMatBuff = new BYTE [ MatBuffPitch * MatBuffPitch ] ) ) return ;
2011-03-12 13:59:41 +00:00
memset ( pSolidMaskMatBuff , 0 , MatBuffPitch * MatBuffPitch ) ;
2009-05-08 13:28:41 +00:00
sfcBitmap - > Unlock ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4SolidMask : : ~ C4SolidMask ( )
2010-03-28 18:58:01 +00:00
{
2010-04-20 20:38:18 +00:00
Remove ( false ) ;
2009-05-08 13:28:41 +00:00
// Update linked list
if ( Next ) Next - > Prev = Prev ;
if ( Prev ) Prev - > Next = Next ;
if ( First = = this ) First = Next ;
if ( Last = = this ) Last = Prev ;
2010-04-20 20:38:18 +00:00
delete [ ] pSolidMask ;
delete [ ] pSolidMaskMatBuff ;
delete [ ] ppAttachingObjects ;
}
void C4SolidMask : : RemoveSolidMasks ( )
{
C4Rect SolidMaskRect ( 0 , 0 , GBackWdt , GBackHgt ) ;
C4SolidMask * pSolid ;
for ( pSolid = C4SolidMask : : Last ; pSolid ; pSolid = pSolid - > Prev )
{
pSolid - > RemoveTemporary ( SolidMaskRect ) ;
}
}
void C4SolidMask : : PutSolidMasks ( )
{
C4Rect SolidMaskRect ( 0 , 0 , GBackWdt , GBackHgt ) ;
C4SolidMask * pSolid ;
// Restore Solidmasks
for ( pSolid = C4SolidMask : : First ; pSolid ; pSolid = pSolid - > Next )
{
pSolid - > PutTemporary ( SolidMaskRect ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4SolidMask * C4SolidMask : : First = 0 ;
C4SolidMask * C4SolidMask : : Last = 0 ;
# ifdef SOLIDMASK_DEBUG
bool C4SolidMask : : CheckConsistency ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Rect SolidMaskRect ( 0 , 0 , GBackWdt , GBackHgt ) ;
C4SolidMask * pSolid ;
for ( pSolid = C4SolidMask : : Last ; pSolid ; pSolid = pSolid - > Prev )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pSolid - > RemoveTemporary ( SolidMaskRect ) ;
2010-03-28 18:58:01 +00:00
}
2009-06-05 15:20:41 +00:00
assert ( ! : : Landscape . MatCount [ MVehic ] ) ;
2009-05-08 13:28:41 +00:00
// Restore Solidmasks
for ( pSolid = C4SolidMask : : First ; pSolid ; pSolid = pSolid - > Next )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pSolid - > PutTemporary ( SolidMaskRect ) ;
}
2010-03-28 18:58:01 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
# endif