- implemented the inventory bar. This object is a bit special because it requires a lot of parameters, most of which are easily set to defaults. To make handling easier, most are passed through a container object which does some processing up front.

- finished work on the Doom status bar. I also took the opportunity to fix the layout of the inventory bar which is a bit broken in SBARINFO.
- tuned the selection rules for deciding what creates the status bar, so that the most recent definition that can be found is chosen.
This commit is contained in:
Christoph Oelckers 2017-03-27 01:02:10 +02:00
parent e791c957d9
commit a112b29c43
7 changed files with 181 additions and 34 deletions

View file

@ -115,7 +115,7 @@ static FFont * IndexFont; // The font for the inventory indices
static FTexture * healthpic; // Health icon static FTexture * healthpic; // Health icon
static FTexture * berserkpic; // Berserk icon (Doom only) static FTexture * berserkpic; // Berserk icon (Doom only)
static FTexture * fragpic; // Frags icon static FTexture * fragpic; // Frags icon
static FTexture * invgems[4]; // Inventory arrows static FTexture * invgems[2]; // Inventory arrows
static int hudwidth, hudheight; // current width/height for HUD display static int hudwidth, hudheight; // current width/height for HUD display
static int statspace; static int statspace;
@ -816,7 +816,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y)
{ {
if(rover->PrevInv()) if(rover->PrevInv())
{ {
screen->DrawTexture(invgems[!!(level.time&4)], x-10, y, screen->DrawTexture(invgems[0], x-10, y,
DTA_KeepRatio, true, DTA_KeepRatio, true,
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE); DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE);
} }
@ -852,7 +852,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y)
} }
if(rover) if(rover)
{ {
screen->DrawTexture(invgems[2 + !!(level.time&4)], x-10, y, screen->DrawTexture(invgems[1], x-10, y,
DTA_KeepRatio, true, DTA_KeepRatio, true,
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE); DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE);
} }
@ -1279,9 +1279,7 @@ void HUD_InitHud()
if (IndexFont == NULL) IndexFont = ConFont; // Emergency fallback if (IndexFont == NULL) IndexFont = ConFont; // Emergency fallback
invgems[0] = TexMan.FindTexture("INVGEML1"); invgems[0] = TexMan.FindTexture("INVGEML1");
invgems[1] = TexMan.FindTexture("INVGEML2"); invgems[1] = TexMan.FindTexture("INVGEMR1");
invgems[2] = TexMan.FindTexture("INVGEMR1");
invgems[3] = TexMan.FindTexture("INVGEMR2");
fragpic = TexMan.FindTexture("HU_FRAGS"); // Sadly, I don't have anything usable for this. :( fragpic = TexMan.FindTexture("HU_FRAGS"); // Sadly, I don't have anything usable for this. :(

View file

@ -984,13 +984,13 @@ public:
"USEARTIA", "USEARTIB", "USEARTIC", "USEARTID", "USEARTIA", "USEARTIB", "USEARTIC", "USEARTID",
}; };
TArray<const char *> patchnames; TArray<const char *> patchnames;
patchnames.Resize(script->Images.Size()+10); patchnames.Resize(script->Images.Size()+9);
unsigned int i = 0; unsigned int i = 0;
for(i = 0;i < script->Images.Size();i++) for(i = 0;i < script->Images.Size();i++)
{ {
patchnames[i] = script->Images[i]; patchnames[i] = script->Images[i];
} }
for(i = 0;i < 10;i++) for(i = 0;i < 9;i++)
{ {
patchnames[i+script->Images.Size()] = InventoryBarLumps[i]; patchnames[i+script->Images.Size()] = InventoryBarLumps[i];
} }

View file

