mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-27 22:42:57 +00:00
- implemented the status bar's DrawString function and ported the fullscreen HUD part of the Strife status bar to use the new functionality.
This commit is contained in:
parent
ac518e23bf
commit
6760e01a0d
5 changed files with 424 additions and 229 deletions
|
@ -1517,8 +1517,135 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d
|
|||
x -= static_cast<int> ((spacing)* cstring.Len()) / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t* str = (const uint8_t*)cstring.GetChars();
|
||||
const EColorRange boldTranslation = EColorRange(translation ? translation - 1 : NumTextColors - 1);
|
||||
int fontcolor = translation;
|
||||
double orgx = 0, orgy = 0;
|
||||
|
||||
if (fullscreenOffsets)
|
||||
{
|
||||
if (hud_scale)
|
||||
{
|
||||
shadowX *= (int)cleanScale.X;
|
||||
shadowY *= (int)cleanScale.Y;
|
||||
}
|
||||
|
||||
switch (screenalign & HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case HCENTER: orgx = screen->GetWidth() / 2; break;
|
||||
case RIGHT: orgx = screen->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (screenalign & VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case VCENTER: orgy = screen->GetHeight() / 2; break;
|
||||
case BOTTOM: orgy = screen->GetHeight(); break;
|
||||
}
|
||||
|
||||
if (screenalign == (RIGHT | TOP) && vid_fps) orgy += 10;
|
||||
}
|
||||
int ch;
|
||||
while (ch = *str++, ch != '\0')
|
||||
{
|
||||
if (ch == ' ')
|
||||
{
|
||||
x += monospaced ? spacing : font->GetSpaceWidth() + spacing;
|
||||
continue;
|
||||
}
|
||||
else if (ch == TEXTCOLOR_ESCAPE)
|
||||
{
|
||||
EColorRange newColor = V_ParseFontColor(str, translation, boldTranslation);
|
||||
if (newColor != CR_UNDEFINED)
|
||||
fontcolor = newColor;
|
||||
continue;
|
||||
}
|
||||
|
||||
int width;
|
||||
FTexture* c = font->GetChar((unsigned char)ch, &width);
|
||||
if (c == NULL) //missing character.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!monospaced) //If we are monospaced lets use the offset
|
||||
x += (c->LeftOffset + 1); //ignore x offsets since we adapt to character size
|
||||
|
||||
double rx, ry, rw, rh;
|
||||
rx = x + drawOffset.X;
|
||||
ry = y + drawOffset.Y;
|
||||
rw = c->GetScaledWidthDouble();
|
||||
rh = c->GetScaledHeightDouble();
|
||||
|
||||
if (monospaced)
|
||||
{
|
||||
// align the character in the monospaced cell according to the general alignment to ensure that it gets positioned properly
|
||||
// (i.e. right aligned text aligns to the right edge of the character and not the empty part of the cell.)
|
||||
switch (align)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case ALIGN_CENTER:
|
||||
rx -= (spacing) / 2;
|
||||
break;
|
||||
case ALIGN_RIGHT:
|
||||
rx -= spacing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
rx += ST_X;
|
||||
ry += ST_Y - (Scaled ? VerticalResolution : 200) + RelTop;
|
||||
if (Scaled)
|
||||
screen->VirtualToRealCoords(rx, ry, rw, rh, HorizontalResolution, VerticalResolution, true);
|
||||
else
|
||||
{
|
||||
ry += (200 - VerticalResolution);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hud_scale)
|
||||
{
|
||||
rx *= cleanScale.X;
|
||||
ry *= cleanScale.Y;
|
||||
rw *= cleanScale.X;
|
||||
rh *= cleanScale.Y;
|
||||
}
|
||||
rx += orgx;
|
||||
ry += orgy;
|
||||
}
|
||||
// This is not really such a great way to draw shadows because they can overlap with previously drawn characters.
|
||||
// This may have to be changed to draw the shadow text up front separately.
|
||||
if (shadowX != 0 || shadowY != 0)
|
||||
{
|
||||
screen->DrawChar(font, CR_UNTRANSLATED, rx + shadowX, ry + shadowY, ch,
|
||||
DTA_DestWidthF, rw,
|
||||
DTA_DestHeightF, rh,
|
||||
DTA_Alpha, (Alpha * HR_SHADOW),
|
||||
DTA_FillColor, 0,
|
||||
TAG_DONE);
|
||||
}
|
||||
screen->DrawChar(font, fontcolor, rx, ry, ch,
|
||||
DTA_DestWidthF, rw,
|
||||
DTA_DestHeightF, rh,
|
||||
DTA_Alpha, Alpha,
|
||||
TAG_DONE);
|
||||
|
||||
if (!monospaced)
|
||||
x += width + spacing - (c->LeftOffset + 1);
|
||||
else
|
||||
x += spacing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DBaseStatusBar);
|
||||
|
@ -1527,7 +1654,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString)
|
|||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(alpha);
|
||||
PARAM_BOOL(trans);
|
||||
PARAM_INT(trans);
|
||||
PARAM_INT(ialign);
|
||||
PARAM_INT(salign);
|
||||
PARAM_INT_DEF(spacing);
|
||||
|
@ -1636,3 +1763,46 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetGlobalACSArrayString)
|
|||
PARAM_INT(index);
|
||||
ACTION_RETURN_STRING(FBehavior::StaticLookupString(ACS_GlobalArrays[arrayno][index]));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetGlobalACSValue)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(index);
|
||||
ACTION_RETURN_INT(ACS_GlobalVars[index]);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetGlobalACSArrayValue)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(arrayno);
|
||||
PARAM_INT(index);
|
||||
ACTION_RETURN_INT(ACS_GlobalArrays[arrayno][index]);
|
||||
}
|
||||
|
||||
enum ENumFlags
|
||||
{
|
||||
FNF_FILLZEROS,
|
||||
FNF_WHENNOTZERO,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DBaseStatusBar, FormatNumber)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(number);
|
||||
PARAM_INT(minsize);
|
||||
PARAM_INT(maxsize);
|
||||
PARAM_INT(flags);
|
||||
PARAM_STRING_DEF(prefix);
|
||||
static int maxvals[] = { 1, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999 };
|
||||
|
||||
if (number == 0 && (flags & FNF_WHENNOTZERO)) ACTION_RETURN_STRING("");
|
||||
if (maxsize > 0 && maxsize < 10)
|
||||
{
|
||||
number = clamp(number, -maxvals[maxsize - 1], maxvals[maxsize]);
|
||||
}
|
||||
FString fmt;
|
||||
if (minsize <= 1) fmt.Format("%s%d", prefix.GetChars(), number);
|
||||
else if (flags & FNF_FILLZEROS) fmt.Format("%s%0*d", prefix.GetChars(), minsize, number);
|
||||
else fmt.Format("%s%*d", prefix.GetChars(), minsize, number);
|
||||
ACTION_RETURN_STRING(fmt);
|
||||
}
|
||||
|
|
|
@ -490,7 +490,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded)
|
|||
mSpriteU[1] = mSpriteV[1] = 1.f;
|
||||
|
||||
FTexture *basetex = (tx->bWarped && gl.legacyMode)? tx : tx->GetRedirect(false);
|
||||
// allow the redirect only if the textute is not expanded or the scale matches.
|
||||
// allow the redirect only if the texture is not expanded or the scale matches.
|
||||
if (!expanded || (tx->Scale.X == basetex->Scale.X && tx->Scale.Y == basetex->Scale.Y))
|
||||
{
|
||||
mBaseLayer = ValidateSysTexture(basetex, expanded);
|
||||
|
|
|
@ -61,6 +61,35 @@ INDEXFONT_DOOM
|
|||
9 STYSNUM9
|
||||
}
|
||||
|
||||
INDEXFONT_STRIFE_YELLOW
|
||||
{
|
||||
% INVFONY%
|
||||
0 INVFONY0
|
||||
1 INVFONY1
|
||||
2 INVFONY2
|
||||
3 INVFONY3
|
||||
4 INVFONY4
|
||||
5 INVFONY5
|
||||
6 INVFONY6
|
||||
7 INVFONY7
|
||||
8 INVFONY8
|
||||
9 INVFONY9
|
||||
}
|
||||
|
||||
INDEXFONT_STRIFE_GREEN
|
||||
{
|
||||
% INVFONG%
|
||||
0 INVFONG0
|
||||
1 INVFONG1
|
||||
2 INVFONG2
|
||||
3 INVFONG3
|
||||
4 INVFONG4
|
||||
5 INVFONG5
|
||||
6 INVFONG6
|
||||
7 INVFONG7
|
||||
8 INVFONG8
|
||||
9 INVFONG9
|
||||
}
|
||||
|
||||
// Doom and Chex intermissions use special text glyphs. The Raven and Strife
|
||||
// games just use the standard big font.
|
||||
|
|
|
@ -46,19 +46,24 @@ class BaseStatusBar native ui
|
|||
DI_SKIPREADY = 0x8,
|
||||
DI_ALTICONFIRST = 0x10,
|
||||
DI_TRANSLATABLE = 0x20,
|
||||
DI_FORCESCALE = 0x40
|
||||
DI_FORCESCALE = 0x40,
|
||||
DI_DIM = 0x80,
|
||||
};
|
||||
|
||||
enum IconType
|
||||
{
|
||||
PLAYERICON = 1000,
|
||||
AMMO1,
|
||||
AMMO2,
|
||||
ARMOR,
|
||||
WEAPONICON,
|
||||
SIGIL,
|
||||
WEAPONSLOT,
|
||||
SELECTEDINVENTORYICON,
|
||||
ITYPE_PLAYERICON = 1000,
|
||||
ITYPE_AMMO1,
|
||||
ITYPE_AMMO2,
|
||||
ITYPE_ARMOR,
|
||||
ITYPE_WEAPON,
|
||||
ITYPE_SIGIL,
|
||||
ITYPE_WEAPONSLOT,
|
||||
ITYPE_SELECTEDINVENTORY,
|
||||
}
|
||||
|
||||
enum HexArmorType
|
||||
{
|
||||
HEXENARMOR_ARMOR,
|
||||
HEXENARMOR_SHIELD,
|
||||
HEXENARMOR_HELM,
|
||||
|
@ -67,35 +72,36 @@ class BaseStatusBar native ui
|
|||
|
||||
enum EAlign
|
||||
{
|
||||
TOP = 0,
|
||||
VCENTER = 1,
|
||||
BOTTOM = 2,
|
||||
VOFFSET = 3,
|
||||
VMASK = 3,
|
||||
ALIGN_TOP = 0,
|
||||
ALIGN_VCENTER = 1,
|
||||
ALIGN_BOTTOM = 2,
|
||||
ALIGN_VOFFSET = 3,
|
||||
ALIGN_VMASK = 3,
|
||||
|
||||
LEFT = 0,
|
||||
HCENTER = 4,
|
||||
RIGHT = 8,
|
||||
HOFFSET = 12,
|
||||
HMASK = 12,
|
||||
ALIGN_LEFT = 0,
|
||||
ALIGN_HCENTER = 4,
|
||||
ALIGN_RIGHT = 8,
|
||||
ALIGN_HOFFSET = 12,
|
||||
ALIGN_HMASK = 12,
|
||||
|
||||
CENTER = VCENTER|HCENTER,
|
||||
CENTER_BOTTOM = BOTTOM|HCENTER
|
||||
ALIGN_CENTER = ALIGN_VCENTER|ALIGN_HCENTER,
|
||||
ALIGN_CENTER_BOTTOM = ALIGN_BOTTOM|ALIGN_HCENTER,
|
||||
ALIGN_OFFSETS = ALIGN_HOFFSET|ALIGN_VOFFSET
|
||||
};
|
||||
|
||||
enum ETextAlign
|
||||
{
|
||||
ALIGN_LEFT = 0,
|
||||
ALIGN_CENTER = 1,
|
||||
ALIGN_RIGHT = 2
|
||||
TEXT_LEFT = 0,
|
||||
TEXT_CENTER = 1,
|
||||
TEXT_RIGHT = 2
|
||||
};
|
||||
|
||||
enum SBGameModes
|
||||
{
|
||||
SINGLEPLAYER = 0x1,
|
||||
COOPERATIVE = 0x2,
|
||||
DEATHMATCH = 0x4,
|
||||
TEAMGAME = 0x8
|
||||
GAMEMODE_SINGLEPLAYER = 0x1,
|
||||
GAMEMODE_COOPERATIVE = 0x2,
|
||||
GAMEMODE_DEATHMATCH = 0x4,
|
||||
GAMEMODE_TEAMGAME = 0x8
|
||||
};
|
||||
|
||||
enum AmmoModes
|
||||
|
@ -112,6 +118,12 @@ class BaseStatusBar native ui
|
|||
HUD_HorizCenter
|
||||
}
|
||||
|
||||
enum ENumFlags
|
||||
{
|
||||
FNF_FILLZEROS,
|
||||
FNF_WHENNOTZERO,
|
||||
}
|
||||
|
||||
const XHAIRSHRINKSIZE =(1./18);
|
||||
const XHAIRPICKUPSIZE = (2+XHAIRSHRINKSIZE);
|
||||
|
||||
|
@ -154,11 +166,13 @@ class BaseStatusBar native ui
|
|||
virtual void SetMugShotState (String state_name, bool wait_till_done=false, bool reset=false) {}
|
||||
|
||||
native void RefreshBackground () const;
|
||||
|
||||
// These functions are kept native solely for performance reasons. They get called repeatedly and can drag down performance easily if they get too slow.
|
||||
native Inventory ValidateInvFirst (int numVisible) const;
|
||||
native static TextureID, bool GetInventoryIcon(Inventory item, int flags);
|
||||
|
||||
native void DrawGraphic(TextureID texture, bool animate, Vector2 pos, double Alpha, bool translatable, bool dim, int imgAlign, int screenalign, bool alphamap, Vector2 box);
|
||||
native void DrawString(Font font, String string, Vector2 pos , double Alpha, int translation, int align, int screenalign, int spacing=0, bool monospaced = false, int shadowX=0, int shadowY=0, int wrapwidth = -1, int linespacing = 4);
|
||||
native static String FormatNumber(int number, int minsize, int maxsize, int format, String prefix = "");
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
@ -243,10 +257,74 @@ class BaseStatusBar native ui
|
|||
if (w == null) return "";
|
||||
return w.GetTag();
|
||||
}
|
||||
|
||||
|
||||
// These cannot be done in ZScript.
|
||||
native String GetGlobalACSString(int index);
|
||||
native String GetGlobalACSArrayString(int arrayno, int index);
|
||||
native int GetGlobalACSValue(int index);
|
||||
native int GetGlobalACSArrayValue(int arrayno, int index);
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Convenience functions to retrieve some numbers
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
int GetArmorAmount()
|
||||
{
|
||||
let armor = CPlayer.mo.FindInventory("BasicArmor");
|
||||
return armor? armor.Amount : 0;
|
||||
}
|
||||
|
||||
int GetMaxAmount(class<Inventory> item)
|
||||
{
|
||||
let it = CPlayer.mo.FindInventory(item);
|
||||
return it? it.MaxAmount : GetDefaultByType(item).MaxAmount;
|
||||
}
|
||||
|
||||
int GetArmorSavePercent()
|
||||
{
|
||||
double add = 0;
|
||||
let harmor = HexenArmor(CPlayer.mo.FindInventory("HexenArmor"));
|
||||
if(harmor != NULL)
|
||||
{
|
||||
add = harmor.Slots[0] + harmor.Slots[1] + harmor.Slots[2] + harmor.Slots[3] + harmor.Slots[4];
|
||||
}
|
||||
//Hexen counts basic armor also so we should too.
|
||||
let armor = BasicArmor(CPlayer.mo.FindInventory("BasicArmor"));
|
||||
if(armor != NULL)
|
||||
{
|
||||
add += armor.SavePercent * 100;
|
||||
}
|
||||
return int(add);
|
||||
}
|
||||
|
||||
// Note that this retrieves the value in tics, not seconds like the equivalent SBARINFO function.
|
||||
// The idea is to let the caller decide what to do with it instead of destroying accuracy here.
|
||||
int GetAirTime()
|
||||
{
|
||||
if(CPlayer.mo.waterlevel < 3)
|
||||
return level.airsupply;
|
||||
else
|
||||
return max(CPlayer.air_finished - level.time, 0);
|
||||
}
|
||||
|
||||
int GetSelectedInventoryAmount()
|
||||
{
|
||||
if(CPlayer.mo.InvSel != NULL) return CPlayer.mo.InvSel.Amount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetKeyCount()
|
||||
{
|
||||
int num = 0;
|
||||
for(Inventory item = CPlayer.mo.Inv;item != NULL;item = item.Inv)
|
||||
{
|
||||
if(item is "Key") num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// various checker functions, based on SBARINFOs condition nodes.
|
||||
|
@ -261,10 +339,10 @@ class BaseStatusBar native ui
|
|||
|
||||
bool CheckGameMode(int ValidModes)
|
||||
{
|
||||
return (!multiplayer && (ValidModes & SINGLEPLAYER)) ||
|
||||
(deathmatch && (ValidModes & DEATHMATCH)) ||
|
||||
(multiplayer && !deathmatch && (ValidModes & COOPERATIVE)) ||
|
||||
(teamplay && (ValidModes & TEAMGAME));
|
||||
return (!multiplayer && (ValidModes & GAMEMODE_SINGLEPLAYER)) ||
|
||||
(deathmatch && (ValidModes & GAMEMODE_DEATHMATCH)) ||
|
||||
(multiplayer && !deathmatch && (ValidModes & GAMEMODE_COOPERATIVE)) ||
|
||||
(teamplay && (ValidModes & GAMEMODE_TEAMGAME));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -436,7 +514,7 @@ class BaseStatusBar native ui
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void DrawTexture(TextureID texture, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0, Vector2 scale = (1., 1.) )
|
||||
void DrawTexture(TextureID texture, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0, Vector2 scale = (1., 1.) )
|
||||
{
|
||||
if (!texture.IsValid()) return; // nothing to draw
|
||||
|
||||
|
@ -467,13 +545,12 @@ class BaseStatusBar native ui
|
|||
else scale1 = min(scale1, scale2);
|
||||
|
||||
boxsize = texsize * scale1;
|
||||
screenAlign = TOP|LEFT; // anything else makes no sense here.
|
||||
}
|
||||
else
|
||||
{
|
||||
boxsize = texsize;
|
||||
}
|
||||
DrawGraphic(texture, animated, pos, Alpha, !!(flags & DI_TRANSLATABLE), false, itemAlign, screenAlign, false, boxsize);
|
||||
DrawGraphic(texture, animated, pos, Alpha, !!(flags & DI_TRANSLATABLE), !!(flags & DI_DIM), itemAlign, screenAlign, false, boxsize);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -482,7 +559,7 @@ class BaseStatusBar native ui
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void DrawImage(String imagename, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0, Vector2 scale = (1., 1.) )
|
||||
void DrawImage(String imagename, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0, Vector2 scale = (1., 1.) )
|
||||
{
|
||||
let tex = TexMan.CheckForTexture(imagename, TexMan.TYPE_MiscPatch);
|
||||
DrawTexture(tex, pos, animated, screenalign, alpha, boxsize, itemAlign, flags, scale);
|
||||
|
@ -494,36 +571,36 @@ class BaseStatusBar native ui
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void DrawIcon(int icontype, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0)
|
||||
void DrawIcon(int icontype, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0)
|
||||
{
|
||||
TextureID texture;
|
||||
Vector2 applyscale = (1, 1);
|
||||
Inventory atype1, atype2;
|
||||
switch (icontype)
|
||||
{
|
||||
case PLAYERICON:
|
||||
case ITYPE_PLAYERICON:
|
||||
texture = CPlayer.mo.ScoreIcon;
|
||||
break;
|
||||
|
||||
case AMMO1:
|
||||
case AMMO2:
|
||||
case ITYPE_AMMO1:
|
||||
case ITYPE_AMMO2:
|
||||
[atype1, atype2] = GetCurrentAmmo();
|
||||
[texture, applyscale] = GetIcon(icontype == AMMO1? atype1 : atype2, flags, true);
|
||||
[texture, applyscale] = GetIcon(icontype == ITYPE_AMMO1? atype1 : atype2, flags, true);
|
||||
break;
|
||||
|
||||
case ARMOR:
|
||||
case ITYPE_ARMOR:
|
||||
[texture, applyscale] = GetIcon(CPlayer.mo.FindInventory("BasicArmor"), flags, false);
|
||||
break;
|
||||
|
||||
case WEAPONICON:
|
||||
case ITYPE_WEAPON:
|
||||
[texture, applyscale] = GetIcon(CPlayer.ReadyWeapon, flags, false);
|
||||
break;
|
||||
|
||||
case SIGIL:
|
||||
case ITYPE_SIGIL:
|
||||
[texture, applyscale] = GetIcon(CPlayer.mo.FindInventory("Sigil"), flags, false);
|
||||
break;
|
||||
|
||||
case SELECTEDINVENTORYICON:
|
||||
case ITYPE_SELECTEDINVENTORY:
|
||||
if (CPlayer.mo.InvSel != NULL)
|
||||
texture = CPlayer.mo.InvSel.Icon;
|
||||
break;
|
||||
|
@ -537,7 +614,7 @@ class BaseStatusBar native ui
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void DrawHexenArmor(int armortype, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0)
|
||||
void DrawHexenArmor(int armortype, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0)
|
||||
{
|
||||
let harmor = HexenArmor(statusBar.CPlayer.mo.FindInventory("HexenArmor"));
|
||||
if (harmor != NULL)
|
||||
|
@ -561,7 +638,7 @@ class BaseStatusBar native ui
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void DrawInventoryIcon(class<Inventory> item, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0)
|
||||
void DrawInventoryIcon(class<Inventory> item, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0)
|
||||
{
|
||||
let texture = GetDefaultByType(item).Icon;
|
||||
if (texture.IsValid())
|
||||
|
@ -570,3 +647,82 @@ class BaseStatusBar native ui
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// a generic value interpolator for status bar elements that can change
|
||||
// gradually to their new value.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
class LinearValueInterpolator : Object
|
||||
{
|
||||
int mCurrentValue;
|
||||
int mMaxChange;
|
||||
|
||||
static LinearValueInterpolator Create(int startval, int maxchange)
|
||||
{
|
||||
let v = new("LinearValueInterpolator");
|
||||
v.mCurrentValue = startval;
|
||||
v.mMaxChange = maxchange;
|
||||
return v;
|
||||
}
|
||||
|
||||
// This must be called peroiodically in the status bar's Tick function.
|
||||
// Do not call this in the Draw function because that may skip some frames!
|
||||
void Update(int destvalue)
|
||||
{
|
||||
if (mCurrentValue > destvalue)
|
||||
{
|
||||
mCurrentValue = max(destvalue, mCurrentValue - mMaxChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentValue = min(destvalue, mCurrentValue + mMaxChange);
|
||||
}
|
||||
}
|
||||
|
||||
// This must be called in the draw function to retrieve the value for output.
|
||||
int GetValue()
|
||||
{
|
||||
return mCurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
class DynamicValueInterpolator : Object
|
||||
{
|
||||
int mCurrentValue;
|
||||
int mMinChange;
|
||||
double mChangeFactor;
|
||||
|
||||
|
||||
static DynamicValueInterpolator Create(int startval, double changefactor, int minchange)
|
||||
{
|
||||
let v = new("DynamicValueInterpolator");
|
||||
v.mCurrentValue = startval;
|
||||
v.mMinChange = minchange;
|
||||
v.mChangeFactor = changefactor;
|
||||
return v;
|
||||
}
|
||||
|
||||
// This must be called peroiodically in the status bar's Tick function.
|
||||
// Do not call this in the Draw function because that may skip some frames!
|
||||
void Update(int destvalue)
|
||||
{
|
||||
int diff = int(max(abs(destvalue - mCurrentValue) * mChangeFactor, mMinChange));
|
||||
if (mCurrentValue > destvalue)
|
||||
{
|
||||
mCurrentValue = max(destvalue, mCurrentValue - diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentValue = min(destvalue, mCurrentValue + diff);
|
||||
}
|
||||
}
|
||||
|
||||
// This must be called in the draw function to retrieve the value for output.
|
||||
int GetValue()
|
||||
{
|
||||
return mCurrentValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -371,15 +371,16 @@ class StrifeStatusBar : BaseStatusBar
|
|||
{
|
||||
fullscreenoffsets = true;
|
||||
// Draw health
|
||||
DrINumberOuter (CPlayer.health, 4, -10, false, 7);
|
||||
DrawTexture(Images[imgMEDI], (14, -17), false, 1.0, BOTTOM|LEFT, itemalign: BOTTOM|HCENTER);
|
||||
|
||||
DrawString("Indexfont_Strife_Green", FormatNumber(CPlayer.health, 3, 0, 0), (4, -10), 1., (CPlayer.health < CPlayer.mo.RunHealth)? Font.CR_BRICK : Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, 7, true, 1, 1);
|
||||
DrawTexture(Images[imgMEDI], (14, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER);
|
||||
|
||||
// Draw armor
|
||||
let armor = CPlayer.mo.FindInventory('BasicArmor');
|
||||
if (armor != NULL && armor.Amount != 0)
|
||||
{
|
||||
DrINumberOuter (armor.Amount, 35, -10, false, 7);
|
||||
DrawTexture(armor.Icon, (45, -17), false, 1.0, BOTTOM|LEFT, itemalign: BOTTOM|HCENTER);
|
||||
DrawString("Indexfont_Strife_Yellow", FormatNumber(armor.Amount, 3, 0, 0), (35, -10), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, 7, true, 1, 1);
|
||||
DrawTexture(armor.Icon, (45, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER);
|
||||
}
|
||||
|
||||
// Draw ammo
|
||||
|
@ -390,19 +391,19 @@ class StrifeStatusBar : BaseStatusBar
|
|||
if (ammo1 != NULL)
|
||||
{
|
||||
// Draw primary ammo in the bottom-right corner
|
||||
DrINumberOuter (ammo1.Amount, -23, -10, false, 7);
|
||||
DrawTexture(ammo1.Icon, (-14, -17), false, 1.0, BOTTOM|RIGHT, itemalign: BOTTOM|HCENTER);
|
||||
DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 0, 0), (-23, -10), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_BOTTOM, 7, true, 1, 1);
|
||||
DrawTexture(ammo1.Icon, (-14, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER);
|
||||
if (ammo2 != NULL && ammo1!=ammo2)
|
||||
{
|
||||
// Draw secondary ammo just above the primary ammo
|
||||
DrINumberOuter (ammo2.Amount, -23, -48, false, 7);
|
||||
DrawTexture(ammo1.Icon, (-14, -55), false, 1.0, BOTTOM|RIGHT, itemalign: BOTTOM|HCENTER);
|
||||
DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 0, 0), (-23, -48), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_BOTTOM, 7, true, 1, 1);
|
||||
DrawTexture(ammo1.Icon, (-14, -55), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER);
|
||||
}
|
||||
}
|
||||
|
||||
if (deathmatch)
|
||||
{ // Draw frags (in DM)
|
||||
DrBNumberOuterFont (CPlayer.fragcount, -44, 1);
|
||||
DrawString("BigFont", FormatNumber(CPlayer.FragCount, 3, 0, 0), (-44, 1), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_TOP, 0, false, 2, 2);
|
||||
}
|
||||
|
||||
// Draw inventory
|
||||
|
@ -412,18 +413,10 @@ class StrifeStatusBar : BaseStatusBar
|
|||
{
|
||||
if (ItemFlash > 0)
|
||||
{
|
||||
vector2 size = TexMan.GetScaledSize(Images[CursorImage]);
|
||||
screen.DrawTexture (Images[CursorImage], true, -28, -15,
|
||||
DTA_HUDRules, HUD_Normal,
|
||||
DTA_LeftOffsetF, size.X,
|
||||
DTA_TopOffsetF, size.Y,
|
||||
DTA_Alpha, ItemFlash);
|
||||
DrawTexture(Images[CursorImage], (-28, -15), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_RIGHT);
|
||||
}
|
||||
DrINumberOuter (CPlayer.mo.InvSel.Amount, -51, -10, false, 7);
|
||||
screen.DrawTexture (CPlayer.mo.InvSel.Icon, true, -42, -17,
|
||||
DTA_HUDRules, HUD_Normal,
|
||||
DTA_CenterBottomOffset, true,
|
||||
DTA_ColorOverlay, CPlayer.mo.InvSel.Amount > 0 ? 0 : Color(170, 0, 0, 0));
|
||||
DrawString("Indexfont_Strife_Yellow", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 5, 0), (-23, -10), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_BOTTOM|ALIGN_RIGHT, 7, true, 1, 1);
|
||||
DrawTexture(CPlayer.mo.InvSel.Icon, (-42, -17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_HCENTER, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -431,23 +424,20 @@ class StrifeStatusBar : BaseStatusBar
|
|||
CPlayer.mo.InvFirst = ValidateInvFirst (6);
|
||||
int i = 0;
|
||||
Inventory item;
|
||||
Vector2 box = TexMan.GetScaledSize(Images[CursorImage]) - (4, 4); // Fit oversized icons into the box.
|
||||
if (CPlayer.mo.InvFirst != NULL)
|
||||
{
|
||||
for (item = CPlayer.mo.InvFirst; item != NULL && i < 6; item = item.NextInv())
|
||||
{
|
||||
if (item == CPlayer.mo.InvSel)
|
||||
{
|
||||
screen.DrawTexture (Images[CursorImage], true, -100+i*35, -21,
|
||||
DTA_HUDRules, HUD_HorizCenter,
|
||||
DTA_Alpha, 0.75);
|
||||
DrawTexture(Images[CursorImage], (-90+i*35, -3), true, 0.75, ALIGN_CENTER_BOTTOM, ItemAlign:ALIGN_CENTER_BOTTOM);
|
||||
}
|
||||
if (item.Icon.isValid())
|
||||
{
|
||||
screen.DrawTexture (item.Icon, true, -94 + i*35, -19,
|
||||
DTA_HUDRules, HUD_HorizCenter,
|
||||
DTA_ColorOverlay, CPlayer.mo.InvSel.Amount > 0 ? 0 : Color(170, 0, 0, 0));
|
||||
DrawTexture(item.Icon, (-90+i*35, -5), true, 0.75, ALIGN_CENTER_BOTTOM, box, ALIGN_CENTER_BOTTOM, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM);
|
||||
}
|
||||
DrINumberOuter (item.Amount, -89 + i*35, -10, true, 7);
|
||||
DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (-65 + i*35, -8), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_CENTER_BOTTOM, 7, true, 1, 1);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -480,14 +470,8 @@ class StrifeStatusBar : BaseStatusBar
|
|||
{
|
||||
case POP_Log:
|
||||
{
|
||||
int seconds = Thinker.Tics2Seconds(level.time);
|
||||
// Draw the latest log message.
|
||||
buff = String.Format("%02d:%02d:%02d",
|
||||
seconds / 3600,
|
||||
(seconds % 3600) / 60,
|
||||
(seconds) % 60);
|
||||
|
||||
screen.DrawText(SmallFont2, Font.CR_UNTRANSLATED, left + 210 * xscale, top + 8 * yscale, buff,
|
||||
screen.DrawText(SmallFont2, Font.CR_UNTRANSLATED, left + 210 * xscale, top + 8 * yscale, Level.TimeFormatted(),
|
||||
DTA_CleanNoMove, true);
|
||||
|
||||
if (CPlayer.LogText.Length() > 0)
|
||||
|
@ -679,150 +663,6 @@ class StrifeStatusBar : BaseStatusBar
|
|||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC DrINumberOuter
|
||||
//
|
||||
// Draws a number outside the status bar, possibly scaled.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void DrINumberOuter(int val, int x, int y, bool center, int w) const
|
||||
{
|
||||
bool negative = false;
|
||||
|
||||
x += w * 2;
|
||||
if (val < 0)
|
||||
{
|
||||
negative = true;
|
||||
val = -val;
|
||||
}
|
||||
else if (val == 0)
|
||||
{
|
||||
screen.DrawTexture(Images[imgINumbers], true, x + 1, y + 1,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW,
|
||||
DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal);
|
||||
screen.DrawTexture(Images[imgINumbers], true, x, y,
|
||||
DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal);
|
||||
return;
|
||||
}
|
||||
|
||||
int oval = val;
|
||||
int ox = x;
|
||||
|
||||
// First the shadow
|
||||
while (val != 0)
|
||||
{
|
||||
screen.DrawTexture(Images[imgINumbers + val % 10], true, x + 1, y + 1,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW,
|
||||
DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal);
|
||||
x -= w;
|
||||
val /= 10;
|
||||
}
|
||||
if (negative)
|
||||
{
|
||||
screen.DrawTexture(Images[imgNEGATIVE], true, x + 1, y + 1,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW,
|
||||
DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal);
|
||||
}
|
||||
|
||||
// Then the real deal
|
||||
val = oval;
|
||||
x = ox;
|
||||
while (val != 0)
|
||||
{
|
||||
screen.DrawTexture(Images[imgINumbers + val % 10], true, x, y,
|
||||
DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal);
|
||||
x -= w;
|
||||
val /= 10;
|
||||
}
|
||||
if (negative)
|
||||
{
|
||||
screen.DrawTexture(Images[imgNEGATIVE], true, x, y,
|
||||
DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC DrBNumberOuter
|
||||
//
|
||||
// Draws a three digit number using the real big font outside the status bar.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void DrBNumberOuterFont(int val, int x, int y, int size = 3) const
|
||||
{
|
||||
int v;
|
||||
bool negative = false;
|
||||
TextureID pic;
|
||||
|
||||
int w = BigFont.GetCharWidth("0");
|
||||
int ww = w;
|
||||
|
||||
if (w > 1)
|
||||
{
|
||||
w--;
|
||||
}
|
||||
int xpos = x + w / 2 + (size - 1)*w;
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, "0",
|
||||
DTA_HUDRules, HUD_Normal,
|
||||
DTA_Alpha, HR_SHADOW,
|
||||
DTA_FillColor, 0);
|
||||
screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2, y, "0",
|
||||
DTA_HUDRules, HUD_Normal);
|
||||
return;
|
||||
}
|
||||
else if (val < 0)
|
||||
{
|
||||
negative = true;
|
||||
val = -val;
|
||||
}
|
||||
|
||||
int oval = val;
|
||||
int oxpos = xpos;
|
||||
|
||||
// First the shadow
|
||||
while (val != 0)
|
||||
{
|
||||
v = BigFont.GetCharWidth(int("0") + val % 10);
|
||||
screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2,
|
||||
DTA_HUDRules, HUD_Normal,
|
||||
DTA_Alpha, HR_SHADOW,
|
||||
DTA_FillColor, 0);
|
||||
val /= 10;
|
||||
xpos -= w;
|
||||
}
|
||||
if (negative)
|
||||
{
|
||||
v = BigFont.GetCharWidth("-");
|
||||
screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, "-",
|
||||
DTA_HUDRules, HUD_Normal,
|
||||
DTA_Alpha, HR_SHADOW,
|
||||
DTA_FillColor, 0);
|
||||
}
|
||||
|
||||
// Then the foreground number
|
||||
val = oval;
|
||||
xpos = oxpos;
|
||||
while (val != 0)
|
||||
{
|
||||
v = BigFont.GetCharWidth(int("0") + val % 10);
|
||||
screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2, y, "0", DTA_HUDRules, HUD_Normal);
|
||||
val /= 10;
|
||||
xpos -= w;
|
||||
}
|
||||
if (negative)
|
||||
{
|
||||
v = BigFont.GetCharWidth("-");
|
||||
screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2, y, "-", DTA_HUDRules, HUD_Normal);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC DrawImage
|
||||
|
|
Loading…
Reference in a new issue