openclonk/src/graphics/C4Facet.cpp

570 lines
16 KiB
C++
Raw Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, Matthes Bender
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
2016-04-03 18:18:29 +00:00
* Copyright (c) 2009-2016, The OpenClonk Team and contributors
2009-05-08 13:28:41 +00:00
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
2009-05-08 13:28:41 +00:00
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
2009-05-08 13:28:41 +00:00
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
2009-05-08 13:28:41 +00:00
*/
/* A piece of a DirectDraw surface */
#include "C4Include.h"
#include "graphics/C4Draw.h"
#include "graphics/C4Facet.h"
#include "graphics/C4GraphicsResource.h"
2009-05-08 13:28:41 +00:00
#include "lib/StdAdaptors.h"
2009-05-08 13:28:41 +00:00
#ifdef WITH_GLIB
#include <glib.h>
#endif
void C4Facet::Default()
2010-03-28 18:58:01 +00:00
{
Set(nullptr,0,0,0,0);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Facet::Set(C4Surface * nsfc, float nx, float ny, float nwdt, float nhgt)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Surface=nsfc; X=nx; Y=ny; Wdt=nwdt; Hgt=nhgt;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Facet::C4Facet()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Default();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
int32_t C4Facet::GetSectionCount()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (Hgt==0) return 0;
return Wdt/Hgt;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Facet C4Facet::GetSection(int32_t iSection)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Facet rval;
rval.Set(Surface,X+Hgt*iSection,Y,Hgt,Hgt);
return rval;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Facet C4Facet::GetPhase(int iPhaseX, int iPhaseY)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Facet fctResult;
fctResult.Set(Surface,X+Wdt*iPhaseX,Y+Hgt*iPhaseY,Wdt,Hgt);
return fctResult;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::Draw(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return;
2009-05-08 13:28:41 +00:00
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
sfcTarget,
iX,iY,Wdt,Hgt,true);
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::DrawT(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return;
2009-05-08 13:28:41 +00:00
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
sfcTarget,
iX,iY,Wdt,Hgt,true,pTransform);
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawT(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !cgo.Surface || !Wdt || !Hgt) return;
2009-05-08 13:28:41 +00:00
// Drawing area
C4Facet ccgo = cgo;
// Adjust for fixed aspect ratio
if (fAspect)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// By height
if (100*cgo.Wdt/Wdt<100*cgo.Hgt/Hgt)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ccgo.Hgt=Hgt*cgo.Wdt/Wdt;
ccgo.Y+=(cgo.Hgt-ccgo.Hgt)/2;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// By width
else if (100*cgo.Hgt/Hgt<100*cgo.Wdt/Wdt)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ccgo.Wdt=Wdt*cgo.Hgt/Hgt;
ccgo.X+=(cgo.Wdt-ccgo.Wdt)/2;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
ccgo.Surface,ccgo.X,ccgo.Y,ccgo.Wdt,ccgo.Hgt,
true,pTransform);
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawTUnscaled(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
{
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return;
pDraw->BlitUnscaled(Surface,
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
sfcTarget,
iX,iY,Wdt,Hgt,true,pTransform);
}
void C4Facet::DrawTUnscaled(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
{
if (!pDraw || !Surface || !cgo.Surface || !Wdt || !Hgt) return;
// Drawing area
C4Facet ccgo = cgo;
// Adjust for fixed aspect ratio
if (fAspect)
{
// By height
if (100*cgo.Wdt/Wdt<100*cgo.Hgt/Hgt)
{
ccgo.Hgt=Hgt*cgo.Wdt/Wdt;
ccgo.Y+=(cgo.Hgt-ccgo.Hgt)/2;
}
// By width
else if (100*cgo.Hgt/Hgt<100*cgo.Wdt/Wdt)
{
ccgo.Wdt=Wdt*cgo.Hgt/Hgt;
ccgo.X+=(cgo.Wdt-ccgo.Wdt)/2;
}
}
pDraw->BlitUnscaled(Surface,
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
ccgo.Surface,ccgo.X,ccgo.Y,ccgo.Wdt,ccgo.Hgt,
true,pTransform);
}
void C4Facet::Draw(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, bool fTransparent)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Valid parameter check
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !cgo.Surface || !Wdt || !Hgt) return;
2009-05-08 13:28:41 +00:00
// Drawing area
C4Facet ccgo = cgo;
// Adjust for fixed aspect ratio (letterbox)
2009-05-08 13:28:41 +00:00
if (fAspect)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// By height
if (cgo.Wdt / Wdt < cgo.Hgt / Hgt)
2010-03-28 18:58:01 +00:00
{
ccgo.Hgt = Hgt * cgo.Wdt / Wdt;
ccgo.Y += (cgo.Hgt - ccgo.Hgt) / 2;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// By width
else if (cgo.Hgt / Hgt < cgo.Wdt / Wdt)
2010-03-28 18:58:01 +00:00
{
ccgo.Wdt = Wdt * cgo.Hgt / Hgt;
ccgo.X += (cgo.Wdt - ccgo.Wdt) / 2;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Blit
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
ccgo.Surface,
ccgo.X,ccgo.Y,ccgo.Wdt,ccgo.Hgt,
fTransparent);
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawFullScreen(C4Facet &cgo)
2010-03-28 18:58:01 +00:00
{
// Valid parameter check
if (!pDraw || !Surface || !cgo.Surface || !Wdt || !Hgt) return;
// Drawing area
C4Facet ccgo = cgo;
2009-05-08 13:28:41 +00:00
// stretched fullscreen blit: make sure right and lower side are cleared, because this may be missed due to stretching
if (cgo.Wdt > Wdt+2 || cgo.Hgt > Wdt+2)
2010-03-28 18:58:01 +00:00
{
ccgo.X -= 1; ccgo.Y -= 1;
ccgo.Wdt += 2; ccgo.Hgt += 2;
}
// Adjust for fixed aspect ratio (crop)
// By height
if (cgo.Wdt / Wdt < cgo.Hgt / Hgt)
{
ccgo.Wdt = Wdt * cgo.Hgt / Hgt;
ccgo.X += (cgo.Wdt - ccgo.Wdt) / 2;
}
// By width
else if (cgo.Hgt / Hgt < cgo.Wdt / Wdt)
{
ccgo.Hgt = Hgt * cgo.Wdt / Wdt;
ccgo.Y += (cgo.Hgt - ccgo.Hgt) / 2;
2010-03-28 18:58:01 +00:00
}
// Blit
pDraw->Blit(Surface, X, Y, Wdt, Hgt, ccgo.Surface, ccgo.X, ccgo.Y, ccgo.Wdt, ccgo.Hgt);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawClr(C4Facet &cgo, bool fAspect, DWORD dwClr)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (!Surface) return;
// set ColorByOwner-color
Surface->SetClr(dwClr);
// draw
Draw(cgo, fAspect);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::DrawXClr(C4Surface * sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, DWORD dwClr)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set ColorByOwner-color
Surface->SetClr(dwClr);
// draw
DrawX(sfcTarget, iX, iY, iWdt, iHgt);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawValue2Clr(C4Facet &cgo, int32_t iValue1, int32_t iValue2, DWORD dwClr)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set ColorByOwner-color
Surface->SetClr(dwClr);
// draw
DrawValue2(cgo, iValue1, iValue2);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::DrawXR(C4Surface * sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iSectionX, int32_t iSectionY, int32_t r)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return;
C4BltTransform rot;
rot.SetRotate(r / 100.0f, (float) (iX+iX+iWdt)/2, (float) (iY+iY+iHgt)/2);
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iSectionX),float(Y+Hgt*iSectionY),float(Wdt),float(Hgt),
sfcTarget,
iX,iY,iWdt,iHgt,
true,&rot);
}
2009-05-08 13:28:41 +00:00
C4Facet C4Facet::TruncateSection(int32_t iAlign)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Facet fctResult; fctResult.Set(Surface,0,0,0,0);
// Calculate section size
int32_t iWdt=Wdt,iHgt=Hgt;
switch (iAlign & C4FCT_Alignment)
2010-03-28 18:58:01 +00:00
{
case C4FCT_Left: case C4FCT_Right:
iWdt=Hgt;
if (iAlign & C4FCT_Triple) iWdt*=3;
if (iAlign & C4FCT_Double) iWdt*=2;
if (iAlign & C4FCT_Half) iWdt/=2;
break;
case C4FCT_Top: case C4FCT_Bottom:
iHgt=Wdt;
if (iAlign & C4FCT_Triple) iHgt*=3;
if (iAlign & C4FCT_Double) iHgt*=2;
if (iAlign & C4FCT_Half) iHgt/=2;
break;
}
2009-05-08 13:28:41 +00:00
// Size safety
if ((iWdt>Wdt) || (iHgt>Hgt)) return fctResult;
// Truncate
switch (iAlign & C4FCT_Alignment)
2010-03-28 18:58:01 +00:00
{
case C4FCT_Left: fctResult.Set(Surface,X,Y,iWdt,iHgt); X+=iWdt; Wdt-=iWdt; break;
case C4FCT_Right: fctResult.Set(Surface,X+Wdt-iWdt,Y,iWdt,iHgt); Wdt-=iWdt; break;
case C4FCT_Top: fctResult.Set(Surface,X,Y,iWdt,iHgt); Y+=iHgt; Hgt-=iHgt; break;
case C4FCT_Bottom: fctResult.Set(Surface,X,Y+Hgt-iHgt,iWdt,iHgt); Hgt-=iHgt; break;
}
2009-05-08 13:28:41 +00:00
// Done
return fctResult;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Facet C4Facet::Truncate(int32_t iAlign, int32_t iSize)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Facet fctResult; fctResult.Set(Surface,0,0,0,0);
// Calculate section size
int32_t iWdt=Wdt,iHgt=Hgt;
switch (iAlign)
2010-03-28 18:58:01 +00:00
{
case C4FCT_Left: case C4FCT_Right: iWdt=iSize; break;
case C4FCT_Top: case C4FCT_Bottom: iHgt=iSize; break;
}
2009-05-08 13:28:41 +00:00
// Size safety
if ((iWdt>Wdt) || (iHgt>Hgt)) return fctResult;
// Truncate
switch (iAlign)
2010-03-28 18:58:01 +00:00
{
case C4FCT_Left: fctResult.Set(Surface,X,Y,iWdt,iHgt); X+=iWdt; Wdt-=iWdt; break;
case C4FCT_Right: fctResult.Set(Surface,X+Wdt-iWdt,Y,iWdt,iHgt); Wdt-=iWdt; break;
case C4FCT_Top: fctResult.Set(Surface,X,Y,iWdt,iHgt); Y+=iHgt; Hgt-=iHgt; break;
case C4FCT_Bottom: fctResult.Set(Surface,X,Y+Hgt-iHgt,iWdt,iHgt); Hgt-=iHgt; break;
}
2009-05-08 13:28:41 +00:00
// Done
return fctResult;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawValue(C4Facet &cgo, int32_t iValue, int32_t iSectionX, int32_t iSectionY, int32_t iAlign)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw) return;
2009-05-08 13:28:41 +00:00
char ostr[25]; sprintf(ostr,"%i",iValue);
switch (iAlign)
2010-03-28 18:58:01 +00:00
{
case C4FCT_Center:
Draw(cgo, true, iSectionX, iSectionY);
2011-10-03 14:30:18 +00:00
pDraw->TextOut(ostr, ::GraphicsResource.FontRegular, 1.0, cgo.Surface,
2011-10-03 14:34:08 +00:00
cgo.X + cgo.Wdt - 1, cgo.Y + cgo.Hgt - 1, C4Draw::DEFAULT_MESSAGE_COLOR, ARight);
2010-03-28 18:58:01 +00:00
break;
case C4FCT_Right:
{
int32_t textwdt, texthgt;
::GraphicsResource.FontRegular.GetTextExtent(ostr, textwdt, texthgt, false);
2011-10-03 14:30:18 +00:00
pDraw->TextOut(ostr, ::GraphicsResource.FontRegular, 1.0, cgo.Surface,
2011-10-03 14:34:08 +00:00
cgo.X + cgo.Wdt - 1, cgo.Y, C4Draw::DEFAULT_MESSAGE_COLOR, ARight);
2010-03-28 18:58:01 +00:00
cgo.Set(cgo.Surface, cgo.X + cgo.Wdt - 1 - textwdt - 2 * cgo.Hgt, cgo.Y, 2 * cgo.Hgt, cgo.Hgt);
Draw(cgo, true, iSectionX, iSectionY);
break;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawValue2(C4Facet &cgo, int32_t iValue1, int32_t iValue2, int32_t iSectionX, int32_t iSectionY, int32_t iAlign, int32_t *piUsedWidth)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw) return;
2009-05-08 13:28:41 +00:00
char ostr[25]; sprintf(ostr,"%i/%i",iValue1,iValue2);
switch (iAlign)
2010-03-28 18:58:01 +00:00
{
case C4FCT_Center:
Draw(cgo, true, iSectionX, iSectionY);
2011-10-03 14:30:18 +00:00
pDraw->TextOut(ostr, ::GraphicsResource.FontRegular, 1.0, cgo.Surface,
2011-10-03 14:34:08 +00:00
cgo.X + cgo.Wdt - 1, cgo.Y + cgo.Hgt - 1, C4Draw::DEFAULT_MESSAGE_COLOR, ARight);
2010-03-28 18:58:01 +00:00
break;
case C4FCT_Right:
{
int32_t textwdt, texthgt;
::GraphicsResource.FontRegular.GetTextExtent(ostr, textwdt, texthgt, false);
textwdt += Wdt + 3;
2011-10-03 14:30:18 +00:00
pDraw->TextOut(ostr, ::GraphicsResource.FontRegular, 1.0, cgo.Surface,
2011-10-03 14:34:08 +00:00
cgo.X + cgo.Wdt - 1, cgo.Y, C4Draw::DEFAULT_MESSAGE_COLOR, ARight);
2010-03-28 18:58:01 +00:00
cgo.Set(cgo.Surface, cgo.X + cgo.Wdt - textwdt, cgo.Y, 2 * cgo.Hgt, cgo.Hgt);
Draw(cgo, true, iSectionX, iSectionY);
if (piUsedWidth) *piUsedWidth = textwdt;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
break;
}
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::DrawX(C4Surface * sfcTarget, float iX, float iY, float iWdt, float iHgt, int32_t iSectionX, int32_t iSectionY) const
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return;
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iSectionX),float(Y+Hgt*iSectionY),float(Wdt),float(Hgt),
sfcTarget,
iX,iY,iWdt,iHgt,
true);
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::DrawXFloat(C4Surface * sfcTarget, float fX, float fY, float fWdt, float fHgt) const
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt || fWdt<=0 || fHgt<=0) return;
2009-05-08 13:28:41 +00:00
// Since only source coordinates are available as floats for blitting, go inwards into this facet to match blit
// for closest integer target coordinates
float zx = fWdt / float(Wdt), zy = fHgt / float(Hgt);
int32_t iX = (int32_t) ceilf(fX), iY = (int32_t) ceilf(fY), iX2 = (int32_t) floorf(fX+fWdt), iY2 = (int32_t) floorf(fY+fHgt);
float ox = (-fX+iX)/zx, oy = (-fY+iY)/zy;
float oxs = (+fX+fWdt-iX2)/zx, oys = (+fY+fHgt-iY2)/zy;
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X)+ox, float(Y)+oy, float(Wdt)-ox-oxs, float(Hgt)-oy-oys,
sfcTarget,
iX,iY,iX2-iX,iY2-iY,
true);
2009-05-08 13:28:41 +00:00
zx=(iX2-iX)/(float(Wdt)-ox-oxs);
zy=(iY2-iY)/(float(Hgt)-oy-oys);
2010-03-28 18:58:01 +00:00
/* int32_t iX = floorf(fX+0.5)-1, iY = floorf(fY+0.5)-1, iX2 = floorf(fX+fWdt+0.5)-1, iY2 = floorf(fY+fHgt+0.5)-1;
2011-10-03 14:30:18 +00:00
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
X, Y, Wdt, Hgt,
sfcTarget,
iX,iY,iX2-iX+1,iY2-iY+1,
true);*/
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void C4Facet::DrawXT(C4Surface * sfcTarget, float iX, float iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return;
pDraw->Blit(Surface,
2010-03-28 18:58:01 +00:00
float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt),
sfcTarget,
iX,iY,iWdt,iHgt,
true, pTransform);
}
2009-05-08 13:28:41 +00:00
void C4Facet::DrawEnergyLevelEx(int32_t iLevel, int32_t iRange, const C4Facet &gfx, int32_t bar_idx)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// draw energy level using graphics
2011-10-03 14:30:18 +00:00
if (!pDraw || !gfx.Surface) return;
2009-05-08 13:28:41 +00:00
int32_t h=gfx.Hgt;
int32_t yBar = Hgt - Clamp<int32_t>(iLevel,0,iRange) * Hgt / std::max<int32_t>(iRange,1);
2009-05-08 13:28:41 +00:00
int32_t iY = 0, vidx=0;
C4Facet gfx_draw = gfx;
bool filled = false;
while (iY < Hgt)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t dy = iY % h;
int32_t dh = (iY >= Hgt-h) ? Hgt - iY : h - dy;
if (!filled)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (iY >= yBar)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
filled = true; // fully filled
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if (iY + h >= yBar)
dh = yBar - iY; // partially filled
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if (!vidx && iY && iY + dh > h)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (iY < h)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// had a break within top section of bar; finish top section
dh = h - iY;
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
// top section finished
++vidx;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if (iY + dh >= Hgt - h)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (iY >= Hgt - h)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// within bottom section
vidx = 2;
dy = iY + h - Hgt;
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
// finish middle section
dh = Hgt - h - iY;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// draw it; partially if necessary
gfx_draw.Y = gfx.Y + vidx*h + dy;
gfx_draw.Hgt = dh;
gfx_draw.Draw(Surface, X, Y+iY, bar_idx+bar_idx+!filled);
iY += dh;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Facet::Set(C4Surface &rSfc)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Set(&rSfc,0,0,rSfc.Wdt,rSfc.Hgt);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Facet::Expand(int32_t iLeft, int32_t iRight, int32_t iTop, int32_t iBottom)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
X-=iLeft; Wdt+=iLeft;
Wdt+=iRight;
Y-=iTop; Hgt+=iTop;
Hgt+=iBottom;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Facet::GetPhaseNum(int32_t &rX, int32_t &rY)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
if (!Surface) return false;
// newgfx: use locally stored size
rX=Surface->Wdt/Wdt; rY=Surface->Hgt/Hgt;
// success
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4DrawTransform::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
bool fCompiler = pComp->isCompiler();
int i;
// hacky. StdCompiler doesn't allow floats to be safed directly.
2010-03-28 18:58:01 +00:00
for (i = 0; i < 6; i++)
{
2010-04-01 21:08:06 +00:00
if (i) pComp->Separator();
2009-05-08 13:28:41 +00:00
StdStrBuf val;
2010-03-28 18:58:01 +00:00
if (!fCompiler)
{
2009-05-08 13:28:41 +00:00
#ifdef WITH_GLIB
val.SetLength(G_ASCII_DTOSTR_BUF_SIZE);
// g_ascii_dtostr is locale-independent which printf is not.
g_ascii_dtostr(val.getMData(), G_ASCII_DTOSTR_BUF_SIZE, mat[i]);
#else
val.Format("%g", mat[i]);
#endif
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
pComp->Value(mkParAdapt(val, StdCompiler::RCT_Idtf));
2010-03-28 18:58:01 +00:00
if (fCompiler && pComp->hasNaming())
2010-04-01 21:08:06 +00:00
if (pComp->Separator(StdCompiler::SEP_PART))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdStrBuf val2;
pComp->Value(mkParAdapt(val2, StdCompiler::RCT_Idtf));
val.AppendChar('.'); val.Append(val2);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
#ifdef WITH_GLIB
mat[i] = g_ascii_strtod (val.getData(), nullptr);
2009-05-08 13:28:41 +00:00
#else
2010-03-28 18:58:01 +00:00
if (fCompiler) sscanf(val.getData(), "%g", &mat[i]);
2009-05-08 13:28:41 +00:00
#endif
2010-03-28 18:58:01 +00:00
}
2010-04-01 21:08:06 +00:00
pComp->Separator();
2009-05-08 13:28:41 +00:00
pComp->Value(FlipDir);
2010-03-28 18:58:01 +00:00
if (!fCompiler && mat[6] == 0 && mat[7] == 0 && mat[8] == 1) return;
2009-05-08 13:28:41 +00:00
// because of backwards-compatibility, the last row comes after flipdir
2010-03-28 18:58:01 +00:00
for (i = 6; i < 9; ++i)
{
2010-04-01 21:08:06 +00:00
if (!pComp->Separator())
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
mat[i] = (i == 8) ? 1.0f : 0.0f;
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
{
StdStrBuf val; if (!fCompiler) val.Format("%g", mat[i]);
2009-05-08 13:28:41 +00:00
pComp->Value(mkParAdapt(val, StdCompiler::RCT_Idtf));
2010-03-28 18:58:01 +00:00
if (fCompiler && pComp->hasNaming())
2010-04-01 21:08:06 +00:00
if (pComp->Separator(StdCompiler::SEP_PART))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdStrBuf val2;
pComp->Value(mkParAdapt(val2, StdCompiler::RCT_Idtf));
val.AppendChar('.'); val.Append(val2);
2010-03-28 18:58:01 +00:00
}
if (fCompiler) sscanf(val.getData(), "%g", &mat[i]);
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4DrawTransform::SetTransformAt(C4DrawTransform &r, float iOffX, float iOffY)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Set matrix, so that r*(x,y,1)-(x,y,1)==this*(x+iOffX,y+iOffY,1)-(x+iOffX,y+iOffY,1)
float A = r.mat[0] + r.mat[6]*iOffX;
float B = r.mat[1] + r.mat[7]*iOffX;
float D = r.mat[3] + r.mat[6]*iOffY;
float E = r.mat[4] + r.mat[7]*iOffY;
C4BltTransform::Set(
2010-03-28 18:58:01 +00:00
A, B, r.mat[2] - A *iOffX - B *iOffY + r.mat[8]*iOffX,
D, E, r.mat[5] - D *iOffX - E *iOffY + r.mat[8]*iOffY,
r.mat[6], r.mat[7], r.mat[8] - r.mat[6]*iOffX - r.mat[7]*iOffY);
}
2009-05-08 13:28:41 +00:00
C4Facet C4Facet::GetFraction(int32_t percentWdt, int32_t percentHgt, int32_t alignX, int32_t alignY)
{
C4Facet rval;
// Simple spec for square fractions
if (percentHgt == 0) percentHgt = percentWdt;
// Alignment
int iX = X, iY = Y, iWdt = std::max(Wdt*percentWdt/100, 1.0f), iHgt = std::max(Hgt*percentHgt/100, 1.0f);
2010-03-28 18:58:01 +00:00
if (alignX & C4FCT_Right) iX += Wdt - iWdt;
if (alignX & C4FCT_Center) iX += Wdt/2 - iWdt/2;
2009-05-08 13:28:41 +00:00
if (alignY & C4FCT_Bottom) iY += Hgt - iHgt;
2010-03-28 18:58:01 +00:00
if (alignY & C4FCT_Center) iY += Hgt/2 - iHgt/2;
2009-05-08 13:28:41 +00:00
// Set resulting facet
rval.Set(Surface, iX, iY, iWdt, iHgt);
return rval;
}