@ -243,7 +243,14 @@ void ST_CreateStatusBar(bool bTitleLevel)
StatusBar = new DBaseStatusBar(); StatusBar = new DBaseStatusBar();
StatusBar->SetSize(0); StatusBar->SetSize(0);
} }
else if (gameinfo.statusbarclassfile >= gameinfo.statusbarfile) else
{
// The old rule of 'what came last wins' goes here, as well.
// If the most recent SBARINFO definition comes before a status bar class definition it will be picked,
// if the class is defined later, this will be picked. If both come from the same file, the class definition will win.
int sbarinfolump = Wads.CheckNumForName("SBARINFO");
int sbarinfofile = Wads.GetLumpFile(sbarinfolump);
if (gameinfo.statusbarclassfile >= gameinfo.statusbarfile && gameinfo.statusbarclassfile >= sbarinfofile)
{ {
auto cls = PClass::FindClass(gameinfo.statusbarclass); auto cls = PClass::FindClass(gameinfo.statusbarclass);
if (cls != nullptr) if (cls != nullptr)
@ -256,6 +263,7 @@ void ST_CreateStatusBar(bool bTitleLevel)
} }
} }
} }
}
if (StatusBar == nullptr && SBarInfoScript[SCRIPT_CUSTOM] != nullptr) if (StatusBar == nullptr && SBarInfoScript[SCRIPT_CUSTOM] != nullptr)
{ {
int cstype = SBarInfoScript[SCRIPT_CUSTOM]->GetGameType(); int cstype = SBarInfoScript[SCRIPT_CUSTOM]->GetGameType();
@ -283,7 +291,6 @@ void ST_CreateStatusBar(bool bTitleLevel)
auto cls = PClass::FindClass(defname); auto cls = PClass::FindClass(defname);
if (cls != nullptr) if (cls != nullptr)
{ {
StatusBar = (DBaseStatusBar *)cls->CreateNew(); StatusBar = (DBaseStatusBar *)cls->CreateNew();
IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init) IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init)
{ {
@ -1605,8 +1612,8 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla
switch (flags & DI_ITEM_VMASK) switch (flags & DI_ITEM_VMASK)
{ {
case DI_ITEM_VCENTER: y -= texheight / 2; break; case DI_ITEM_VCENTER: y -= boxheight / 2; break;
case DI_ITEM_BOTTOM: y -= texheight; break; case DI_ITEM_BOTTOM: y -= boxheight; break;
case DI_ITEM_VOFFSET: y -= tex->GetScaledTopOffsetDouble() * boxheight / texheight; break; case DI_ITEM_VOFFSET: y -= tex->GetScaledTopOffsetDouble() * boxheight / texheight; break;
} }
@ -1732,6 +1739,8 @@ DEFINE_ACTION_FUNCTION(DHUDFont, Create)
ACTION_RETURN_POINTER(new DHUDFont(fnt, spac, mono, sy, sy)); ACTION_RETURN_POINTER(new DHUDFont(fnt, spac, mono, sy, sy));
} }
DEFINE_FIELD(DHUDFont, mFont);
//============================================================================ //============================================================================
// //
// draw a string // draw a string
@ -2039,3 +2048,4 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetMugshot)
auto tex = self->mugshot.GetFace(self->CPlayer, def_face, accuracy, (FMugShot::StateFlags)stateflags); auto tex = self->mugshot.GetFace(self->CPlayer, def_face, accuracy, (FMugShot::StateFlags)stateflags);
ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1); ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1);
} }

View file

@ -1045,6 +1045,12 @@ AInventory *AActor::FirstInv ()
return Inventory->NextInv (); return Inventory->NextInv ();
} }
DEFINE_ACTION_FUNCTION(AActor, FirstInv)
{
PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_OBJECT(self->FirstInv());
}
//============================================================================ //============================================================================
// //
// AActor :: UseInventory // AActor :: UseInventory

View file

@ -502,6 +502,7 @@ class Actor : Thinker native
native void SetShade(color col); native void SetShade(color col);
native clearscope int GetRenderStyle() const; native clearscope int GetRenderStyle() const;
native clearscope bool CheckKeys(int locknum, bool remote, bool quiet = false); native clearscope bool CheckKeys(int locknum, bool remote, bool quiet = false);
native clearscope Inventory FirstInv() const;
native clearscope string GetTag(string defstr = "") const; native clearscope string GetTag(string defstr = "") const;
native void SetTag(string defstr = ""); native void SetTag(string defstr = "");

View file

