- the new menu displays something.

This commit is contained in:
Christoph Oelckers 2019-11-23 17:50:36 +01:00
parent 9529adb3e1
commit 326d0f5f76
9 changed files with 184 additions and 60 deletions

View file

@ -187,9 +187,7 @@ struct GameInterface
virtual bool mouseInactiveConditional(bool condition) { return condition; } virtual bool mouseInactiveConditional(bool condition) { return condition; }
virtual FString statFPS() { return "FPS display not available"; } virtual FString statFPS() { return "FPS display not available"; }
virtual GameStats getStats() { return {}; } virtual GameStats getStats() { return {}; }
virtual void DrawNativeMenuText(int fontnum, int palnum, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) {} virtual void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) {}
virtual int GetMenuFontHeight(int fontnum) { return 16; /* something arbitrarily non-zero */ }
virtual int GetMenuTextWidth(int fontnum, const char* text) { return 10 * strlen(text); }
}; };
extern GameInterface* gi; extern GameInterface* gi;

View file

@ -255,14 +255,10 @@ void DListMenu::Drawer ()
PreDraw(); PreDraw();
for(unsigned i=0;i<mDesc->mItems.Size(); i++) for(unsigned i=0;i<mDesc->mItems.Size(); i++)
{ {
auto o = origin; if (mDesc->mItems[i]->mEnabled) mDesc->mItems[i]->Drawer(origin, mDesc->mSelectedItem == (int)i);
if (mDesc->mItems[i]->mEnabled) mDesc->mItems[i]->Drawer(o, mDesc->mSelectedItem == (int)i);
o.y += gi->GetMenuFontHeight(mDesc->mNativeFontNum);
} }
/*
if (mDesc->mSelectedItem >= 0 && mDesc->mSelectedItem < (int)mDesc->mItems.Size()) if (mDesc->mSelectedItem >= 0 && mDesc->mSelectedItem < (int)mDesc->mItems.Size())
mDesc->mItems[mDesc->mSelectedItem]->DrawSelector(mDesc->mSelectOfsX, mDesc->mSelectOfsY, mDesc->mSelector); mDesc->mItems[mDesc->mSelectedItem]->DrawSelector(mDesc->mSelectOfsX, mDesc->mSelectOfsY, mDesc->mSelector);
*/
PostDraw(); PostDraw();
Super::Drawer(); Super::Drawer();
} }
@ -574,18 +570,12 @@ void FListMenuItemNativeText::Drawer(const vec2_t& origin, bool selected)
if (mText.Len()) if (mText.Len())
{ {
if (*text == '$') text = GStrings(text + 1); if (*text == '$') text = GStrings(text + 1);
gi->DrawNativeMenuText(mFontnum, selected ? NIT_SelectedColor : mPalnum, mXpos + origin.x, mYpos + origin.y, mFontscale, text); gi->DrawNativeMenuText(mFontnum, selected ? NIT_SelectedState : mEnabled? NIT_ActiveState : NIT_InactiveState, mXpos + origin.x, mYpos + origin.y, 1.f, text, TOR_Center); // needs to be able to handle other orientations, too.
} }
} }
int FListMenuItemText::GetWidth() int FListMenuItemNativeText::GetWidth()
{ {
const char* text = mText;
if (mText.Len())
{
if (*text == '$') text = GStrings(text + 1);
return mFont->StringWidth(text);
}
return 1; return 1;
} }

View file

@ -313,6 +313,8 @@ void M_StartControlPanel (bool makeSound)
} }
BackbuttonTime = 0; BackbuttonTime = 0;
BackbuttonAlpha = 0; BackbuttonAlpha = 0;
DMenu::MenuTime = -1;
M_Ticker(); // This needs to be called once here to make sure that the menu actually has ticked before it gets drawn for the first time.
} }
//============================================================================= //=============================================================================

View file

