qzdoom-gpl/src/menu/optionmenuitems.h
Randy Heit 10f1281977 - Remove LabelOffset from menus entirely and just compute things so that the console font and
small font, when mixed on the same line, align at their baselines.

SVN r3786 (trunk)
2012-07-26 05:27:37 +00:00

960 lines
24 KiB
C++

/*
** optionmenuitems.h
** Control items for option menus
**
**---------------------------------------------------------------------------
** Copyright 2010 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.
**---------------------------------------------------------------------------
**
*/
void M_DrawConText (int color, int x, int y, const char *str);
void M_SetVideoMode();
//=============================================================================
//
// opens a submenu, action is a submenu name
//
//=============================================================================
class FOptionMenuItemSubmenu : public FOptionMenuItem
{
int mParam;
public:
FOptionMenuItemSubmenu(const char *label, const char *menu, int param = 0)
: FOptionMenuItem(label, menu)
{
mParam = param;
}
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColorMore);
return indent;
}
bool Activate()
{
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
M_SetMenu(mAction, mParam);
return true;
}
};
//=============================================================================
//
// Executes a CCMD, action is a CCMD name
//
//=============================================================================
class FOptionMenuItemCommand : public FOptionMenuItemSubmenu
{
public:
FOptionMenuItemCommand(const char *label, const char *menu)
: FOptionMenuItemSubmenu(label, menu)
{
}
bool Activate()
{
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
C_DoCommand(mAction);
return true;
}
};
//=============================================================================
//
// Executes a CCMD after confirmation, action is a CCMD name
//
//=============================================================================
class FOptionMenuItemSafeCommand : public FOptionMenuItemCommand
{
// action is a CCMD
public:
FOptionMenuItemSafeCommand(const char *label, const char *menu)
: FOptionMenuItemCommand(label, menu)
{
}
bool MenuEvent (int mkey, bool fromcontroller)
{
if (mkey == MKEY_MBYes)
{
C_DoCommand(mAction);
return true;
}
return FOptionMenuItemCommand::MenuEvent(mkey, fromcontroller);
}
bool Activate()
{
M_StartMessage("Do you really want to do this?", 0);
return true;
}
};
//=============================================================================
//
// Base class for option lists
//
//=============================================================================
class FOptionMenuItemOptionBase : public FOptionMenuItem
{
protected:
// action is a CVAR
FName mValues; // Entry in OptionValues table
FBaseCVar *mGrayCheck;
int mCenter;
public:
enum
{
OP_VALUES = 0x11001
};
FOptionMenuItemOptionBase(const char *label, const char *menu, const char *values, const char *graycheck, int center)
: FOptionMenuItem(label, menu)
{
mValues = values;
mGrayCheck = (FBoolCVar*)FindCVar(graycheck, NULL);
mCenter = center;
}
bool SetString(int i, const char *newtext)
{
if (i == OP_VALUES)
{
FOptionValues **opt = OptionValues.CheckKey(newtext);
mValues = newtext;
if (opt != NULL && *opt != NULL)
{
int s = GetSelection();
if (s >= (int)(*opt)->mValues.Size()) s = 0;
SetSelection(s); // readjust the CVAR if its value is outside the range now
return true;
}
}
return false;
}
//=============================================================================
virtual int GetSelection() = 0;
virtual void SetSelection(int Selection) = 0;
//=============================================================================
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
bool grayed = mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool);
if (mCenter)
{
indent = (screen->GetWidth() / 2);
}
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, grayed);
int overlay = grayed? MAKEARGB(96,48,0,0) : 0;
const char *text;
int Selection = GetSelection();
FOptionValues **opt = OptionValues.CheckKey(mValues);
if (Selection < 0 || opt == NULL || *opt == NULL)
{
text = "Unknown";
}
else
{
text = (*opt)->mValues[Selection].Text;
}
screen->DrawText (SmallFont, OptionSettings.mFontColorValue, indent + CURSORSPACE, y,
text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE);
return indent;
}
//=============================================================================
bool MenuEvent (int mkey, bool fromcontroller)
{
FOptionValues **opt = OptionValues.CheckKey(mValues);
if (opt != NULL && *opt != NULL && (*opt)->mValues.Size() > 0)
{
int Selection = GetSelection();
if (mkey == MKEY_Left)
{
if (Selection == -1) Selection = 0;
else if (--Selection < 0) Selection = (*opt)->mValues.Size()-1;
}
else if (mkey == MKEY_Right || mkey == MKEY_Enter)
{
if (++Selection >= (int)(*opt)->mValues.Size()) Selection = 0;
}
else
{
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
}
SetSelection(Selection);
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
}
return true;
}
bool Selectable()
{
return !(mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool));
}
};
//=============================================================================
//
// Change a CVAR, action is the CVAR name
//
//=============================================================================
class FOptionMenuItemOption : public FOptionMenuItemOptionBase
{
// action is a CVAR
FBaseCVar *mCVar;
public:
FOptionMenuItemOption(const char *label, const char *menu, const char *values, const char *graycheck, int center)
: FOptionMenuItemOptionBase(label, menu, values, graycheck, center)
{
mCVar = FindCVar(mAction, NULL);
}
//=============================================================================
int GetSelection()
{
int Selection = -1;
FOptionValues **opt = OptionValues.CheckKey(mValues);
if (opt != NULL && *opt != NULL && mCVar != NULL && (*opt)->mValues.Size() > 0)
{
if ((*opt)->mValues[0].TextValue.IsEmpty())
{
UCVarValue cv = mCVar->GetGenericRep(CVAR_Float);
for(unsigned i = 0; i < (*opt)->mValues.Size(); i++)
{
if (fabs(cv.Float - (*opt)->mValues[i].Value) < FLT_EPSILON)
{
Selection = i;
break;
}
}
}
else
{
UCVarValue cv = mCVar->GetGenericRep(CVAR_String);
for(unsigned i = 0; i < (*opt)->mValues.Size(); i++)
{
if ((*opt)->mValues[i].TextValue.CompareNoCase(cv.String) == 0)
{
Selection = i;
break;
}
}
}
}
return Selection;
}
void SetSelection(int Selection)
{
UCVarValue value;
FOptionValues **opt = OptionValues.CheckKey(mValues);
if (opt != NULL && *opt != NULL && mCVar != NULL && (*opt)->mValues.Size() > 0)
{
if ((*opt)->mValues[0].TextValue.IsEmpty())
{
value.Float = (float)(*opt)->mValues[Selection].Value;
mCVar->SetGenericRep (value, CVAR_Float);
}
else
{
value.String = (*opt)->mValues[Selection].TextValue.LockBuffer();
mCVar->SetGenericRep (value, CVAR_String);
(*opt)->mValues[Selection].TextValue.UnlockBuffer();
}
}
}
};
//=============================================================================
//
// This class is used to capture the key to be used as the new key binding
// for a control item
//
//=============================================================================
class DEnterKey : public DMenu
{
DECLARE_CLASS(DEnterKey, DMenu)
int *pKey;
public:
DEnterKey(DMenu *parent, int *keyptr)
: DMenu(parent)
{
pKey = keyptr;
SetMenuMessage(1);
menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture...
}
bool TranslateKeyboardEvents()
{
return false;
}
void SetMenuMessage(int which)
{
if (mParentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu)))
{
DOptionMenu *m = barrier_cast<DOptionMenu*>(mParentMenu);
FListMenuItem *it = m->GetItem(NAME_Controlmessage);
if (it != NULL)
{
it->SetValue(0, which);
}
}
}
bool Responder(event_t *ev)
{
if (ev->type == EV_KeyDown)
{
*pKey = ev->data1;
menuactive = MENU_On;
SetMenuMessage(0);
Close();
mParentMenu->MenuEvent((ev->data1 == KEY_ESCAPE)? MKEY_Abort : MKEY_Input, 0);
return true;
}
return false;
}
void Drawer()
{
mParentMenu->Drawer();
}
};
#ifndef NO_IMP
IMPLEMENT_ABSTRACT_CLASS(DEnterKey)
#endif
//=============================================================================
//
// // Edit a key binding, Action is the CCMD to bind
//
//=============================================================================
class FOptionMenuItemControl : public FOptionMenuItem
{
FKeyBindings *mBindings;
int mInput;
bool mWaiting;
public:
FOptionMenuItemControl(const char *label, const char *menu, FKeyBindings *bindings)
: FOptionMenuItem(label, menu)
{
mBindings = bindings;
mWaiting = false;
}
//=============================================================================
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
drawLabel(indent, y, mWaiting? OptionSettings.mFontColorHighlight:
(selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor));
char description[64];
int Key1, Key2;
mBindings->GetKeysForCommand(mAction, &Key1, &Key2);
C_NameKeys (description, Key1, Key2);
if (description[0])
{
M_DrawConText(CR_WHITE, indent + CURSORSPACE, y + (OptionSettings.mLinespacing-8)*CleanYfac_1, description);
}
else
{
screen->DrawText(SmallFont, CR_BLACK, indent + CURSORSPACE, y + (OptionSettings.mLinespacing-8)*CleanYfac_1, "---",
DTA_CleanNoMove_1, true, TAG_DONE);
}
return indent;
}
//=============================================================================
bool MenuEvent(int mkey, bool fromcontroller)
{
if (mkey == MKEY_Input)
{
mWaiting = false;
mBindings->SetBind(mInput, mAction);
return true;
}
else if (mkey == MKEY_Clear)
{
mBindings->UnbindACommand(mAction);
return true;
}
else if (mkey == MKEY_Abort)
{
mWaiting = false;
return true;
}
return false;
}
bool Activate()
{
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
mWaiting = true;
DMenu *input = new DEnterKey(DMenu::CurrentMenu, &mInput);
M_ActivateMenu(input);
return true;
}
};
//=============================================================================
//
//
//
//=============================================================================
class FOptionMenuItemStaticText : public FOptionMenuItem
{
EColorRange mColor;
public:
FOptionMenuItemStaticText(const char *label, bool header)
: FOptionMenuItem(label, NAME_None, true)
{
mColor = header? OptionSettings.mFontColorHeader : OptionSettings.mFontColor;
}
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
drawLabel(indent, y, mColor);
return -1;
}
bool Selectable()
{
return false;
}
};
//=============================================================================
//
//
//
//=============================================================================
class FOptionMenuItemStaticTextSwitchable : public FOptionMenuItem
{
EColorRange mColor;
FString mAltText;
int mCurrent;
public:
FOptionMenuItemStaticTextSwitchable(const char *label, const char *label2, FName action, bool header)
: FOptionMenuItem(label, action, true)
{
mColor = header? OptionSettings.mFontColorHeader : OptionSettings.mFontColor;
mAltText = label2;
mCurrent = 0;
}
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
const char *txt = mCurrent? (const char*)mAltText : mLabel;
int w = SmallFont->StringWidth(txt) * CleanXfac_1;
int x = (screen->GetWidth() - w) / 2;
screen->DrawText (SmallFont, mColor, x, y, txt, DTA_CleanNoMove_1, true, TAG_DONE);
return -1;
}
bool SetValue(int i, int val)
{
if (i == 0)
{
mCurrent = val;
return true;
}
return false;
}
bool SetString(int i, const char *newtext)
{
if (i == 0)
{
mAltText = newtext;
return true;
}
return false;
}
bool Selectable()
{
return false;
}
};
//=============================================================================
//
//
//
//=============================================================================
class FOptionMenuSliderBase : public FOptionMenuItem
{
// action is a CVAR
double mMin, mMax, mStep;
int mShowValue;
int mDrawX;
int mSliderShort;
public:
FOptionMenuSliderBase(const char *label, double min, double max, double step, int showval)
: FOptionMenuItem(label, NAME_None)
{
mMin = min;
mMax = max;
mStep = step;
mShowValue = showval;
mDrawX = 0;
mSliderShort = 0;
}
virtual double GetValue() = 0;
virtual void SetValue(double val) = 0;
//=============================================================================
//
// Draw a slider. Set fracdigits negative to not display the current value numerically.
//
//=============================================================================
void DrawSlider (int x, int y, double min, double max, double cur, int fracdigits, int indent)
{
char textbuf[16];
double range;
int maxlen = 0;
int right = x + (12*8 + 4) * CleanXfac_1;
int cy = y + (OptionSettings.mLinespacing-8)*CleanYfac_1;
range = max - min;
double ccur = clamp(cur, min, max) - min;
if (fracdigits >= 0)
{
mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, max);
maxlen = SmallFont->StringWidth(textbuf) * CleanXfac_1;
}
mSliderShort = right + maxlen > screen->GetWidth();
if (!mSliderShort)
{
M_DrawConText(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12");
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13");
}
else
{
// On 320x200 we need a shorter slider
M_DrawConText(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x12");
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13");
right -= 5*8*CleanXfac_1;
}
if (fracdigits >= 0 && right + maxlen <= screen->GetWidth())
{
mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur);
screen->DrawText(SmallFont, CR_DARKGRAY, right, y, textbuf, DTA_CleanNoMove_1, true, TAG_DONE);
}
}
//=============================================================================
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor);
mDrawX = indent + CURSORSPACE;
DrawSlider (mDrawX, y, mMin, mMax, GetValue(), mShowValue, indent);
return indent;
}
//=============================================================================
bool MenuEvent (int mkey, bool fromcontroller)
{
double value = GetValue();
if (mkey == MKEY_Left)
{
value -= mStep;
}
else if (mkey == MKEY_Right)
{
value += mStep;
}
else
{
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
}
SetValue(clamp(value, mMin, mMax));
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
return true;
}
bool MouseEvent(int type, int x, int y)
{
DOptionMenu *lm = static_cast<DOptionMenu*>(DMenu::CurrentMenu);
if (type != DMenu::MOUSE_Click)
{
if (!lm->CheckFocus(this)) return false;
}
if (type == DMenu::MOUSE_Release)
{
lm->ReleaseFocus();
}
int slide_left = mDrawX+8*CleanXfac_1;
int slide_right = slide_left + (10*8*CleanXfac_1 >> mSliderShort); // 12 char cells with 8 pixels each.
if (type == DMenu::MOUSE_Click)
{
if (x < slide_left || x >= slide_right) return true;
}
x = clamp(x, slide_left, slide_right);
double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left);
if (v != GetValue())
{
SetValue(v);
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
}
if (type == DMenu::MOUSE_Click)
{
lm->SetFocus(this);
}
return true;
}
};
//=============================================================================
//
//
//
//=============================================================================
class FOptionMenuSliderCVar : public FOptionMenuSliderBase
{
FBaseCVar *mCVar;
public:
FOptionMenuSliderCVar(const char *label, const char *menu, double min, double max, double step, int showval)
: FOptionMenuSliderBase(label, min, max, step, showval)
{
mCVar = FindCVar(menu, NULL);
}
double GetValue()
{
if (mCVar != NULL)
{
return mCVar->GetGenericRep(CVAR_Float).Float;
}
else
{
return 0;
}
}
void SetValue(double val)
{
if (mCVar != NULL)
{
UCVarValue value;
value.Float = (float)val;
mCVar->SetGenericRep(value, CVAR_Float);
}
}
};
//=============================================================================
//
//
//
//=============================================================================
class FOptionMenuSliderVar : public FOptionMenuSliderBase
{
float *mPVal;
public:
FOptionMenuSliderVar(const char *label, float *pVal, double min, double max, double step, int showval)
: FOptionMenuSliderBase(label, min, max, step, showval)
{
mPVal = pVal;
}
double GetValue()
{
return *mPVal;
}
void SetValue(double val)
{
*mPVal = (float)val;
}
};
//=============================================================================
//
// // Edit a key binding, Action is the CCMD to bind
//
//=============================================================================
class FOptionMenuItemColorPicker : public FOptionMenuItem
{
FColorCVar *mCVar;
public:
enum
{
CPF_RESET = 0x20001,
};
FOptionMenuItemColorPicker(const char *label, const char *menu)
: FOptionMenuItem(label, menu)
{
FBaseCVar *cv = FindCVar(menu, NULL);
if (cv->GetRealType() == CVAR_Color)
{
mCVar = (FColorCVar*)cv;
}
else mCVar = NULL;
}
//=============================================================================
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor);
if (mCVar != NULL)
{
int box_x = indent + CURSORSPACE;
int box_y = y + CleanYfac_1;
screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + OptionSettings.mLinespacing*CleanYfac_1,
-1, (uint32)*mCVar | 0xff000000);
}
return indent;
}
bool SetValue(int i, int v)
{
if (i == CPF_RESET && mCVar != NULL)
{
mCVar->ResetToDefault();
return true;
}
return false;
}
bool Activate()
{
if (mCVar != NULL)
{
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
DMenu *picker = StartPickerMenu(DMenu::CurrentMenu, mLabel, mCVar);
if (picker != NULL)
{
M_ActivateMenu(picker);
return true;
}
}
return false;
}
};
class FOptionMenuScreenResolutionLine : public FOptionMenuItem
{
FString mResTexts[3];
int mSelection;
int mHighlight;
int mMaxValid;
public:
enum
{
SRL_INDEX = 0x30000,
SRL_SELECTION = 0x30003,
SRL_HIGHLIGHT = 0x30004,
};
FOptionMenuScreenResolutionLine(const char *action)
: FOptionMenuItem("", action)
{
mSelection = 0;
mHighlight = -1;
}
bool SetValue(int i, int v)
{
if (i == SRL_SELECTION)
{
mSelection = v;
return true;
}
else if (i == SRL_HIGHLIGHT)
{
mHighlight = v;
return true;
}
return false;
}
bool GetValue(int i, int *v)
{
if (i == SRL_SELECTION)
{
*v = mSelection;
return true;
}
return false;
}
bool SetString(int i, const char *newtext)
{
if (i >= SRL_INDEX && i <= SRL_INDEX+2)
{
mResTexts[i-SRL_INDEX] = newtext;
if (mResTexts[0].IsEmpty()) mMaxValid = -1;
else if (mResTexts[1].IsEmpty()) mMaxValid = 0;
else if (mResTexts[2].IsEmpty()) mMaxValid = 1;
else mMaxValid = 2;
return true;
}
return false;
}
bool GetString(int i, char *s, int len)
{
if (i >= SRL_INDEX && i <= SRL_INDEX+2)
{
strncpy(s, mResTexts[i-SRL_INDEX], len-1);
s[len-1] = 0;
return true;
}
return false;
}
bool MenuEvent (int mkey, bool fromcontroller)
{
if (mkey == MKEY_Left)
{
if (--mSelection < 0) mSelection = mMaxValid;
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
return true;
}
else if (mkey == MKEY_Right)
{
if (++mSelection > mMaxValid) mSelection = 0;
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
return true;
}
else
{
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
}
return false;
}
bool MouseEvent(int type, int x, int y)
{
int colwidth = screen->GetWidth() / 3;
mSelection = x / colwidth;
return FOptionMenuItem::MouseEvent(type, x, y);
}
bool Activate()
{
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
M_SetVideoMode();
return true;
}
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{
int colwidth = screen->GetWidth() / 3;
EColorRange color;
for (int x = 0; x < 3; x++)
{
if (selected && mSelection == x)
color = OptionSettings.mFontColorSelection;
else if (x == mHighlight)
color = OptionSettings.mFontColorHighlight;
else
color = OptionSettings.mFontColorValue;
screen->DrawText (SmallFont, color, colwidth * x + 20 * CleanXfac_1, y, mResTexts[x], DTA_CleanNoMove_1, true, TAG_DONE);
}
return colwidth * mSelection + 20 * CleanXfac_1 - CURSORSPACE;
}
bool Selectable()
{
return mMaxValid >= 0;
}
};
#ifndef NO_IMP
CCMD(am_restorecolors)
{
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu)))
{
DOptionMenu *m = (DOptionMenu*)DMenu::CurrentMenu;
const FOptionMenuDescriptor *desc = m->GetDescriptor();
// Find the color cvars by scanning the MapColors menu.
for (unsigned i = 0; i < desc->mItems.Size(); ++i)
{
desc->mItems[i]->SetValue(FOptionMenuItemColorPicker::CPF_RESET, 0);
}
}
}
#endif