- Applied Tesseract's patch for drawimage extensions. (Extended icon support and maximum width/height.)

This commit is contained in:
Braden Obrzut 2013-09-21 12:46:19 -04:00
parent 625883cb0c
commit f73275ad88
4 changed files with 188 additions and 49 deletions

View File

@ -444,6 +444,20 @@ void ST_LoadCrosshair(bool alwaysload=false);
void ST_Clear(); void ST_Clear();
extern FTexture *CrosshairImage; extern FTexture *CrosshairImage;
FTextureID GetWeaponIcon(AWeapon *weapon); FTextureID GetInventoryIcon(AInventory *item, DWORD flags, bool *applyscale);
enum DI_Flags
{
DI_SKIPICON = 0x1,
DI_SKIPALTICON = 0x2,
DI_SKIPSPAWN = 0x4,
DI_SKIPREADY = 0x8,
DI_ALTICONFIRST = 0x10,
DI_DRAWINBOX = 0x20, // Set when either width or height is not zero
DI_FORCESCALE = 0x40,
DI_ALTERNATEONFAIL = 0x80
};
#endif /* __SBAR_H__ */ #endif /* __SBAR_H__ */

View File

@ -1187,8 +1187,12 @@ public:
if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER) if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER)
{ {
dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble(); if (forceWidth < 0) dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble();
dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble(); else dx -= forceWidth*(0.5-(texture->GetScaledLeftOffsetDouble()/texture->GetScaledWidthDouble()));
//Unoptimalized formula is dx -= forceWidth/2.0-(texture->GetScaledLeftOffsetDouble()*forceWidth/texture->GetScaledWidthDouble());
if (forceHeight < 0) dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble();
else dy -= forceHeight*(0.5-(texture->GetScaledTopOffsetDouble()/texture->GetScaledHeightDouble()));
} }
dx += xOffset; dx += xOffset;

View File