@ -61,7 +61,11 @@ enum ENativeFontValues
NIT_ActiveColor = -1, NIT_ActiveColor = -1,
NIT_InactiveColor = -2, NIT_InactiveColor = -2,
NIT_SelectedColor = -3 NIT_SelectedColor = -3,
NIT_ActiveState = 1,
NIT_InactiveState = 2,
NIT_SelectedState = 3
// positive values for color are direct palswap indices. // positive values for color are direct palswap indices.
}; };
@ -124,7 +128,7 @@ struct FListMenuDescriptor : public FMenuDescriptor
int mSelectOfsY; int mSelectOfsY;
FTexture *mSelector; FTexture *mSelector;
int mDisplayTop; int mDisplayTop;
int mXpos, mYpos; int mXpos, mYpos, mYbotton;
int mWLeft, mWRight; int mWLeft, mWRight;
int mLinespacing; // needs to be stored for dynamically created menus int mLinespacing; // needs to be stored for dynamically created menus
int mAutoselect; // this can only be set by internal menu creation functions int mAutoselect; // this can only be set by internal menu creation functions
@ -138,6 +142,11 @@ struct FListMenuDescriptor : public FMenuDescriptor
FMenuDescriptor *mRedirect; // used to redirect overlong skill and episode menus to option menu based alternatives FMenuDescriptor *mRedirect; // used to redirect overlong skill and episode menus to option menu based alternatives
int mCenter; int mCenter;
FListMenuDescriptor()
{
Reset();
}
void Reset() void Reset()
{ {
// Reset the default settings (ignore all other values in the struct) // Reset the default settings (ignore all other values in the struct)
@ -319,11 +328,12 @@ public:
virtual bool MouseEvent(int type, int x, int y); virtual bool MouseEvent(int type, int x, int y);
virtual bool CheckHotkey(int c); virtual bool CheckHotkey(int c);
virtual int GetWidth(); virtual int GetWidth();
void DrawSelector(int xofs, int yofs, FTexture *tex); virtual void DrawSelector(int xofs, int yofs, FTexture *tex);
void OffsetPositionY(int ydelta) { mYpos += ydelta; } void OffsetPositionY(int ydelta) { mYpos += ydelta; }
int GetY() { return mYpos; } int GetY() { return mYpos; }
int GetX() { return mXpos; } int GetX() { return mXpos; }
void SetX(int x) { mXpos = x; } void SetX(int x) { mXpos = x; }
void SetY(int x) { mYpos = x; }
}; };
class FListMenuItemStaticPatch : public FListMenuItem class FListMenuItemStaticPatch : public FListMenuItem
@ -399,6 +409,7 @@ public:
~FListMenuItemNativeText(); ~FListMenuItemNativeText();
void Drawer(const vec2_t& origin, bool selected) override; void Drawer(const vec2_t& origin, bool selected) override;
int GetWidth() override; int GetWidth() override;
void DrawSelector(int xofs, int yofs, FTexture* tex) override { } // The text drawer handles this itself.
}; };

View file