@ -2,7 +2,8 @@ class DoomStatusBar : BaseStatusBar
{ {
HUDFont mHUDFont; HUDFont mHUDFont;
HUDFont mIndexFont; HUDFont mIndexFont;
//DrawInventoryBarParms diparms; HUDFont mAmountFont;
InventoryBarState diparms;
override void Init() override void Init()
@ -10,19 +11,13 @@ class DoomStatusBar : BaseStatusBar
Super.Init(); Super.Init();
SetSize(32, 320, 200); SetSize(32, 320, 200);
// set up the inventory bar drawer.
/*
diparms.SetDefaults(HX_SHADOW);
diparms.SetTextures("SELECTBO", "ARTIBOX", "INVGEML1", "INVGEMR1");
diparms.SetLeftArrow("INVGEML1");
diparms.SetRightArrow("INVGEMR1");
*/
// Create the font used for the fullscreen HUD // Create the font used for the fullscreen HUD
Font fnt = "HUDFONT_DOOM"; Font fnt = "HUDFONT_DOOM";
mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 1, 1); mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 1, 1);
fnt = "INDEXFONT_DOOM"; fnt = "INDEXFONT_DOOM";
mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true); mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true);
mAmountFont = HUDFont.Create("INDEXFONT");
diparms = InventoryBarState.Create();
} }
override void NewGame () override void NewGame ()
@ -120,14 +115,23 @@ class DoomStatusBar : BaseStatusBar
DrawImage("STFBANY", (143, 0), DI_ITEM_OFFSETS|DI_TRANSLATABLE); DrawImage("STFBANY", (143, 0), DI_ITEM_OFFSETS|DI_TRANSLATABLE);
} }
if (CPlayer.mo.InvSel != null) if (CPlayer.mo.InvSel != null && !level.NoInventoryBar)
{ {
//drawinventorybar Doom, 7, INDEXFONT, 50, 170; DrawInventoryIcon(CPlayer.mo.InvSel, (160, 30));
if (CPlayer.mo.InvSel.Amount > 0)
{
DrawString(mAmountFont, FormatNumber(CPlayer.mo.InvSel.Amount), (175, 30-mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT, Font.CR_GOLD);
}
} }
else else
{ {
DrawTexture(GetMugShot(5), (143, 0), DI_ITEM_OFFSETS); DrawTexture(GetMugShot(5), (143, 0), DI_ITEM_OFFSETS);
} }
if (CPlayer.inventorytics != 0 && !level.NoInventoryBar)
{
DrawInventoryBar(diparms, (48, 1), 7, DI_ITEM_LEFT_TOP);
}
} }
protected void DrawFullScreenStuff () protected void DrawFullScreenStuff ()
@ -159,14 +163,14 @@ class DoomStatusBar : BaseStatusBar
DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT);
invY -= 20; invY -= 20;
} }
if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null) if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null && !level.NoInventoryBar)
{ {
DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17)); DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17));
DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT);
} }
if (deathmatch) if (deathmatch)
{ {
DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (-3, 1), DI_TEXT_ALIGN_RIGHT); DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (-3, 1), DI_TEXT_ALIGN_RIGHT, Font.CR_GOLD);
} }
// Draw the keys. This does not use a special draw function like SBARINFO because the specifics will be different for each mod // Draw the keys. This does not use a special draw function like SBARINFO because the specifics will be different for each mod
@ -191,9 +195,9 @@ class DoomStatusBar : BaseStatusBar
} }
} }
} }
if (CPlayer.inventorytics != 0) if (CPlayer.inventorytics != 0 && !level.NoInventoryBar)
{ {
//DrawInventoryBar(diparms, (0, 0), 7, ALIGN_CENTER_BOTTOM, ALIGN_CENTER_BOTTOM); DrawInventoryBar(diparms, (0, 0), 7, DI_SCREEN_CENTER_BOTTOM, HX_SHADOW);
} }
} }
} }

View file

