2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2013-12-17 20:01:09 +00:00
* 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
*
2013-12-17 20:01:09 +00:00
* Distributed under the terms of the ISC license ; see accompanying file
* " COPYING " for details .
2009-05-08 13:28:41 +00:00
*
2013-12-17 20:01:09 +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
*
2013-12-17 20:01:09 +00:00
* To redistribute this file separately , substitute the full license texts
* for the above references .
2009-05-08 13:28:41 +00:00
*/
/* NewGfx interfaces */
2009-10-20 03:39:24 +00:00
# include "C4Include.h"
2012-04-27 17:04:43 +00:00
# include <C4Draw.h>
2011-03-11 02:48:25 +00:00
2011-10-03 15:19:24 +00:00
# include "C4App.h"
2012-11-12 01:30:16 +00:00
# include <C4FontLoader.h>
2011-10-03 15:19:24 +00:00
# include <C4Window.h>
2012-04-27 17:04:43 +00:00
# include <C4DrawGL.h>
# include <C4DrawT.h>
2011-08-27 19:13:15 +00:00
# include <C4Markup.h>
2009-08-12 20:03:50 +00:00
# include "C4Rect.h"
2011-01-24 00:15:58 +00:00
# include <C4Config.h>
2010-01-27 15:50:07 +00:00
# include "StdMesh.h"
2009-05-08 13:28:41 +00:00
# include <stdio.h>
# include <limits.h>
// Global access pointer
2011-10-03 14:34:08 +00:00
C4Draw * pDraw = NULL ;
2009-05-08 13:28:41 +00:00
2010-06-08 22:55:34 +00:00
// Transformation matrix to convert meshes from Ogre to Clonk coordinate system
2011-10-03 14:34:08 +00:00
const StdMeshMatrix C4Draw : : OgreToClonk = StdMeshMatrix : : Scale ( - 1.0f , 1.0f , 1.0f ) * StdMeshMatrix : : Rotate ( float ( M_PI ) / 2.0f , 1.0f , 0.0f , 0.0f ) * StdMeshMatrix : : Rotate ( float ( M_PI ) / 2.0f , 0.0f , 0.0f , 1.0f ) ;
2010-06-08 22:55:34 +00:00
2009-05-08 13:28:41 +00:00
inline DWORD GetTextShadowClr ( DWORD dwTxtClr )
2010-03-28 18:58:01 +00:00
{
return RGBA ( ( ( dwTxtClr > > 0 ) % 256 ) / 3 , ( ( dwTxtClr > > 8 ) % 256 ) / 3 , ( ( dwTxtClr > > 16 ) % 256 ) / 3 , ( dwTxtClr > > 24 ) % 256 ) ;
}
2009-05-08 13:28:41 +00:00
2014-10-08 02:51:34 +00:00
inline void DwTo4UB ( DWORD dwClr , unsigned char ( & r ) [ 4 ] )
{
//unsigned char r[4];
r [ 0 ] = GLubyte ( ( dwClr > > 16 ) & 0xff ) ;
r [ 1 ] = GLubyte ( ( dwClr > > 8 ) & 0xff ) ;
r [ 2 ] = GLubyte ( ( dwClr ) & 0xff ) ;
r [ 3 ] = GLubyte ( ( dwClr > > 24 ) & 0xff ) ;
}
2013-05-25 12:59:58 +00:00
void C4BltTransform : : SetRotate ( float iAngle , float fOffX , float fOffY ) // set by angle and rotation offset
2010-03-28 18:58:01 +00:00
{
2013-05-25 12:59:58 +00:00
// iAngle is in degrees (cycling from 0 to 360)
2009-05-08 13:28:41 +00:00
// determine sine and cos of reversed angle in radians
2013-05-25 12:59:58 +00:00
// fAngle = -iAngle * pi/180 = iAngle * -pi/180
float fAngle = iAngle * - 0.0174532925f ;
float fsin = sinf ( fAngle ) ; float fcos = cosf ( fAngle ) ;
2009-05-08 13:28:41 +00:00
// set matrix values
mat [ 0 ] = + fcos ; mat [ 1 ] = + fsin ; mat [ 2 ] = ( 1 - fcos ) * fOffX - fsin * fOffY ;
mat [ 3 ] = - fsin ; mat [ 4 ] = + fcos ; mat [ 5 ] = ( 1 - fcos ) * fOffY + fsin * fOffX ;
mat [ 6 ] = 0 ; mat [ 7 ] = 0 ; mat [ 8 ] = 1 ;
2010-03-28 18:58:01 +00:00
/* calculation of rotation matrix:
x2 = fcos * ( x1 - fOffX ) + fsin * ( y1 - fOffY ) + fOffX
= fcos * x1 - fcos * fOffX + fsin * y1 - fsin * fOffY + fOffX
= x1 * fcos + y1 * fsin + ( 1 - fcos ) * fOffX - fsin * fOffY
y2 = - fsin * ( x1 - fOffX ) + fcos * ( y1 - fOffY ) + fOffY
= x1 * - fsin + fsin * fOffX + y1 * fcos - fcos * fOffY + fOffY
= x1 * - fsin + y1 * fcos + fsin * fOffX + ( 1 - fcos ) * fOffY */
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
bool C4BltTransform : : SetAsInv ( C4BltTransform & r )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// calc inverse of matrix
float det = r . mat [ 0 ] * r . mat [ 4 ] * r . mat [ 8 ] + r . mat [ 1 ] * r . mat [ 5 ] * r . mat [ 6 ]
2010-03-28 18:58:01 +00:00
+ r . mat [ 2 ] * r . mat [ 3 ] * r . mat [ 7 ] - r . mat [ 2 ] * r . mat [ 4 ] * r . mat [ 6 ]
- r . mat [ 0 ] * r . mat [ 5 ] * r . mat [ 7 ] - r . mat [ 1 ] * r . mat [ 3 ] * r . mat [ 8 ] ;
2009-05-08 13:28:41 +00:00
if ( ! det ) { Set ( 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 ) ; return false ; }
mat [ 0 ] = ( r . mat [ 4 ] * r . mat [ 8 ] - r . mat [ 5 ] * r . mat [ 7 ] ) / det ;
mat [ 1 ] = ( r . mat [ 2 ] * r . mat [ 7 ] - r . mat [ 1 ] * r . mat [ 8 ] ) / det ;
mat [ 2 ] = ( r . mat [ 1 ] * r . mat [ 5 ] - r . mat [ 2 ] * r . mat [ 4 ] ) / det ;
mat [ 3 ] = ( r . mat [ 5 ] * r . mat [ 6 ] - r . mat [ 3 ] * r . mat [ 8 ] ) / det ;
mat [ 4 ] = ( r . mat [ 0 ] * r . mat [ 8 ] - r . mat [ 2 ] * r . mat [ 6 ] ) / det ;
mat [ 5 ] = ( r . mat [ 2 ] * r . mat [ 3 ] - r . mat [ 0 ] * r . mat [ 5 ] ) / det ;
mat [ 6 ] = ( r . mat [ 3 ] * r . mat [ 7 ] - r . mat [ 4 ] * r . mat [ 6 ] ) / det ;
mat [ 7 ] = ( r . mat [ 1 ] * r . mat [ 6 ] - r . mat [ 0 ] * r . mat [ 7 ] ) / det ;
mat [ 8 ] = ( r . mat [ 0 ] * r . mat [ 4 ] - r . mat [ 1 ] * r . mat [ 3 ] ) / det ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
void C4BltTransform : : TransformPoint ( float & rX , float & rY ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// apply matrix
float fW = mat [ 6 ] * rX + mat [ 7 ] * rY + mat [ 8 ] ;
// store in temp, so original rX is used for calculation of rY
float fX = ( mat [ 0 ] * rX + mat [ 1 ] * rY + mat [ 2 ] ) / fW ;
rY = ( mat [ 3 ] * rX + mat [ 4 ] * rY + mat [ 5 ] ) / fW ;
rX = fX ; // apply temp
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
C4Pattern & C4Pattern : : operator = ( const C4Pattern & nPattern )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sfcPattern32 = nPattern . sfcPattern32 ;
if ( sfcPattern32 ) sfcPattern32 - > Lock ( ) ;
delete [ ] CachedPattern ;
if ( nPattern . CachedPattern )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
CachedPattern = new uint32_t [ sfcPattern32 - > Wdt * sfcPattern32 - > Hgt ] ;
memcpy ( CachedPattern , nPattern . CachedPattern , sfcPattern32 - > Wdt * sfcPattern32 - > Hgt * 4 ) ;
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
CachedPattern = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
Wdt = nPattern . Wdt ;
Hgt = nPattern . Hgt ;
Zoom = nPattern . Zoom ;
return * this ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
bool C4Pattern : : Set ( C4Surface * sfcSource , int iZoom )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Safety
if ( ! sfcSource ) return false ;
// Clear existing pattern
Clear ( ) ;
// new style: simply store pattern for modulation or shifting, which will be decided upon use
sfcPattern32 = sfcSource ;
sfcPattern32 - > Lock ( ) ;
Wdt = sfcPattern32 - > Wdt ;
Hgt = sfcPattern32 - > Hgt ;
// set zoom
Zoom = iZoom ;
// set flags
CachedPattern = new uint32_t [ Wdt * Hgt ] ;
if ( ! CachedPattern ) return false ;
for ( int y = 0 ; y < Hgt ; + + y )
for ( int x = 0 ; x < Wdt ; + + x )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
CachedPattern [ y * Wdt + x ] = sfcPattern32 - > GetPixDw ( x , y , false ) ;
2010-03-28 18:58:01 +00:00
}
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
2011-09-30 20:15:51 +00:00
C4Pattern : : C4Pattern ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// disable
sfcPattern32 = NULL ;
CachedPattern = 0 ;
Zoom = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
void C4Pattern : : Clear ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// pattern assigned
if ( sfcPattern32 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// unlock it
sfcPattern32 - > Unlock ( ) ;
// clear field
sfcPattern32 = NULL ;
}
2010-03-28 18:58:01 +00:00
delete [ ] CachedPattern ; CachedPattern = 0 ;
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
DWORD C4Pattern : : PatternClr ( unsigned int iX , unsigned int iY ) const
2010-03-28 18:58:01 +00:00
{
2009-07-24 21:50:04 +00:00
if ( ! CachedPattern ) return 0 ;
// wrap position
iX % = Wdt ; iY % = Hgt ;
return CachedPattern [ iY * Wdt + iX ] ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
void C4GammaControl : : SetClrChannel ( WORD * pBuf , BYTE c1 , BYTE c2 , int c3 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Using this minimum value, gamma ramp errors on some cards can be avoided
int MinGamma = 0x100 ;
// adjust clr3-value
+ + c3 ;
// get rises
int r1 = c2 - c1 , r2 = c3 - c2 , r = ( c3 - c1 ) / 2 ;
// calc beginning and end rise
r1 = 2 * r1 - r ; r2 = 2 * r2 - r ;
// calc ramp
WORD * pBuf2 = pBuf + 128 ;
for ( int i = 0 ; i < 128 ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int i2 = 128 - i ;
// interpolate linear ramps with the rises r1 and r
* pBuf + + = BoundBy ( ( ( c1 + r1 * i / 128 ) * i2 + ( c2 - r * i2 / 128 ) * i ) < < 1 , MinGamma , 0xffff ) ;
// interpolate linear ramps with the rises r and r2
* pBuf2 + + = BoundBy ( ( ( c2 + r * i / 128 ) * i2 + ( c3 - r2 * i2 / 128 ) * i ) < < 1 , MinGamma , 0xffff ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
void C4GammaControl : : Set ( DWORD dwClr1 , DWORD dwClr2 , DWORD dwClr3 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set red, green and blue channel
2011-03-11 02:37:27 +00:00
SetClrChannel ( ramp . red , GetRedValue ( dwClr1 ) , GetRedValue ( dwClr2 ) , GetRedValue ( dwClr3 ) ) ;
SetClrChannel ( ramp . green , GetGreenValue ( dwClr1 ) , GetGreenValue ( dwClr2 ) , GetGreenValue ( dwClr3 ) ) ;
SetClrChannel ( ramp . blue , GetBlueValue ( dwClr1 ) , GetBlueValue ( dwClr2 ) , GetBlueValue ( dwClr3 ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-30 20:15:51 +00:00
DWORD C4GammaControl : : ApplyTo ( DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2009-08-23 21:46:56 +00:00
// apply to red, green and blue color component
2011-03-11 02:37:27 +00:00
return RGBA ( ramp . red [ GetRedValue ( dwClr ) ] > > 8 , ramp . green [ GetGreenValue ( dwClr ) ] > > 8 , ramp . blue [ GetBlueValue ( dwClr ) ] > > 8 , dwClr > > 24 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
//--------------------------------------------------------------------
2011-08-27 14:41:26 +00:00
C4FogOfWar : : ~ C4FogOfWar ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete [ ] pMap ; delete pSurface ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:06:41 +00:00
void C4FogOfWar : : Reset ( int ResX , int ResY , int WdtPx , int HgtPx , int OffX , int OffY , unsigned char StartVis , int x0 , int y0 , uint32_t dwBackClr , class C4Surface * backsfc )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set values
ResolutionX = ResX ; ResolutionY = ResY ;
this - > dwBackClr = dwBackClr ;
this - > OffX = - ( ( OffX ) % ResolutionX ) ;
this - > OffY = - ( ( OffY ) % ResolutionY ) ;
// calc w/h required for map
Wdt = ( WdtPx - this - > OffX + ResolutionX - 1 ) / ResolutionX + 1 ;
Hgt = ( HgtPx - this - > OffY + ResolutionY - 1 ) / ResolutionY + 1 ;
this - > OffX + = x0 ;
this - > OffY + = y0 ;
size_t NewMapSize = Wdt * Hgt ;
if ( NewMapSize > MapSize | | NewMapSize < MapSize / 2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete [ ] pMap ;
pMap = new unsigned char [ MapSize = NewMapSize ] ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( ! pSurface | | pSurface - > Wdt < Wdt | | pSurface - > Hgt < Hgt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete pSurface ;
2011-10-03 14:06:41 +00:00
pSurface = new C4Surface ( Max ( Wdt , Hgt ) , Max ( Wdt , Hgt ) ) ; // force larger texture size by making it squared!
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// is a background color desired?
if ( dwBackClr & & backsfc )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// then draw a background now and fade against transparent later
// FIXME: don't do this if shaders are used
2011-10-03 14:30:18 +00:00
pDraw - > DrawBoxDw ( backsfc , x0 , y0 , x0 + WdtPx - 1 , y0 + HgtPx - 1 , dwBackClr ) ;
2009-05-08 13:28:41 +00:00
FadeTransparent = true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
FadeTransparent = false ;
// reset all of map to given values
memset ( pMap , StartVis , MapSize ) ;
pSurface - > Lock ( ) ;
pSurface - > ClearBoxDw ( 0 , 0 , Wdt , Hgt ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:06:41 +00:00
C4Surface * C4FogOfWar : : GetSurface ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pSurface - > IsLocked ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( int x = 0 ; x < Wdt ; + + x )
for ( int y = 0 ; y < Hgt ; + + y )
pSurface - > SetPixDw ( x , y , pMap [ y * Wdt + x ] < < 24 | ( dwBackClr & 0xFFFFFF ) ) ;
2010-03-28 18:58:01 +00:00
//pSurface->SetPixDw(x, y, 0x7f000000 + (((0xff*x)/iWdt) << 24) + (((0xff*y)/iHgt) << 16));
2009-05-08 13:28:41 +00:00
pSurface - > Unlock ( ) ;
}
2010-03-28 18:58:01 +00:00
return pSurface ;
}
2009-05-08 13:28:41 +00:00
2011-08-27 14:41:26 +00:00
void C4FogOfWar : : ReduceModulation ( int cx , int cy , int Radius , int ( * VisProc ) ( int , int , int , int , int ) )
2010-03-28 18:58:01 +00:00
{
2010-03-21 18:34:22 +00:00
// landscape coordinates: cx, cy, VisProc
// display coordinates: zx, zy, x, y
float zx = float ( cx ) ;
float zy = float ( cy ) ;
2011-10-03 14:30:18 +00:00
pDraw - > ApplyZoom ( zx , zy ) ;
Radius = int ( pDraw - > Zoom * Radius ) ;
2009-05-08 13:28:41 +00:00
// reveal all within iRadius1; fade off squared until iRadius2
int x = OffX , y = OffY , xe = Wdt * ResolutionX + OffX ;
int RadiusSq = Radius * Radius ;
for ( unsigned int i = 0 ; i < MapSize ; i + + )
2010-03-28 18:58:01 +00:00
{
2010-03-21 18:34:22 +00:00
if ( ( x - zx ) * ( x - zx ) + ( y - zy ) * ( y - zy ) < RadiusSq )
2010-03-28 18:58:01 +00:00
{
2010-03-21 18:34:22 +00:00
float lx = float ( x ) ;
float ly = float ( y ) ;
2011-10-03 14:30:18 +00:00
pDraw - > RemoveZoom ( lx , ly ) ;
2010-03-21 18:34:22 +00:00
pMap [ i ] = Max < int > ( pMap [ i ] , VisProc ( 255 , int ( lx ) , int ( ly ) , int ( cx ) , int ( cy ) ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// next pos
x + = ResolutionX ;
if ( x > = xe ) { x = OffX ; y + = ResolutionY ; }
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-08-27 14:41:26 +00:00
void C4FogOfWar : : AddModulation ( int cx , int cy , int Radius , uint8_t Transparency )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
{
float x = float ( cx ) ; float y = float ( cy ) ;
2011-10-03 14:30:18 +00:00
pDraw - > ApplyZoom ( x , y ) ;
2009-05-08 13:28:41 +00:00
cx = int ( x ) ; cy = int ( y ) ;
2010-03-28 18:58:01 +00:00
}
2011-10-03 14:30:18 +00:00
Radius = int ( pDraw - > Zoom * Radius ) ;
2009-05-08 13:28:41 +00:00
// hide all within iRadius1; fade off squared until iRadius2
int x = OffX , y = OffY , xe = Wdt * ResolutionX + OffX ;
int RadiusSq = Radius * Radius ;
for ( unsigned int i = 0 ; i < MapSize ; i + + )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int d = ( x - cx ) * ( x - cx ) + ( y - cy ) * ( y - cy ) ;
if ( d < RadiusSq )
pMap [ i ] = Min < uint8_t > ( Transparency , pMap [ i ] ) ;
// next pos
x + = ResolutionX ;
if ( x > = xe ) { x = OffX ; y + = ResolutionY ; }
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-08-27 14:41:26 +00:00
uint32_t C4FogOfWar : : GetModAt ( int x , int y ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
#if 0
// fast but inaccurate method
x = BoundBy ( ( x - iOffX + iResolutionX / 2 ) / iResolutionX , 0 , iWdt - 1 ) ;
y = BoundBy ( ( y - iOffY + iResolutionY / 2 ) / iResolutionY , 0 , iHgt - 1 ) ;
return pMap [ y * iWdt + x ] - > dwModClr ;
# else
// slower, more accurate method: Interpolate between 4 neighboured modulations
x - = OffX ;
y - = OffY ;
int tx = BoundBy ( x / ResolutionX , 0 , Wdt - 1 ) ;
int ty = BoundBy ( y / ResolutionY , 0 , Hgt - 1 ) ;
int tx2 = Min ( tx + 1 , Wdt - 1 ) ;
int ty2 = Min ( ty + 1 , Hgt - 1 ) ;
2009-08-23 21:46:56 +00:00
// TODO: Alphafixed. Correct?
2009-05-08 13:28:41 +00:00
unsigned char Vis = pMap [ ty * Wdt + tx ] ;
2011-03-13 16:09:47 +00:00
uint32_t c1 = FadeTransparent ? 0xffffff | ( Vis < < 24 ) : C4RGB ( Vis , Vis , Vis ) ;
2009-05-08 13:28:41 +00:00
Vis = pMap [ ty * Wdt + tx2 ] ;
2011-03-13 16:09:47 +00:00
uint32_t c2 = FadeTransparent ? 0xffffff | ( Vis < < 24 ) : C4RGB ( Vis , Vis , Vis ) ;
2009-05-08 13:28:41 +00:00
Vis = pMap [ ty2 * Wdt + tx ] ;
2011-03-13 16:09:47 +00:00
uint32_t c3 = FadeTransparent ? 0xffffff | ( Vis < < 24 ) : C4RGB ( Vis , Vis , Vis ) ;
2009-05-08 13:28:41 +00:00
Vis = pMap [ ty2 * Wdt + tx2 ] ;
2011-03-13 16:09:47 +00:00
uint32_t c4 = FadeTransparent ? 0xffffff | ( Vis < < 24 ) : C4RGB ( Vis , Vis , Vis ) ;
2010-03-21 18:34:22 +00:00
CColorFadeMatrix clrs ( tx * ResolutionX , ty * ResolutionY , ResolutionX , ResolutionY , c1 , c2 , c3 , c4 ) ;
2009-05-08 13:28:41 +00:00
return clrs . GetColorAt ( x , y ) ;
# endif
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// -------------------------------------------------------------------
CColorFadeMatrix : : CColorFadeMatrix ( int iX , int iY , int iWdt , int iHgt , uint32_t dwClr1 , uint32_t dwClr2 , uint32_t dwClr3 , uint32_t dwClr4 )
2010-03-28 18:58:01 +00:00
: ox ( iX ) , oy ( iY ) , w ( iWdt ) , h ( iHgt )
{
2009-05-08 13:28:41 +00:00
uint32_t dwMask = 0xff ;
for ( int iChan = 0 ; iChan < 4 ; ( + + iChan ) , ( dwMask < < = 8 ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int c0 = ( dwClr1 & dwMask ) > > ( iChan * 8 ) ;
int cx = ( dwClr2 & dwMask ) > > ( iChan * 8 ) ;
int cy = ( dwClr3 & dwMask ) > > ( iChan * 8 ) ;
int ce = ( dwClr4 & dwMask ) > > ( iChan * 8 ) ;
clrs [ iChan ] . c0 = c0 ;
clrs [ iChan ] . cx = cx - c0 ;
clrs [ iChan ] . cy = cy - c0 ;
clrs [ iChan ] . ce = ce ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
uint32_t CColorFadeMatrix : : GetColorAt ( int iX , int iY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
iX - = ox ; iY - = oy ;
uint32_t dwResult = 0x00 ;
for ( int iChan = 0 ; iChan < 4 ; + + iChan )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int clr = clrs [ iChan ] . c0 + clrs [ iChan ] . cx * iX / w + clrs [ iChan ] . cy * iY / h ;
clr + = iX * iY * ( clrs [ iChan ] . ce - clr ) / ( w * h ) ;
dwResult | = ( BoundBy ( clr , 0 , 255 ) < < ( iChan * 8 ) ) ;
}
2010-03-28 18:58:01 +00:00
return dwResult ;
}
2009-05-08 13:28:41 +00:00
// -------------------------------------------------------------------
2011-10-03 14:34:08 +00:00
void C4Draw : : Default ( )
2010-03-28 18:58:01 +00:00
{
2010-09-28 18:16:33 +00:00
Editor = true ;
2009-05-08 13:28:41 +00:00
RenderTarget = NULL ;
ClipAll = false ;
Active = false ;
BlitModulated = false ;
dwBlitMode = 0 ;
Gamma . Default ( ) ;
DefRamp . Default ( ) ;
2010-02-06 17:33:30 +00:00
// pClrModMap = NULL; - invalid if !fUseClrModMap anyway
2009-05-08 13:28:41 +00:00
fUseClrModMap = false ;
ZoomX = 0 ; ZoomY = 0 ; Zoom = 1 ;
2010-03-17 12:43:17 +00:00
MeshTransform = NULL ;
2010-02-06 17:33:30 +00:00
fUsePerspective = false ;
2010-10-01 21:36:48 +00:00
for ( int32_t iRamp = 0 ; iRamp < 3 * C4MaxGammaRamps ; iRamp + = 3 )
{ dwGamma [ iRamp + 0 ] = 0 ; dwGamma [ iRamp + 1 ] = 0x808080 ; dwGamma [ iRamp + 2 ] = 0xffffff ; }
fSetGamma = false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : Clear ( )
2010-03-28 18:58:01 +00:00
{
2013-11-09 16:11:29 +00:00
ResetGamma ( ) ;
2009-05-08 13:28:41 +00:00
DisableGamma ( ) ;
Active = BlitModulated = fUseClrModMap = false ;
dwBlitMode = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : GetSurfaceSize ( C4Surface * sfcSurface , int & iWdt , int & iHgt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return sfcSurface - > GetSurfaceSize ( iWdt , iHgt ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : SubPrimaryClipper ( int iX1 , int iY1 , int iX2 , int iY2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Set sub primary clipper
2010-04-26 23:32:45 +00:00
SetPrimaryClipper ( Max ( iX1 , iClipX1 ) , Max ( iY1 , iClipY1 ) , Min ( iX2 , iClipX2 ) , Min ( iY2 , iClipY2 ) ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : StorePrimaryClipper ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Store current primary clipper
fStClipX1 = fClipX1 ; fStClipY1 = fClipY1 ; fStClipX2 = fClipX2 ; fStClipY2 = fClipY2 ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : RestorePrimaryClipper ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Restore primary clipper
SetPrimaryClipper ( fStClipX1 , fStClipY1 , fStClipX2 , fStClipY2 ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : SetPrimaryClipper ( int iX1 , int iY1 , int iX2 , int iY2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set clipper
fClipX1 = iX1 ; fClipY1 = iY1 ; fClipX2 = iX2 ; fClipY2 = iY2 ;
2010-04-26 23:32:45 +00:00
iClipX1 = iX1 ; iClipY1 = iY1 ; iClipX2 = iX2 ; iClipY2 = iY2 ;
2009-05-08 13:28:41 +00:00
UpdateClipper ( ) ;
// Done
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : ApplyPrimaryClipper ( C4Surface * sfcSurface )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
//sfcSurface->SetClipper(lpClipper);
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : DetachPrimaryClipper ( C4Surface * sfcSurface )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
//sfcSurface->SetClipper(NULL);
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : NoPrimaryClipper ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// apply maximum clipper
SetPrimaryClipper ( 0 , 0 , 439832 , 439832 ) ;
// Done
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : BlitLandscape ( C4Surface * sfcSource , float fx , float fy ,
2011-10-03 14:07:07 +00:00
C4Surface * sfcTarget , float tx , float ty , float wdt , float hgt , const C4Surface * textures [ ] )
2010-03-28 18:58:01 +00:00
{
2009-08-15 18:50:32 +00:00
Blit ( sfcSource , fx , fy , wdt , hgt , sfcTarget , tx , ty , wdt , hgt , false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : Blit8Fast ( CSurface8 * sfcSource , int fx , int fy ,
2011-10-03 14:07:07 +00:00
C4Surface * sfcTarget , int tx , int ty , int wdt , int hgt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// blit 8bit-sfc
// lock surfaces
assert ( sfcTarget - > fPrimary ) ;
bool fRender = sfcTarget - > IsRenderTarget ( ) ;
if ( ! fRender ) if ( ! sfcTarget - > Lock ( ) )
2010-03-28 18:58:01 +00:00
{ return ; }
2010-09-07 15:00:27 +00:00
float tfx = tx , tfy = ty , twdt = wdt , thgt = hgt ;
if ( Zoom ! = 1.0 )
{
ApplyZoom ( tfx , tfy ) ;
twdt * = Zoom ;
thgt * = Zoom ;
}
2014-10-08 02:51:34 +00:00
// blit 8 bit pix in batches of 1024 pixels
static const int BUF_SIZE = 1024 ;
C4BltVertex * vertices = new C4BltVertex [ BUF_SIZE ] ;
int bufcnt = 0 ;
2010-09-07 15:00:27 +00:00
for ( int ycnt = 0 ; ycnt < thgt ; + + ycnt )
2014-10-08 02:51:34 +00:00
{
2010-09-07 15:00:27 +00:00
for ( int xcnt = 0 ; xcnt < twdt ; + + xcnt )
2010-03-28 18:58:01 +00:00
{
2010-09-07 15:00:27 +00:00
BYTE byPix = sfcSource - > GetPix ( fx + wdt * xcnt / twdt , fy + hgt * ycnt / thgt ) ;
2014-10-08 02:51:34 +00:00
DWORD dwClr = byPix ? sfcSource - > pPal - > GetClr ( byPix ) : 0x00000000 ;
vertices [ bufcnt ] . ftx = ( float ) ( tx + xcnt / Zoom ) ;
vertices [ bufcnt ] . fty = ( float ) ( ty + ycnt / Zoom ) ;
DwTo4UB ( dwClr , vertices [ bufcnt ] . color ) ;
+ + bufcnt ;
if ( bufcnt = = BUF_SIZE )
{
PerformMultiPix ( sfcTarget , vertices , BUF_SIZE ) ;
bufcnt = 0 ;
}
2010-03-28 18:58:01 +00:00
}
2014-10-08 02:51:34 +00:00
}
if ( bufcnt > 0 )
PerformMultiPix ( sfcTarget , vertices , bufcnt ) ;
delete [ ] vertices ;
2009-05-08 13:28:41 +00:00
// unlock
if ( ! fRender ) sfcTarget - > Unlock ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : Blit ( C4Surface * sfcSource , float fx , float fy , float fwdt , float fhgt ,
2011-10-03 14:06:41 +00:00
C4Surface * sfcTarget , float tx , float ty , float twdt , float thgt ,
2011-09-30 20:15:51 +00:00
bool fSrcColKey , const C4BltTransform * pTransform )
2012-02-25 16:35:24 +00:00
{
return BlitUnscaled ( sfcSource , fx * sfcSource - > Scale , fy * sfcSource - > Scale , fwdt * sfcSource - > Scale , fhgt * sfcSource - > Scale ,
sfcTarget , tx , ty , twdt , thgt , fSrcColKey , pTransform ) ;
}
bool C4Draw : : BlitUnscaled ( C4Surface * sfcSource , float fx , float fy , float fwdt , float fhgt ,
C4Surface * sfcTarget , float tx , float ty , float twdt , float thgt ,
bool fSrcColKey , const C4BltTransform * pTransform )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
2009-08-15 18:50:32 +00:00
if ( ! sfcSource | | ! sfcTarget | | ! twdt | | ! thgt | | ! fwdt | | ! fhgt ) return false ;
2009-05-08 13:28:41 +00:00
// Apply Zoom
2011-09-30 20:15:51 +00:00
C4BltTransform t ;
2009-05-08 13:28:41 +00:00
if ( pTransform & & Zoom ! = 1.0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
//tx = tx * Zoom - ZoomX * Zoom + ZoomX;
//ty = ty * Zoom - ZoomY * Zoom + ZoomY;
// The transformation is not location-independant, thus has to be zoomed, too.
2011-09-18 13:54:22 +00:00
t . Set ( pTransform - > mat [ 0 ] * Zoom , pTransform - > mat [ 1 ] * Zoom , pTransform - > mat [ 2 ] * Zoom + ZoomX * ( 1 - Zoom ) ,
pTransform - > mat [ 3 ] * Zoom , pTransform - > mat [ 4 ] * Zoom , pTransform - > mat [ 5 ] * Zoom + ZoomY * ( 1 - Zoom ) ,
pTransform - > mat [ 6 ] , pTransform - > mat [ 7 ] , pTransform - > mat [ 8 ] ) ;
pTransform = & t ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if ( Zoom ! = 1.0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ApplyZoom ( tx , ty ) ;
twdt * = Zoom ;
thgt * = Zoom ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// emulated blit?
if ( ! sfcTarget - > IsRenderTarget ( ) )
return Blit8 ( sfcSource , int ( fx ) , int ( fy ) , int ( fwdt ) , int ( fhgt ) , sfcTarget , int ( tx ) , int ( ty ) , int ( twdt ) , int ( thgt ) , fSrcColKey , pTransform ) ;
// calc stretch
float scaleX = twdt / fwdt ;
float scaleY = thgt / fhgt ;
// bound
2009-08-15 18:50:32 +00:00
if ( ClipAll ) return true ;
2009-05-08 13:28:41 +00:00
// check exact
bool fExact = ! pTransform & & fwdt = = twdt & & fhgt = = thgt ;
// manual clipping? (primary surface only)
2010-09-28 17:07:47 +00:00
if ( Config . Graphics . ClipManuallyE & & ! pTransform & & sfcTarget - > fPrimary )
2010-03-28 18:58:01 +00:00
{
2010-02-18 16:24:43 +00:00
float iOver ;
// Left
iOver = tx - iClipX1 ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2010-02-18 16:24:43 +00:00
twdt + = iOver ;
fwdt + = iOver / scaleX ;
fx - = iOver / scaleX ;
tx = float ( iClipX1 ) ;
2010-03-28 18:58:01 +00:00
}
2010-02-18 16:24:43 +00:00
// Top
iOver = ty - iClipY1 ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2010-02-18 16:24:43 +00:00
thgt + = iOver ;
fhgt + = iOver / scaleY ;
fy - = iOver / scaleY ;
ty = float ( iClipY1 ) ;
2010-03-28 18:58:01 +00:00
}
2010-02-18 16:24:43 +00:00
// Right
iOver = iClipX2 + 1 - ( tx + twdt ) ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2010-02-18 16:24:43 +00:00
fwdt + = iOver / scaleX ;
twdt + = iOver ;
2010-03-28 18:58:01 +00:00
}
2010-02-18 16:24:43 +00:00
// Bottom
iOver = iClipY2 + 1 - ( ty + thgt ) ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2010-02-18 16:24:43 +00:00
fhgt + = iOver / scaleY ;
thgt + = iOver ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// inside screen?
2009-08-15 18:50:32 +00:00
if ( twdt < = 0 | | thgt < = 0 ) return false ;
2009-05-08 13:28:41 +00:00
// prepare rendering to surface
2009-08-15 18:50:32 +00:00
if ( ! PrepareRendering ( sfcTarget ) ) return false ;
2009-05-08 13:28:41 +00:00
// texture present?
if ( ! sfcSource - > ppTex )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// primary surface?
if ( sfcSource - > fPrimary )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// blit emulated
return Blit8 ( sfcSource , int ( fx ) , int ( fy ) , int ( fwdt ) , int ( fhgt ) , sfcTarget , int ( tx ) , int ( ty ) , int ( twdt ) , int ( thgt ) , fSrcColKey ) ;
}
2010-03-28 18:58:01 +00:00
return false ;
}
2009-05-08 13:28:41 +00:00
// create blitting struct
2011-09-30 20:15:51 +00:00
C4BltData BltData ;
2009-05-08 13:28:41 +00:00
// pass down pTransform
BltData . pTransform = pTransform ;
// blit with basesfc?
bool fBaseSfc = false ;
if ( sfcSource - > pMainSfc ) if ( sfcSource - > pMainSfc - > ppTex ) fBaseSfc = true ;
// set blitting state - done by PerformBlt
// get involved texture offsets
2010-09-04 17:30:45 +00:00
int iTexSizeX = sfcSource - > iTexSize ;
int iTexSizeY = sfcSource - > iTexSize ;
int iTexX = Max ( int ( fx / iTexSizeX ) , 0 ) ;
int iTexY = Max ( int ( fy / iTexSizeY ) , 0 ) ;
int iTexX2 = Min ( ( int ) ( fx + fwdt - 1 ) / iTexSizeX + 1 , sfcSource - > iTexX ) ;
int iTexY2 = Min ( ( int ) ( fy + fhgt - 1 ) / iTexSizeY + 1 , sfcSource - > iTexY ) ;
2009-05-08 13:28:41 +00:00
// calc stretch regarding texture size and indent
2012-06-15 16:16:49 +00:00
/* float scaleX2 = scaleX * iTexSizeX;
float scaleY2 = scaleY * iTexSizeY ; */
2009-06-02 23:38:01 +00:00
// Enable textures
2009-05-08 13:28:41 +00:00
SetTexture ( ) ;
2009-06-02 23:38:01 +00:00
// blit from all these textures
2009-05-08 13:28:41 +00:00
for ( int iY = iTexY ; iY < iTexY2 ; + + iY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( int iX = iTexX ; iX < iTexX2 ; + + iX )
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:16:38 +00:00
C4TexRef * pTex = * ( sfcSource - > ppTex + iY * sfcSource - > iTexX + iX ) ;
2010-09-04 17:30:45 +00:00
// get current blitting offset in texture
int iBlitX = sfcSource - > iTexSize * iX ;
int iBlitY = sfcSource - > iTexSize * iY ;
2009-05-08 13:28:41 +00:00
// size changed? recalc dependant, relevant (!) values
2010-09-04 17:30:45 +00:00
if ( iTexSizeX ! = pTex - > iSizeX )
2010-03-28 18:58:01 +00:00
{
2010-09-04 17:30:45 +00:00
iTexSizeX = pTex - > iSizeX ;
2012-06-15 16:16:49 +00:00
/*scaleX2 = scaleX * iTexSizeX;*/
2010-03-28 18:58:01 +00:00
}
2010-09-04 17:30:45 +00:00
if ( iTexSizeY ! = pTex - > iSizeY )
{
iTexSizeY = pTex - > iSizeY ;
2012-06-15 16:16:49 +00:00
/*scaleY2 = scaleY * iTexSizeY;*/
2010-09-04 17:30:45 +00:00
}
2009-05-08 13:28:41 +00:00
// get new texture source bounds
FLOAT_RECT fTexBlt ;
fTexBlt . left = Max < float > ( fx - iBlitX , 0 ) ;
fTexBlt . top = Max < float > ( fy - iBlitY , 0 ) ;
2010-09-04 17:30:45 +00:00
fTexBlt . right = Min < float > ( fx + fwdt - ( float ) iBlitX , ( float ) iTexSizeX ) ;
fTexBlt . bottom = Min < float > ( fy + fhgt - ( float ) iBlitY , ( float ) iTexSizeY ) ;
2009-05-08 13:28:41 +00:00
// get new dest bounds
FLOAT_RECT tTexBlt ;
tTexBlt . left = ( fTexBlt . left + iBlitX - fx ) * scaleX + tx ;
tTexBlt . top = ( fTexBlt . top + iBlitY - fy ) * scaleY + ty ;
tTexBlt . right = ( fTexBlt . right + iBlitX - fx ) * scaleX + tx ;
tTexBlt . bottom = ( fTexBlt . bottom + iBlitY - fy ) * scaleY + ty ;
// prepare blit data texture matrix
// translate back to texture 0/0 regarding indent and blit offset
2010-02-18 20:11:14 +00:00
/*BltData.TexPos.SetMoveScale(-tTexBlt.left, -tTexBlt.top, 1, 1);
2009-05-08 13:28:41 +00:00
// apply back scaling and texture-indent - simply scale matrix down
int i ;
for ( i = 0 ; i < 3 ; + + i ) BltData . TexPos . mat [ i ] / = scaleX2 ;
for ( i = 3 ; i < 6 ; + + i ) BltData . TexPos . mat [ i ] / = scaleY2 ;
// now, finally, move in texture - this must be done last, so no stupid zoom is applied...
BltData . TexPos . MoveScale ( ( ( float ) fTexBlt . left ) / iTexSize ,
2010-03-28 18:58:01 +00:00
( ( float ) fTexBlt . top ) / iTexSize , 1 , 1 ) ; */
2009-05-08 13:28:41 +00:00
// Set resulting matrix directly
2010-09-04 16:17:59 +00:00
/*BltData.TexPos.SetMoveScale(
2010-09-04 17:30:45 +00:00
fTexBlt . left / iTexSizeX - tTexBlt . left / scaleX2 ,
fTexBlt . top / iTexSizeY - tTexBlt . top / scaleY2 ,
2010-03-28 18:58:01 +00:00
1 / scaleX2 ,
2010-09-04 16:17:59 +00:00
1 / scaleY2 ) ; */
// get tex bounds
// The code below is commented out since the problem
// in question is currently fixed by using non-power-of-two
// and non-square textures.
#if 0
2011-01-02 23:03:28 +00:00
// Size of this texture actually containing image data
const int iImgSizeX = ( iX = = sfcSource - > iTexX - 1 ) ? ( ( sfcSource - > Wdt - 1 ) % iTexSizeX + 1 ) : ( iTexSizeX ) ;
const int iImgSizeY = ( iY = = sfcSource - > iTexY - 1 ) ? ( ( sfcSource - > Hgt - 1 ) % iTexSizeY + 1 ) : ( iTexSizeY ) ;
2010-09-04 16:17:59 +00:00
// Make sure we don't access border pixels. Normally this is prevented
// by GL_CLAMP_TO_EDGE anyway but for the bottom and rightmost textures
// this does not work as the textures might only be partially filled.
// This is the case if iImgSizeX != iTexSize or iImgSizeY != iTexSize.
// See bug #396.
fTexBlt . left = Max < float > ( fTexBlt . left , 0.5 ) ;
fTexBlt . top = Max < float > ( fTexBlt . top , 0.5 ) ;
fTexBlt . right = Min < float > ( fTexBlt . right , iImgSizeX - 0.5 ) ;
fTexBlt . bottom = Min < float > ( fTexBlt . bottom , iImgSizeY - 0.5 ) ;
# endif
2009-05-08 13:28:41 +00:00
// set up blit data as rect
BltData . byNumVertices = 4 ;
2010-02-18 20:11:14 +00:00
BltData . vtVtx [ 0 ] . ftx = tTexBlt . left ; BltData . vtVtx [ 0 ] . fty = tTexBlt . top ;
BltData . vtVtx [ 1 ] . ftx = tTexBlt . right ; BltData . vtVtx [ 1 ] . fty = tTexBlt . top ;
BltData . vtVtx [ 2 ] . ftx = tTexBlt . right ; BltData . vtVtx [ 2 ] . fty = tTexBlt . bottom ;
BltData . vtVtx [ 3 ] . ftx = tTexBlt . left ; BltData . vtVtx [ 3 ] . fty = tTexBlt . bottom ;
2010-09-04 16:17:59 +00:00
BltData . vtVtx [ 0 ] . tx = fTexBlt . left / iTexSizeX ; BltData . vtVtx [ 0 ] . ty = fTexBlt . top / iTexSizeY ;
BltData . vtVtx [ 1 ] . tx = fTexBlt . right / iTexSizeX ; BltData . vtVtx [ 1 ] . ty = fTexBlt . top / iTexSizeY ;
BltData . vtVtx [ 2 ] . tx = fTexBlt . right / iTexSizeX ; BltData . vtVtx [ 2 ] . ty = fTexBlt . bottom / iTexSizeY ;
BltData . vtVtx [ 3 ] . tx = fTexBlt . left / iTexSizeX ; BltData . vtVtx [ 3 ] . ty = fTexBlt . bottom / iTexSizeY ;
2009-05-08 13:28:41 +00:00
2011-10-03 14:16:38 +00:00
C4TexRef * pBaseTex = pTex ;
2009-05-08 13:28:41 +00:00
// is there a base-surface to be blitted first?
if ( fBaseSfc )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// then get this surface as same offset as from other surface
// assuming this is only valid as long as there's no texture management,
// organizing partially used textures together!
pBaseTex = * ( sfcSource - > pMainSfc - > ppTex + iY * sfcSource - > iTexX + iX ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// base blit
2009-08-23 21:46:56 +00:00
PerformBlt ( BltData , pBaseTex , BlitModulated ? BlitModulateClr : 0xffffffff , ! ! ( dwBlitMode & C4GFXBLIT_MOD2 ) , fExact ) ;
2009-05-08 13:28:41 +00:00
// overlay
if ( fBaseSfc )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
DWORD dwModClr = sfcSource - > ClrByOwnerClr ;
// apply global modulation to overlay surfaces only if desired
if ( BlitModulated & & ! ( dwBlitMode & C4GFXBLIT_CLRSFC_OWNCLR ) )
ModulateClr ( dwModClr , BlitModulateClr ) ;
PerformBlt ( BltData , pTex , dwModClr , ! ! ( dwBlitMode & C4GFXBLIT_CLRSFC_MOD2 ) , fExact ) ;
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// reset texture
ResetTexture ( ) ;
// success
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : RenderMesh ( StdMeshInstance & instance , C4Surface * sfcTarget , float tx , float ty , float twdt , float thgt , DWORD dwPlayerColor , C4BltTransform * pTransform )
2009-07-10 23:10:18 +00:00
{
// TODO: Emulate rendering
2009-08-28 01:35:55 +00:00
if ( ! sfcTarget - > IsRenderTarget ( ) ) return false ;
2009-07-10 23:10:18 +00:00
// TODO: Clip
// prepare rendering to surface
2009-08-28 01:35:55 +00:00
if ( ! PrepareRendering ( sfcTarget ) ) return false ;
2010-01-10 21:02:40 +00:00
// Update bone matrices and vertex data (note this also updates attach transforms and child transforms)
2010-01-06 01:11:56 +00:00
instance . UpdateBoneTransforms ( ) ;
2010-06-08 22:55:34 +00:00
// Order faces according to MeshTransformation (note pTransform does not affect Z coordinate, so does not need to be taken into account for correct ordering)
StdMeshMatrix mat = OgreToClonk ;
if ( MeshTransform ) mat = * MeshTransform * mat ;
instance . ReorderFaces ( & mat ) ;
2010-01-06 01:11:56 +00:00
// Render mesh
2010-07-21 20:23:34 +00:00
PerformMesh ( instance , tx , ty , twdt , thgt , dwPlayerColor , pTransform ) ;
2009-07-10 23:10:18 +00:00
// success
2009-08-28 01:35:55 +00:00
return true ;
2009-07-10 23:10:18 +00:00
}
2011-10-03 14:34:08 +00:00
bool C4Draw : : Blit8 ( C4Surface * sfcSource , int fx , int fy , int fwdt , int fhgt ,
2011-10-03 14:07:07 +00:00
C4Surface * sfcTarget , int tx , int ty , int twdt , int thgt ,
2011-09-30 20:15:51 +00:00
bool fSrcColKey , const C4BltTransform * pTransform )
2010-03-28 18:58:01 +00:00
{
2013-05-25 12:18:20 +00:00
if ( ! pTransform ) return BlitSimple ( sfcSource , fx , fy , fwdt , fhgt , sfcTarget , tx , ty , twdt , thgt , fSrcColKey ! = false ) ;
2009-05-08 13:28:41 +00:00
// safety
2009-08-15 18:50:32 +00:00
if ( ! fwdt | | ! fhgt ) return true ;
2009-05-08 13:28:41 +00:00
// Lock the surfaces
if ( ! sfcSource - > Lock ( ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
if ( ! sfcTarget - > Lock ( ) )
2009-08-15 18:50:32 +00:00
{ sfcSource - > Unlock ( ) ; return false ; }
2009-05-08 13:28:41 +00:00
// transformed, emulated blit
// Calculate transform target rect
2011-09-30 20:15:51 +00:00
C4BltTransform Transform ;
2009-05-08 13:28:41 +00:00
Transform . SetMoveScale ( tx - ( float ) fx * twdt / fwdt , ty - ( float ) fy * thgt / fhgt , ( float ) twdt / fwdt , ( float ) thgt / fhgt ) ;
Transform * = * pTransform ;
2011-09-30 20:15:51 +00:00
C4BltTransform TransformBack ;
2009-05-08 13:28:41 +00:00
TransformBack . SetAsInv ( Transform ) ;
float ttx0 = ( float ) tx , tty0 = ( float ) ty , ttx1 = ( float ) ( tx + twdt ) , tty1 = ( float ) ( ty + thgt ) ;
float ttx2 = ( float ) ttx0 , tty2 = ( float ) tty1 , ttx3 = ( float ) ttx1 , tty3 = ( float ) tty0 ;
pTransform - > TransformPoint ( ttx0 , tty0 ) ;
pTransform - > TransformPoint ( ttx1 , tty1 ) ;
pTransform - > TransformPoint ( ttx2 , tty2 ) ;
pTransform - > TransformPoint ( ttx3 , tty3 ) ;
int ttxMin = Max < int > ( ( int ) floor ( Min ( Min ( ttx0 , ttx1 ) , Min ( ttx2 , ttx3 ) ) ) , 0 ) ;
int ttxMax = Min < int > ( ( int ) ceil ( Max ( Max ( ttx0 , ttx1 ) , Max ( ttx2 , ttx3 ) ) ) , sfcTarget - > Wdt ) ;
int ttyMin = Max < int > ( ( int ) floor ( Min ( Min ( tty0 , tty1 ) , Min ( tty2 , tty3 ) ) ) , 0 ) ;
int ttyMax = Min < int > ( ( int ) ceil ( Max ( Max ( tty0 , tty1 ) , Max ( tty2 , tty3 ) ) ) , sfcTarget - > Hgt ) ;
// blit within target rect
for ( int y = ttyMin ; y < ttyMax ; + + y )
for ( int x = ttxMin ; x < ttxMax ; + + x )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
float ffx = ( float ) x , ffy = ( float ) y ;
TransformBack . TransformPoint ( ffx , ffy ) ;
int ifx = static_cast < int > ( ffx ) , ify = static_cast < int > ( ffy ) ;
if ( ifx < fx | | ify < fy | | ifx > = fx + fwdt | | ify > = fy + fhgt ) continue ;
sfcTarget - > BltPix ( x , y , sfcSource , ifx , ify , ! ! fSrcColKey ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Unlock the surfaces
sfcSource - > Unlock ( ) ;
sfcTarget - > Unlock ( ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2013-05-25 12:18:20 +00:00
bool C4Draw : : BlitSimple ( C4Surface * sfcSource , int fx , int fy , int fwdt , int fhgt ,
2011-10-03 14:07:07 +00:00
C4Surface * sfcTarget , int tx , int ty , int twdt , int thgt ,
2013-05-25 12:18:20 +00:00
bool fTransparency )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// rendertarget?
if ( sfcTarget - > IsRenderTarget ( ) )
2010-03-28 18:58:01 +00:00
{
2013-05-25 12:18:20 +00:00
return Blit ( sfcSource , float ( fx ) , float ( fy ) , float ( fwdt ) , float ( fhgt ) , sfcTarget , float ( tx ) , float ( ty ) , float ( twdt ) , float ( thgt ) , true ) ;
2010-03-28 18:58:01 +00:00
}
2013-05-25 12:18:20 +00:00
// Object is first stretched to dest rect
int xcnt , ycnt , tcx , tcy , cpcx , cpcy ;
2010-03-27 16:05:02 +00:00
if ( ! fwdt | | ! fhgt | | ! twdt | | ! thgt ) return false ;
// Lock the surfaces
if ( ! sfcSource - > Lock ( ) )
return false ;
if ( ! sfcTarget - > Lock ( ) )
{ sfcSource - > Unlock ( ) ; return false ; }
// Rectangle centers
tcx = twdt / 2 ; tcy = thgt / 2 ;
2013-05-25 12:18:20 +00:00
for ( ycnt = 0 ; ycnt < thgt ; ycnt + + )
if ( Inside ( cpcy = ty + tcy - thgt / 2 + ycnt , 0 , sfcTarget - > Hgt - 1 ) )
for ( xcnt = 0 ; xcnt < twdt ; xcnt + + )
if ( Inside ( cpcx = tx + tcx - twdt / 2 + xcnt , 0 , sfcTarget - > Wdt - 1 ) )
sfcTarget - > BltPix ( cpcx , cpcy , sfcSource , xcnt * fwdt / twdt + fx , ycnt * fhgt / thgt + fy , fTransparency ) ;
2010-03-27 16:05:02 +00:00
// Unlock the surfaces
2009-05-08 13:28:41 +00:00
sfcSource - > Unlock ( ) ;
sfcTarget - > Unlock ( ) ;
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : Error ( const char * szMsg )
2010-03-28 18:58:01 +00:00
{
2009-05-12 21:42:34 +00:00
if ( pApp ) pApp - > Error ( szMsg ) ;
2009-05-08 13:28:41 +00:00
Log ( szMsg ) ; return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : CreatePrimaryClipper ( unsigned int iXRes , unsigned int iYRes )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// simply setup primary viewport
// assume no zoom has been set yet
assert ( Zoom = = 1.0f ) ;
2010-04-26 23:32:45 +00:00
SetPrimaryClipper ( 0 , 0 , iXRes - 1 , iYRes - 1 ) ;
2009-05-08 13:28:41 +00:00
StorePrimaryClipper ( ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : BlitSurface ( C4Surface * sfcSurface , C4Surface * sfcTarget , int tx , int ty , bool fBlitBase )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( fBlitBase )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Blit ( sfcSurface , 0.0f , 0.0f , ( float ) sfcSurface - > Wdt , ( float ) sfcSurface - > Hgt , sfcTarget , float ( tx ) , float ( ty ) , float ( sfcSurface - > Wdt ) , float ( sfcSurface - > Hgt ) , false ) ;
2009-08-15 18:50:32 +00:00
return 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-08-15 18:50:32 +00:00
if ( ! sfcSurface ) return false ;
2011-10-03 14:06:41 +00:00
C4Surface * pSfcBase = sfcSurface - > pMainSfc ;
2009-05-08 13:28:41 +00:00
sfcSurface - > pMainSfc = NULL ;
Blit ( sfcSurface , 0.0f , 0.0f , ( float ) sfcSurface - > Wdt , ( float ) sfcSurface - > Hgt , sfcTarget , float ( tx ) , float ( ty ) , float ( sfcSurface - > Wdt ) , float ( sfcSurface - > Hgt ) , false ) ;
sfcSurface - > pMainSfc = pSfcBase ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-27 16:05:02 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : BlitSurfaceTile ( C4Surface * sfcSurface , C4Surface * sfcTarget , int iToX , int iToY , int iToWdt , int iToHgt , int iOffsetX , int iOffsetY , bool fSrcColKey )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
int iSourceWdt , iSourceHgt , iX , iY , iBlitX , iBlitY , iBlitWdt , iBlitHgt ;
2009-05-08 13:28:41 +00:00
// Get source surface size
2010-03-27 16:05:02 +00:00
if ( ! GetSurfaceSize ( sfcSurface , iSourceWdt , iSourceHgt ) ) return false ;
2009-05-08 13:28:41 +00:00
// reduce offset to needed size
iOffsetX % = iSourceWdt ;
iOffsetY % = iSourceHgt ;
// Vertical blits
2010-03-27 16:05:02 +00:00
for ( iY = iToY + iOffsetY ; iY < iToY + iToHgt ; iY + = iSourceHgt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Vertical blit size
iBlitY = Max ( iToY - iY , 0 ) ; iBlitHgt = Min ( iSourceHgt , iToY + iToHgt - iY ) - iBlitY ;
// Horizontal blits
for ( iX = iToX + iOffsetX ; iX < iToX + iToWdt ; iX + = iSourceWdt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Horizontal blit size
iBlitX = Max ( iToX - iX , 0 ) ; iBlitWdt = Min ( iSourceWdt , iToX + iToWdt - iX ) - iBlitX ;
// Blit
2009-08-15 18:50:32 +00:00
if ( ! Blit ( sfcSurface , float ( iBlitX ) , float ( iBlitY ) , float ( iBlitWdt ) , float ( iBlitHgt ) , sfcTarget , float ( iX + iBlitX ) , float ( iY + iBlitY ) , float ( iBlitWdt ) , float ( iBlitHgt ) , fSrcColKey ) ) return false ;
2009-05-08 13:28:41 +00:00
}
2010-03-27 16:05:02 +00:00
}
2010-03-28 18:58:01 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : BlitSurfaceTile2 ( C4Surface * sfcSurface , C4Surface * sfcTarget , int iToX , int iToY , int iToWdt , int iToHgt , int iOffsetX , int iOffsetY , bool fSrcColKey )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// if it's a render target, simply blit with repeating texture
// repeating textures, however, aren't currently supported
/*if (sfcTarget->IsRenderTarget())
2010-03-28 18:58:01 +00:00
return Blit ( sfcSurface , iOffsetX , iOffsetY , iToWdt , iToHgt , sfcTarget , iToX , iToY , iToWdt , iToHgt , false ) ; */
2010-03-27 16:05:02 +00:00
int tx , ty , iBlitX , iBlitY , iBlitWdt , iBlitHgt ;
2009-05-08 13:28:41 +00:00
// get tile size
int iTileWdt = sfcSurface - > Wdt ;
int iTileHgt = sfcSurface - > Hgt ;
// adjust size of offsets
iOffsetX % = iTileWdt ;
iOffsetY % = iTileHgt ;
if ( iOffsetX < 0 ) iOffsetX + = iTileWdt ;
if ( iOffsetY < 0 ) iOffsetY + = iTileHgt ;
// get start pos for blitting
int iStartX = iToX - iOffsetX ;
int iStartY = iToY - iOffsetY ;
ty = 0 ;
// blit vertical
for ( int iY = iStartY ; ty < iToHgt ; iY + = iTileHgt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get vertical blit bounds
iBlitY = 0 ; iBlitHgt = iTileHgt ;
if ( iY < iToY ) { iBlitY = iToY - iY ; iBlitHgt + = iY - iToY ; }
int iOver = ty + iBlitHgt - iToHgt ; if ( iOver > 0 ) iBlitHgt - = iOver ;
// blit horizontal
tx = 0 ;
for ( int iX = iStartX ; tx < iToWdt ; iX + = iTileWdt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get horizontal blit bounds
iBlitX = 0 ; iBlitWdt = iTileWdt ;
if ( iX < iToX ) { iBlitX = iToX - iX ; iBlitWdt + = iX - iToX ; }
iOver = tx + iBlitWdt - iToWdt ; if ( iOver > 0 ) iBlitWdt - = iOver ;
// blit
2013-09-14 18:04:15 +00:00
if ( ! Blit ( sfcSurface , float ( iBlitX ) , float ( iBlitY ) , float ( iBlitWdt ) , float ( iBlitHgt ) , sfcTarget , float ( tx + iToX ) , float ( ty + iToY ) , float ( iBlitWdt ) , float ( iBlitHgt ) , fSrcColKey ) )
{
// Ignore blit errors. This is usually due to blit border lying outside surface and shouldn't cause remaining blits to fail.
}
2009-05-08 13:28:41 +00:00
// next col
tx + = iBlitWdt ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// next line
ty + = iBlitHgt ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// success
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : TextOut ( const char * szText , CStdFont & rFont , float fZoom , C4Surface * sfcDest , float iTx , float iTy , DWORD dwFCol , BYTE byForm , bool fDoMarkup )
2010-03-28 18:58:01 +00:00
{
2011-08-27 19:13:15 +00:00
C4Markup Markup ( true ) ;
2009-05-08 13:28:41 +00:00
static char szLinebuf [ 2500 + 1 ] ;
2013-10-18 16:49:21 +00:00
for ( int cnt = 0 ; SCopySegmentEx ( szText , cnt , szLinebuf , fDoMarkup ? ' | ' : ' \n ' , ' \n ' , 2500 ) ; cnt + + , iTy + = int ( fZoom * rFont . GetLineHeight ( ) ) )
2009-08-15 18:50:32 +00:00
if ( ! StringOut ( szLinebuf , sfcDest , iTx , iTy , dwFCol , byForm , fDoMarkup , Markup , & rFont , fZoom ) ) return false ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : StringOut ( const char * szText , CStdFont & rFont , float fZoom , C4Surface * sfcDest , float iTx , float iTy , DWORD dwFCol , BYTE byForm , bool fDoMarkup )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// init markup
2011-08-27 19:13:15 +00:00
C4Markup Markup ( true ) ;
2009-05-08 13:28:41 +00:00
// output string
return StringOut ( szText , sfcDest , iTx , iTy , dwFCol , byForm , fDoMarkup , Markup , & rFont , fZoom ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : StringOut ( const char * szText , C4Surface * sfcDest , float iTx , float iTy , DWORD dwFCol , BYTE byForm , bool fDoMarkup , C4Markup & Markup , CStdFont * pFont , float fZoom )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// clip
if ( ClipAll ) return true ;
// safety
if ( ! PrepareRendering ( sfcDest ) ) return false ;
// convert align
int iFlags = 0 ;
switch ( byForm )
2010-03-28 18:58:01 +00:00
{
case ACenter : iFlags | = STDFONT_CENTERED ; break ;
case ARight : iFlags | = STDFONT_RIGHTALGN ; break ;
}
2009-05-08 13:28:41 +00:00
if ( ! fDoMarkup ) iFlags | = STDFONT_NOMARKUP ;
// draw text
pFont - > DrawText ( sfcDest , iTx , iTy , dwFCol , szText , iFlags , Markup , fZoom ) ;
// done, success
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : DrawPix ( C4Surface * sfcDest , float tx , float ty , DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Draw
2014-10-08 02:51:34 +00:00
C4BltVertex vtx ;
vtx . ftx = tx ;
vtx . fty = ty ;
DwTo4UB ( dwClr , vtx . color ) ;
PerformMultiPix ( sfcDest , & vtx , 1 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2012-06-08 14:19:36 +00:00
void C4Draw : : DrawLineDw ( C4Surface * sfcTarget , float x1 , float y1 , float x2 , float y2 , DWORD dwClr , float width )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ApplyZoom ( x1 , y1 ) ;
ApplyZoom ( x2 , y2 ) ;
2010-03-28 18:58:01 +00:00
// manual clipping?
2010-09-28 17:07:47 +00:00
if ( Config . Graphics . ClipManuallyE )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
float i ;
// sort left/right
if ( x1 > x2 ) { i = x1 ; x1 = x2 ; x2 = i ; i = y1 ; y1 = y2 ; y2 = i ; }
// clip horizontally
if ( x1 < iClipX1 )
if ( x2 < iClipX1 )
return ; // left out
else
{ y1 + = ( y2 - y1 ) * ( ( float ) iClipX1 - x1 ) / ( x2 - x1 ) ; x1 = ( float ) iClipX1 ; } // clip left
else if ( x2 > iClipX2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( x1 > iClipX2 )
return ; // right out
else
{ y2 - = ( y2 - y1 ) * ( x2 - ( float ) iClipX2 ) / ( x2 - x1 ) ; x2 = ( float ) iClipX2 ; } // clip right
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// sort top/bottom
if ( y1 > y2 ) { i = x1 ; x1 = x2 ; x2 = i ; i = y1 ; y1 = y2 ; y2 = i ; }
// clip vertically
if ( y1 < iClipY1 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( y2 < iClipY1 )
return ; // top out
else
{ x1 + = ( x2 - x1 ) * ( ( float ) iClipY1 - y1 ) / ( y2 - y1 ) ; y1 = ( float ) iClipY1 ; } // clip top
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if ( y2 > iClipY2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( y1 > iClipY2 )
return ; // bottom out
else
{ x2 - = ( x2 - x1 ) * ( y2 - ( float ) iClipY2 ) / ( y2 - y1 ) ; y2 = ( float ) iClipY2 ; } // clip bottom
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// apply color modulation
ClrByCurrentBlitMod ( dwClr ) ;
2012-06-08 14:19:36 +00:00
PerformLine ( sfcTarget , x1 , y1 , x2 , y2 , dwClr , width ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : DrawFrameDw ( C4Surface * sfcDest , int x1 , int y1 , int x2 , int y2 , DWORD dwClr ) // make these parameters float...?
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
DrawLineDw ( sfcDest , ( float ) x1 , ( float ) y1 , ( float ) x2 , ( float ) y1 , dwClr ) ;
DrawLineDw ( sfcDest , ( float ) x2 , ( float ) y1 , ( float ) x2 , ( float ) y2 , dwClr ) ;
DrawLineDw ( sfcDest , ( float ) x2 , ( float ) y2 , ( float ) x1 , ( float ) y2 , dwClr ) ;
DrawLineDw ( sfcDest , ( float ) x1 , ( float ) y2 , ( float ) x1 , ( float ) y1 , dwClr ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Globally locked surface variables - for DrawLine callback crap
2011-10-03 14:06:41 +00:00
C4Surface * GLSBuffer = NULL ;
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
bool LockSurfaceGlobal ( C4Surface * sfcTarget )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
if ( GLSBuffer ) return false ;
GLSBuffer = sfcTarget ;
2009-05-08 13:28:41 +00:00
return ! ! sfcTarget - > Lock ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
bool UnLockSurfaceGlobal ( C4Surface * sfcTarget )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
if ( ! GLSBuffer ) return false ;
2009-05-08 13:28:41 +00:00
sfcTarget - > Unlock ( ) ;
2010-03-27 16:05:02 +00:00
GLSBuffer = NULL ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool DLineSPixDw ( int32_t x , int32_t y , int32_t dwClr )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
if ( ! GLSBuffer ) return false ;
GLSBuffer - > SetPixDw ( x , y , ( DWORD ) dwClr ) ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : DrawPatternedCircle ( C4Surface * sfcDest , int x , int y , int r , BYTE col , C4Pattern & Pattern , CStdPalette & rPal )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! sfcDest - > Lock ( ) ) return ;
for ( int ycnt = - r ; ycnt < r ; ycnt + + )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int lwdt = ( int ) sqrt ( float ( r * r - ycnt * ycnt ) ) ;
// Set line
for ( int xcnt = x - lwdt ; xcnt < x + lwdt ; + + xcnt )
2010-03-28 18:58:01 +00:00
{
2009-07-24 21:50:04 +00:00
sfcDest - > SetPixDw ( xcnt , y + ycnt , Pattern . PatternClr ( xcnt , y + ycnt ) ) ;
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 18:58:01 +00:00
sfcDest - > Unlock ( ) ;
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : Grayscale ( C4Surface * sfcSfc , int32_t iOffset )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
if ( ! sfcSfc ) return ;
// change colors
int xcnt , ycnt , wdt = sfcSfc - > Wdt , hgt = sfcSfc - > Hgt ;
// Lock surface
if ( ! sfcSfc - > Lock ( ) ) return ;
for ( ycnt = 0 ; ycnt < hgt ; ycnt + + )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( xcnt = 0 ; xcnt < wdt ; xcnt + + )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
DWORD dwColor = sfcSfc - > GetPixDw ( xcnt , ycnt , false ) ;
2011-03-11 02:37:27 +00:00
uint32_t r = GetRedValue ( dwColor ) , g = GetGreenValue ( dwColor ) , b = GetBlueValue ( dwColor ) , a = dwColor > > 24 ;
2009-05-08 13:28:41 +00:00
int32_t gray = BoundBy < int32_t > ( ( r + g + b ) / 3 + iOffset , 0 , 255 ) ;
sfcSfc - > SetPixDw ( xcnt , ycnt , RGBA ( gray , gray , gray , a ) ) ;
}
}
2010-03-28 18:58:01 +00:00
sfcSfc - > Unlock ( ) ;
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : GetPrimaryClipper ( int & rX1 , int & rY1 , int & rX2 , int & rY2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Store drawing clip values
2010-03-28 18:58:01 +00:00
rX1 = fClipX1 ; rY1 = fClipY1 ; rX2 = fClipX2 ; rY2 = fClipY2 ;
2009-05-08 13:28:41 +00:00
// Done
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : SetGamma ( DWORD dwClr1 , DWORD dwClr2 , DWORD dwClr3 , int32_t iRampIndex )
2010-03-28 18:58:01 +00:00
{
2010-10-01 21:36:48 +00:00
// No gamma effects
if ( Config . Graphics . DisableGamma ) return ;
if ( iRampIndex < 0 | | iRampIndex > = C4MaxGammaRamps ) return ;
// turn ramp index into array offset
iRampIndex * = 3 ;
// set array members
dwGamma [ iRampIndex + 0 ] = dwClr1 ;
dwGamma [ iRampIndex + 1 ] = dwClr2 ;
dwGamma [ iRampIndex + 2 ] = dwClr3 ;
// mark gamma ramp to be recalculated
fSetGamma = true ;
}
2013-11-09 16:11:29 +00:00
void C4Draw : : ResetGamma ( )
{
2014-01-12 20:32:58 +00:00
pApp - > ApplyGammaRamp ( DefRamp . ramp , false ) ;
2013-11-09 16:11:29 +00:00
}
2011-10-03 14:34:08 +00:00
void C4Draw : : ApplyGamma ( )
2010-10-01 21:36:48 +00:00
{
// No gamma effects
if ( Config . Graphics . DisableGamma ) return ;
if ( ! fSetGamma ) return ;
// calculate color channels by adding the difference between the gamma ramps to their normals
int32_t ChanOff [ 3 ] ;
DWORD tGamma [ 3 ] ;
const int32_t DefChanVal [ 3 ] = { 0x00 , 0x80 , 0xff } ;
// calc offset for curve points
for ( int32_t iCurve = 0 ; iCurve < 3 ; + + iCurve )
{
2011-03-12 13:59:41 +00:00
memset ( ChanOff , 0 , sizeof ( int32_t ) * 3 ) ;
2010-10-01 21:36:48 +00:00
// ...channels...
for ( int32_t iChan = 0 ; iChan < 3 ; + + iChan )
// ...ramps...
for ( int32_t iRamp = 0 ; iRamp < C4MaxGammaRamps ; + + iRamp )
// add offset
ChanOff [ iChan ] + = ( int32_t ) BYTE ( dwGamma [ iRamp * 3 + iCurve ] > > ( 16 - iChan * 8 ) ) - DefChanVal [ iCurve ] ;
// calc curve point
tGamma [ iCurve ] = C4RGB ( BoundBy < int32_t > ( DefChanVal [ iCurve ] + ChanOff [ 0 ] , 0 , 255 ) , BoundBy < int32_t > ( DefChanVal [ iCurve ] + ChanOff [ 1 ] , 0 , 255 ) , BoundBy < int32_t > ( DefChanVal [ iCurve ] + ChanOff [ 2 ] , 0 , 255 ) ) ;
}
2009-05-08 13:28:41 +00:00
// calc ramp
2010-10-01 21:36:48 +00:00
Gamma . Set ( tGamma [ 0 ] , tGamma [ 1 ] , tGamma [ 2 ] ) ;
// set gamma
2012-02-28 19:40:19 +00:00
pApp - > ApplyGammaRamp ( Gamma . ramp , false ) ;
2010-10-01 21:36:48 +00:00
fSetGamma = false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : DisableGamma ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set it
2012-02-28 19:40:19 +00:00
pApp - > ApplyGammaRamp ( DefRamp . ramp , true ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : EnableGamma ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set it
2012-02-28 19:40:19 +00:00
pApp - > ApplyGammaRamp ( Gamma . ramp , false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
DWORD C4Draw : : ApplyGammaTo ( DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return Gamma . ApplyTo ( dwClr ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : SetZoom ( int X , int Y , float Zoom )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
this - > ZoomX = X ; this - > ZoomY = Y ; this - > Zoom = Zoom ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : ApplyZoom ( float & X , float & Y )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
X = ( X - ZoomX ) * Zoom + ZoomX ;
Y = ( Y - ZoomY ) * Zoom + ZoomY ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : RemoveZoom ( float & X , float & Y )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
X = ( X - ZoomX ) / Zoom + ZoomX ;
Y = ( Y - ZoomY ) / Zoom + ZoomY ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2013-10-29 13:27:18 +00:00
bool DDrawInit ( C4AbstractApp * pApp , bool Editor , bool fUsePageLock , unsigned int iXRes , unsigned int iYRes , int iBitDepth , unsigned int iMonitor )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// create engine
2013-10-29 13:27:18 +00:00
# ifndef USE_CONSOLE
pDraw = new CStdGL ( ) ;
# else
pDraw = new CStdNoGfx ( ) ;
# endif
2011-10-03 14:30:18 +00:00
if ( ! pDraw ) return false ;
2009-05-08 13:28:41 +00:00
// init it
2011-10-03 14:30:18 +00:00
if ( ! pDraw - > Init ( pApp , Editor , fUsePageLock , iXRes , iYRes , iBitDepth , iMonitor ) )
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
delete pDraw ;
2010-09-28 18:35:26 +00:00
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// done, success
2010-09-28 18:35:26 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
bool C4Draw : : Init ( C4AbstractApp * pApp , bool Editor , bool fUsePageLock , unsigned int iXRes , unsigned int iYRes , int iBitDepth , unsigned int iMonitor )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
this - > pApp = pApp ;
// store default gamma
2012-02-28 19:40:19 +00:00
if ( ! pApp - > SaveDefaultGammaRamp ( DefRamp . ramp ) )
DefRamp . Default ( ) ;
2009-05-08 13:28:41 +00:00
2011-10-03 14:06:41 +00:00
pApp - > pWindow - > pSurface = new C4Surface ( pApp , pApp - > pWindow ) ;
2010-03-06 14:07:30 +00:00
2010-09-28 18:16:33 +00:00
if ( ! CreatePrimarySurfaces ( Editor , iXRes , iYRes , iBitDepth , iMonitor ) )
2009-06-02 23:59:04 +00:00
return false ;
2009-05-08 13:28:41 +00:00
if ( ! CreatePrimaryClipper ( iXRes , iYRes ) )
return Error ( " Clipper failure. " ) ;
2010-09-28 18:16:33 +00:00
this - > Editor = Editor ;
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : DrawBoxFade ( C4Surface * sfcDest , float iX , float iY , float iWdt , float iHgt , DWORD dwClr1 , DWORD dwClr2 , DWORD dwClr3 , DWORD dwClr4 , int iBoxOffX , int iBoxOffY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ApplyZoom ( iX , iY ) ;
iWdt * = Zoom ;
iHgt * = Zoom ;
// clipping not performed - this fn should be called for clipped rects only
// apply modulation map: Must sectionize blit
if ( fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2011-08-27 14:41:26 +00:00
int iModResX = pClrModMap ? pClrModMap - > GetResolutionX ( ) : C4FogOfWar : : DefResolutionX ;
int iModResY = pClrModMap ? pClrModMap - > GetResolutionY ( ) : C4FogOfWar : : DefResolutionY ;
2009-05-08 13:28:41 +00:00
iBoxOffX % = iModResX ;
iBoxOffY % = iModResY ;
if ( iWdt + iBoxOffX > iModResX | | iHgt + iBoxOffY > iModResY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( iWdt < = 0 | | iHgt < = 0 ) return ;
CColorFadeMatrix clrs ( int ( iX ) , int ( iY ) , int ( iWdt ) , int ( iHgt ) , dwClr1 , dwClr2 , dwClr3 , dwClr4 ) ;
float iMaxH = float ( iModResY - iBoxOffY ) ;
float w , h ;
for ( float y = iY , H = iHgt ; H > 0 ; ( y + = h ) , ( H - = h ) , ( iMaxH = float ( iModResY ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
h = Min ( H , iMaxH ) ;
float iMaxW = float ( iModResX - iBoxOffX ) ;
for ( float x = iX , W = iWdt ; W > 0 ; ( x + = w ) , ( W - = w ) , ( iMaxW = float ( iModResX ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
w = Min ( W , iMaxW ) ;
//DrawBoxFade(sfcDest, x,y,w,h, clrs.GetColorAt(x,y), clrs.GetColorAt(x+w,y), clrs.GetColorAt(x,y+h), clrs.GetColorAt(x+w,y+h), 0,0);
float vtx [ 8 ] ;
vtx [ 0 ] = x ; vtx [ 1 ] = y ;
vtx [ 2 ] = x ; vtx [ 3 ] = y + h ;
vtx [ 4 ] = x + w ; vtx [ 5 ] = y + h ;
vtx [ 6 ] = x + w ; vtx [ 7 ] = y ;
DrawQuadDw ( sfcDest , vtx , clrs . GetColorAt ( int ( x ) , int ( y ) ) , clrs . GetColorAt ( int ( x ) , int ( y + h ) ) , clrs . GetColorAt ( int ( x + w ) , int ( y + h ) ) , clrs . GetColorAt ( int ( x + w ) , int ( y ) ) ) ;
}
}
2010-03-28 18:58:01 +00:00
return ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// set vertex buffer data
// vertex order:
// 0=upper left dwClr1
// 1=lower left dwClr3
// 2=lower right dwClr4
// 3=upper right dwClr2
float vtx [ 8 ] ;
vtx [ 0 ] = iX ; vtx [ 1 ] = iY ;
vtx [ 2 ] = iX ; vtx [ 3 ] = iY + iHgt ;
vtx [ 4 ] = iX + iWdt ; vtx [ 5 ] = iY + iHgt ;
vtx [ 6 ] = iX + iWdt ; vtx [ 7 ] = iY ;
DrawQuadDw ( sfcDest , vtx , dwClr1 , dwClr3 , dwClr4 , dwClr2 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:34:08 +00:00
void C4Draw : : DrawBoxDw ( C4Surface * sfcDest , int iX1 , int iY1 , int iX2 , int iY2 , DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
DrawBoxFade ( sfcDest , float ( iX1 ) , float ( iY1 ) , float ( iX2 - iX1 + 1 ) , float ( iY2 - iY1 + 1 ) , dwClr , dwClr , dwClr , dwClr , 0 , 0 ) ;
}