@ -266,6 +266,16 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
sc.MustGetStringName(","); sc.MustGetStringName(",");
sc.MustGetNumber(); sc.MustGetNumber();
desc->mYpos = sc.Number; desc->mYpos = sc.Number;
if (sc.CheckString(","))
{
sc.MustGetNumber();
desc->mYbotton = sc.Number;
if (sc.CheckString(","))
{
sc.MustGetNumber();
desc->mCenter = sc.Number;
}
}
} }
else if (sc.Compare("Centermenu")) else if (sc.Compare("Centermenu"))
{ {
@ -381,7 +391,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
auto it = new FListMenuItemNativeText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mNativeFontNum, desc->mNativePalNum, desc->mNativeFontScale, action, param); auto it = new FListMenuItemNativeText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mNativeFontNum, desc->mNativePalNum, desc->mNativeFontScale, action, param);
desc->mItems.Push(it); desc->mItems.Push(it);
desc->mYpos += desc->mLinespacing; //desc->mYpos += desc->mLinespacing;
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size() - 1; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size() - 1;
} }
@ -414,18 +424,6 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
} }
} }
} }
else if (sc.Compare("Position"))
{
sc.MustGetNumber();
sc.MustGetStringName(",");
desc->mXpos = sc.Number;
sc.MustGetNumber();
desc->mYpos = sc.Number;
if (sc.CheckString(","))
{
desc->mCenter = sc.Number;
}
}
else if (sc.Compare("Font")) else if (sc.Compare("Font"))
{ {
sc.MustGetString(); sc.MustGetString();

View file

@ -44,6 +44,17 @@ BEGIN_DUKE_NS
#define MENU_MARGIN_CENTER 160 #define MENU_MARGIN_CENTER 160
#define MENU_HEIGHT_CENTER 100 #define MENU_HEIGHT_CENTER 100
enum MenuTextFlags_t
{
MT_Selected = 1 << 0,
MT_Disabled = 1 << 1,
MT_XCenter = 1 << 2,
MT_XRight = 1 << 3,
MT_YCenter = 1 << 4,
MT_Literal = 1 << 5,
MT_RightSide = 1 << 6,
};
// common font types // common font types
// tilenums are set after namesdyn runs. // tilenums are set after namesdyn runs.
@ -80,17 +91,118 @@ static void Menu_DrawTopBarCaption(const char *caption, const vec2_t origin)
captionmenutext(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (24<<16) + ((15>>1)<<16), t); captionmenutext(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (24<<16) + ((15>>1)<<16), t);
} }
int GetMenuFontHeight(int fontnum) static void Menu_GetFmt(const MenuFont_t* font, uint8_t const status, int32_t* s, int32_t* z)
{ {
if (status & MT_Selected)
*s = VM_OnEventWithReturn(EVENT_MENUSHADESELECTED, -1, myconnectindex, sintable[((int32_t)totalclock << 5) & 2047] >> 12);
else
*s = font->shade_deselected;
// sum shade values
if (status & MT_Disabled)
*s += font->shade_disabled;
if (FURY && status & MT_Selected)
*z += (*z >> 4);
} }
int GetMenuTextWidth(int fontnum, const char* text) static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t* font, const char* t, uint8_t status, int32_t ydim_upper, int32_t ydim_lower)
{ {
int32_t s, p, ybetween = font->between.y;
int32_t f = font->textflags;
if (status & MT_XCenter)
f |= TEXT_XCENTER;
if (status & MT_XRight)
f |= TEXT_XRIGHT;
if (status & MT_YCenter)
{
f |= TEXT_YCENTER | TEXT_YOFFSETZERO;
ybetween = font->emptychar.y; // <^ the battle against 'Q'
}
if (status & MT_Literal)
f |= TEXT_LITERALESCAPE;
int32_t z = font->zoom;
if (status & MT_Disabled)
p = (status & MT_RightSide) ? font->pal_disabled_right : font->pal_disabled;
else if (status & MT_Selected)
p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected;
else
p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected;
Menu_GetFmt(font, status, &s, &z);
return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim - 1, ydim_lower);
} }
void GameInterface::DrawNativeMenuText(int fontnum, int palnum, int xpos, int ypos, float fontscale, const char* text, int orientation) static int32_t Menu_CursorShade(void)
{ {
return VM_OnEventWithReturn(EVENT_MENUCURSORSHADE, -1, myconnectindex, 4 - (sintable[((int32_t)totalclock << 4) & 2047] >> 11));
}
static void Menu_DrawCursorCommon(int32_t x, int32_t y, int32_t z, int32_t picnum, int32_t ydim_upper = 0, int32_t ydim_lower = ydim - 1)
{
rotatesprite_(x, y, z, 0, picnum, Menu_CursorShade(), 0, 2 | 8, 0, 0, 0, ydim_upper, xdim - 1, ydim_lower);
}
static void Menu_DrawCursorLeft(int32_t x, int32_t y, int32_t z)
{
if (FURY) return;
Menu_DrawCursorCommon(x, y, z, VM_OnEventWithReturn(EVENT_MENUCURSORLEFT, -1, myconnectindex, SPINNINGNUKEICON + (((int32_t)totalclock >> 3) % 7)));
}
static void Menu_DrawCursorRight(int32_t x, int32_t y, int32_t z)
{
if (FURY) return;
Menu_DrawCursorCommon(x, y, z, VM_OnEventWithReturn(EVENT_MENUCURSORRIGHT, -1, myconnectindex, SPINNINGNUKEICON + 6 - ((6 + ((int32_t)totalclock >> 3)) % 7)));
}
static int Menu_GetFontHeight(int fontnum)
{
auto& font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont;
return font.get_yline();
}
void GameInterface::DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation)
{
int ydim_upper = 0;
int ydim_lower = ydim - 1;
int32_t const indent = 0; // not set for any relevant menu
int32_t x = xpos << 16;
uint8_t status = 0;
if (state == NIT_SelectedState)
status |= MT_Selected;
if (state == NIT_InactiveState)
status |= MT_Disabled;
if (orientation == TOR_Center)
status |= MT_XCenter;
bool const dodraw = true;
MenuFont_t &font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont;
int32_t const height = font.get_yline();
status |= MT_YCenter;
int32_t const y_internal = (ypos + (height >> 17)) << 16;// -menu->scrollPos;
vec2_t textsize;
if (dodraw)
textsize = Menu_Text(x, y_internal, &font, text, status, ydim_upper, ydim_lower);
if (orientation == TOR_Right)
status |= MT_XRight;
if (dodraw && (status & MT_Selected) && state != 1)
{
if (status & MT_XCenter)
{
Menu_DrawCursorLeft(x + font.cursorCenterPosition, y_internal, font.cursorScale);
Menu_DrawCursorRight(x - font.cursorCenterPosition, y_internal, font.cursorScale);
}
else
Menu_DrawCursorLeft(x /*+ indent*/ - font.cursorLeftPosition, y_internal, font.cursorScale);
}
} }
@ -113,6 +225,38 @@ protected:
} }
} }
void Ticker() override
{
// Lay out the menu. Since scripts are allowed to mess around with the font this needs to be redone each frame.
int32_t y_upper = mDesc->mYpos;
int32_t y_lower = y_upper + mDesc->mYbotton;
int32_t y = 0;
int32_t calculatedentryspacing = 0;
int32_t const height = Menu_GetFontHeight(mDesc->mNativeFontNum) >> 16;
// None of the menus still being supported will hide entries - only decactivate them if not applicable.
int32_t totalheight = 0, numvalidentries = mDesc->mItems.Size();
for (int e = 0; e < numvalidentries; ++e)
{
totalheight += height;
}
calculatedentryspacing = std::max(0, (y_lower - y_upper - totalheight) / (numvalidentries > 1 ? numvalidentries - 1 : 1));
// totalHeight calculating pass
int totalHeight;
for (int e = 0; e < numvalidentries; ++e)
{
auto entry = mDesc->mItems[e];
entry->SetY(y_upper + y);
y += height;
totalHeight = y;
y += calculatedentryspacing;
}
}
void PreDraw() override void PreDraw() override
{ {
CallScript(CurrentMenu == this ? EVENT_DISPLAYMENU : EVENT_DISPLAYMENUREST, true); CallScript(CurrentMenu == this ? EVENT_DISPLAYMENU : EVENT_DISPLAYMENUREST, true);
@ -122,13 +266,6 @@ protected:
{ {
CallScript(CurrentMenu == this ? EVENT_DISPLAYMENUREST : EVENT_DISPLAYINACTIVEMENUREST, false); CallScript(CurrentMenu == this ? EVENT_DISPLAYMENUREST : EVENT_DISPLAYINACTIVEMENUREST, false);
} }
void Drawer() override
{
auto v = origin;
Super::Drawer();
origin = v;
}
}; };
class DukeNewGameCustomSubMenu : public DukeListMenu class DukeNewGameCustomSubMenu : public DukeListMenu

View file

@ -156,9 +156,7 @@ struct GameInterface : ::GameInterface
GameStats getStats() override; GameStats getStats() override;
// Access to the front end specific menu code. Use is restricted to the main menu, the ingame menu and the skill/episode selection. // Access to the front end specific menu code. Use is restricted to the main menu, the ingame menu and the skill/episode selection.
// Everything else is either custom screens or will use the generic option menu style. // Everything else is either custom screens or will use the generic option menu style.
void DrawNativeMenuText(int fontnum, int palnum, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) override; void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) override;
int GetMenuFontHeight(int fontnum) override;
int GetMenuTextWidth(int fontnum, const char* text) override;
}; };

View file

@ -4342,17 +4342,6 @@ static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t *font, const char
return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2|8|16|ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim-1, ydim_lower); return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2|8|16|ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim-1, ydim_lower);
} }
#if 0
static vec2_t Menu_TextSize(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status)
{
int32_t f = font->textflags;
if (status & MT_Literal)
f |= TEXT_LITERALESCAPE;
return G_ScreenTextSize(font->tilenum, x, y, font->zoom, 0, t, 2|8|16|ROTATESPRITE_FULL16, font->emptychar.x, font->emptychar.y, font->between.x, font->between.y, f, 0, 0, xdim-1, ydim-1);
}
#endif
static int32_t Menu_FindOptionBinarySearch(MenuOption_t *object, const int32_t query, uint16_t searchstart, uint16_t searchend) static int32_t Menu_FindOptionBinarySearch(MenuOption_t *object, const int32_t query, uint16_t searchstart, uint16_t searchend)
{ {
const uint16_t thissearch = (searchstart + searchend) / 2; const uint16_t thissearch = (searchstart + searchend) / 2;

View file

@ -10,11 +10,12 @@ LISTMENU "MainMenu"
{ {
ifgame(fury) ifgame(fury)
{ {
position 40, 130, -160 position 40, 130, 60, -160
} }
else else
{ {
position 160, 55 position 160, 55, 115, 0
centermenu
} }
linespacing 15 linespacing 15
class "Duke.MainMenu" class "Duke.MainMenu"