- 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 * berserkpic; // Berserk icon (Doom only)
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 statspace;
@ -816,7 +816,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y)
{
if(rover->PrevInv())
{
screen->DrawTexture(invgems[!!(level.time&4)], x-10, y,
screen->DrawTexture(invgems[0], x-10, y,
DTA_KeepRatio, true,
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)
{
screen->DrawTexture(invgems[2 + !!(level.time&4)], x-10, y,
screen->DrawTexture(invgems[1], x-10, y,
DTA_KeepRatio, true,
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
invgems[0] = TexMan.FindTexture("INVGEML1");
invgems[1] = TexMan.FindTexture("INVGEML2");
invgems[2] = TexMan.FindTexture("INVGEMR1");
invgems[3] = TexMan.FindTexture("INVGEMR2");
invgems[1] = TexMan.FindTexture("INVGEMR1");
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",
};
TArray<const char *> patchnames;
patchnames.Resize(script->Images.Size()+10);
patchnames.Resize(script->Images.Size()+9);
unsigned int i = 0;
for(i = 0;i < script->Images.Size();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];
}

View file

@ -243,16 +243,24 @@ void ST_CreateStatusBar(bool bTitleLevel)
StatusBar = new DBaseStatusBar();
StatusBar->SetSize(0);
}
else if (gameinfo.statusbarclassfile >= gameinfo.statusbarfile)
else
{
auto cls = PClass::FindClass(gameinfo.statusbarclass);
if (cls != nullptr)
// 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)
{
StatusBar = (DBaseStatusBar *)cls->CreateNew();
IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init)
auto cls = PClass::FindClass(gameinfo.statusbarclass);
if (cls != nullptr)
{
VMValue params[] = { StatusBar };
GlobalVMStack.Call(func, params, 1, nullptr, 0);
StatusBar = (DBaseStatusBar *)cls->CreateNew();
IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init)
{
VMValue params[] = { StatusBar };
GlobalVMStack.Call(func, params, 1, nullptr, 0);
}
}
}
}
@ -283,7 +291,6 @@ void ST_CreateStatusBar(bool bTitleLevel)
auto cls = PClass::FindClass(defname);
if (cls != nullptr)
{
StatusBar = (DBaseStatusBar *)cls->CreateNew();
IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init)
{
@ -1605,8 +1612,8 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla
switch (flags & DI_ITEM_VMASK)
{
case DI_ITEM_VCENTER: y -= texheight / 2; break;
case DI_ITEM_BOTTOM: y -= texheight; break;
case DI_ITEM_VCENTER: y -= boxheight / 2; break;
case DI_ITEM_BOTTOM: y -= boxheight; 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));
}
DEFINE_FIELD(DHUDFont, mFont);
//============================================================================
//
// 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);
ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1);
}

View file

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

View file

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

View file

@ -2,7 +2,8 @@ class DoomStatusBar : BaseStatusBar
{
HUDFont mHUDFont;
HUDFont mIndexFont;
//DrawInventoryBarParms diparms;
HUDFont mAmountFont;
InventoryBarState diparms;
override void Init()
@ -10,19 +11,13 @@ class DoomStatusBar : BaseStatusBar
Super.Init();
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
Font fnt = "HUDFONT_DOOM";
mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 1, 1);
fnt = "INDEXFONT_DOOM";
mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true);
mAmountFont = HUDFont.Create("INDEXFONT");
diparms = InventoryBarState.Create();
}
override void NewGame ()
@ -120,14 +115,23 @@ class DoomStatusBar : BaseStatusBar
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
{
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 ()
@ -159,14 +163,14 @@ class DoomStatusBar : BaseStatusBar
DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT);
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));
DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT);
}
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
@ -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
{
// 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);
}
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
{
@ -130,6 +177,7 @@ class BaseStatusBar native ui
DI_ALPHAMAPPED = 0x2000000,
DI_NOSHADOW = 0x4000000,
DI_ALWAYSSHOWCOUNTERS = 0x8000000,
};
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);
}
}
}
//============================================================================