mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 23:11:58 +00:00
- scriptified the entire OptionMenu class and all still existing native subclasses.
This commit is contained in:
parent
12db190f41
commit
46c0d27fe7
8 changed files with 471 additions and 551 deletions
|
@ -124,13 +124,6 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap)
|
|||
|
||||
DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy);
|
||||
|
||||
class DJoystickConfigMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DJoystickConfigMenu, DOptionMenu)
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DJoystickConfigMenu, false, false)
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Joystick Menu
|
||||
|
@ -295,7 +288,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
if (i == (int)Joysticks.Size())
|
||||
{
|
||||
SELECTED_JOYSTICK = NULL;
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DJoystickConfigMenu)))
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf("JoystickConfigMenu"))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
}
|
||||
|
|
|
@ -378,6 +378,24 @@ void DMenu::Ticker ()
|
|||
{
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, Ticker)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
self->Drawer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DMenu::CallTicker()
|
||||
{
|
||||
IFVIRTUAL(DMenu, Ticker)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
else Drawer();
|
||||
}
|
||||
|
||||
|
||||
void DMenu::Drawer ()
|
||||
{
|
||||
if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
|
@ -608,10 +626,14 @@ void M_SetMenu(FName menu, int param)
|
|||
else if ((*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor)))
|
||||
{
|
||||
DOptionMenuDescriptor *ld = static_cast<DOptionMenuDescriptor*>(*desc);
|
||||
const PClass *cls = ld->mClass == nullptr? RUNTIME_CLASS(DOptionMenu) : ld->mClass;
|
||||
const PClass *cls = ld->mClass == nullptr? PClass::FindClass("OptionMenu") : ld->mClass;
|
||||
|
||||
DOptionMenu *newmenu = (DOptionMenu *)cls->CreateNew();
|
||||
newmenu->Init(DMenu::CurrentMenu, ld);
|
||||
DMenu *newmenu = (DMenu*)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init)
|
||||
{
|
||||
VMValue params[3] = { newmenu, DMenu::CurrentMenu, ld };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0);
|
||||
}
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
return;
|
||||
|
@ -847,7 +869,7 @@ void M_Ticker (void)
|
|||
DMenu::MenuTime++;
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
DMenu::CurrentMenu->Ticker();
|
||||
DMenu::CurrentMenu->CallTicker();
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
|
@ -856,7 +878,7 @@ void M_Ticker (void)
|
|||
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
||||
{
|
||||
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
||||
DMenu::CurrentMenu->MenuEvent(i, MenuButtonOrigin[i]);
|
||||
DMenu::CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1170,9 +1192,6 @@ CCMD(undocolorpic)
|
|||
|
||||
|
||||
|
||||
//native void OptionMenuDescriptor.CalcIndent();
|
||||
//native OptionMenuItem OptionMenuDescriptor.GetItem(Name iname);
|
||||
|
||||
DEFINE_FIELD(DMenu, mParentMenu)
|
||||
|
||||
DEFINE_FIELD(DMenuDescriptor, mMenuName)
|
||||
|
@ -1211,12 +1230,6 @@ DEFINE_FIELD(DOptionMenuDescriptor, mIndent)
|
|||
DEFINE_FIELD(DOptionMenuDescriptor, mPosition)
|
||||
DEFINE_FIELD(DOptionMenuDescriptor, mDontDim)
|
||||
|
||||
DEFINE_FIELD(DOptionMenu, CanScrollUp)
|
||||
DEFINE_FIELD(DOptionMenu, CanScrollDown)
|
||||
DEFINE_FIELD(DOptionMenu, VisBottom)
|
||||
DEFINE_FIELD(DOptionMenu, mFocusControl)
|
||||
DEFINE_FIELD(DOptionMenu, mDesc)
|
||||
|
||||
DEFINE_FIELD(FOptionMenuSettings, mTitleColor)
|
||||
DEFINE_FIELD(FOptionMenuSettings, mFontColor)
|
||||
DEFINE_FIELD(FOptionMenuSettings, mFontColorValue)
|
||||
|
|
|
@ -282,6 +282,7 @@ public:
|
|||
bool CallResponder(event_t *ev);
|
||||
bool CallMenuEvent(int mkey, bool fromcontroller);
|
||||
bool CallMouseEvent(int type, int x, int y);
|
||||
void CallTicker();
|
||||
void CallDrawer();
|
||||
|
||||
bool MouseEventBack(int type, int x, int y);
|
||||
|
@ -394,50 +395,6 @@ typedef TMap< FName, FOptionValues* > FOptionMap;
|
|||
extern FOptionMap OptionValues;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Option menu class runs a menu described by a DOptionMenuDescriptor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DOptionMenu, DMenu)
|
||||
HAS_OBJECT_POINTERS;
|
||||
|
||||
public: // needs to be public for script access
|
||||
bool CanScrollUp;
|
||||
bool CanScrollDown;
|
||||
int VisBottom;
|
||||
DMenuItemBase *mFocusControl;
|
||||
DOptionMenuDescriptor *mDesc;
|
||||
|
||||
//public:
|
||||
DMenuItemBase *GetItem(FName name);
|
||||
DOptionMenu(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL);
|
||||
virtual void Init(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL);
|
||||
int FirstSelectable();
|
||||
bool Responder (event_t *ev);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void Ticker ();
|
||||
void Drawer ();
|
||||
const DOptionMenuDescriptor *GetDescriptor() const { return mDesc; }
|
||||
void SetFocus(DMenuItemBase *fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
}
|
||||
bool CheckFocus(DMenuItemBase *fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Input some text
|
||||
|
|
|
@ -700,7 +700,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
|
|||
{
|
||||
sc.MustGetString();
|
||||
const PClass *cls = PClass::FindClass(sc.String);
|
||||
if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(DOptionMenu)))
|
||||
if (cls == nullptr || !cls->IsDescendantOf("OptionMenu"))
|
||||
{
|
||||
sc.ScriptError("Unknown menu class '%s'", sc.String);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
** Handler class for the option menus and associated items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -49,431 +49,12 @@
|
|||
#include "menu/menu.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Draws a string in the console font, scaled to the 8x8 cells
|
||||
// used by the default console font.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_DrawConText (int color, int x, int y, const char *str)
|
||||
{
|
||||
screen->DrawText (ConFont, color, x, y, str,
|
||||
DTA_CellX, 8 * CleanXfac_1,
|
||||
DTA_CellY, 8 * CleanYfac_1,
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(DOptionMenu, false, false)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DOptionMenu)
|
||||
IMPLEMENT_POINTER(mFocusControl)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DOptionMenu::DOptionMenu(DMenu *parent, DOptionMenuDescriptor *desc)
|
||||
: DMenu(parent)
|
||||
{
|
||||
CanScrollUp = false;
|
||||
CanScrollDown = false;
|
||||
VisBottom = 0;
|
||||
mFocusControl = NULL;
|
||||
Init(parent, desc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Init(DMenu *parent, DOptionMenuDescriptor *desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
GC::WriteBarrier(this, parent);
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc->mSelectedItem == -1) mDesc->mSelectedItem = FirstSelectable();
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int DOptionMenu::FirstSelectable()
|
||||
{
|
||||
if (mDesc != NULL)
|
||||
{
|
||||
// Go down to the first selectable item
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
}
|
||||
while (i < (int)mDesc->mItems.Size() && !mDesc->mItems[i]->Selectable());
|
||||
if (i>=0 && i < (int)mDesc->mItems.Size()) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DMenuItemBase *DOptionMenu::GetItem(FName name)
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mDesc->mItems[i]->GetAction(NULL);
|
||||
if (nm == name) return mDesc->mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_WheelUp)
|
||||
{
|
||||
int scrollamt = MIN(2, mDesc->mScrollPos);
|
||||
mDesc->mScrollPos -= scrollamt;
|
||||
return true;
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_WheelDown)
|
||||
{
|
||||
if (CanScrollDown)
|
||||
{
|
||||
if (VisBottom < (int)(mDesc->mItems.Size()-2))
|
||||
{
|
||||
mDesc->mScrollPos += 2;
|
||||
VisBottom += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc->mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int startedAt = mDesc->mSelectedItem;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (mDesc->mSelectedItem == -1)
|
||||
{
|
||||
mDesc->mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
--mDesc->mSelectedItem;
|
||||
|
||||
if (mDesc->mScrollPos > 0 &&
|
||||
mDesc->mSelectedItem <= mDesc->mScrollTop + mDesc->mScrollPos)
|
||||
{
|
||||
mDesc->mScrollPos = MAX(mDesc->mSelectedItem - mDesc->mScrollTop - 1, 0);
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem < 0)
|
||||
{
|
||||
// Figure out how many lines of text fit on the menu
|
||||
int y = mDesc->mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc->mTitle.IsNotEmpty())
|
||||
{
|
||||
y = -y + BigFont->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
y *= CleanYfac_1;
|
||||
int rowheight = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
int maxitems = (screen->GetHeight() - rowheight - y) / rowheight + 1;
|
||||
|
||||
mDesc->mScrollPos = MAX (0, (int)mDesc->mItems.Size() - maxitems + mDesc->mScrollTop);
|
||||
mDesc->mSelectedItem = mDesc->mItems.Size()-1;
|
||||
}
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_Down:
|
||||
if (mDesc->mSelectedItem == -1)
|
||||
{
|
||||
mDesc->mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
++mDesc->mSelectedItem;
|
||||
|
||||
if (CanScrollDown && mDesc->mSelectedItem == VisBottom)
|
||||
{
|
||||
mDesc->mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
if (mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
if (startedAt == -1)
|
||||
{
|
||||
mDesc->mSelectedItem = -1;
|
||||
mDesc->mScrollPos = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
mDesc->mScrollPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (mDesc->mScrollPos > 0)
|
||||
{
|
||||
mDesc->mScrollPos -= VisBottom - mDesc->mScrollPos - mDesc->mScrollTop;
|
||||
if (mDesc->mScrollPos < 0)
|
||||
{
|
||||
mDesc->mScrollPos = 0;
|
||||
}
|
||||
if (mDesc->mSelectedItem != -1)
|
||||
{
|
||||
mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos + 1;
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable())
|
||||
{
|
||||
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc->mScrollPos > mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (CanScrollDown)
|
||||
{
|
||||
int pagesize = VisBottom - mDesc->mScrollPos - mDesc->mScrollTop;
|
||||
mDesc->mScrollPos += pagesize;
|
||||
if (mDesc->mScrollPos + mDesc->mScrollTop + pagesize > (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mItems.Size() - mDesc->mScrollTop - pagesize;
|
||||
}
|
||||
if (mDesc->mSelectedItem != -1)
|
||||
{
|
||||
mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos;
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable())
|
||||
{
|
||||
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc->mScrollPos > mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// fall through to default
|
||||
default:
|
||||
if (mDesc->mSelectedItem >= 0 &&
|
||||
mDesc->mItems[mDesc->mSelectedItem]->MenuEvent(mkey, fromcontroller)) return true;
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem != startedAt)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
y = (y / CleanYfac_1) - mDesc->mDrawTop;
|
||||
|
||||
if (mFocusControl)
|
||||
{
|
||||
mFocusControl->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int yline = (y / OptionSettings.mLinespacing);
|
||||
if (yline >= mDesc->mScrollTop)
|
||||
{
|
||||
yline += mDesc->mScrollPos;
|
||||
}
|
||||
if ((unsigned)yline < mDesc->mItems.Size() && mDesc->mItems[yline]->Selectable())
|
||||
{
|
||||
if (yline != mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mSelectedItem = yline;
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc->mItems[yline]->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mDesc->mSelectedItem = -1;
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Ticker ()
|
||||
{
|
||||
Super::Ticker();
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
mDesc->mItems[i]->Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Drawer ()
|
||||
{
|
||||
int y = mDesc->mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc->mTitle.IsNotEmpty())
|
||||
{
|
||||
const char *tt = mDesc->mTitle;
|
||||
if (*tt == '$') tt = GStrings(tt+1);
|
||||
screen->DrawText (BigFont, OptionSettings.mTitleColor,
|
||||
(screen->GetWidth() - BigFont->StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1,
|
||||
tt, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
y = -y + BigFont->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
mDesc->mDrawTop = y;
|
||||
int fontheight = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
y *= CleanYfac_1;
|
||||
|
||||
int indent = mDesc->mIndent;
|
||||
if (indent > 280)
|
||||
{ // kludge for the compatibility options with their extremely long labels
|
||||
if (indent + 40 <= CleanWidth_1)
|
||||
{
|
||||
indent = (screen->GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = screen->GetWidth() - 40 * CleanXfac_1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = (indent - 160) * CleanXfac_1 + screen->GetWidth() / 2;
|
||||
}
|
||||
|
||||
int ytop = y + mDesc->mScrollTop * 8 * CleanYfac_1;
|
||||
int lastrow = screen->GetHeight() - SmallFont->GetHeight() * CleanYfac_1;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < mDesc->mItems.Size() && y <= lastrow; i++, y += fontheight)
|
||||
{
|
||||
// Don't scroll the uppermost items
|
||||
if ((int)i == mDesc->mScrollTop)
|
||||
{
|
||||
i += mDesc->mScrollPos;
|
||||
if (i >= mDesc->mItems.Size()) break; // skipped beyond end of menu
|
||||
}
|
||||
bool isSelected = mDesc->mSelectedItem == (int)i;
|
||||
int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, isSelected);
|
||||
if (cur_indent >= 0 && isSelected && mDesc->mItems[i]->Selectable())
|
||||
{
|
||||
if (((DMenu::MenuTime%8) < 6) || DMenu::CurrentMenu != this)
|
||||
{
|
||||
M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CanScrollUp = (mDesc->mScrollPos > 0);
|
||||
CanScrollDown = (i < mDesc->mItems.Size());
|
||||
VisBottom = i - 1;
|
||||
|
||||
if (CanScrollUp)
|
||||
{
|
||||
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a");
|
||||
}
|
||||
if (CanScrollDown)
|
||||
{
|
||||
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b");
|
||||
}
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
void DOptionMenuDescriptor::CalcIndent()
|
||||
{
|
||||
// calculate the menu indent
|
||||
|
|
|
@ -22,7 +22,7 @@ inline unsigned GetVirtualIndex(PClass *cls, const char *funcname)
|
|||
#define IFVIRTUALPTRNAME(self, cls, funcname) \
|
||||
static unsigned VIndex = ~0u; \
|
||||
if (VIndex == ~0u) { \
|
||||
VIndex = GetVirtualIndex(PClass::FindActor(cls), #funcname); \
|
||||
VIndex = GetVirtualIndex(PClass::FindClass(cls), #funcname); \
|
||||
assert(VIndex != ~0u); \
|
||||
} \
|
||||
auto clss = self->GetClass(); \
|
||||
|
|
|
@ -104,6 +104,7 @@ class Menu : Object native
|
|||
native virtual bool Responder(InputEvent ev);
|
||||
native virtual bool MenuEvent (int mkey, bool fromcontroller);
|
||||
native virtual bool MouseEvent(int type, int mx, int my);
|
||||
native virtual void Ticker();
|
||||
native virtual void Drawer();
|
||||
native void Close();
|
||||
native MenuItemBase GetItem(Name n);
|
||||
|
@ -200,66 +201,3 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
}
|
||||
}
|
||||
|
||||
class OptionMenu : Menu native
|
||||
{
|
||||
native OptionMenuDescriptor mDesc;
|
||||
native bool CanScrollUp;
|
||||
native bool CanScrollDown;
|
||||
native int VisBottom;
|
||||
native OptionMenuItem mFocusControl;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual void Init(Menu parent, OptionMenuDescriptor desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int FirstSelectable()
|
||||
{
|
||||
if (mDesc != NULL)
|
||||
{
|
||||
// Go down to the first selectable item
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
}
|
||||
while (i < mDesc.mItems.Size() && !mDesc.mItems[i].Selectable());
|
||||
if (i>=0 && i < mDesc.mItems.Size()) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
override void SetFocus(MenuItemBase fc)
|
||||
{
|
||||
mFocusControl = OptionMenuItem(fc);
|
||||
}
|
||||
|
||||
override bool CheckFocus(MenuItemBase fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
|
||||
override void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,439 @@
|
|||
/*
|
||||
** optionmenu.cpp
|
||||
** Handler class for the option menus and associated items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class OptionMenu : Menu
|
||||
{
|
||||
OptionMenuDescriptor mDesc;
|
||||
bool CanScrollUp;
|
||||
bool CanScrollDown;
|
||||
int VisBottom;
|
||||
OptionMenuItem mFocusControl;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual void Init(Menu parent, OptionMenuDescriptor desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int FirstSelectable()
|
||||
{
|
||||
if (mDesc != NULL)
|
||||
{
|
||||
// Go down to the first selectable item
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
}
|
||||
while (i < mDesc.mItems.Size() && !mDesc.mItems[i].Selectable());
|
||||
if (i>=0 && i < mDesc.mItems.Size()) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEvent ev)
|
||||
{
|
||||
if (ev.type == InputEvent.GUI_Event)
|
||||
{
|
||||
if (ev.subtype == InputEvent.GUI_WheelUp)
|
||||
{
|
||||
int scrollamt = MIN(2, mDesc.mScrollPos);
|
||||
mDesc.mScrollPos -= scrollamt;
|
||||
return true;
|
||||
}
|
||||
else if (ev.subtype == InputEvent.GUI_WheelDown)
|
||||
{
|
||||
if (CanScrollDown)
|
||||
{
|
||||
if (VisBottom >= 0 && VisBottom < (mDesc.mItems.Size()-2))
|
||||
{
|
||||
mDesc.mScrollPos += 2;
|
||||
VisBottom += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc.mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int startedAt = mDesc.mSelectedItem;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (mDesc.mSelectedItem == -1)
|
||||
{
|
||||
mDesc.mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
--mDesc.mSelectedItem;
|
||||
|
||||
if (mDesc.mScrollPos > 0 &&
|
||||
mDesc.mSelectedItem <= mDesc.mScrollTop + mDesc.mScrollPos)
|
||||
{
|
||||
mDesc.mScrollPos = MAX(mDesc.mSelectedItem - mDesc.mScrollTop - 1, 0);
|
||||
}
|
||||
|
||||
if (mDesc.mSelectedItem < 0)
|
||||
{
|
||||
// Figure out how many lines of text fit on the menu
|
||||
int y = mDesc.mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc.mTitle.Length() > 0)
|
||||
{
|
||||
y = -y + BigFont.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
y *= CleanYfac_1;
|
||||
int rowheight = OptionMenuSettings.mLinespacing * CleanYfac_1;
|
||||
int maxitems = (screen.GetHeight() - rowheight - y) / rowheight + 1;
|
||||
|
||||
mDesc.mScrollPos = MAX (0, mDesc.mItems.Size() - maxitems + mDesc.mScrollTop);
|
||||
mDesc.mSelectedItem = mDesc.mItems.Size()-1;
|
||||
}
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_Down:
|
||||
if (mDesc.mSelectedItem == -1)
|
||||
{
|
||||
mDesc.mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
++mDesc.mSelectedItem;
|
||||
|
||||
if (CanScrollDown && mDesc.mSelectedItem == VisBottom)
|
||||
{
|
||||
mDesc.mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
if (mDesc.mSelectedItem >= mDesc.mItems.Size())
|
||||
{
|
||||
if (startedAt == -1)
|
||||
{
|
||||
mDesc.mSelectedItem = -1;
|
||||
mDesc.mScrollPos = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc.mSelectedItem = 0;
|
||||
mDesc.mScrollPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (mDesc.mScrollPos > 0)
|
||||
{
|
||||
mDesc.mScrollPos -= VisBottom - mDesc.mScrollPos - mDesc.mScrollTop;
|
||||
if (mDesc.mScrollPos < 0)
|
||||
{
|
||||
mDesc.mScrollPos = 0;
|
||||
}
|
||||
if (mDesc.mSelectedItem != -1)
|
||||
{
|
||||
mDesc.mSelectedItem = mDesc.mScrollTop + mDesc.mScrollPos + 1;
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable())
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size())
|
||||
{
|
||||
mDesc.mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc.mScrollPos > mDesc.mSelectedItem)
|
||||
{
|
||||
mDesc.mScrollPos = mDesc.mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (CanScrollDown)
|
||||
{
|
||||
int pagesize = VisBottom - mDesc.mScrollPos - mDesc.mScrollTop;
|
||||
mDesc.mScrollPos += pagesize;
|
||||
if (mDesc.mScrollPos + mDesc.mScrollTop + pagesize > mDesc.mItems.Size())
|
||||
{
|
||||
mDesc.mScrollPos = mDesc.mItems.Size() - mDesc.mScrollTop - pagesize;
|
||||
}
|
||||
if (mDesc.mSelectedItem != -1)
|
||||
{
|
||||
mDesc.mSelectedItem = mDesc.mScrollTop + mDesc.mScrollPos;
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable())
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size())
|
||||
{
|
||||
mDesc.mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc.mScrollPos > mDesc.mSelectedItem)
|
||||
{
|
||||
mDesc.mScrollPos = mDesc.mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mItems[mDesc.mSelectedItem].Activate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// fall through to default
|
||||
default:
|
||||
if (mDesc.mSelectedItem >= 0 &&
|
||||
mDesc.mItems[mDesc.mSelectedItem].MenuEvent(mkey, fromcontroller)) return true;
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
if (mDesc.mSelectedItem != startedAt)
|
||||
{
|
||||
MenuSound ("menu/cursor");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
y = (y / CleanYfac_1) - mDesc.mDrawTop;
|
||||
|
||||
if (mFocusControl)
|
||||
{
|
||||
mFocusControl.MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int yline = (y / OptionMenuSettings.mLinespacing);
|
||||
if (yline >= mDesc.mScrollTop)
|
||||
{
|
||||
yline += mDesc.mScrollPos;
|
||||
}
|
||||
if (yline >= 0 && yline < mDesc.mItems.Size() && mDesc.mItems[yline].Selectable())
|
||||
{
|
||||
if (yline != mDesc.mSelectedItem)
|
||||
{
|
||||
mDesc.mSelectedItem = yline;
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc.mItems[yline].MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mDesc.mSelectedItem = -1;
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Ticker ()
|
||||
{
|
||||
Super.Ticker();
|
||||
for(int i = 0; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
mDesc.mItems[i].Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
int y = mDesc.mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc.mTitle.Length() > 0)
|
||||
{
|
||||
let tt = Stringtable.Localize(mDesc.mTitle);
|
||||
screen.DrawText (BigFont, OptionMenuSettings.mTitleColor,
|
||||
(screen.GetWidth() - BigFont.StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1,
|
||||
tt, DTA_CleanNoMove_1, true);
|
||||
y = -y + BigFont.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
mDesc.mDrawTop = y;
|
||||
int fontheight = OptionMenuSettings.mLinespacing * CleanYfac_1;
|
||||
y *= CleanYfac_1;
|
||||
|
||||
int indent = mDesc.mIndent;
|
||||
if (indent > 280)
|
||||
{ // kludge for the compatibility options with their extremely long labels
|
||||
if (indent + 40 <= CleanWidth_1)
|
||||
{
|
||||
indent = (screen.GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = screen.GetWidth() - 40 * CleanXfac_1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = (indent - 160) * CleanXfac_1 + screen.GetWidth() / 2;
|
||||
}
|
||||
|
||||
int ytop = y + mDesc.mScrollTop * 8 * CleanYfac_1;
|
||||
int lastrow = screen.GetHeight() - SmallFont.GetHeight() * CleanYfac_1;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < mDesc.mItems.Size() && y <= lastrow; i++)
|
||||
{
|
||||
// Don't scroll the uppermost items
|
||||
if (i == mDesc.mScrollTop)
|
||||
{
|
||||
i += mDesc.mScrollPos;
|
||||
if (i >= mDesc.mItems.Size()) break; // skipped beyond end of menu
|
||||
}
|
||||
bool isSelected = mDesc.mSelectedItem == i;
|
||||
int cur_indent = mDesc.mItems[i].Draw(mDesc, y, indent, isSelected);
|
||||
if (cur_indent >= 0 && isSelected && mDesc.mItems[i].Selectable())
|
||||
{
|
||||
if (((MenuTime() % 8) < 6) || GetCurrentMenu() != self)
|
||||
{
|
||||
DrawConText(OptionMenuSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd");
|
||||
}
|
||||
}
|
||||
y += fontheight;
|
||||
}
|
||||
|
||||
CanScrollUp = (mDesc.mScrollPos > 0);
|
||||
CanScrollDown = (i < mDesc.mItems.Size());
|
||||
VisBottom = i - 1;
|
||||
|
||||
if (CanScrollUp)
|
||||
{
|
||||
DrawConText(Font.CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a");
|
||||
}
|
||||
if (CanScrollDown)
|
||||
{
|
||||
DrawConText(Font.CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b");
|
||||
}
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void SetFocus(MenuItemBase fc)
|
||||
{
|
||||
mFocusControl = OptionMenuItem(fc);
|
||||
}
|
||||
|
||||
override bool CheckFocus(MenuItemBase fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
|
||||
override void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class GameplayMenu : OptionMenu
|
||||
|
@ -29,3 +461,9 @@ class CompatibilityMenu : OptionMenu
|
|||
DTA_CleanNoMove_1, true);
|
||||
}
|
||||
}
|
||||
|
||||
class JoystickConfigMenu : OptionMenu
|
||||
{
|
||||
// This is not really needed anymore but needs to be kept for old MENUDEFs that keep the entry
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue