openclonk/engine/src/C4FacetEx.cpp

259 lines
7.3 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2004, 2008 Matthes Bender
* Copyright (c) 2002, 2006, 2008 Sven Eberhardt
* Copyright (c) 2006-2008 Günther Brammer
* 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.
*/
/* A facet that can hold its own surface and also target coordinates */
#include <C4Include.h>
#include <C4FacetEx.h>
#ifndef BIG_C4INCLUDE
#include <C4Random.h>
#include <C4Shape.h>
#include <C4Group.h>
#endif
void C4TargetFacet::Set(SURFACE nsfc, int nx, int ny, int nwdt, int nhgt, float ntx, float nty)
{
C4Facet::Set(nsfc,nx,ny,nwdt,nhgt);
TargetX=ntx; TargetY=nty;
}
void C4TargetFacet::Set(SURFACE nsfc, const C4Rect & r, float ntx, float nty)
{
Set(nsfc, r.x, r.y, r.Wdt, r.Hgt, ntx, nty);
}
void C4TargetFacet::SetRect(C4TargetRect &rSrc)
{
X=rSrc.x; Y=rSrc.y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt; TargetX=rSrc.tx; TargetY=rSrc.ty;
}
void C4TargetFacet::DrawLine(int iX1, int iY1, int iX2, int iY2, BYTE bCol1, BYTE bCol2)
{
if (!lpDDraw || !Surface || !Wdt || !Hgt) return;
// Scroll position
iX1-=TargetX; iY1-=TargetY; iX2-=TargetX; iY2-=TargetY;
// No clipping is done here, because clipping will be done by gfx wrapper anyway
// Draw line
lpDDraw->DrawLine(Surface,X+iX1,Y+iY1,X+iX2,Y+iY2,bCol1);
lpDDraw->DrawPix(Surface,(float)(X+iX1),(float)(Y+iY1),lpDDraw->Pal.GetClr(bCol2));
}
// bolt random size
#define DrawBoltR1 7
#define DrawBoltR2 3
void C4TargetFacet::DrawBolt(int iX1, int iY1, int iX2, int iY2, BYTE bCol, BYTE bCol2)
{
if (!lpDDraw || !Surface || !Wdt || !Hgt) return;
// Scroll position
iX1-=TargetX; iY1-=TargetY; iX2-=TargetX; iY2-=TargetY;
// Facet bounds
if (!Inside(iX1,0,Wdt-1) && !Inside(iX2,0,Wdt-1)) return;
if (!Inside(iY1,0,Hgt-1) && !Inside(iY2,0,Hgt-1)) return;
iX1+=X; iX2+=X; iY1+=Y; iY2+=Y;
// Draw bolt
float pvtx[2*4];
pvtx[0]=iX1; pvtx[1]=iY1; pvtx[2]=iX2; pvtx[3]=iY2;
pvtx[4]=iX2+SafeRandom(DrawBoltR1)-DrawBoltR2; pvtx[5]=iY2+SafeRandom(DrawBoltR1)-DrawBoltR2;
pvtx[6]=iX1+SafeRandom(DrawBoltR1)-DrawBoltR2; pvtx[7]=iY1+SafeRandom(DrawBoltR1)-DrawBoltR2;
// Draw in surface
DWORD dwClr1=lpDDraw->Pal.GetClr(bCol),dwClr2;
DWORD dwClr3=lpDDraw->Pal.GetClr(bCol2),dwClr4;
/*if (DDrawCfg.NoBoxFades)
{*/
dwClr2=dwClr1;
dwClr4=dwClr3;
/*}
else
{
DWORD dwClr2=dwClr1|0xff000000; ...this leads to black and white lightning bolts. Who wants that?
DWORD dwClr4=dwClr3|0xff000000;
}*/
lpDDraw->DrawQuadDw(Surface,pvtx,dwClr1,dwClr3,dwClr4,dwClr2);
}
// ------------------------
// C4FacetSurface
BOOL C4FacetSurface::Create(int iWdt, int iHgt, int iWdt2, int iHgt2)
{
Clear();
// Create surface
Face.Default();
if (!Face.Create(iWdt,iHgt)) return FALSE;
// Set facet
if (iWdt2==C4FCT_Full) iWdt2=Face.Wdt; if (iWdt2==C4FCT_Height) iWdt2=Face.Hgt; if (iWdt2==C4FCT_Width) iWdt2=Face.Wdt;
if (iHgt2==C4FCT_Full) iHgt2=Face.Hgt; if (iHgt2==C4FCT_Height) iHgt2=Face.Hgt; if (iHgt2==C4FCT_Width) iHgt2=Face.Wdt;
Set(&Face,0,0,iWdt2,iHgt2,0,0);
return TRUE;
}
BOOL C4FacetSurface::CreateClrByOwner(CSurface *pBySurface)
{
Clear();
// create surface
if (!Face.CreateColorByOwner(pBySurface)) return FALSE;
// set facet
Set(&Face,0,0,Face.Wdt,Face.Hgt,0,0);
// success
return TRUE;
}
BOOL C4FacetSurface::EnsureSize(int iMinWdt, int iMinHgt)
{
// safety
if (!Surface) return FALSE;
// check size
int iWdt=Face.Wdt,iHgt=Face.Hgt;
if (iWdt>=iMinWdt && iHgt>=iMinHgt) return TRUE;
// create temp surface
CSurface *sfcDup=new CSurface(iWdt,iHgt);
if (!sfcDup) return FALSE;
if (!lpDDraw->BlitSurface(&Face,sfcDup,0,0,false))
{ delete sfcDup; return FALSE; }
// calc needed size
int iDstWdt=Surface->Wdt,iDstHgt=iHgt;
while (iDstWdt<iMinWdt) iDstWdt+=iWdt;
while (iDstHgt<iMinHgt) iDstHgt+=iHgt;
// recreate this one
if (!Face.Create(iDstWdt, iDstHgt)) { delete sfcDup; Clear(); return FALSE; }
// blit tiled into it
BOOL fSuccess=lpDDraw->BlitSurfaceTile(sfcDup, &Face, 0, 0, iDstWdt, iDstHgt, 0, 0, FALSE);
// del temp surface
delete sfcDup;
// done
return fSuccess;
}
/*BOOL C4FacetSurface::Save(C4Group &hGroup, const char *szName)
{
// Empty
if (!Wdt || !Hgt) return FALSE;
// Full surface
if ((Wdt==Face.Wdt) && (Hgt==Face.Hgt))
{
if (!Face.Save(hGroup,szName)) return FALSE;
}
// Surface section
else
{
C4Surface sfcFacet;
if (!sfcFacet.Create(Wdt,Hgt)) return FALSE;
Draw(&sfcFacet,0,0);
if (!sfcFacet.Save(hGroup,szName)) return FALSE;
}
// Success
return TRUE;
}*/
BOOL C4FacetSurface::Load(C4Group &hGroup, const char *szName, int iWdt, int iHgt, bool fOwnPal, bool fNoErrIfNotFound)
{
Clear();
// Entry name
char szFilename[_MAX_FNAME+1];
SCopy(szName,szFilename,_MAX_FNAME);
char *szExt = GetExtension(szFilename);
if (!*szExt)
{
// no extension: Default to extension that is found as file in group
const char * const extensions[] = { "png", "bmp", "jpeg", "jpg", NULL };
int i = 0; const char *szExt;
while (szExt = extensions[i++])
{
EnforceExtension(szFilename, szExt);
if (hGroup.FindEntry(szFilename)) break;
}
}
// Load surface
if (!Face.Load(hGroup,szFilename,fOwnPal,fNoErrIfNotFound)) return FALSE;
// Set facet
if (iWdt==C4FCT_Full) iWdt=Face.Wdt; if (iWdt==C4FCT_Height) iWdt=Face.Hgt; if (iWdt==C4FCT_Width) iWdt=Face.Wdt;
if (iHgt==C4FCT_Full) iHgt=Face.Hgt; if (iHgt==C4FCT_Height) iHgt=Face.Hgt; if (iHgt==C4FCT_Width) iHgt=Face.Wdt;
Set(&Face,0,0,iWdt,iHgt,0,0);
return TRUE;
}
bool C4FacetSurface::CopyFromSfcMaxSize(C4Surface &srcSfc, int32_t iMaxSize, uint32_t dwColor)
{
// safety
if (!srcSfc.Wdt || !srcSfc.Hgt) return false;
Clear();
// no scale?
bool fNeedsScale = !(srcSfc.Wdt <= iMaxSize && srcSfc.Hgt <= iMaxSize);
if (!fNeedsScale && !dwColor)
{
// no change necessary; just copy then
Face.Copy(srcSfc);
}
else
{
// must scale down or colorize. Just blit.
C4Facet fctSource;
fctSource.Set(&srcSfc, 0,0,srcSfc.Wdt,srcSfc.Hgt);
int32_t iTargetWdt, iTargetHgt;
if (fNeedsScale)
{
if (fctSource.Wdt > fctSource.Hgt)
{
iTargetWdt = iMaxSize;
iTargetHgt = fctSource.Hgt * iTargetWdt / fctSource.Wdt;
}
else
{
iTargetHgt = iMaxSize;
iTargetWdt = fctSource.Wdt * iTargetHgt / fctSource.Hgt;
}
}
else
{
iTargetWdt = fctSource.Wdt;
iTargetHgt = fctSource.Hgt;
}
if (dwColor) srcSfc.SetClr(dwColor);
Create(iTargetWdt, iTargetHgt);
lpDDraw->Blit(&srcSfc, 0.0f,0.0f,float(fctSource.Wdt),float(fctSource.Hgt),
&Face, 0,0,iTargetWdt,iTargetHgt);
}
Set(&Face, 0,0, Face.Wdt, Face.Hgt);
return true;
}
void C4FacetSurface::Grayscale(int32_t iOffset)
{
if (!lpDDraw || !Surface || !Wdt || !Hgt) return;
lpDDraw->Grayscale(Surface, iOffset);
}
bool C4FacetSurface::EnsureOwnSurface()
{
// is it a link?
if (Surface != &Face)
{
// then recreate in same size
C4Facet fctOld = *this;
if (!Create(fctOld.Wdt, fctOld.Hgt)) return false;
fctOld.Draw(*this);
}
return true;
}