@ -41,28 +41,65 @@
// classes. // classes.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandDrawImage : public SBarInfoCommandFlowControl
class CommandDrawImage : public SBarInfoCommand
{ {
public: public:
CommandDrawImage(SBarInfo *script) : SBarInfoCommand(script), CommandDrawImage(SBarInfo *script) : SBarInfoCommandFlowControl(script),
translatable(false), type(NORMAL_IMAGE), image(-1), offset(static_cast<Offset> (TOP|LEFT)), translatable(false), type(NORMAL_IMAGE), image(-1), maxwidth(-1),
maxheight(-1), spawnScaleX(1.0f), spawnScaleY(1.0f), flags(0),
applyscale(false), offset(static_cast<Offset> (TOP|LEFT)),
texture(NULL), alpha(FRACUNIT) texture(NULL), alpha(FRACUNIT)
{ {
} }
void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar)
{ {
if(flags & DI_ALTERNATEONFAIL)
SBarInfoCommandFlowControl::Draw(block, statusBar);
if(texture == NULL) if(texture == NULL)
return; return;
int w = maxwidth, h = maxheight;
// We must calculate this per frame in order to prevent glitches with cl_capfps true. // We must calculate this per frame in order to prevent glitches with cl_capfps true.
fixed_t frameAlpha = block->Alpha(); fixed_t frameAlpha = block->Alpha();
if(alpha != FRACUNIT) if(alpha != FRACUNIT)
frameAlpha = fixed_t(((double) block->Alpha() / (double) FRACUNIT) * ((double) alpha / (double) OPAQUE) * FRACUNIT); frameAlpha = fixed_t(((double) block->Alpha() / (double) FRACUNIT) * ((double) alpha / (double) OPAQUE) * FRACUNIT);
if(flags & DI_DRAWINBOX)
{
double scale1, scale2;
scale1 = scale2 = 1.0f;
double texwidth = (int) (texture->GetScaledWidthDouble()*spawnScaleX);
double texheight = (int) (texture->GetScaledHeightDouble()*spawnScaleY);
if (w != -1 && (w<texwidth || (flags & DI_FORCESCALE)))
{
scale1 = w/texwidth;
}
if (h != -1 && (h<texheight || (flags & DI_FORCESCALE)))
{
scale2 = h/texheight;
}
if (flags & DI_FORCESCALE)
{
if (w == -1 || (h != -1 && scale2<scale1))
scale1=scale2;
}
else if (scale2<scale1) scale1=scale2;
w=(int)(texwidth*scale1);
h=(int)(texheight*scale1);
}
else if (applyscale)
{
w=(int) (texture->GetScaledWidthDouble()*spawnScaleX);
h=(int) (texture->GetScaledHeightDouble()*spawnScaleY);
}
statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), frameAlpha, block->FullScreenOffsets(), statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), frameAlpha, block->FullScreenOffsets(),
translatable, false, offset); translatable, false, offset, false, w, h);
} }
void Parse(FScanner &sc, bool fullScreenOffsets) void Parse(FScanner &sc, bool fullScreenOffsets)
{ {
@ -98,7 +135,7 @@ class CommandDrawImage : public SBarInfoCommand
type = HEXENARMOR_AMULET; type = HEXENARMOR_AMULET;
else else
{ {
sc.ScriptMessage("Unkown armor type: '%s'", sc.String); sc.ScriptMessage("Unknown armor type: '%s'", sc.String);
type = HEXENARMOR_ARMOR; type = HEXENARMOR_ARMOR;
} }
sc.MustGetToken(','); sc.MustGetToken(',');
@ -141,48 +178,90 @@ class CommandDrawImage : public SBarInfoCommand
offset = CENTER; offset = CENTER;
else if(sc.Compare("centerbottom")) else if(sc.Compare("centerbottom"))
offset = static_cast<Offset> (HMIDDLE|BOTTOM); offset = static_cast<Offset> (HMIDDLE|BOTTOM);
else else if(!sc.Compare("lefttop")) //That's already set
sc.ScriptError("'%s' is not a valid alignment.", sc.String); sc.ScriptError("'%s' is not a valid alignment.", sc.String);
} }
sc.MustGetToken(';'); if(sc.CheckToken(','))
{
sc.MustGetToken(TK_IntConst);
if((maxwidth = sc.Number) > 0)
flags |= DI_DRAWINBOX;
else
maxwidth = -1;
sc.MustGetToken(',');
sc.MustGetToken(TK_IntConst);
if ((maxheight = sc.Number) > 0)
flags |= DI_DRAWINBOX;
else
maxheight = -1;
}
if(sc.CheckToken(','))
{
while(sc.CheckToken(TK_Identifier))
{
if(sc.Compare("skipicon"))
flags |= DI_SKIPICON;
else if(sc.Compare("skipalticon"))
flags |= DI_SKIPALTICON;
else if(sc.Compare("skipspawn"))
flags |= DI_SKIPSPAWN;
else if(sc.Compare("skipready"))
flags |= DI_SKIPREADY;
else if(sc.Compare("alticonfirst"))
flags |= DI_ALTICONFIRST;
else if(sc.Compare("forcescale"))
{
if(flags & DI_DRAWINBOX)
flags |= DI_FORCESCALE;
}
else if(sc.Compare("alternateonfail"))
flags |= DI_ALTERNATEONFAIL;
else
sc.ScriptError("Unknown flag '%s'.", sc.String);
if(!sc.CheckToken('|') && !sc.CheckToken(',')) break;
}
}
if(flags & DI_ALTERNATEONFAIL)
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
else
sc.MustGetToken(';');
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged);
texture = NULL; texture = NULL;
alpha = FRACUNIT; alpha = FRACUNIT;
if (applyscale)
{
spawnScaleX = spawnScaleY = 1.0f;
applyscale = false;
}
if(type == PLAYERICON) if(type == PLAYERICON)
texture = TexMan[statusBar->CPlayer->mo->ScoreIcon]; texture = TexMan[statusBar->CPlayer->mo->ScoreIcon];
else if(type == AMMO1) else if(type == AMMO1)
{ {
if(statusBar->ammo1 != NULL) AAmmo *ammo = statusBar->ammo1;
texture = TexMan[statusBar->ammo1->Icon]; if(ammo != NULL)
GetIcon(ammo);
} }
else if(type == AMMO2) else if(type == AMMO2)
{ {
if(statusBar->ammo2 != NULL) AAmmo *ammo = statusBar->ammo2;
texture = TexMan[statusBar->ammo2->Icon]; if(ammo != NULL)
GetIcon(ammo);
} }
else if(type == ARMOR) else if(type == ARMOR)
{ {
if(statusBar->armor != NULL && statusBar->armor->Amount != 0) ABasicArmor *armor = statusBar->armor;
texture = TexMan(statusBar->armor->Icon); if(armor != NULL && armor->Amount != 0)
GetIcon(armor);
} }
else if(type == WEAPONICON) else if(type == WEAPONICON)
{ {
AWeapon *weapon = statusBar->CPlayer->ReadyWeapon; AWeapon *weapon = statusBar->CPlayer->ReadyWeapon;
if(weapon != NULL) if(weapon != NULL)
{ GetIcon(weapon);
FTextureID icon;
if (weapon->Icon.isValid())
{
icon = weapon->Icon;
}
else
{
icon = GetWeaponIcon(weapon);
}
texture = TexMan[icon];
}
} }
else if(type == SIGIL) else if(type == SIGIL)
{ {
@ -213,8 +292,26 @@ class CommandDrawImage : public SBarInfoCommand
texture = TexMan(statusBar->CPlayer->mo->InvSel->Icon); texture = TexMan(statusBar->CPlayer->mo->InvSel->Icon);
else if(image >= 0) else if(image >= 0)
texture = statusBar->Images[image]; texture = statusBar->Images[image];
if (flags & DI_ALTERNATEONFAIL)
{
SetTruth(texture == NULL || !(texture->GetID().isValid()), block, statusBar);
}
} }
protected: protected:
void GetIcon(AInventory *item)
{
FTextureID icon = GetInventoryIcon(item, flags, &applyscale);
if (applyscale)
{
spawnScaleX = FIXED2FLOAT(item->scaleX);
spawnScaleY = FIXED2FLOAT(item->scaleY);
}
texture = TexMan[icon];
}
enum ImageType enum ImageType
{ {
PLAYERICON, PLAYERICON,
@ -238,6 +335,12 @@ class CommandDrawImage : public SBarInfoCommand
ImageType type; ImageType type;
int image; int image;
FTextureID sprite; FTextureID sprite;
int maxwidth;
int maxheight;
double spawnScaleX;
double spawnScaleY;
DWORD flags;
bool applyscale; //Set remotely from from GetInventoryIcon when selected sprite comes from Spawn state
// I'm using imgx/imgy here so that I can inherit drawimage with drawnumber for some commands. // I'm using imgx/imgy here so that I can inherit drawimage with drawnumber for some commands.
SBarInfoCoordinate imgx; SBarInfoCoordinate imgx;
SBarInfoCoordinate imgy; SBarInfoCoordinate imgy;
@ -1479,11 +1582,11 @@ class CommandDrawMugShot : public SBarInfoCommand
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandDrawSelectedInventory : public SBarInfoCommandFlowControl, private CommandDrawImage, private CommandDrawNumber class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDrawNumber
{ {
public: public:
CommandDrawSelectedInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), CommandDrawSelectedInventory(SBarInfo *script) : CommandDrawImage(script),
CommandDrawImage(script), CommandDrawNumber(script), alternateOnEmpty(false), CommandDrawNumber(script), alternateOnEmpty(false),
artiflash(false), alwaysShowCounter(false) artiflash(false), alwaysShowCounter(false)
{ {
length = INT_MAX; // Counter size length = INT_MAX; // Counter size
@ -3011,7 +3114,7 @@ class CommandDrawGem : public SBarInfoCommand
else else
sc.ScriptError("Unknown drawgem flag '%s'.", sc.String); sc.ScriptError("Unknown drawgem flag '%s'.", sc.String);
if(!sc.CheckToken('|')) if(!sc.CheckToken('|'))
sc.MustGetToken(','); sc.MustGetToken(',');
} }
sc.MustGetToken(TK_StringConst); //chain sc.MustGetToken(TK_StringConst); //chain
chain = script->newImage(sc.String); chain = script->newImage(sc.String);

View File

@ -135,12 +135,12 @@ static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans
if (tex) if (tex)
{ {
int texwidth=tex->GetWidth(); double texwidth=tex->GetScaledWidthDouble();
int texheight=tex->GetHeight(); double texheight=tex->GetScaledHeightDouble();
if (w<texwidth) scale1=(double)w/texwidth; if (w<texwidth) scale1=w/texwidth;
else scale1=1.0f; else scale1=1.0f;
if (h<texheight) scale2=(double)h/texheight; if (h<texheight) scale2=h/texheight;
else scale2=1.0f; else scale2=1.0f;
if (scale2<scale1) scale1=scale2; if (scale2<scale1) scale1=scale2;
@ -606,22 +606,40 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
// Weapons List // Weapons List
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
FTextureID GetInventoryIcon(AInventory *item, DWORD flags, bool *applyscale=NULL) // This function is also used by SBARINFO
FTextureID GetWeaponIcon(AWeapon *weapon) // This function is also used by SBARINFO
{ {
FTextureID AltIcon = GetHUDIcon(weapon->GetClass()); FTextureID picnum, AltIcon = GetHUDIcon(item->GetClass());
FState * state=NULL, *ReadyState; FState * state=NULL, *ReadyState;
FTextureID picnum = !AltIcon.isNull()? AltIcon : weapon->Icon; picnum.SetNull();
if (flags & DI_ALTICONFIRST)
if (picnum.isNull())
{ {
if (weapon->SpawnState && weapon->SpawnState->sprite!=0) if (!(flags & DI_SKIPALTICON) && AltIcon.isValid())
picnum = AltIcon;
else if (!(flags & DI_SKIPICON))
picnum = item->Icon;
}
else
{
if (!(flags & DI_SKIPICON) && item->Icon.isValid())
picnum = item->Icon;
else if (!(flags & DI_SKIPALTICON))
picnum = AltIcon;
}
if (!picnum.isValid()) //isNull() is bad for checking, because picnum could be also invalid (-1)
{
if (!(flags & DI_SKIPSPAWN) && item->SpawnState && item->SpawnState->sprite!=0)
{ {
state = weapon->SpawnState; state = item->SpawnState;
if (applyscale != NULL && !(flags & DI_FORCESCALE))
{
*applyscale = true;
}
} }
// no spawn state - now try the ready state // no spawn state - now try the ready state if it's weapon
else if ((ReadyState = weapon->FindState(NAME_Ready)) && ReadyState->sprite!=0) else if (!(flags & DI_SKIPREADY) && item->GetClass()->IsDescendantOf(RUNTIME_CLASS(AWeapon)) && (ReadyState = item->FindState(NAME_Ready)) && ReadyState->sprite!=0)
{ {
state = ReadyState; state = ReadyState;
} }
@ -651,7 +669,7 @@ static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AWeapon * weapon)
if (weapon==CPlayer->ReadyWeapon || weapon==CPlayer->ReadyWeapon->SisterWeapon) trans=0xd999; if (weapon==CPlayer->ReadyWeapon || weapon==CPlayer->ReadyWeapon->SisterWeapon) trans=0xd999;
} }
FTextureID picnum = GetWeaponIcon(weapon); FTextureID picnum = GetInventoryIcon(weapon, DI_ALTICONFIRST);
if (picnum.isValid()) if (picnum.isValid())
{ {