mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 06:53:58 +00:00
Merge remote-tracking branch 'gzdoom/master' into qzdoom
# Conflicts: # src/v_video.cpp
This commit is contained in:
commit
42a7dbe33a
41 changed files with 2100 additions and 2498 deletions
|
@ -922,15 +922,12 @@ set( FASTMATH_PCH_SOURCES
|
|||
intermission/intermission.cpp
|
||||
intermission/intermission_parse.cpp
|
||||
menu/joystickmenu.cpp
|
||||
menu/listmenu.cpp
|
||||
menu/loadsavemenu.cpp
|
||||
menu/menu.cpp
|
||||
menu/menudef.cpp
|
||||
menu/menuinput.cpp
|
||||
menu/messagebox.cpp
|
||||
menu/optionmenu.cpp
|
||||
menu/playermenu.cpp
|
||||
menu/readthis.cpp
|
||||
menu/videomenu.cpp
|
||||
oplsynth/fmopl.cpp
|
||||
oplsynth/mlopl.cpp
|
||||
|
|
|
@ -207,7 +207,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetInt)
|
|||
{
|
||||
// Only menus are allowed to change CVARs.
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
if (!(self->GetFlags() & CVAR_MOD) && DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (!(self->GetFlags() & CVAR_MOD) && CurrentMenu == nullptr) return 0;
|
||||
PARAM_INT(val);
|
||||
UCVarValue v;
|
||||
v.Int = val;
|
||||
|
@ -219,7 +219,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetFloat)
|
|||
{
|
||||
// Only menus are allowed to change CVARs.
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
if (!(self->GetFlags() & CVAR_MOD) && DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (!(self->GetFlags() & CVAR_MOD) && CurrentMenu == nullptr) return 0;
|
||||
PARAM_FLOAT(val);
|
||||
UCVarValue v;
|
||||
v.Float = (float)val;
|
||||
|
@ -231,7 +231,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetString)
|
|||
{
|
||||
// Only menus are allowed to change CVARs.
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
if (!(self->GetFlags() & CVAR_MOD) && DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (!(self->GetFlags() & CVAR_MOD) && CurrentMenu == nullptr) return 0;
|
||||
PARAM_STRING(val);
|
||||
UCVarValue v;
|
||||
v.String = val.GetChars();
|
||||
|
|
|
@ -666,7 +666,7 @@ void C_DoCommand (const char *cmd, int keynum)
|
|||
// This is only accessible to the special menu item to run CCMDs.
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand)
|
||||
{
|
||||
if (DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (CurrentMenu == nullptr) return 0;
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(cmd);
|
||||
C_DoCommand(cmd);
|
||||
|
|
|
@ -95,23 +95,6 @@ char *copystring (const char *s)
|
|||
return b;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// ncopystring
|
||||
//
|
||||
// If the string has no content, returns NULL. Otherwise, returns a copy.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
char *ncopystring (const char *string)
|
||||
{
|
||||
if (string == NULL || string[0] == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return copystring (string);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ReplaceString
|
||||
|
|
|
@ -38,7 +38,6 @@ int ParseHex(const char *str, FScriptPosition *sc = nullptr);
|
|||
bool IsNum (const char *str); // [RH] added
|
||||
|
||||
char *copystring(const char *s);
|
||||
char *ncopystring(const char *s);
|
||||
void ReplaceString (char **ptr, const char *str);
|
||||
|
||||
bool CheckWildcards (const char *pattern, const char *text);
|
||||
|
|
|
@ -73,7 +73,7 @@ EXTERN_CVAR (Int, autosavecount)
|
|||
#define SIMULATEERRORS 0
|
||||
|
||||
extern BYTE *demo_p; // [RH] Special "ticcmds" get recorded in demos
|
||||
extern char savedescription[SAVESTRINGSIZE];
|
||||
extern FString savedescription;
|
||||
extern FString savegamefile;
|
||||
|
||||
extern short consistancy[MAXPLAYERS][BACKUPTICS];
|
||||
|
@ -2418,8 +2418,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
|||
savegamefile = s;
|
||||
delete[] s;
|
||||
s = ReadString (stream);
|
||||
memset (savedescription, 0, sizeof(savedescription));
|
||||
strncpy (savedescription, s, sizeof(savedescription));
|
||||
savedescription = s;
|
||||
if (player != consoleplayer)
|
||||
{
|
||||
// Paths sent over the network will be valid for the system that sent
|
||||
|
|
|
@ -226,7 +226,7 @@ int mousex;
|
|||
int mousey;
|
||||
|
||||
FString savegamefile;
|
||||
char savedescription[SAVESTRINGSIZE];
|
||||
FString savedescription;
|
||||
|
||||
// [RH] Name of screenshot file to generate (usually NULL)
|
||||
FString shotfile;
|
||||
|
@ -1081,7 +1081,7 @@ void G_Ticker ()
|
|||
G_DoSaveGame (true, savegamefile, savedescription);
|
||||
gameaction = ga_nothing;
|
||||
savegamefile = "";
|
||||
savedescription[0] = '\0';
|
||||
savedescription = "";
|
||||
break;
|
||||
case ga_autosave:
|
||||
G_DoAutoSave ();
|
||||
|
@ -2068,8 +2068,7 @@ void G_SaveGame (const char *filename, const char *description)
|
|||
else
|
||||
{
|
||||
savegamefile = filename;
|
||||
strncpy (savedescription, description, sizeof(savedescription)-1);
|
||||
savedescription[sizeof(savedescription)-1] = '\0';
|
||||
savedescription = description;
|
||||
sendsave = true;
|
||||
}
|
||||
}
|
||||
|
@ -2119,7 +2118,7 @@ extern void P_CalcHeight (player_t *);
|
|||
|
||||
void G_DoAutoSave ()
|
||||
{
|
||||
char description[SAVESTRINGSIZE];
|
||||
FString description;
|
||||
FString file;
|
||||
// Keep up to four autosaves at a time
|
||||
UCVarValue num;
|
||||
|
@ -2147,10 +2146,7 @@ void G_DoAutoSave ()
|
|||
}
|
||||
|
||||
readableTime = myasctime ();
|
||||
strcpy (description, "Autosave ");
|
||||
strncpy (description+9, readableTime+4, 12);
|
||||
description[9+12] = 0;
|
||||
|
||||
description.Format("Autosave %.12s", readableTime + 4);
|
||||
G_DoSaveGame (false, file, description);
|
||||
}
|
||||
|
||||
|
@ -2310,7 +2306,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
|
||||
WriteZip(filename, savegame_filenames, savegame_content);
|
||||
|
||||
savegameManager.NotifyNewSave (filename.GetChars(), description, okForQuicksave);
|
||||
savegameManager.NotifyNewSave (filename, description, okForQuicksave);
|
||||
|
||||
// delete the JSON buffers we created just above. Everything else will
|
||||
// either still be needed or taken care of automatically.
|
||||
|
|
|
@ -1462,6 +1462,7 @@ void G_InitLevelLocals ()
|
|||
level.LevelName = level.info->LookupLevelName();
|
||||
level.NextMap = info->NextMap;
|
||||
level.NextSecretMap = info->NextSecretMap;
|
||||
level.F1Pic = info->F1Pic;
|
||||
|
||||
compatflags.Callback();
|
||||
compatflags2.Callback();
|
||||
|
@ -1910,6 +1911,7 @@ DEFINE_FIELD(FLevelLocals, LevelName)
|
|||
DEFINE_FIELD(FLevelLocals, MapName)
|
||||
DEFINE_FIELD(FLevelLocals, NextMap)
|
||||
DEFINE_FIELD(FLevelLocals, NextSecretMap)
|
||||
DEFINE_FIELD(FLevelLocals, F1Pic)
|
||||
DEFINE_FIELD(FLevelLocals, maptype)
|
||||
DEFINE_FIELD(FLevelLocals, Music)
|
||||
DEFINE_FIELD(FLevelLocals, musicorder)
|
||||
|
|
|
@ -25,6 +25,7 @@ struct FLevelLocals
|
|||
FString MapName; // the lump name (E1M1, MAP01, etc)
|
||||
FString NextMap; // go here when using the regular exit
|
||||
FString NextSecretMap; // map to go to when used secret exit
|
||||
FString F1Pic;
|
||||
EMapType maptype;
|
||||
|
||||
TStaticArray<vertex_t> vertexes;
|
||||
|
|
|
@ -1970,6 +1970,7 @@ static void ClearMapinfo()
|
|||
DefaultSkill = -1;
|
||||
DeinitIntermissions();
|
||||
level.info = NULL;
|
||||
level.F1Pic = "";
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -51,6 +51,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1)
|
|||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, norandomplayerclass)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, infoPages)
|
||||
|
||||
|
||||
const char *GameNames[17] =
|
||||
|
|
|
@ -186,12 +186,12 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
{
|
||||
opt->mSelectedItem = opt->mItems.Size() - 1;
|
||||
}
|
||||
opt->CalcIndent();
|
||||
//opt->CalcIndent();
|
||||
|
||||
// If the joystick config menu is open, close it if the device it's open for is gone.
|
||||
if (DMenu::CurrentMenu != nullptr && (DMenu::CurrentMenu->IsKindOf("JoystickConfigMenu")))
|
||||
if (CurrentMenu != nullptr && (CurrentMenu->IsKindOf("JoystickConfigMenu")))
|
||||
{
|
||||
auto p = DMenu::CurrentMenu->PointerVar<IJoystickConfig>("mJoy");
|
||||
auto p = CurrentMenu->PointerVar<IJoystickConfig>("mJoy");
|
||||
if (p != nullptr)
|
||||
{
|
||||
unsigned i;
|
||||
|
@ -204,7 +204,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
}
|
||||
if (i == Joysticks.Size())
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
CurrentMenu->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
** listmenu.cpp
|
||||
** A simple menu consisting of a list of items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "v_video.h"
|
||||
#include "v_font.h"
|
||||
#include "cmdlib.h"
|
||||
#include "gstrings.h"
|
||||
#include "g_level.h"
|
||||
#include "gi.h"
|
||||
#include "d_gui.h"
|
||||
#include "d_event.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
IMPLEMENT_CLASS(DListMenu, false, false)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DListMenu)
|
||||
IMPLEMENT_POINTER(mFocusControl)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DListMenu::DListMenu(DMenu *parent, DListMenuDescriptor *desc)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mDesc = NULL;
|
||||
if (desc != NULL) Init(parent, desc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Init(DMenu *parent, DListMenuDescriptor *desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
GC::WriteBarrier(this, parent);
|
||||
mDesc = desc;
|
||||
if (desc->mCenter)
|
||||
{
|
||||
int center = 160;
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
int xpos = mDesc->mItems[i]->GetX();
|
||||
int width = mDesc->mItems[i]->GetWidth();
|
||||
int curx = mDesc->mSelectOfsX;
|
||||
|
||||
if (width > 0 && mDesc->mItems[i]->Selectable())
|
||||
{
|
||||
int left = 160 - (width - curx) / 2 - curx;
|
||||
if (left < center) center = left;
|
||||
}
|
||||
}
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
int width = mDesc->mItems[i]->GetWidth();
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
mDesc->mItems[i]->SetX(center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DMenuItemBase *DListMenu::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 DListMenu::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
int ch = tolower (ev->data1);
|
||||
|
||||
for(unsigned i = mDesc->mSelectedItem + 1; i < mDesc->mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->CheckHotkey(ch))
|
||||
{
|
||||
mDesc->mSelectedItem = i;
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < mDesc->mSelectedItem; i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->CheckHotkey(ch))
|
||||
{
|
||||
mDesc->mSelectedItem = i;
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int oldSelect = mDesc->mSelectedItem;
|
||||
int startedAt = mDesc->mSelectedItem;
|
||||
if (startedAt < 0) startedAt = 0;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
do
|
||||
{
|
||||
if (--mDesc->mSelectedItem < 0) mDesc->mSelectedItem = mDesc->mItems.Size()-1;
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
if (mDesc->mSelectedItem == startedAt) mDesc->mSelectedItem = oldSelect;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
do
|
||||
{
|
||||
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) mDesc->mSelectedItem = 0;
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
if (mDesc->mSelectedItem == startedAt) mDesc->mSelectedItem = oldSelect;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (mFocusControl != NULL)
|
||||
{
|
||||
mFocusControl->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((mDesc->mWLeft <= 0 || x > mDesc->mWLeft) &&
|
||||
(mDesc->mWRight <= 0 || x < mDesc->mWRight))
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->CheckCoordinate(x, y))
|
||||
{
|
||||
if ((int)i != mDesc->mSelectedItem)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc->mSelectedItem = i;
|
||||
mDesc->mItems[i]->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mDesc->mSelectedItem = -1;
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Ticker ()
|
||||
{
|
||||
Super::Ticker();
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
mDesc->mItems[i]->Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Drawer ()
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->mEnabled) mDesc->mItems[i]->Drawer(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);
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DMenuItemBase, false, false)
|
File diff suppressed because it is too large
Load diff
|
@ -63,24 +63,23 @@
|
|||
CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE)
|
||||
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE)
|
||||
CVAR(Int, m_use_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DMenu *DMenu::CurrentMenu;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu)
|
||||
{
|
||||
ACTION_RETURN_OBJECT(DMenu::CurrentMenu);
|
||||
ACTION_RETURN_OBJECT(CurrentMenu);
|
||||
}
|
||||
|
||||
int DMenu::MenuTime;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, MenuTime)
|
||||
{
|
||||
ACTION_RETURN_INT(DMenu::MenuTime);
|
||||
ACTION_RETURN_INT(MenuTime);
|
||||
}
|
||||
|
||||
FGameStartup GameStartupInfo;
|
||||
|
@ -92,6 +91,8 @@ bool MenuButtonOrigin[NUM_MKEYS];
|
|||
int BackbuttonTime;
|
||||
float BackbuttonAlpha;
|
||||
static bool MenuEnabled = true;
|
||||
DMenu *CurrentMenu;
|
||||
int MenuTime;
|
||||
|
||||
void M_InitVideoModes();
|
||||
extern PClass *DefaultListMenuClass;
|
||||
|
@ -140,7 +141,7 @@ void M_MarkMenus()
|
|||
{
|
||||
GC::Mark(pair->Value);
|
||||
}
|
||||
GC::Mark(DMenu::CurrentMenu);
|
||||
GC::Mark(CurrentMenu);
|
||||
}
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -237,7 +238,7 @@ bool DMenu::MenuEvent (int mkey, bool fromcontroller)
|
|||
{
|
||||
Close();
|
||||
S_Sound (CHAN_VOICE | CHAN_UI,
|
||||
DMenu::CurrentMenu != nullptr? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
|
||||
CurrentMenu != nullptr? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -272,13 +273,13 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
|
|||
|
||||
void DMenu::Close ()
|
||||
{
|
||||
if (DMenu::CurrentMenu == nullptr) return; // double closing can happen in the save menu.
|
||||
assert(DMenu::CurrentMenu == this);
|
||||
DMenu::CurrentMenu = mParentMenu;
|
||||
if (CurrentMenu == nullptr) return; // double closing can happen in the save menu.
|
||||
assert(CurrentMenu == this);
|
||||
CurrentMenu = mParentMenu;
|
||||
Destroy();
|
||||
if (DMenu::CurrentMenu != nullptr)
|
||||
if (CurrentMenu != nullptr)
|
||||
{
|
||||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
GC::WriteBarrier(CurrentMenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -401,7 +402,7 @@ void DMenu::CallTicker()
|
|||
|
||||
void DMenu::Drawer ()
|
||||
{
|
||||
if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
if (this == CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
{
|
||||
FTexture *tex = TexMan(gameinfo.mBackButton);
|
||||
int w = tex->GetScaledWidth() * CleanXfac;
|
||||
|
@ -444,21 +445,6 @@ DEFINE_ACTION_FUNCTION(DMenu, Close)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_NAME(name);
|
||||
ACTION_RETURN_OBJECT(self->GetItem(name));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuDescriptor, GetItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DOptionMenuDescriptor);
|
||||
PARAM_NAME(name);
|
||||
ACTION_RETURN_OBJECT(self->GetItem(name));
|
||||
}
|
||||
|
||||
|
||||
bool DMenu::DimAllowed()
|
||||
{
|
||||
return true;
|
||||
|
@ -486,7 +472,7 @@ bool DMenu::TranslateKeyboardEvents()
|
|||
void M_StartControlPanel (bool makeSound)
|
||||
{
|
||||
// intro might call this repeatedly
|
||||
if (DMenu::CurrentMenu != nullptr)
|
||||
if (CurrentMenu != nullptr)
|
||||
return;
|
||||
|
||||
ResetButtonStates ();
|
||||
|
@ -518,9 +504,9 @@ void M_StartControlPanel (bool makeSound)
|
|||
void M_ActivateMenu(DMenu *menu)
|
||||
{
|
||||
if (menuactive == MENU_Off) menuactive = MENU_On;
|
||||
if (DMenu::CurrentMenu != nullptr) DMenu::CurrentMenu->ReleaseCapture();
|
||||
DMenu::CurrentMenu = menu;
|
||||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
if (CurrentMenu != nullptr) CurrentMenu->ReleaseCapture();
|
||||
CurrentMenu = menu;
|
||||
GC::WriteBarrier(CurrentMenu);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu)
|
||||
|
@ -602,6 +588,11 @@ void M_SetMenu(FName menu, int param)
|
|||
M_InitVideoModes();
|
||||
break;
|
||||
|
||||
case NAME_Quitmenu:
|
||||
// The separate menu class no longer exists but the name still needs support for existing mods.
|
||||
C_DoCommand("menu_quit");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// End of special checks
|
||||
|
@ -629,10 +620,10 @@ void M_SetMenu(FName menu, int param)
|
|||
if (cls == nullptr) cls = DefaultListMenuClass;
|
||||
if (cls == nullptr) cls = PClass::FindClass("ListMenu");
|
||||
|
||||
DListMenu *newmenu = (DListMenu *)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init)
|
||||
DMenu *newmenu = (DMenu *)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "ListMenu", Init)
|
||||
{
|
||||
VMValue params[3] = { newmenu, DMenu::CurrentMenu, ld };
|
||||
VMValue params[3] = { newmenu, CurrentMenu, ld };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0);
|
||||
}
|
||||
M_ActivateMenu(newmenu);
|
||||
|
@ -648,7 +639,7 @@ void M_SetMenu(FName menu, int param)
|
|||
DMenu *newmenu = (DMenu*)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init)
|
||||
{
|
||||
VMValue params[3] = { newmenu, DMenu::CurrentMenu, ld };
|
||||
VMValue params[3] = { newmenu, CurrentMenu, ld };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0);
|
||||
}
|
||||
M_ActivateMenu(newmenu);
|
||||
|
@ -663,7 +654,7 @@ void M_SetMenu(FName menu, int param)
|
|||
if (menuclass->IsDescendantOf(RUNTIME_CLASS(DMenu)))
|
||||
{
|
||||
DMenu *newmenu = (DMenu*)menuclass->CreateNew();
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
newmenu->mParentMenu = CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
return;
|
||||
}
|
||||
|
@ -699,7 +690,7 @@ bool M_Responder (event_t *ev)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
// There are a few input sources we are interested in:
|
||||
//
|
||||
|
@ -734,9 +725,9 @@ bool M_Responder (event_t *ev)
|
|||
}
|
||||
|
||||
// pass everything else on to the current menu
|
||||
return DMenu::CurrentMenu->CallResponder(ev);
|
||||
return CurrentMenu->CallResponder(ev);
|
||||
}
|
||||
else if (DMenu::CurrentMenu->TranslateKeyboardEvents())
|
||||
else if (CurrentMenu->TranslateKeyboardEvents())
|
||||
{
|
||||
ch = ev->data1;
|
||||
keyup = ev->subtype == EV_GUI_KeyUp;
|
||||
|
@ -755,7 +746,7 @@ bool M_Responder (event_t *ev)
|
|||
default:
|
||||
if (!keyup)
|
||||
{
|
||||
return DMenu::CurrentMenu->CallResponder(ev);
|
||||
return CurrentMenu->CallResponder(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -838,11 +829,11 @@ bool M_Responder (event_t *ev)
|
|||
{
|
||||
MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
|
||||
}
|
||||
DMenu::CurrentMenu->CallMenuEvent(mkey, fromcontroller);
|
||||
CurrentMenu->CallMenuEvent(mkey, fromcontroller);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return DMenu::CurrentMenu->CallResponder(ev) || !keyup;
|
||||
return CurrentMenu->CallResponder(ev) || !keyup;
|
||||
}
|
||||
else if (MenuEnabled)
|
||||
{
|
||||
|
@ -883,10 +874,10 @@ bool M_Responder (event_t *ev)
|
|||
|
||||
void M_Ticker (void)
|
||||
{
|
||||
DMenu::MenuTime++;
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
MenuTime++;
|
||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
DMenu::CurrentMenu->CallTicker();
|
||||
CurrentMenu->CallTicker();
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
|
@ -895,7 +886,7 @@ void M_Ticker (void)
|
|||
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
||||
{
|
||||
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
||||
DMenu::CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]);
|
||||
CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -935,14 +926,14 @@ void M_Drawer (void)
|
|||
}
|
||||
|
||||
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
if (DMenu::CurrentMenu->DimAllowed())
|
||||
if (CurrentMenu->DimAllowed())
|
||||
{
|
||||
screen->Dim(fade);
|
||||
V_SetBorderNeedRefresh();
|
||||
}
|
||||
DMenu::CurrentMenu->CallDrawer();
|
||||
CurrentMenu->CallDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -955,10 +946,10 @@ void M_Drawer (void)
|
|||
void M_ClearMenus ()
|
||||
{
|
||||
M_DemoNoPlay = false;
|
||||
if (DMenu::CurrentMenu != nullptr)
|
||||
if (CurrentMenu != nullptr)
|
||||
{
|
||||
DMenu::CurrentMenu->Destroy();
|
||||
DMenu::CurrentMenu = nullptr;
|
||||
CurrentMenu->Destroy();
|
||||
CurrentMenu = nullptr;
|
||||
}
|
||||
V_SetBorderNeedRefresh();
|
||||
menuactive = MENU_Off;
|
||||
|
@ -1196,11 +1187,11 @@ CCMD(reset2saved)
|
|||
// This really should be in the script but we can't do scripted CCMDs yet.
|
||||
CCMD(undocolorpic)
|
||||
{
|
||||
if (DMenu::CurrentMenu != NULL)
|
||||
if (CurrentMenu != NULL)
|
||||
{
|
||||
IFVIRTUALPTR(DMenu::CurrentMenu, DMenu, ResetColor)
|
||||
IFVIRTUALPTR(CurrentMenu, DMenu, ResetColor)
|
||||
{
|
||||
VMValue params[] = { (DObject*)DMenu::CurrentMenu };
|
||||
VMValue params[] = { (DObject*)CurrentMenu };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -1210,6 +1201,8 @@ CCMD(undocolorpic)
|
|||
|
||||
|
||||
DEFINE_FIELD(DMenu, mParentMenu)
|
||||
DEFINE_FIELD(DMenu, mMouseCapture);
|
||||
DEFINE_FIELD(DMenu, mBackbuttonSelected);
|
||||
|
||||
DEFINE_FIELD(DMenuDescriptor, mMenuName)
|
||||
DEFINE_FIELD(DMenuDescriptor, mNetgameMessage)
|
||||
|
@ -1220,9 +1213,6 @@ DEFINE_FIELD(DMenuItemBase, mYpos)
|
|||
DEFINE_FIELD(DMenuItemBase, mAction)
|
||||
DEFINE_FIELD(DMenuItemBase, mEnabled)
|
||||
|
||||
DEFINE_FIELD(DListMenu, mDesc)
|
||||
DEFINE_FIELD(DListMenu, mFocusControl)
|
||||
|
||||
DEFINE_FIELD(DListMenuDescriptor, mItems)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectedItem)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectOfsX)
|
||||
|
@ -1322,50 +1312,6 @@ DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, con
|
|||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckCoordinate(int x, int y)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, CheckCoordinate)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, x, y };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::Ticker()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Ticker)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DMenuItemBase::Drawer(bool selected)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Drawer)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, selected };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Selectable()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Selectable)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Activate()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Activate)
|
||||
|
@ -1378,18 +1324,6 @@ bool DMenuItemBase::Activate()
|
|||
}
|
||||
return false;
|
||||
}
|
||||
FName DMenuItemBase::GetAction(int *pparam)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetAction)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval[2];
|
||||
VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]);
|
||||
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
|
||||
return ENamedName(retval[0]);
|
||||
}
|
||||
return NAME_None;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::SetString(int i, const char *s)
|
||||
{
|
||||
|
@ -1447,112 +1381,4 @@ bool DMenuItemBase::GetValue(int i, int *pvalue)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DMenuItemBase::Enable(bool on)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Enable)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, on };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, MenuEvent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, mkey, fromcontroller };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, MouseEvent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, type, x, y };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckHotkey(int c)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, CheckHotkey)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, c };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetWidth()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetWidth)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetIndent()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetIndent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Draw)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, desc, y, indent, selected };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((DMenu::MenuTime % 8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture(TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS(DMenuItemBase, false, false)
|
||||
|
|
147
src/menu/menu.h
147
src/menu/menu.h
|
@ -58,46 +58,58 @@ extern FGameStartup GameStartupInfo;
|
|||
|
||||
struct FSaveGameNode
|
||||
{
|
||||
char Title[SAVESTRINGSIZE];
|
||||
FString SaveTitle;
|
||||
FString Filename;
|
||||
bool bOldVersion;
|
||||
bool bMissingWads;
|
||||
bool bNoDelete;
|
||||
|
||||
FSaveGameNode() { bNoDelete = false; }
|
||||
bool bOldVersion = false;
|
||||
bool bMissingWads = false;
|
||||
bool bNoDelete = false;
|
||||
};
|
||||
|
||||
struct SavegameManager
|
||||
struct FSavegameManager
|
||||
{
|
||||
private:
|
||||
TArray<FSaveGameNode*> SaveGames;
|
||||
FSaveGameNode NewSaveNode;
|
||||
int LastSaved = -1;
|
||||
int LastAccessed = -1;
|
||||
int WindowSize = 0;
|
||||
FSaveGameNode *quickSaveSlot = nullptr;
|
||||
|
||||
FileReader *currentSavePic = nullptr;
|
||||
TArray<char> SavePicData;
|
||||
|
||||
FTexture *SavePic = nullptr;
|
||||
FBrokenLines *SaveComment = nullptr;
|
||||
|
||||
void ClearSaveGames();
|
||||
public:
|
||||
int WindowSize = 0;
|
||||
FSaveGameNode *quickSaveSlot = nullptr;
|
||||
~FSavegameManager();
|
||||
|
||||
private:
|
||||
int InsertSaveNode(FSaveGameNode *node);
|
||||
int RemoveSaveSlot(int index);
|
||||
public:
|
||||
void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave);
|
||||
void ClearSaveGames();
|
||||
|
||||
void ReadSaveStrings();
|
||||
void NotifyNewSave(const char *file, const char *title, bool okForQuicksave);
|
||||
void UnloadSaveData();
|
||||
|
||||
int RemoveSaveSlot(int index);
|
||||
void LoadSavegame(int Selected);
|
||||
void DoSave(int Selected, const char *savegamestring);
|
||||
void DeleteEntry(int Selected);
|
||||
void ExtractSaveData(int index);
|
||||
void UnloadSaveData();
|
||||
unsigned ExtractSaveData(int index);
|
||||
void ClearSaveStuff();
|
||||
bool DrawSavePic(int x, int y, int w, int h);
|
||||
void DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor);
|
||||
void SetFileInfo(int Selected);
|
||||
unsigned SavegameCount();
|
||||
FSaveGameNode *GetSavegame(int i);
|
||||
void InsertNewSaveNode();
|
||||
bool RemoveNewSaveNode();
|
||||
|
||||
};
|
||||
|
||||
extern SavegameManager savegameManager;
|
||||
extern FSavegameManager savegameManager;
|
||||
class DMenu;
|
||||
extern DMenu *CurrentMenu;
|
||||
extern int MenuTime;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -241,9 +253,7 @@ class DMenu : public DObject
|
|||
DECLARE_CLASS (DMenu, DObject)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
protected:
|
||||
bool mMouseCapture;
|
||||
bool mBackbuttonSelected;
|
||||
|
||||
|
||||
public:
|
||||
enum
|
||||
|
@ -258,10 +268,9 @@ public:
|
|||
BACKBUTTON_TIME = 4*TICRATE
|
||||
};
|
||||
|
||||
static DMenu *CurrentMenu;
|
||||
static int MenuTime;
|
||||
|
||||
TObjPtr<DMenu> mParentMenu;
|
||||
bool mMouseCapture;
|
||||
bool mBackbuttonSelected;
|
||||
|
||||
DMenu(DMenu *parent = NULL);
|
||||
virtual bool Responder (event_t *ev);
|
||||
|
@ -277,8 +286,6 @@ public:
|
|||
virtual bool CheckFocus(DMenuItemBase *fc) { return false; }
|
||||
virtual void ReleaseFocus() {}
|
||||
|
||||
virtual DMenuItemBase *GetItem(FName name) { return nullptr; }
|
||||
|
||||
bool CallResponder(event_t *ev);
|
||||
bool CallMenuEvent(int mkey, bool fromcontroller);
|
||||
bool CallMouseEvent(int type, int x, int y);
|
||||
|
@ -308,70 +315,15 @@ public:
|
|||
FNameNoInit mAction;
|
||||
bool mEnabled;
|
||||
|
||||
bool CheckCoordinate(int x, int y);
|
||||
void Ticker();
|
||||
void Drawer(bool selected);
|
||||
bool Selectable();
|
||||
bool Activate();
|
||||
FName GetAction(int *pparam);
|
||||
bool SetString(int i, const char *s);
|
||||
bool GetString(int i, char *s, int len);
|
||||
bool SetValue(int i, int value);
|
||||
bool GetValue(int i, int *pvalue);
|
||||
void Enable(bool on);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
bool CheckHotkey(int c);
|
||||
int GetWidth();
|
||||
int GetIndent();
|
||||
int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected);
|
||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||
int GetY() { return mYpos; }
|
||||
int GetX() { return mXpos; }
|
||||
void SetX(int x) { mXpos = x; }
|
||||
|
||||
void DrawSelector(int xofs, int yofs, FTextureID tex);
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// list menu class runs a menu described by a DListMenuDescriptor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DListMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DListMenu, DMenu)
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
|
||||
DListMenuDescriptor *mDesc;
|
||||
DMenuItemBase *mFocusControl;
|
||||
|
||||
DListMenu(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL);
|
||||
virtual void Init(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL);
|
||||
DMenuItemBase *GetItem(FName name);
|
||||
bool Responder (event_t *ev);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void Ticker ();
|
||||
void Drawer ();
|
||||
void SetFocus(DMenuItemBase *fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
}
|
||||
bool CheckFocus(DMenuItemBase *fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -396,41 +348,10 @@ extern FOptionMap OptionValues;
|
|||
|
||||
//=============================================================================
|
||||
//
|
||||
// Input some text
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DTextEnterMenu : public DMenu
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DTextEnterMenu, DMenu)
|
||||
|
||||
public:
|
||||
FString mEnterString;
|
||||
unsigned int mEnterSize;
|
||||
unsigned int mEnterPos;
|
||||
int mSizeMode; // 1: size is length in chars. 2: also check string width
|
||||
bool mInputGridOkay;
|
||||
|
||||
int InputGridX;
|
||||
int InputGridY;
|
||||
|
||||
// [TP]
|
||||
bool AllowColors;
|
||||
|
||||
|
||||
// [TP] Added allowcolors
|
||||
DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false);
|
||||
|
||||
void Drawer ();
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool Responder(event_t *ev);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
FString GetText();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct event_t;
|
||||
void M_EnableMenu (bool on) ;
|
||||
bool M_Responder (event_t *ev);
|
||||
|
|
|
@ -147,7 +147,7 @@ static void DeinitMenus()
|
|||
}
|
||||
MenuDescriptors.Clear();
|
||||
OptionValues.Clear();
|
||||
DMenu::CurrentMenu = nullptr;
|
||||
CurrentMenu = nullptr;
|
||||
savegameManager.ClearSaveGames();
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
{
|
||||
sc.MustGetString();
|
||||
PClass *cls = PClass::FindClass(sc.String);
|
||||
if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(DListMenu)))
|
||||
if (cls == nullptr || !cls->IsDescendantOf("ListMenu"))
|
||||
{
|
||||
sc.ScriptError("Unknown menu class '%s'", sc.String);
|
||||
}
|
||||
|
@ -868,7 +868,6 @@ static void ParseOptionMenu(FScanner &sc)
|
|||
|
||||
ParseOptionMenuBody(sc, desc);
|
||||
ReplaceMenu(sc, desc);
|
||||
if (desc->mIndent == 0) desc->CalcIndent();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1340,7 +1339,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
// Delete previous contents
|
||||
for(unsigned i=0; i<ld->mItems.Size(); i++)
|
||||
{
|
||||
FName n = ld->mItems[i]->GetAction(nullptr);
|
||||
FName n = ld->mItems[i]->mAction;
|
||||
if (n == NAME_Startgame || n == NAME_StartgameConfirm)
|
||||
{
|
||||
ld->mItems.Resize(i);
|
||||
|
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
** menuinput.cpp
|
||||
** The string input code
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "v_video.h"
|
||||
#include "c_cvars.h"
|
||||
#include "d_event.h"
|
||||
#include "d_gui.h"
|
||||
#include "v_font.h"
|
||||
#include "v_palette.h"
|
||||
#include "cmdlib.h"
|
||||
// [TP] New #includes
|
||||
#include "v_text.h"
|
||||
|
||||
IMPLEMENT_CLASS(DTextEnterMenu, true, false)
|
||||
|
||||
#define INPUTGRID_WIDTH 13
|
||||
#define INPUTGRID_HEIGHT 5
|
||||
|
||||
// Heretic and Hexen do not, by default, come with glyphs for all of these
|
||||
// characters. Oh well. Doom and Strife do.
|
||||
static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] =
|
||||
"ABCDEFGHIJKLM"
|
||||
"NOPQRSTUVWXYZ"
|
||||
"0123456789+-="
|
||||
".,!?@'\":;[]()"
|
||||
"<>^#$%&*/_ \b";
|
||||
|
||||
|
||||
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DEFINE_FIELD(DTextEnterMenu, mInputGridOkay)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// [TP] Added allowcolors
|
||||
DTextEnterMenu::DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mEnterString = textbuffer;
|
||||
mEnterSize = maxlen < 0 ? UINT_MAX : unsigned(maxlen);
|
||||
mSizeMode = sizemode;
|
||||
mInputGridOkay = showgrid || m_showinputgrid;
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
InputGridX = INPUTGRID_WIDTH - 1;
|
||||
InputGridY = INPUTGRID_HEIGHT - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are naming a new save, don't start the cursor on "end".
|
||||
InputGridX = 0;
|
||||
InputGridY = 0;
|
||||
}
|
||||
AllowColors = allowcolors; // [TP]
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FString DTextEnterMenu::GetText()
|
||||
{
|
||||
return mEnterString;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
// Save game and player name string input
|
||||
if (ev->subtype == EV_GUI_Char)
|
||||
{
|
||||
mInputGridOkay = false;
|
||||
if (mEnterString.Len() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString.AppendFormat("%c", (char)ev->data1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
char ch = (char)ev->data1;
|
||||
if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b')
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
if (ch == GK_ESCAPE)
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->CallMenuEvent(MKEY_Abort, false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == '\r')
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
// [TP] If we allow color codes, colorize the string now.
|
||||
if (AllowColors)
|
||||
mEnterString = strbin1(mEnterString);
|
||||
|
||||
DMenu *parent = mParentMenu;
|
||||
parent->CallMenuEvent(MKEY_Input, false);
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
const int cell_width = 18 * CleanXfac;
|
||||
const int cell_height = 12 * CleanYfac;
|
||||
const int screen_y = screen->GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
||||
const int screen_x = (screen->GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
||||
|
||||
if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y)
|
||||
{
|
||||
InputGridX = (x - screen_x) / cell_width;
|
||||
InputGridY = (y - screen_y) / cell_height;
|
||||
if (type == DMenu::MOUSE_Release)
|
||||
{
|
||||
if (CallMenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InputGridX = InputGridY = -1;
|
||||
}
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
||||
{
|
||||
if (key == MKEY_Back)
|
||||
{
|
||||
mParentMenu->CallMenuEvent(MKEY_Abort, false);
|
||||
return Super::MenuEvent(key, fromcontroller);
|
||||
}
|
||||
if (fromcontroller)
|
||||
{
|
||||
mInputGridOkay = true;
|
||||
}
|
||||
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
int ch;
|
||||
|
||||
if (InputGridX == -1 || InputGridY == -1)
|
||||
{
|
||||
InputGridX = InputGridY = 0;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case MKEY_Down:
|
||||
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Up:
|
||||
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Right:
|
||||
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Left:
|
||||
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Clear:
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
assert(unsigned(InputGridX) < INPUTGRID_WIDTH && unsigned(InputGridY) < INPUTGRID_HEIGHT);
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
|
||||
if (ch == 0) // end
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->CallMenuEvent(MKEY_Input, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ch == '\b') // bs
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
}
|
||||
else if (mEnterString.Len() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString += char(ch);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DTextEnterMenu::Drawer ()
|
||||
{
|
||||
mParentMenu->CallDrawer();
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
const int cell_width = 18 * CleanXfac;
|
||||
const int cell_height = 12 * CleanYfac;
|
||||
const int top_padding = cell_height / 2 - SmallFont->GetHeight() * CleanYfac / 2;
|
||||
|
||||
// Darken the background behind the character grid.
|
||||
// Unless we frame it with a border, I think it looks better to extend the
|
||||
// background across the full width of the screen.
|
||||
screen->Dim(0, 0.8f,
|
||||
0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/,
|
||||
screen->GetHeight() - INPUTGRID_HEIGHT * cell_height,
|
||||
screen->GetWidth() /*13 * cell_width*/,
|
||||
INPUTGRID_HEIGHT * cell_height);
|
||||
|
||||
if (InputGridX >= 0 && InputGridY >= 0)
|
||||
{
|
||||
// Highlight the background behind the selected character.
|
||||
screen->Dim(MAKERGB(255,248,220), 0.6f,
|
||||
InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2,
|
||||
InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(),
|
||||
cell_width, cell_height);
|
||||
}
|
||||
|
||||
for (int y = 0; y < INPUTGRID_HEIGHT; ++y)
|
||||
{
|
||||
const int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight();
|
||||
for (int x = 0; x < INPUTGRID_WIDTH; ++x)
|
||||
{
|
||||
int width;
|
||||
const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2;
|
||||
const int ch = InputGridChars[y * INPUTGRID_WIDTH + x];
|
||||
FTexture *pic = SmallFont->GetChar(ch, &width);
|
||||
EColorRange color;
|
||||
|
||||
// The highlighted character is yellow; the rest are dark gray.
|
||||
color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY;
|
||||
|
||||
if (pic != NULL)
|
||||
{
|
||||
// Draw a normal character.
|
||||
screen->DrawChar(SmallFont, color, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, ch, DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
else if (ch == ' ')
|
||||
{
|
||||
FRemapTable *remap = SmallFont->GetColorTranslation(color);
|
||||
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
||||
const int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
||||
const int x2 = x1 + width * 3 * CleanXfac / 2;
|
||||
const int y1 = yy + top_padding;
|
||||
const int y2 = y1 + SmallFont->GetHeight() * CleanYfac;
|
||||
const int palentry = remap->Remap[remap->NumEntries * 2 / 3];
|
||||
const uint32 palcolor = remap->Palette[remap->NumEntries * 2 / 3];
|
||||
screen->Clear(x1, y1, x2, y1+CleanYfac, palentry, palcolor); // top
|
||||
screen->Clear(x1, y2, x2, y2+CleanYfac, palentry, palcolor); // bottom
|
||||
screen->Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palentry, palcolor); // left
|
||||
screen->Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palentry, palcolor); // right
|
||||
}
|
||||
else if (ch == '\b' || ch == 0)
|
||||
{
|
||||
// Draw the backspace and end "characters".
|
||||
const char *const str = ch == '\b' ? "BS" : "ED";
|
||||
screen->DrawText(SmallFont, color,
|
||||
xx + cell_width/2 - SmallFont->StringWidth(str)*CleanXfac/2,
|
||||
yy + top_padding, str, DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DTextEnterMenu, Open)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(parent, DMenu);
|
||||
PARAM_STRING(text);
|
||||
PARAM_INT(maxlen);
|
||||
PARAM_INT(sizemode);
|
||||
PARAM_BOOL(fromcontroller);
|
||||
auto m = new DTextEnterMenu(parent, text.GetChars(), maxlen, sizemode, fromcontroller, false);
|
||||
M_ActivateMenu(m);
|
||||
ACTION_RETURN_OBJECT(m);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DTextEnterMenu, GetText)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DTextEnterMenu);
|
||||
ACTION_RETURN_STRING(self->GetText());
|
||||
}
|
|
@ -46,52 +46,15 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "g_game.h"
|
||||
|
||||
|
||||
EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd]
|
||||
|
||||
class DMessageBoxMenu : public DMenu
|
||||
typedef void(*hfunc)();
|
||||
DEFINE_ACTION_FUNCTION(DMessageBoxMenu, CallHandler)
|
||||
{
|
||||
DECLARE_CLASS(DMessageBoxMenu, DMenu)
|
||||
|
||||
FBrokenLines *mMessage;
|
||||
int mMessageMode;
|
||||
int messageSelection;
|
||||
int mMouseLeft, mMouseRight, mMouseY;
|
||||
FName mAction;
|
||||
|
||||
public:
|
||||
|
||||
DMessageBoxMenu(DMenu *parent = NULL, const char *message = NULL, int messagemode = 0, bool playsound = false, FName action = NAME_None);
|
||||
void OnDestroy() override;
|
||||
void Init(DMenu *parent, const char *message, int messagemode, bool playsound = false);
|
||||
void Drawer();
|
||||
bool Responder(event_t *ev);
|
||||
bool MenuEvent(int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void CloseSound();
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DMessageBoxMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DMessageBoxMenu::DMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mAction = action;
|
||||
messageSelection = 0;
|
||||
mMouseLeft = 140;
|
||||
mMouseY = INT_MIN;
|
||||
int mr1 = 170 + SmallFont->StringWidth(GStrings["TXT_YES"]);
|
||||
int mr2 = 170 + SmallFont->StringWidth(GStrings["TXT_NO"]);
|
||||
mMouseRight = MAX(mr1, mr2);
|
||||
|
||||
Init(parent, message, messagemode, playsound);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTERTYPE(Handler, hfunc);
|
||||
Handler();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -100,325 +63,15 @@ DMessageBoxMenu::DMessageBoxMenu(DMenu *parent, const char *message, int message
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::Init(DMenu *parent, const char *message, int messagemode, bool playsound)
|
||||
DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action = NAME_None, hfunc handler = nullptr)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
if (message != NULL)
|
||||
{
|
||||
if (*message == '$') message = GStrings(message+1);
|
||||
mMessage = V_BreakLines(SmallFont, 300, message);
|
||||
}
|
||||
else mMessage = NULL;
|
||||
mMessageMode = messagemode;
|
||||
if (playsound)
|
||||
{
|
||||
S_StopSound (CHAN_VOICE);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/prompt", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
auto c = PClass::FindClass("MessageBoxMenu");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, parent, FString(message), messagemode, playsound, action.GetIndex(), handler };
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::OnDestroy()
|
||||
{
|
||||
if (mMessage != NULL) V_FreeBrokenLines(mMessage);
|
||||
mMessage = NULL;
|
||||
Super::OnDestroy();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::CloseSound()
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI,
|
||||
DMenu::CurrentMenu != NULL? "menu/backup" : "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::HandleResult(bool res)
|
||||
{
|
||||
if (mParentMenu != NULL)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mAction == NAME_None)
|
||||
{
|
||||
mParentMenu->CallMenuEvent(res? MKEY_MBYes : MKEY_MBNo, false);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
if (res) M_SetMenu(mAction, -1);
|
||||
}
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::Drawer ()
|
||||
{
|
||||
int i, y;
|
||||
PalEntry fade = 0;
|
||||
|
||||
int fontheight = SmallFont->GetHeight();
|
||||
//V_SetBorderNeedRefresh();
|
||||
//ST_SetNeedRefresh();
|
||||
|
||||
y = 100;
|
||||
|
||||
if (mMessage != NULL)
|
||||
{
|
||||
for (i = 0; mMessage[i].Width >= 0; i++)
|
||||
y -= SmallFont->GetHeight () / 2;
|
||||
|
||||
for (i = 0; mMessage[i].Width >= 0; i++)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, 160 - mMessage[i].Width/2, y, mMessage[i].Text,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
y += fontheight;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
y += fontheight;
|
||||
mMouseY = y;
|
||||
screen->DrawText(SmallFont,
|
||||
messageSelection == 0? OptionSettings.mFontColorSelection : OptionSettings.mFontColor,
|
||||
160, y, GStrings["TXT_YES"], DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText(SmallFont,
|
||||
messageSelection == 1? OptionSettings.mFontColorSelection : OptionSettings.mFontColor,
|
||||
160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (messageSelection >= 0)
|
||||
{
|
||||
if ((DMenu::MenuTime%8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(150 - 160) * CleanXfac + screen->GetWidth() / 2,
|
||||
(y + (fontheight + 1) * messageSelection - 100 + fontheight/2 - 5) * CleanYfac + screen->GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMessageBoxMenu::Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
int ch = tolower(ev->data1);
|
||||
if (ch == 'n' || ch == ' ')
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == 'y')
|
||||
{
|
||||
HandleResult(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ev->type == EV_KeyDown)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMessageBoxMenu::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mkey == MKEY_Up || mkey == MKEY_Down)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
messageSelection = !messageSelection;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
// 0 is yes, 1 is no
|
||||
HandleResult(!messageSelection);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMessageBoxMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mMessageMode == 1)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = SmallFont->GetHeight() + 1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + 2 * fh)
|
||||
{
|
||||
sel = y >= mMouseY + fh;
|
||||
}
|
||||
if (sel != -1 && sel != messageSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
messageSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DQuitMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DQuitMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DQuitMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DQuitMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuitMenu::DQuitMenu(bool playsound)
|
||||
{
|
||||
int messageindex = gametic % gameinfo.quitmessages.Size();
|
||||
FString EndString;
|
||||
const char *msg = gameinfo.quitmessages[messageindex];
|
||||
if (msg[0] == '$')
|
||||
{
|
||||
if (msg[1] == '*')
|
||||
{
|
||||
EndString = GStrings(msg+2);
|
||||
}
|
||||
else
|
||||
{
|
||||
EndString.Format("%s\n\n%s", GStrings(msg+1), GStrings("DOSY"));
|
||||
}
|
||||
}
|
||||
else EndString = gameinfo.quitmessages[messageindex];
|
||||
|
||||
Init(NULL, EndString, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuitMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
if (!netgame)
|
||||
{
|
||||
if (gameinfo.quitSound.IsNotEmpty())
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.quitSound, snd_menuvolume, ATTN_NONE);
|
||||
I_WaitVBL (105);
|
||||
}
|
||||
}
|
||||
ST_Endoom();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenu*)p;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -430,70 +83,42 @@ void DQuitMenu::HandleResult(bool res)
|
|||
CCMD (menu_quit)
|
||||
{ // F10
|
||||
M_StartControlPanel (true);
|
||||
DMenu *newmenu = new DQuitMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
|
||||
int messageindex = gametic % gameinfo.quitmessages.Size();
|
||||
FString EndString;
|
||||
const char *msg = gameinfo.quitmessages[messageindex];
|
||||
if (msg[0] == '$')
|
||||
{
|
||||
if (msg[1] == '*')
|
||||
{
|
||||
EndString = GStrings(msg + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
EndString.Format("%s\n\n%s", GStrings(msg + 1), GStrings("DOSY"));
|
||||
}
|
||||
}
|
||||
else EndString = gameinfo.quitmessages[messageindex];
|
||||
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString, 0, false, NAME_None, []()
|
||||
{
|
||||
if (!netgame)
|
||||
{
|
||||
if (gameinfo.quitSound.IsNotEmpty())
|
||||
{
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, gameinfo.quitSound, snd_menuvolume, ATTN_NONE);
|
||||
I_WaitVBL(105);
|
||||
}
|
||||
}
|
||||
ST_Endoom();
|
||||
});
|
||||
|
||||
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DEndGameMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DEndGameMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DEndGameMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DEndGameMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DEndGameMenu::DEndGameMenu(bool playsound)
|
||||
{
|
||||
Init(NULL, GStrings(netgame ? "NETEND" : "ENDGAME"), 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DEndGameMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
M_ClearMenus ();
|
||||
if (!netgame)
|
||||
{
|
||||
D_StartTitle ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -510,67 +135,18 @@ CCMD (menu_endgame)
|
|||
|
||||
//M_StartControlPanel (true);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
DMenu *newmenu = new DEndGameMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DQuickSaveMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DQuickSaveMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DQuickSaveMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DQuickSaveMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuickSaveMenu::DQuickSaveMenu(bool playsound)
|
||||
{
|
||||
FString tempstring;
|
||||
|
||||
tempstring.Format(GStrings("QSPROMPT"), savegameManager.quickSaveSlot->Title);
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuickSaveMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
FString tempstring = GStrings(netgame ? "NETEND" : "ENDGAME");
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||
{
|
||||
G_SaveGame (savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
if (!netgame)
|
||||
{
|
||||
D_StartTitle();
|
||||
}
|
||||
});
|
||||
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -601,72 +177,23 @@ CCMD (quicksave)
|
|||
// [mxd]. Just save the game, no questions asked.
|
||||
if (!saveloadconfirmation)
|
||||
{
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title);
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
return;
|
||||
}
|
||||
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
DMenu *newmenu = new DQuickSaveMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DQuickLoadMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DQuickLoadMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DQuickLoadMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DQuickLoadMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuickLoadMenu::DQuickLoadMenu(bool playsound)
|
||||
{
|
||||
FString tempstring;
|
||||
tempstring.Format(GStrings("QSPROMPT"), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
|
||||
tempstring.Format(GStrings("QLPROMPT"), savegameManager.quickSaveSlot->Title);
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuickLoadMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||
{
|
||||
G_LoadGame (savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
});
|
||||
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -699,10 +226,17 @@ CCMD (quickload)
|
|||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
return;
|
||||
}
|
||||
FString tempstring;
|
||||
tempstring.Format(GStrings("QLPROMPT"), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
|
||||
M_StartControlPanel(true);
|
||||
DMenu *newmenu = new DQuickLoadMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||
{
|
||||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
});
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
@ -714,13 +248,13 @@ CCMD (quickload)
|
|||
|
||||
void M_StartMessage(const char *message, int messagemode, FName action)
|
||||
{
|
||||
if (DMenu::CurrentMenu == NULL)
|
||||
if (CurrentMenu == NULL)
|
||||
{
|
||||
// only play a sound if no menu was active before
|
||||
M_StartControlPanel(menuactive == MENU_Off);
|
||||
}
|
||||
DMenu *newmenu = new DMessageBoxMenu(DMenu::CurrentMenu, message, messagemode, false, action);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, message, messagemode, false, action);
|
||||
newmenu->mParentMenu = CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
@ -732,4 +266,4 @@ DEFINE_ACTION_FUNCTION(DMenu, StartMessage)
|
|||
PARAM_NAME_DEF(action);
|
||||
M_StartMessage(msg, mode, action);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,32 +49,6 @@
|
|||
#include "menu/menu.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenuDescriptor::CalcIndent()
|
||||
{
|
||||
// calculate the menu indent
|
||||
int widest = 0, thiswidth;
|
||||
|
||||
for (unsigned i = 0; i < mItems.Size(); i++)
|
||||
{
|
||||
thiswidth = mItems[i]->GetIndent();
|
||||
if (thiswidth > widest) widest = thiswidth;
|
||||
}
|
||||
mIndent = widest + 4;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuDescriptor, CalcIndent)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DOptionMenuDescriptor);
|
||||
self->CalcIndent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -85,7 +59,7 @@ DMenuItemBase *DOptionMenuDescriptor::GetItem(FName name)
|
|||
{
|
||||
for(unsigned i=0;i<mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mItems[i]->GetAction(NULL);
|
||||
FName nm = mItems[i]->mAction;
|
||||
if (nm == name) return mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -61,12 +61,12 @@ EXTERN_CVAR(Bool, cl_run)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(r);
|
||||
PARAM_INT(g);
|
||||
PARAM_INT(b);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
char command[24];
|
||||
players[consoleplayer].userinfo.ColorChanged(MAKERGB(r, g, b));
|
||||
|
@ -86,12 +86,12 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_STRING(s);
|
||||
const char *pp = s;
|
||||
FString command("name \"");
|
||||
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
// Escape any backslashes or quotation marks before sending the name to the console.
|
||||
for (auto p = pp; *p != '\0'; ++p)
|
||||
|
@ -116,9 +116,9 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorSetChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(sel);
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
players[consoleplayer].userinfo.ColorSetChanged(sel);
|
||||
char command[24];
|
||||
|
@ -136,10 +136,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorSetChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ClassChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(sel);
|
||||
PARAM_POINTER(cls, FPlayerClass);
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
players[consoleplayer].userinfo.PlayerClassNumChanged(gameinfo.norandomplayerclass ? sel : sel - 1);
|
||||
cvar_set("playerclass", sel == 0 && !gameinfo.norandomplayerclass ? "Random" : GetPrintableDisplayName(cls->Type).GetChars());
|
||||
|
@ -156,9 +156,9 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, ClassChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, SkinChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(sel);
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
players[consoleplayer].userinfo.SkinNumChanged(sel);
|
||||
cvar_set("skin", Skins[sel].Name);
|
||||
|
@ -174,10 +174,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, SkinChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, AutoaimChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_FLOAT(val);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
autoaim = float(val);
|
||||
}
|
||||
|
@ -192,10 +192,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, AutoaimChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, TeamChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(val);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
team = val == 0 ? TEAM_NONE : val - 1;
|
||||
}
|
||||
|
@ -210,10 +210,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, TeamChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, GenderChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
cvar_set("gender", v == 0 ? "male" : v == 1 ? "female" : "other");
|
||||
}
|
||||
|
@ -228,10 +228,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, GenderChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, SwitchOnPickupChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
neverswitchonpickup = !!v;
|
||||
}
|
||||
|
@ -246,10 +246,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, SwitchOnPickupChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, AlwaysRunChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DListMenu);
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == DMenu::CurrentMenu)
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
cl_run = !!v;
|
||||
}
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
** readthis.cpp
|
||||
** Help screens
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "v_video.h"
|
||||
#include "g_level.h"
|
||||
#include "gi.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "textures/textures.h"
|
||||
|
||||
class DReadThisMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DReadThisMenu, DMenu)
|
||||
int mScreen;
|
||||
int mInfoTic;
|
||||
|
||||
public:
|
||||
|
||||
DReadThisMenu(DMenu *parent = NULL);
|
||||
void Drawer();
|
||||
bool MenuEvent(int mkey, bool fromcontroller);
|
||||
bool DimAllowed () { return false; }
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DReadThisMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Read This Menus
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DReadThisMenu::DReadThisMenu(DMenu *parent)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mScreen = 1;
|
||||
mInfoTic = gametic;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DReadThisMenu::Drawer()
|
||||
{
|
||||
FTexture *tex = NULL, *prevpic = NULL;
|
||||
double alpha;
|
||||
|
||||
// Did the mapper choose a custom help page via MAPINFO?
|
||||
if ((level.info != NULL) && level.info->F1Pic.Len() != 0)
|
||||
{
|
||||
tex = TexMan.FindTexture(level.info->F1Pic);
|
||||
mScreen = 1;
|
||||
}
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
tex = TexMan[gameinfo.infoPages[mScreen-1].GetChars()];
|
||||
}
|
||||
|
||||
if (mScreen > 1)
|
||||
{
|
||||
prevpic = TexMan[gameinfo.infoPages[mScreen-2].GetChars()];
|
||||
}
|
||||
|
||||
screen->Dim(0, 1.0, 0,0, SCREENWIDTH, SCREENHEIGHT);
|
||||
alpha = MIN((gametic - mInfoTic) * (3. / TICRATE), 1.);
|
||||
if (alpha < 1. && prevpic != NULL)
|
||||
{
|
||||
screen->DrawTexture (prevpic, 0, 0, DTA_Fullscreen, true, TAG_DONE);
|
||||
}
|
||||
screen->DrawTexture (tex, 0, 0, DTA_Fullscreen, true, DTA_Alpha, alpha, TAG_DONE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DReadThisMenu::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
mScreen++;
|
||||
mInfoTic = gametic;
|
||||
if ((level.info != NULL && level.info->F1Pic.Len() != 0) || mScreen > int(gameinfo.infoPages.Size()))
|
||||
{
|
||||
Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DReadThisMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -347,7 +347,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeaker
|
|||
}
|
||||
|
||||
// Convert the rest of the data to our own internal format.
|
||||
node->Dialogue = ncopystring (speech.Dialogue);
|
||||
node->Dialogue = speech.Dialogue;
|
||||
|
||||
// The speaker's portrait, if any.
|
||||
speech.Dialogue[0] = 0; //speech.Backdrop[8] = 0;
|
||||
|
@ -360,7 +360,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeaker
|
|||
|
||||
// The speaker's name, if any.
|
||||
speech.Sound[0] = 0; //speech.Name[16] = 0;
|
||||
node->SpeakerName = ncopystring(speech.Name);
|
||||
node->SpeakerName = speech.Name;
|
||||
|
||||
// The item the speaker should drop when killed.
|
||||
node->DropType = dyn_cast<PClassActor>(GetStrifeType(speech.DropType));
|
||||
|
@ -422,7 +422,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeaker
|
|||
}
|
||||
|
||||
// Convert the rest of the data to our own internal format.
|
||||
node->Dialogue = ncopystring (speech.Dialogue);
|
||||
node->Dialogue = speech.Dialogue;
|
||||
|
||||
// The Teaser version doesn't have portraits.
|
||||
node->Backdrop.SetInvalid();
|
||||
|
@ -440,7 +440,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeaker
|
|||
|
||||
// The speaker's name, if any.
|
||||
speech.Dialogue[0] = 0; //speech.Name[16] = 0;
|
||||
node->SpeakerName = ncopystring (speech.Name);
|
||||
node->SpeakerName = speech.Name;
|
||||
|
||||
// The item the speaker should drop when killed.
|
||||
node->DropType = dyn_cast<PClassActor>(GetStrifeType (speech.DropType));
|
||||
|
@ -505,7 +505,7 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
|
||||
// The message to record in the log for this reply.
|
||||
reply->LogNumber = rsp->Log;
|
||||
reply->LogString = NULL;
|
||||
reply->LogString = "";
|
||||
|
||||
// The item to receive when this reply is used.
|
||||
reply->GiveType = dyn_cast<PClassActor>(GetStrifeType (rsp->GiveType));
|
||||
|
@ -520,31 +520,32 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
reply->ItemCheck[k].Item = inv;
|
||||
reply->ItemCheck[k].Amount = rsp->Count[k];
|
||||
}
|
||||
reply->PrintAmount = reply->ItemCheck[0].Amount;
|
||||
reply->ItemCheckRequire.Clear();
|
||||
reply->ItemCheckExclude.Clear();
|
||||
|
||||
// If the first item check has a positive amount required, then
|
||||
// add that to the reply string. Otherwise, use the reply as-is.
|
||||
reply->Reply = copystring (rsp->Reply);
|
||||
reply->Reply = rsp->Reply;
|
||||
reply->NeedsGold = (rsp->Count[0] > 0);
|
||||
|
||||
// QuickYes messages are shown when you meet the item checks.
|
||||
// QuickNo messages are shown when you don't.
|
||||
if (rsp->Yes[0] == '_' && rsp->Yes[1] == 0)
|
||||
{
|
||||
reply->QuickYes = NULL;
|
||||
reply->QuickYes = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->QuickYes = ncopystring (rsp->Yes);
|
||||
reply->QuickYes = rsp->Yes;
|
||||
}
|
||||
if (reply->ItemCheck[0].Item != 0)
|
||||
{
|
||||
reply->QuickNo = ncopystring (rsp->No);
|
||||
reply->QuickNo = rsp->No;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->QuickNo = NULL;
|
||||
reply->QuickNo = "";
|
||||
}
|
||||
reply->Next = *replyptr;
|
||||
*replyptr = reply;
|
||||
|
@ -560,9 +561,6 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
|
||||
FStrifeDialogueNode::~FStrifeDialogueNode ()
|
||||
{
|
||||
if (SpeakerName != NULL) delete[] SpeakerName;
|
||||
if (Dialogue != NULL) delete[] Dialogue;
|
||||
if (Goodbye != nullptr) delete[] Goodbye;
|
||||
FStrifeDialogueReply *tokill = Children;
|
||||
while (tokill != NULL)
|
||||
{
|
||||
|
@ -580,9 +578,6 @@ FStrifeDialogueNode::~FStrifeDialogueNode ()
|
|||
|
||||
FStrifeDialogueReply::~FStrifeDialogueReply ()
|
||||
{
|
||||
if (Reply != NULL) delete[] Reply;
|
||||
if (QuickYes != NULL) delete[] QuickYes;
|
||||
if (QuickNo != NULL) delete[] QuickNo;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -672,7 +667,7 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
|
|||
|
||||
static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
|
||||
{
|
||||
if (reply->Reply == nullptr)
|
||||
if (reply->Reply.IsEmpty())
|
||||
return true;
|
||||
|
||||
int i;
|
||||
|
@ -772,7 +767,7 @@ public:
|
|||
ReplyText = GStrings(ReplyText + 1);
|
||||
}
|
||||
FString ReplyString = ReplyText;
|
||||
if (reply->NeedsGold) ReplyString.AppendFormat(" for %u", reply->ItemCheck[0].Amount);
|
||||
if (reply->NeedsGold) ReplyString.AppendFormat(" for %u", reply->PrintAmount);
|
||||
|
||||
FBrokenLines *ReplyLines = V_BreakLines (SmallFont, 320-50-10, ReplyString);
|
||||
|
||||
|
@ -785,7 +780,7 @@ public:
|
|||
V_FreeBrokenLines (ReplyLines);
|
||||
}
|
||||
const char *goodbyestr = CurNode->Goodbye;
|
||||
if (goodbyestr == nullptr)
|
||||
if (*goodbyestr == 0)
|
||||
{
|
||||
char goodbye[25];
|
||||
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1 + (pr_randomspeech() % NUM_RANDOM_GOODBYES));
|
||||
|
@ -1012,7 +1007,7 @@ public:
|
|||
linesize = 10 * CleanYfac;
|
||||
|
||||
// Who is talking to you?
|
||||
if (CurNode->SpeakerName != NULL)
|
||||
if (CurNode->SpeakerName.IsNotEmpty())
|
||||
{
|
||||
speakerName = CurNode->SpeakerName;
|
||||
if (speakerName[0] == '$') speakerName = GStrings(speakerName+1);
|
||||
|
@ -1097,7 +1092,7 @@ public:
|
|||
|
||||
if (response == mSelection+1)
|
||||
{
|
||||
int color = ((DMenu::MenuTime%8) < 4) || DMenu::CurrentMenu != this ? CR_RED:CR_GREY;
|
||||
int color = ((MenuTime%8) < 4) || CurrentMenu != this ? CR_RED:CR_GREY;
|
||||
|
||||
x = (50 + 3 - 160) * CleanXfac + screen->GetWidth() / 2;
|
||||
int yy = (y + fontheight/2 - 5 - 100) * CleanYfac + screen->GetHeight() / 2;
|
||||
|
@ -1135,9 +1130,9 @@ void P_FreeStrifeConversations ()
|
|||
ClassRoots.Clear();
|
||||
|
||||
PrevNode = NULL;
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
||||
if (CurrentMenu != NULL && CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
CurrentMenu->Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1310,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
|||
if (!CheckStrifeItem(player, reply->ItemCheck[i].Item, reply->ItemCheck[i].Amount))
|
||||
{
|
||||
// No, you don't. Say so and let the NPC animate negatively.
|
||||
if (reply->QuickNo && isconsole)
|
||||
if (reply->QuickNo.IsNotEmpty() && isconsole)
|
||||
{
|
||||
TerminalResponse(reply->QuickNo);
|
||||
}
|
||||
|
@ -1396,7 +1391,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
|||
}
|
||||
|
||||
// Update the quest log, if needed.
|
||||
if (reply->LogString != NULL)
|
||||
if (reply->LogString.IsNotEmpty())
|
||||
{
|
||||
const char *log = reply->LogString;
|
||||
if (log[0] == '$')
|
||||
|
@ -1482,10 +1477,10 @@ void P_ConversationCommand (int netcode, int pnum, BYTE **stream)
|
|||
|
||||
// The conversation menus are normally closed by the menu code, but that
|
||||
// doesn't happen during demo playback, so we need to do it here.
|
||||
if (demoplayback && DMenu::CurrentMenu != NULL &&
|
||||
DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
||||
if (demoplayback && CurrentMenu != NULL &&
|
||||
CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
CurrentMenu->Close();
|
||||
}
|
||||
if (netcode == DEM_CONVREPLY)
|
||||
{
|
||||
|
|
|
@ -26,11 +26,11 @@ struct FStrifeDialogueNode
|
|||
int ItemCheckNode; // index into StrifeDialogues
|
||||
|
||||
PClassActor *SpeakerType;
|
||||
char *SpeakerName;
|
||||
FString SpeakerName;
|
||||
FSoundID SpeakerVoice;
|
||||
FTextureID Backdrop;
|
||||
char *Dialogue;
|
||||
char *Goodbye = nullptr; // must init to null for binary scripts to work as intended
|
||||
FString Dialogue;
|
||||
FString Goodbye; // must init to null for binary scripts to work as intended
|
||||
|
||||
FStrifeDialogueReply *Children;
|
||||
};
|
||||
|
@ -44,15 +44,16 @@ struct FStrifeDialogueReply
|
|||
PClassActor *GiveType;
|
||||
int ActionSpecial;
|
||||
int Args[5];
|
||||
int PrintAmount;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheck;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheckRequire;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheckExclude;
|
||||
char *Reply;
|
||||
char *QuickYes;
|
||||
FString Reply;
|
||||
FString QuickYes;
|
||||
FString QuickNo;
|
||||
FString LogString;
|
||||
int NextNode; // index into StrifeDialogues
|
||||
int LogNumber;
|
||||
char *LogString;
|
||||
char *QuickNo;
|
||||
bool NeedsGold;
|
||||
};
|
||||
|
||||
|
|
|
@ -232,20 +232,21 @@ class USDFParser : public UDMFParserBase
|
|||
// Todo: Finalize
|
||||
if (reply->ItemCheck.Size() > 0)
|
||||
{
|
||||
if (reply->ItemCheck[0].Amount <= 0) reply->NeedsGold = false;
|
||||
reply->PrintAmount = reply->ItemCheck[0].Amount;
|
||||
if (reply->PrintAmount <= 0) reply->NeedsGold = false;
|
||||
}
|
||||
|
||||
reply->Reply = ncopystring(ReplyString);
|
||||
reply->QuickYes = ncopystring(QuickYes);
|
||||
reply->Reply = ReplyString;
|
||||
reply->QuickYes = QuickYes;
|
||||
if (reply->ItemCheck.Size() > 0 && reply->ItemCheck[0].Item != NULL)
|
||||
{
|
||||
reply->QuickNo = ncopystring(QuickNo);
|
||||
reply->QuickNo = QuickNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->QuickNo = NULL;
|
||||
reply->QuickNo = "";
|
||||
}
|
||||
reply->LogString = ncopystring(LogString);
|
||||
reply->LogString = LogString;
|
||||
if(!closeDialog) reply->NextNode *= -1;
|
||||
return true;
|
||||
}
|
||||
|
@ -373,9 +374,9 @@ class USDFParser : public UDMFParserBase
|
|||
}
|
||||
}
|
||||
}
|
||||
node->SpeakerName = ncopystring(SpeakerName);
|
||||
node->Dialogue = ncopystring(Dialogue);
|
||||
node->Goodbye = ncopystring(Goodbye);
|
||||
node->SpeakerName = SpeakerName;
|
||||
node->Dialogue = Dialogue;
|
||||
node->Goodbye = Goodbye;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -802,7 +802,7 @@ void R_InitSkins (void)
|
|||
|
||||
if (spr == 0 && maxframe <= 0)
|
||||
{
|
||||
Printf (PRINT_BOLD, "Skin %s (#%u) has no frames. Removing.\n", Skins[i].Name, i);
|
||||
Printf (PRINT_BOLD, "Skin %s (#%u) has no frames. Removing.\n", Skins[i].Name.GetChars(), i);
|
||||
remove = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -906,7 +906,10 @@ void InitThingdef()
|
|||
fieldptr = new PField("OptionMenuSettings", NewStruct("FOptionMenuSettings", nullptr), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&OptionSettings);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
|
||||
fieldptr = new PField("gametic", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gametic);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
|
||||
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
|
||||
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
|
||||
// is to create a static variable from it and reference that in the script. Yuck!!!
|
||||
|
@ -1213,10 +1216,12 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Mid)
|
|||
ACTION_RETURN_STRING(s);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Len)
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Truncate)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
ACTION_RETURN_INT((int)self->Len());
|
||||
PARAM_UINT(len);
|
||||
self->Truncate(len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int.
|
||||
|
@ -1239,3 +1244,10 @@ DEFINE_ACTION_FUNCTION(FStringStruct, CharCodeAt)
|
|||
ACTION_RETURN_INT(0);
|
||||
ACTION_RETURN_INT((*self)[pos]);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Filter)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
ACTION_RETURN_STRING(strbin1(*self));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "doomerrors.h"
|
||||
#include "memarena.h"
|
||||
|
||||
class DObject;
|
||||
|
||||
extern FMemArena ClassDataAllocator;
|
||||
|
||||
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
|
||||
|
@ -1028,6 +1030,7 @@ void NullParam(const char *varname);
|
|||
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass());
|
||||
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
|
||||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||
#define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type x = (type )param[p].a;
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x);
|
||||
|
@ -1072,6 +1075,7 @@ void NullParam(const char *varname);
|
|||
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
|
||||
#define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x)
|
||||
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
|
||||
#define PARAM_POINTERTYPE(x,type) ++paramnum; PARAM_POINTERTYPE_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
|
||||
#define PARAM_POINTER_NOT_NULL(x,type) ++paramnum; PARAM_POINTER_NOT_NULL_AT(paramnum,x,type)
|
||||
|
|
|
@ -337,6 +337,20 @@ void DCanvas::Dim (PalEntry color)
|
|||
Dim (dimmer, amount, 0, 0, Width, Height);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, Dim)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(color);
|
||||
PARAM_FLOAT(amount);
|
||||
PARAM_INT(x1);
|
||||
PARAM_INT(y1);
|
||||
PARAM_INT(w);
|
||||
PARAM_INT(h);
|
||||
screen->Dim(color, float(amount), x1, y1, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DCanvas :: GetScreenshotBuffer
|
||||
|
|
|
@ -100,7 +100,4 @@ const char *GetVersionString();
|
|||
#endif
|
||||
|
||||
|
||||
// The maximum length of one save game description for the menus.
|
||||
#define SAVESTRINGSIZE 24
|
||||
|
||||
#endif //__VERSION_H__
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
|
||||
#include "zscript/menu/menuitembase.txt"
|
||||
#include "zscript/menu/menu.txt"
|
||||
#include "zscript/menu/messagebox.txt"
|
||||
#include "zscript/menu/listmenu.txt"
|
||||
#include "zscript/menu/listmenuitems.txt"
|
||||
#include "zscript/menu/optionmenu.txt"
|
||||
#include "zscript/menu/optionmenuitems.txt"
|
||||
#include "zscript/menu/colorpickermenu.txt"
|
||||
#include "zscript/menu/joystickmenu.txt"
|
||||
#include "zscript/menu/loadsavemenu.txt"
|
||||
#include "zscript/menu/playermenu.txt"
|
||||
#include "zscript/menu/playerdisplay.txt"
|
||||
#include "zscript/menu/playercontrols.txt"
|
||||
#include "zscript/menu/textentermenu.txt"
|
||||
#include "zscript/menu/videomenu.txt"
|
||||
#include "zscript/menu/readthis.txt"
|
||||
|
||||
#include "zscript/inventory/inventory.txt"
|
||||
#include "zscript/inventory/inv_misc.txt"
|
||||
|
|
|
@ -158,15 +158,11 @@ enum DrawTextureTags
|
|||
|
||||
struct Screen native
|
||||
{
|
||||
int CleanWidth, CleanHeight;
|
||||
int CleanXFac, CleanYFac;
|
||||
int CleanWidth_1, CleanHeight_1;
|
||||
int CleanXFac_1, CleanYFac_1;
|
||||
|
||||
native static Color PaletteColor(int index);
|
||||
native static int GetWidth();
|
||||
native static int GetHeight();
|
||||
native static void Clear(int left, int top, int right, int bottom, Color color, int palcolor = -1);
|
||||
native static void Dim(Color col, double amount, int x, int y, int w, int h);
|
||||
|
||||
native static void DrawHUDTexture(TextureID tex, double x, double y);
|
||||
native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...);
|
||||
|
@ -175,13 +171,6 @@ struct Screen native
|
|||
native static void DrawFrame(int x, int y, int w, int h);
|
||||
}
|
||||
|
||||
class BrokenLines : Object native
|
||||
{
|
||||
native int Count();
|
||||
native int StringWidth(int line);
|
||||
native String StringAt(int line);
|
||||
}
|
||||
|
||||
struct Font native
|
||||
{
|
||||
enum EColorRange
|
||||
|
@ -252,7 +241,7 @@ struct Font native
|
|||
native static int FindFontColor(Name color);
|
||||
native static Font FindFont(Name fontname);
|
||||
native static Font GetFont(Name fontname);
|
||||
native static BrokenLines BreakLines(String text, int maxlen);
|
||||
native BrokenLines BreakLines(String text, int maxlen);
|
||||
}
|
||||
|
||||
struct Translation
|
||||
|
@ -310,6 +299,7 @@ struct GameInfoStruct native
|
|||
native String ArmorIcon2;
|
||||
native int gametype;
|
||||
native bool norandomplayerclass;
|
||||
native Array<Name> infoPages;
|
||||
}
|
||||
|
||||
class Object native
|
||||
|
@ -336,6 +326,13 @@ class Object native
|
|||
virtual void OnDestroy() {}
|
||||
}
|
||||
|
||||
class BrokenLines : Object native
|
||||
{
|
||||
native int Count();
|
||||
native int StringWidth(int line);
|
||||
native String StringAt(int line);
|
||||
}
|
||||
|
||||
class Thinker : Object native
|
||||
{
|
||||
enum EStatnums
|
||||
|
@ -440,6 +437,7 @@ struct LevelLocals native
|
|||
native readonly String MapName;
|
||||
native String NextMap;
|
||||
native String NextSecretMap;
|
||||
native String F1Pic;
|
||||
native readonly int maptype;
|
||||
native readonly String Music;
|
||||
native readonly int musicorder;
|
||||
|
@ -582,9 +580,10 @@ struct StringStruct native
|
|||
|
||||
native void Replace(String pattern, String replacement);
|
||||
native String Mid(int pos = 0, int len = 2147483647);
|
||||
native int Len();
|
||||
native void Truncate(int newlen);
|
||||
native String CharAt(int pos);
|
||||
native int CharCodeAt(int pos);
|
||||
native String Filter();
|
||||
}
|
||||
|
||||
class Floor : Thinker native
|
||||
|
|
|
@ -40,10 +40,10 @@ class ListMenuDescriptor : MenuDescriptor native
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenu : Menu native
|
||||
class ListMenu : Menu
|
||||
{
|
||||
native ListMenuDescriptor mDesc;
|
||||
native MenuItemBase mFocusControl;
|
||||
ListMenuDescriptor mDesc;
|
||||
MenuItemBase mFocusControl;
|
||||
|
||||
virtual void Init(Menu parent = NULL, ListMenuDescriptor desc = NULL)
|
||||
{
|
||||
|
@ -76,7 +76,13 @@ class ListMenu : Menu native
|
|||
}
|
||||
}
|
||||
|
||||
MenuItemBase GetItem(Name name)
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
ListMenuItem GetItem(Name name)
|
||||
{
|
||||
for(int i = 0; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
|
@ -86,12 +92,173 @@ class ListMenu : Menu native
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//bool Responder (InputEventData ev);
|
||||
//bool MenuEvent (int mkey, bool fromcontroller);
|
||||
//bool MouseEvent(int type, int x, int y);
|
||||
//void Ticker ();
|
||||
//void Drawer ();
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event)
|
||||
{
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
// tolower
|
||||
int ch = ev.data1;
|
||||
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
||||
|
||||
for(int i = mDesc.mSelectedItem + 1; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].CheckHotkey(ch))
|
||||
{
|
||||
mDesc.mSelectedItem = i;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < mDesc.mSelectedItem; i++)
|
||||
{
|
||||
if (mDesc.mItems[i].CheckHotkey(ch))
|
||||
{
|
||||
mDesc.mSelectedItem = i;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int oldSelect = mDesc.mSelectedItem;
|
||||
int startedAt = mDesc.mSelectedItem;
|
||||
if (startedAt < 0) startedAt = 0;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
do
|
||||
{
|
||||
if (--mDesc.mSelectedItem < 0) mDesc.mSelectedItem = mDesc.mItems.Size()-1;
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
if (mDesc.mSelectedItem == startedAt) mDesc.mSelectedItem = oldSelect;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
do
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size()) mDesc.mSelectedItem = 0;
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
if (mDesc.mSelectedItem == startedAt) mDesc.mSelectedItem = oldSelect;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mItems[mDesc.mSelectedItem].Activate())
|
||||
{
|
||||
MenuSound("menu/choose");
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen.GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen.GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (mFocusControl != NULL)
|
||||
{
|
||||
mFocusControl.MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((mDesc.mWLeft <= 0 || x > mDesc.mWLeft) &&
|
||||
(mDesc.mWRight <= 0 || x < mDesc.mWRight))
|
||||
{
|
||||
for(int i=0;i<mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].CheckCoordinate(x, y))
|
||||
{
|
||||
if (i != mDesc.mSelectedItem)
|
||||
{
|
||||
//MenuSound("menu/cursor");
|
||||
}
|
||||
mDesc.mSelectedItem = i;
|
||||
mDesc.mItems[i].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 ()
|
||||
{
|
||||
for(int i=0;i<mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].mEnabled) mDesc.mItems[i].Drawer(mDesc.mSelectedItem == i);
|
||||
}
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mSelectedItem < mDesc.mItems.Size())
|
||||
mDesc.mItems[mDesc.mSelectedItem].DrawSelector(mDesc.mSelectOfsX, mDesc.mSelectOfsY, mDesc.mSelector);
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void SetFocus(MenuItemBase fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
|
@ -106,3 +273,4 @@ class ListMenu : Menu native
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class ListMenuItem : MenuItemBase
|
|||
}
|
||||
else
|
||||
{
|
||||
screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true);
|
||||
screen.DrawTexture (tex, true, mXpos + xofs, mYpos + yofs, DTA_Clean, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
577
wadsrc/static/zscript/menu/loadsavemenu.txt
Normal file
577
wadsrc/static/zscript/menu/loadsavemenu.txt
Normal file
|
@ -0,0 +1,577 @@
|
|||
/*
|
||||
** loacpp
|
||||
** The load game and save game menus
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
struct SaveGameNode native
|
||||
{
|
||||
native String SaveTitle;
|
||||
native String Filename;
|
||||
native bool bOldVersion;
|
||||
native bool bMissingWads;
|
||||
native bool bNoDelete;
|
||||
}
|
||||
|
||||
struct SavegameManager native
|
||||
{
|
||||
native int WindowSize;
|
||||
native SaveGameNode quickSaveSlot;
|
||||
|
||||
native static SavegameManager GetManager();
|
||||
native void ReadSaveStrings();
|
||||
native void UnloadSaveData();
|
||||
|
||||
native int RemoveSaveSlot(int index);
|
||||
native void LoadSavegame(int Selected);
|
||||
native void DoSave(int Selected, String savegamestring);
|
||||
native int ExtractSaveData(int index);
|
||||
native void ClearSaveStuff();
|
||||
native bool DrawSavePic(int x, int y, int w, int h);
|
||||
native void DrawSaveComment(Font font, int cr, int x, int y, int scalefactor);
|
||||
native void SetFileInfo(int Selected);
|
||||
native int SavegameCount();
|
||||
native SaveGameNode GetSavegame(int i);
|
||||
native void InsertNewSaveNode();
|
||||
native bool RemoveNewSaveNode();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class LoadSaveMenu : ListMenu
|
||||
{
|
||||
SavegameManager manager;
|
||||
int TopItem;
|
||||
int Selected;
|
||||
|
||||
int savepicLeft;
|
||||
int savepicTop;
|
||||
int savepicWidth;
|
||||
int savepicHeight;
|
||||
int rowHeight;
|
||||
int listboxLeft;
|
||||
int listboxTop;
|
||||
int listboxWidth;
|
||||
|
||||
int listboxRows;
|
||||
int listboxHeight;
|
||||
int listboxRight;
|
||||
int listboxBottom;
|
||||
|
||||
int commentLeft;
|
||||
int commentTop;
|
||||
int commentWidth;
|
||||
int commentHeight;
|
||||
int commentRight;
|
||||
int commentBottom;
|
||||
|
||||
bool mEntering;
|
||||
TextEnterMenu mInput;
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
manager = SavegameManager.GetManager();
|
||||
manager.ReadSaveStrings();
|
||||
|
||||
savepicLeft = 10;
|
||||
savepicTop = 54*CleanYfac;
|
||||
savepicWidth = 216*screen.GetWidth()/640;
|
||||
savepicHeight = 135*screen.GetHeight()/400;
|
||||
manager.WindowSize = savepicWidth / CleanXfac;
|
||||
|
||||
rowHeight = (SmallFont.GetHeight() + 1) * CleanYfac;
|
||||
listboxLeft = savepicLeft + savepicWidth + 14;
|
||||
listboxTop = savepicTop;
|
||||
listboxWidth = screen.GetWidth() - listboxLeft - 10;
|
||||
int listboxHeight1 = screen.GetHeight() - listboxTop - 10;
|
||||
listboxRows = (listboxHeight1 - 1) / rowHeight;
|
||||
listboxHeight = listboxRows * rowHeight + 1;
|
||||
listboxRight = listboxLeft + listboxWidth;
|
||||
listboxBottom = listboxTop + listboxHeight;
|
||||
|
||||
commentLeft = savepicLeft;
|
||||
commentTop = savepicTop + savepicHeight + 16;
|
||||
commentWidth = savepicWidth;
|
||||
commentHeight = (51+(screen.GetHeight()>200?10:0))*CleanYfac;
|
||||
commentRight = commentLeft + commentWidth;
|
||||
commentBottom = commentTop + commentHeight;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
manager.ClearSaveStuff ();
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
Super.Drawer();
|
||||
|
||||
SaveGameNode node;
|
||||
int i;
|
||||
int j;
|
||||
bool didSeeSelected = false;
|
||||
|
||||
// Draw picture area
|
||||
if (gameaction == ga_loadgame || gameaction == ga_loadgamehidecon || gameaction == ga_savegame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Screen.DrawFrame (savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
||||
if (!manager.DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight))
|
||||
{
|
||||
screen.Clear (savepicLeft, savepicTop, savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0);
|
||||
|
||||
if (manager.SavegameCount() > 0)
|
||||
{
|
||||
String text = (Selected == -1 || !manager.GetSavegame(Selected).bOldVersion)? Stringtable.Localize("$MNU_NOPICTURE") : Stringtable.Localize("$MNU_DIFFVERSION");
|
||||
int textlen = SmallFont.StringWidth(text) * CleanXfac;
|
||||
|
||||
screen.DrawText (SmallFont, Font.CR_GOLD, savepicLeft+(savepicWidth-textlen)/2,
|
||||
savepicTop+(savepicHeight-rowHeight)/2, text, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw comment area
|
||||
Screen.DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
||||
screen.Clear (commentLeft, commentTop, commentRight, commentBottom, 0, 0);
|
||||
|
||||
manager.DrawSaveComment(SmallFont, Font.CR_GOLD, commentLeft, commentTop, CleanYfac);
|
||||
|
||||
// Draw file area
|
||||
Screen.DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
||||
screen.Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0);
|
||||
|
||||
if (manager.SavegameCount() == 0)
|
||||
{
|
||||
String text = Stringtable.Localize("$MNU_NOFILES");
|
||||
int textlen = SmallFont.StringWidth(text) * CleanXfac;
|
||||
|
||||
screen.DrawText (SmallFont, Font.CR_GOLD, listboxLeft+(listboxWidth-textlen)/2, listboxTop+(listboxHeight-rowHeight)/2, text, DTA_CleanNoMove, true);
|
||||
return;
|
||||
}
|
||||
|
||||
j = TopItem;
|
||||
for (i = 0; i < listboxRows && j < manager.SavegameCount(); i++)
|
||||
{
|
||||
int colr;
|
||||
node = manager.GetSavegame(j);
|
||||
if (node.bOldVersion)
|
||||
{
|
||||
colr = Font.CR_BLUE;
|
||||
}
|
||||
else if (node.bMissingWads)
|
||||
{
|
||||
colr = Font.CR_ORANGE;
|
||||
}
|
||||
else if (j == Selected)
|
||||
{
|
||||
colr = Font.CR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
colr = Font.CR_TAN;
|
||||
}
|
||||
|
||||
if (j == Selected)
|
||||
{
|
||||
screen.Clear (listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1), mEntering ? Color(255,255,0,0) : Color(255,0,0,255));
|
||||
didSeeSelected = true;
|
||||
if (!mEntering)
|
||||
{
|
||||
screen.DrawText (SmallFont, colr, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node.SaveTitle, DTA_CleanNoMove, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = mInput.GetText() .. SmallFont.GetCursor();
|
||||
screen.DrawText (SmallFont, Font.CR_WHITE, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, s, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawText (SmallFont, colr, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node.SaveTitle, DTA_CleanNoMove, true);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (Selected == -1) Selected = TopItem;
|
||||
else
|
||||
{
|
||||
if (--Selected < 0) Selected = manager.SavegameCount()-1;
|
||||
if (Selected < TopItem) TopItem = Selected;
|
||||
else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1);
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (Selected == -1) Selected = TopItem;
|
||||
else
|
||||
{
|
||||
if (++Selected >= manager.SavegameCount()) Selected = 0;
|
||||
if (Selected < TopItem) TopItem = Selected;
|
||||
else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1);
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (TopItem >= manager.SavegameCount() - listboxRows)
|
||||
{
|
||||
TopItem = 0;
|
||||
if (Selected != -1) Selected = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
TopItem = MIN(TopItem + listboxRows, manager.SavegameCount() - listboxRows);
|
||||
if (TopItem > Selected && Selected != -1) Selected = TopItem;
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (TopItem == 0)
|
||||
{
|
||||
TopItem = MAX(0, manager.SavegameCount() - listboxRows);
|
||||
if (Selected != -1) Selected = TopItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
TopItem = MAX(TopItem - listboxRows, 0);
|
||||
if (Selected >= TopItem + listboxRows) Selected = TopItem;
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
return false; // This event will be handled by the subclasses
|
||||
|
||||
case MKEY_MBYes:
|
||||
{
|
||||
if (Selected < manager.SavegameCount())
|
||||
{
|
||||
Selected = manager.RemoveSaveSlot (Selected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (x >= listboxLeft && x < listboxLeft + listboxWidth &&
|
||||
y >= listboxTop && y < listboxTop + listboxHeight)
|
||||
{
|
||||
int lineno = (y - listboxTop) / rowHeight;
|
||||
|
||||
if (TopItem + lineno < manager.SavegameCount())
|
||||
{
|
||||
Selected = TopItem + lineno;
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
if (MenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else Selected = -1;
|
||||
}
|
||||
else Selected = -1;
|
||||
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event)
|
||||
{
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (Selected < manager.SavegameCount())
|
||||
{
|
||||
switch (ev.data1)
|
||||
{
|
||||
case UIEvent.Key_F1:
|
||||
manager.SetFileInfo(Selected);
|
||||
return true;
|
||||
|
||||
case UIEvent.Key_DEL:
|
||||
{
|
||||
String EndString;
|
||||
EndString = String.Format("%s%s%s%s?\n\n%s", Stringtable.Localize("$MNU_DELETESG"), TEXTCOLOR_WHITE, manager.GetSavegame(Selected).SaveTitle, TEXTCOLOR_NORMAL, Stringtable.Localize("$PRESSYN"));
|
||||
StartMessage (EndString, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ev.subtype == InputEventData.GUI_WheelUp)
|
||||
{
|
||||
if (TopItem > 0) TopItem--;
|
||||
return true;
|
||||
}
|
||||
else if (ev.subtype == InputEventData.GUI_WheelDown)
|
||||
{
|
||||
if (TopItem < manager.SavegameCount() - listboxRows) TopItem++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class SaveMenu : LoadSaveMenu
|
||||
{
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
manager.InsertNewSaveNode();
|
||||
TopItem = 0;
|
||||
Selected = manager.ExtractSaveData (-1);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
if (manager.RemoveNewSaveNode())
|
||||
{
|
||||
Selected--;
|
||||
}
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
const SAVESTRINGSIZE = 32;
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
|
||||
if (Super.MenuEvent(mkey, fromcontroller))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Selected == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
String SavegameString = (Selected != 0)? manager.GetSavegame(Selected).SaveTitle : "";
|
||||
mInput = TextEnterMenu.Open(self, SavegameString, SAVESTRINGSIZE, 1, fromcontroller);
|
||||
mInput.ActivateMenu();
|
||||
mEntering = true;
|
||||
}
|
||||
else if (mkey == MKEY_Input)
|
||||
{
|
||||
mEntering = false;
|
||||
manager.DoSave(Selected, mInput.GetText());
|
||||
mInput = null;
|
||||
}
|
||||
else if (mkey == MKEY_Abort)
|
||||
{
|
||||
mEntering = false;
|
||||
mInput = null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (Selected != -1)
|
||||
{
|
||||
switch (ev.data1)
|
||||
{
|
||||
case UIEvent.Key_DEL:
|
||||
// cannot delete 'new save game' item
|
||||
if (Selected == 0) return true;
|
||||
break;
|
||||
|
||||
case 78://'N':
|
||||
Selected = TopItem = 0;
|
||||
manager.UnloadSaveData ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class LoadMenu : LoadSaveMenu
|
||||
{
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
TopItem = 0;
|
||||
Selected = manager.ExtractSaveData (-1);
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (Super.MenuEvent(mkey, fromcontroller))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Selected == -1 || manager.SavegameCount() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
manager.LoadSavegame(Selected);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -87,6 +87,8 @@ class Menu : Object native
|
|||
};
|
||||
|
||||
native Menu mParentMenu;
|
||||
native bool mMouseCapture;
|
||||
native bool mBackbuttonSelected;
|
||||
|
||||
void Init(Menu parent)
|
||||
{
|
||||
|
@ -111,7 +113,6 @@ class Menu : Object native
|
|||
native virtual void Ticker();
|
||||
native virtual void Drawer();
|
||||
native void Close();
|
||||
native MenuItemBase GetItem(Name n);
|
||||
native void ActivateMenu();
|
||||
|
||||
static void MenuSound(Sound snd)
|
||||
|
|
293
wadsrc/static/zscript/menu/messagebox.txt
Normal file
293
wadsrc/static/zscript/menu/messagebox.txt
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
** messagebox.cpp
|
||||
** Confirmation, notification screns
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 MessageBoxMenu : Menu
|
||||
{
|
||||
BrokenLines mMessage;
|
||||
voidptr Handler;
|
||||
int mMessageMode;
|
||||
int messageSelection;
|
||||
int mMouseLeft, mMouseRight, mMouseY;
|
||||
Name mAction;
|
||||
|
||||
native static void CallHandler(voidptr hnd);
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Init(Menu parent, String message, int messagemode, bool playsound = false, Name cmd = 'None', voidptr native_handler = null)
|
||||
{
|
||||
Super.Init(parent);
|
||||
mAction = cmd;
|
||||
messageSelection = 0;
|
||||
mMouseLeft = 140;
|
||||
mMouseY = 0x80000000;
|
||||
int mr1 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_YES"));
|
||||
int mr2 = 170 + SmallFont.StringWidth(Stringtable.Localize("TXT_NO"));
|
||||
mMouseRight = MAX(mr1, mr2);
|
||||
mParentMenu = parent;
|
||||
mMessage = SmallFont.BreakLines(message, 300);
|
||||
mMessageMode = messagemode;
|
||||
if (playsound)
|
||||
{
|
||||
MenuSound ("menu/prompt");
|
||||
}
|
||||
Handler = native_handler;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
int i, y;
|
||||
|
||||
int fontheight = SmallFont.GetHeight();
|
||||
|
||||
y = 100;
|
||||
|
||||
int c = mMessage.Count();
|
||||
for (i = 0; i < c; i++)
|
||||
y -= SmallFont.GetHeight () / 2;
|
||||
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, 160 - mMessage.StringWidth(i)/2, y, mMessage.StringAt(i), DTA_Clean, true);
|
||||
y += fontheight;
|
||||
}
|
||||
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
y += fontheight;
|
||||
mMouseY = y;
|
||||
screen.DrawText(SmallFont, messageSelection == 0? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, 160, y, Stringtable.Localize("$TXT_YES"), DTA_Clean, true);
|
||||
screen.DrawText(SmallFont, messageSelection == 1? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, 160, y + fontheight + 1, Stringtable.Localize("$TXT_NO"), DTA_Clean, true);
|
||||
|
||||
if (messageSelection >= 0)
|
||||
{
|
||||
if ((MenuTime() % 8) < 6)
|
||||
{
|
||||
screen.DrawText(ConFont, OptionMenuSettings.mFontColorSelection,
|
||||
(150 - 160) * CleanXfac + screen.GetWidth() / 2,
|
||||
(y + (fontheight + 1) * messageSelection - 100 + fontheight/2 - 5) * CleanYfac + screen.GetHeight() / 2,
|
||||
"\xd", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void CloseSound()
|
||||
{
|
||||
MenuSound (GetCurrentMenu() != NULL? "menu/backup" : "menu/dismiss");
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual void HandleResult(bool res)
|
||||
{
|
||||
if (Handler != null)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
CallHandler(Handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
else if (mParentMenu != NULL)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mAction == 'None')
|
||||
{
|
||||
mParentMenu.MenuEvent(res? MKEY_MBYes : MKEY_MBNo, false);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
if (res) SetMenu(mAction, -1);
|
||||
}
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder(InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event && ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
// tolower
|
||||
int ch = ev.data1;
|
||||
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
||||
|
||||
if (ch == 78 /*'n'*/ || ch == 32)
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == 89 /*'y'*/)
|
||||
{
|
||||
HandleResult(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ev.type == InputEventData.KeyDown)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mkey == MKEY_Up || mkey == MKEY_Down)
|
||||
{
|
||||
MenuSound("menu/cursor");
|
||||
messageSelection = !messageSelection;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
// 0 is yes, 1 is no
|
||||
HandleResult(!messageSelection);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mMessageMode == 1)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = SmallFont.GetHeight() + 1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen.GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen.GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + 2 * fh)
|
||||
{
|
||||
sel = y >= mMouseY + fh;
|
||||
}
|
||||
if (sel != -1 && sel != messageSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
messageSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -56,8 +56,6 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
native int mPosition;
|
||||
native bool mDontDim;
|
||||
|
||||
native void CalcIndent();
|
||||
native OptionMenuItem GetItem(Name iname);
|
||||
void Reset()
|
||||
{
|
||||
// Reset the default settings (ignore all other values in the struct)
|
||||
|
@ -66,6 +64,25 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
mIndent = 0;
|
||||
mDontDim = 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void CalcIndent()
|
||||
{
|
||||
// calculate the menu indent
|
||||
int widest = 0, thiswidth;
|
||||
|
||||
for (int i = 0; i < mItems.Size(); i++)
|
||||
{
|
||||
thiswidth = mItems[i].GetIndent();
|
||||
if (thiswidth > widest) widest = thiswidth;
|
||||
}
|
||||
mIndent = widest + 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,10 +105,27 @@ class OptionMenu : Menu
|
|||
mParentMenu = parent;
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
||||
|
||||
mDesc.CalcIndent();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
OptionMenuItem GetItem(Name name)
|
||||
{
|
||||
for(int i = 0; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
Name nm = mDesc.mItems[i].GetAction();
|
||||
if (nm == name) return mDesc.mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -136,7 +136,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu
|
|||
// don't execute if no menu is active
|
||||
if (m == null) return false;
|
||||
// don't execute if this item cannot be found in the current menu.
|
||||
if (m.mDesc.GetItem(mAction) != self) return false;
|
||||
if (m.GetItem(mAction) != self) return false;
|
||||
Menu.MenuSound("menu/choose");
|
||||
DoCommand(mAction);
|
||||
return true;
|
||||
|
@ -388,7 +388,7 @@ class EnterKey : Menu
|
|||
let parent = OptionMenu(mParentMenu);
|
||||
if (parent != null)
|
||||
{
|
||||
let it = parent.mDesc.GetItem('Controlmessage');
|
||||
let it = parent.GetItem('Controlmessage');
|
||||
if (it != null)
|
||||
{
|
||||
it.SetValue(0, which);
|
||||
|
|
124
wadsrc/static/zscript/menu/readthis.txt
Normal file
124
wadsrc/static/zscript/menu/readthis.txt
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
** readthis.cpp
|
||||
** Help screens
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class ReadThisMenu : Menu
|
||||
{
|
||||
int mScreen;
|
||||
int mInfoTic;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer()
|
||||
{
|
||||
double alpha;
|
||||
TextureID tex, prevpic;
|
||||
|
||||
if (mScreen == 0)
|
||||
{
|
||||
mScreen = 1;
|
||||
mInfoTic = gametic;
|
||||
}
|
||||
|
||||
// Did the mapper choose a custom help page via MAPINFO?
|
||||
if (level.F1Pic.Length() != 0)
|
||||
{
|
||||
tex = TexMan.CheckForTexture(level.F1Pic, TexMan.Type_MiscPatch);
|
||||
mScreen = 1;
|
||||
}
|
||||
|
||||
if (!tex.IsValid())
|
||||
{
|
||||
tex = TexMan.CheckForTexture(gameinfo.infoPages[mScreen-1], TexMan.Type_MiscPatch);
|
||||
}
|
||||
|
||||
if (mScreen > 1)
|
||||
{
|
||||
prevpic = TexMan.CheckForTexture(gameinfo.infoPages[mScreen-2], TexMan.Type_MiscPatch);
|
||||
}
|
||||
|
||||
screen.Dim(0, 1.0, 0,0, screen.GetWidth(), screen.GetHeight());
|
||||
alpha = MIN((gametic - mInfoTic) * (3. / Thinker.TICRATE), 1.);
|
||||
if (alpha < 1. && prevpic.IsValid())
|
||||
{
|
||||
screen.DrawTexture (prevpic, false, 0, 0, DTA_Fullscreen, true);
|
||||
}
|
||||
else alpha = 1;
|
||||
screen.DrawTexture (tex, false, 0, 0, DTA_Fullscreen, true, DTA_Alpha, alpha);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
MenuSound("menu/choose");
|
||||
mScreen++;
|
||||
mInfoTic = gametic;
|
||||
if (level.F1Pic.Length() != 0 || mScreen > gameinfo.infoPages.Size())
|
||||
{
|
||||
Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +1,365 @@
|
|||
/*
|
||||
** menuinput.cpp
|
||||
** The string input code
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// This is only the parts that are needed to make the menu fully work right now. More to come later.
|
||||
class TextEnterMenu : Menu native
|
||||
|
||||
class TextEnterMenu : Menu
|
||||
{
|
||||
native bool mInputGridOkay;
|
||||
const INPUTGRID_WIDTH = 13;
|
||||
const INPUTGRID_HEIGHT = 5;
|
||||
|
||||
native static TextEnterMenu Open(Menu parent, String text, int maxlen, int sizemode, bool fromcontroller);
|
||||
native String GetText();
|
||||
const Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-=.,!?@'\":;[]()<>^#$%&*/_ \b";
|
||||
|
||||
String mEnterString;
|
||||
int mEnterSize;
|
||||
int mEnterPos;
|
||||
int mSizeMode; // 1: size is length in chars. 2: also check string width
|
||||
bool mInputGridOkay;
|
||||
int InputGridX;
|
||||
int InputGridY;
|
||||
bool AllowColors;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// [TP] Added allowcolors
|
||||
private void Init(Menu parent, String textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
|
||||
{
|
||||
Super.init(parent);
|
||||
mEnterString = textbuffer;
|
||||
mEnterSize = maxlen < 0 ? 0x7fffffff : maxlen;
|
||||
mSizeMode = sizemode;
|
||||
mInputGridOkay = showgrid || m_showinputgrid;
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
InputGridX = INPUTGRID_WIDTH - 1;
|
||||
InputGridY = INPUTGRID_HEIGHT - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are naming a new save, don't start the cursor on "end".
|
||||
InputGridX = 0;
|
||||
InputGridY = 0;
|
||||
}
|
||||
AllowColors = allowcolors; // [TP]
|
||||
}
|
||||
|
||||
static TextEnterMenu Open(Menu parent, String textbuffer, int maxlen, int sizemode, bool showgrid = false, bool allowcolors = false)
|
||||
{
|
||||
let me = new("TextEnterMenu");
|
||||
me.Init(parent, textbuffer, maxlen, sizemode, showgrid, allowcolors);
|
||||
return me;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
String GetText()
|
||||
{
|
||||
return mEnterString;
|
||||
}
|
||||
|
||||
override bool TranslateKeyboardEvents()
|
||||
{
|
||||
return mInputGridOkay;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder(InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event)
|
||||
{
|
||||
// Save game and player name string input
|
||||
if (ev.subtype == InputEventData.GUI_Char)
|
||||
{
|
||||
mInputGridOkay = false;
|
||||
if (mEnterString.Length() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || SmallFont.StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString.AppendFormat("%c", ev.data1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int ch = ev.data1;
|
||||
if ((ev.subtype == InputEventData.GUI_KeyDown || ev.subtype == InputEventData.GUI_KeyRepeat) && ch == 8)
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
}
|
||||
}
|
||||
else if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (ch == UIEvent.Key_ESCAPE)
|
||||
{
|
||||
Menu parent = mParentMenu;
|
||||
Close();
|
||||
parent.MenuEvent(MKEY_Abort, false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == 13)
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
// [TP] If we allow color codes, colorize the string now.
|
||||
if (AllowColors)
|
||||
mEnterString = mEnterString.Filter();
|
||||
|
||||
Menu parent = mParentMenu;
|
||||
parent.MenuEvent(MKEY_Input, false);
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown || ev.subtype == InputEventData.GUI_KeyRepeat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mMouseCapture || m_use_mouse == 1)
|
||||
{
|
||||
int cell_width = 18 * CleanXfac;
|
||||
int cell_height = 12 * CleanYfac;
|
||||
int screen_y = screen.GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
||||
int screen_x = (screen.GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
||||
|
||||
if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y)
|
||||
{
|
||||
InputGridX = (x - screen_x) / cell_width;
|
||||
InputGridY = (y - screen_y) / cell_height;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
if (MenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
MenuSound("menu/choose");
|
||||
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InputGridX = InputGridY = -1;
|
||||
}
|
||||
}
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int key, bool fromcontroller)
|
||||
{
|
||||
String InputGridChars = Chars;
|
||||
if (key == MKEY_Back)
|
||||
{
|
||||
mParentMenu.MenuEvent(MKEY_Abort, false);
|
||||
return Super.MenuEvent(key, fromcontroller);
|
||||
}
|
||||
if (fromcontroller)
|
||||
{
|
||||
mInputGridOkay = true;
|
||||
}
|
||||
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
int ch;
|
||||
|
||||
if (InputGridX == -1 || InputGridY == -1)
|
||||
{
|
||||
InputGridX = InputGridY = 0;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case MKEY_Down:
|
||||
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Up:
|
||||
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Right:
|
||||
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Left:
|
||||
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Clear:
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
String c = InputGridChars.CharAt(InputGridX + InputGridY * INPUTGRID_WIDTH);
|
||||
int ch = c.CharCodeAt(0);
|
||||
if (ch == 0) // end
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
Menu parent = mParentMenu;
|
||||
Close();
|
||||
parent.MenuEvent(MKEY_Input, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ch == 8) // bs
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
}
|
||||
}
|
||||
else if (mEnterString.Length() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || SmallFont.StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString = mEnterString .. c;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
mParentMenu.Drawer();
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
String InputGridChars = Chars;
|
||||
int cell_width = 18 * CleanXfac;
|
||||
int cell_height = 12 * CleanYfac;
|
||||
int top_padding = cell_height / 2 - SmallFont.GetHeight() * CleanYfac / 2;
|
||||
|
||||
// Darken the background behind the character grid.
|
||||
screen.Dim(0, 0.8, 0, screen.GetHeight() - INPUTGRID_HEIGHT * cell_height, screen.GetWidth(), INPUTGRID_HEIGHT * cell_height);
|
||||
|
||||
if (InputGridX >= 0 && InputGridY >= 0)
|
||||
{
|
||||
// Highlight the background behind the selected character.
|
||||
screen.Dim(Color(255,248,220), 0.6,
|
||||
InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen.GetWidth() / 2,
|
||||
InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen.GetHeight(),
|
||||
cell_width, cell_height);
|
||||
}
|
||||
|
||||
for (int y = 0; y < INPUTGRID_HEIGHT; ++y)
|
||||
{
|
||||
int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen.GetHeight();
|
||||
for (int x = 0; x < INPUTGRID_WIDTH; ++x)
|
||||
{
|
||||
int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen.GetWidth() / 2;
|
||||
int ch = InputGridChars.CharCodeAt(y * INPUTGRID_WIDTH + x);
|
||||
int width = SmallFont.GetCharWidth(ch);
|
||||
|
||||
// The highlighted character is yellow; the rest are dark gray.
|
||||
int colr = (x == InputGridX && y == InputGridY) ? Font.CR_YELLOW : Font.CR_DARKGRAY;
|
||||
Color palcolor = (x == InputGridX && y == InputGridY) ? Color(160, 120, 0) : Color(120, 120, 120);
|
||||
|
||||
if (ch > 32)
|
||||
{
|
||||
// Draw a normal character.
|
||||
screen.DrawChar(SmallFont, colr, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, ch, DTA_CleanNoMove, true);
|
||||
}
|
||||
else if (ch == 32)
|
||||
{
|
||||
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
||||
int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
||||
int x2 = x1 + width * 3 * CleanXfac / 2;
|
||||
int y1 = yy + top_padding;
|
||||
int y2 = y1 + SmallFont.GetHeight() * CleanYfac;
|
||||
screen.Clear(x1, y1, x2, y1+CleanYfac, palcolor); // top
|
||||
screen.Clear(x1, y2, x2, y2+CleanYfac, palcolor); // bottom
|
||||
screen.Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palcolor); // left
|
||||
screen.Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palcolor); // right
|
||||
}
|
||||
else if (ch == 8 || ch == 0)
|
||||
{
|
||||
// Draw the backspace and end "characters".
|
||||
String str = ch == 8 ? "BS" : "ED";
|
||||
screen.DrawText(SmallFont, colr,
|
||||
xx + cell_width/2 - SmallFont.StringWidth(str)*CleanXfac/2,
|
||||
yy + top_padding, str, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue