- 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 FString statFPS() { return "FPS display not available"; }
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 int GetMenuFontHeight(int fontnum) { return 16; /* something arbitrarily non-zero */ }
virtual int GetMenuTextWidth(int fontnum, const char* text) { return 10 * strlen(text); }
virtual void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) {}
};
extern GameInterface* gi;

View file

@ -255,14 +255,10 @@ void DListMenu::Drawer ()
PreDraw();
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
{
auto o = origin;
if (mDesc->mItems[i]->mEnabled) mDesc->mItems[i]->Drawer(o, mDesc->mSelectedItem == (int)i);
o.y += gi->GetMenuFontHeight(mDesc->mNativeFontNum);
if (mDesc->mItems[i]->mEnabled) mDesc->mItems[i]->Drawer(origin, mDesc->mSelectedItem == (int)i);
}
/*
if (mDesc->mSelectedItem >= 0 && mDesc->mSelectedItem < (int)mDesc->mItems.Size())
mDesc->mItems[mDesc->mSelectedItem]->DrawSelector(mDesc->mSelectOfsX, mDesc->mSelectOfsY, mDesc->mSelector);
*/
PostDraw();
Super::Drawer();
}
@ -574,18 +570,12 @@ void FListMenuItemNativeText::Drawer(const vec2_t& origin, bool selected)
if (mText.Len())
{
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;
}

View file

@ -313,6 +313,8 @@ void M_StartControlPanel (bool makeSound)
}
BackbuttonTime = 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_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.
};
@ -124,7 +128,7 @@ struct FListMenuDescriptor : public FMenuDescriptor
int mSelectOfsY;
FTexture *mSelector;
int mDisplayTop;
int mXpos, mYpos;
int mXpos, mYpos, mYbotton;
int mWLeft, mWRight;
int mLinespacing; // needs to be stored for dynamically created menus
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
int mCenter;
FListMenuDescriptor()
{
Reset();
}
void Reset()
{
// Reset the default settings (ignore all other values in the struct)
@ -319,12 +328,13 @@ public:
virtual bool MouseEvent(int type, int x, int y);
virtual bool CheckHotkey(int c);
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; }
int GetY() { return mYpos; }
int GetX() { return mXpos; }
void SetX(int x) { mXpos = x; }
};
void SetY(int x) { mYpos = x; }
};
class FListMenuItemStaticPatch : public FListMenuItem
{
@ -399,6 +409,7 @@ public:
~FListMenuItemNativeText();
void Drawer(const vec2_t& origin, bool selected) 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.MustGetNumber();
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"))
{
@ -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);
desc->mItems.Push(it);
desc->mYpos += desc->mLinespacing;
//desc->mYpos += desc->mLinespacing;
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"))
{
sc.MustGetString();

View file

@ -44,6 +44,17 @@ BEGIN_DUKE_NS
#define MENU_MARGIN_CENTER 160
#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
// 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);
}
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
{
CallScript(CurrentMenu == this ? EVENT_DISPLAYMENU : EVENT_DISPLAYMENUREST, true);
@ -122,13 +266,6 @@ protected:
{
CallScript(CurrentMenu == this ? EVENT_DISPLAYMENUREST : EVENT_DISPLAYINACTIVEMENUREST, false);
}
void Drawer() override
{
auto v = origin;
Super::Drawer();
origin = v;
}
};
class DukeNewGameCustomSubMenu : public DukeListMenu

View file

@ -156,9 +156,7 @@ struct GameInterface : ::GameInterface
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.
// 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;
int GetMenuFontHeight(int fontnum) override;
int GetMenuTextWidth(int fontnum, const char* text) override;
void DrawNativeMenuText(int fontnum, int state, int xpos, int ypos, float fontscale, const char* text, int orientation = TOR_Default) 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);
}
#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)
{
const uint16_t thissearch = (searchstart + searchend) / 2;

View file

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