@ -17,10 +17,57 @@ struct MugShot
class HUDFont native ui class HUDFont native ui
{ {
// This is intentionally opaque to the script side. native Font mFont;
native static HUDFont Create(Font fnt, int spacing = 0, bool monospaced = false, int shadowx = 0, int shadowy = 0); native static HUDFont Create(Font fnt, int spacing = 0, bool monospaced = false, int shadowx = 0, int shadowy = 0);
} }
class InventoryBarState ui
{
TextureID box;
TextureID selector;
Vector2 boxsize;
Vector2 innersize;
int boxframesize;
TextureID left;
TextureID right;
Vector2 arrowoffset;
double itemalpha;
HUDFont amountfont;
int cr;
int flags;
// The default settings here are what SBARINFO is using.
static InventoryBarState Create(HUDFont indexfont = null, int cr = Font.CR_UNTRANSLATED, double itemalpha = 1.,
String boxgfx = "ARTIBOX", String selgfx = "SELECTBO", int fsize = 2,
String leftgfx = "INVGEML1", String rightgfx = "INVGEMR1", Vector2 arrowoffs = (0, 0), int flags = 0)
{
let me = new ("InventoryBarState");
me.itemalpha = itemalpha;
me.box = TexMan.CheckForTexture(boxgfx, TexMan.TYPE_MiscPatch);
me.selector = TexMan.CheckForTexture(selgfx, TexMan.TYPE_MiscPatch);
me.boxframesize = fsize;
if (me.box.IsValid() || me.selector.IsValid()) me.boxsize = TexMan.GetScaledSize(me.box.IsValid()? me.box : me.selector);
else me.boxsize = (32., 32.);
me.innersize = me.boxsize - (2.*fsize, 2.*fsize);
me.left = TexMan.CheckForTexture(leftgfx, TexMan.TYPE_MiscPatch);
me.right = TexMan.CheckForTexture(rightgfx, TexMan.TYPE_MiscPatch);
me.arrowoffset = arrowoffs;
me.arrowoffset.Y += me.boxsize.Y/2; // default is centered to the side of the box.
if (indexfont == null)
{
me.amountfont = HUDFont.Create("INDEXFONT");
if (cr == Font.CR_UNTRANSLATED) cr = Font.CR_GOLD;
}
else me.amountfont = indexfont;
me.cr = cr;
me.flags = flags;
return me;
}
}
class BaseStatusBar native ui class BaseStatusBar native ui
{ {
@ -130,6 +177,7 @@ class BaseStatusBar native ui
DI_ALPHAMAPPED = 0x2000000, DI_ALPHAMAPPED = 0x2000000,
DI_NOSHADOW = 0x4000000, DI_NOSHADOW = 0x4000000,
DI_ALWAYSSHOWCOUNTERS = 0x8000000,
}; };
enum IconType enum IconType
@ -630,6 +678,86 @@ class BaseStatusBar native ui
} }
} }
//============================================================================
//
// DrawInventoryBar
//
// This function needs too many parameters, so most have been offloaded to
// a struct to keep code readable and allow initialization somewhere outside
// the actual drawing code.
//
//============================================================================
// Except for the placement information this gets all info from the struct that gets passed in.
void DrawInventoryBar(InventoryBarState parms, Vector2 position, int numfields, int flags = 0, double bgalpha = 1.)
{
double width = parms.boxsize.X * numfields;
// This must be done here, before altered coordinates get sent to the draw functions.
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
{
if (position.x < 0) flags |= DI_SCREEN_RIGHT;
else flags |= DI_SCREEN_LEFT;
if (position.y < 0) flags |= DI_SCREEN_BOTTOM;
else flags |= DI_SCREEN_TOP;
}
// placement by offset is not supported because the inventory bar is a composite.
switch (flags & DI_ITEM_HMASK)
{
case DI_ITEM_HCENTER: position.x -= width / 2; break;
case DI_ITEM_RIGHT: position.x -= width; break;
}
switch (flags & DI_ITEM_VMASK)
{
case DI_ITEM_VCENTER: position.y -= parms.boxsize.Y / 2; break;
case DI_ITEM_BOTTOM: position.y -= parms.boxsize.Y; break;
}
// clear all alignment flags so that the following code only passed on the rest
flags &= ~(DI_ITEM_VMASK|DI_ITEM_HMASK);
CPlayer.mo.InvFirst = ValidateInvFirst(numfields);
if (CPlayer.mo.InvFirst == null) return; // Player has no listed inventory items.
Vector2 boxsize = parms.boxsize;
// First draw all the boxes
for(int i = 0; i < numfields; i++)
{
DrawTexture(parms.box, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP, bgalpha);
}
// now the items and the rest
Vector2 itempos = position + (boxsize.X / 2, boxsize.Y - parms.boxframesize);
Vector2 textpos = position + boxsize - (parms.boxframesize*2, parms.boxframesize + parms.amountfont.mFont.GetHeight());
int i = 0;
Inventory item;
for(item = CPlayer.mo.InvFirst; item != NULL && i < numfields; item = item.NextInv())
{
if ((parms.flags & DI_DRAWCURSORFIRST) && item == CPlayer.mo.InvSel) DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP);
DrawInventoryIcon(item, itempos + (boxsize.X * i, 0), flags | DI_ITEM_CENTER_BOTTOM );
if (!(parms.flags & DI_DRAWCURSORFIRST) && item == CPlayer.mo.InvSel) DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP);
if (parms.amountfont != null && (item.Amount > 1 || (parms.flags & DI_ALWAYSSHOWCOUNTERS)))
{
DrawString(parms.amountfont, FormatNumber(item.Amount, 0, 5), textpos + (boxsize.X * i, 0), flags | DI_TEXT_ALIGN_RIGHT, parms.cr, parms.itemalpha);
}
i++;
}
// Is there something to the left?
if (CPlayer.mo.FirstInv() != CPlayer.mo.InvFirst)
{
DrawTexture(parms.left, position + (-parms.arrowoffset.X, parms.arrowoffset.Y), flags | DI_ITEM_RIGHT|DI_ITEM_VCENTER);
}
// Is there something to the right?
if (item != NULL)
{
DrawTexture(parms.right, position + parms.arrowoffset + (width, 0), flags | DI_ITEM_LEFT|DI_ITEM_VCENTER);
}
}
} }
//============================================================================ //============================================================================