mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 14:51:46 +00:00
- merged menu branch back into trunk.
SVN r2768 (trunk)
This commit is contained in:
parent
ec0b07b5e2
commit
579502ab74
86 changed files with 13680 additions and 9299 deletions
|
@ -649,13 +649,13 @@ add_executable( zdoom WIN32
|
|||
hu_scores.cpp
|
||||
i_net.cpp
|
||||
info.cpp
|
||||
keysections.cpp
|
||||
lumpconfigfile.cpp
|
||||
m_alloc.cpp
|
||||
m_argv.cpp
|
||||
m_bbox.cpp
|
||||
m_cheat.cpp
|
||||
m_joy.cpp
|
||||
m_menu.cpp
|
||||
m_misc.cpp
|
||||
m_options.cpp
|
||||
m_png.cpp
|
||||
|
@ -788,6 +788,19 @@ add_executable( zdoom WIN32
|
|||
g_shared/sbar_mugshot.cpp
|
||||
g_shared/shared_hud.cpp
|
||||
g_shared/shared_sbar.cpp
|
||||
menu/colorpickermenu.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/playerdisplay.cpp
|
||||
menu/playermenu.cpp
|
||||
menu/readthis.cpp
|
||||
menu/videomenu.cpp
|
||||
oplsynth/fmopl.cpp
|
||||
oplsynth/mlopl.cpp
|
||||
oplsynth/mlopl_io.cpp
|
||||
|
|
|
@ -583,7 +583,7 @@ void FKeyBindings::ArchiveBindings(FConfigFile *f, const char *matchcmd)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
int FKeyBindings::GetKeysForCommand (char *cmd, int *first, int *second)
|
||||
int FKeyBindings::GetKeysForCommand (const char *cmd, int *first, int *second)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
|
@ -609,7 +609,7 @@ int FKeyBindings::GetKeysForCommand (char *cmd, int *first, int *second)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::UnbindACommand (char *str)
|
||||
void FKeyBindings::UnbindACommand (const char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
19
src/c_bind.h
19
src/c_bind.h
|
@ -57,8 +57,8 @@ public:
|
|||
void SetBinds(const FBinding *binds);
|
||||
bool DoKey(event_t *ev);
|
||||
void ArchiveBindings(FConfigFile *F, const char *matchcmd = NULL);
|
||||
int GetKeysForCommand (char *cmd, int *first, int *second);
|
||||
void UnbindACommand (char *str);
|
||||
int GetKeysForCommand (const char *cmd, int *first, int *second);
|
||||
void UnbindACommand (const char *str);
|
||||
void UnbindAll ();
|
||||
void UnbindKey(const char *key);
|
||||
void DoBind (const char *key, const char *bind);
|
||||
|
@ -85,6 +85,7 @@ public:
|
|||
extern FKeyBindings Bindings;
|
||||
extern FKeyBindings DoubleBindings;
|
||||
extern FKeyBindings AutomapBindings;
|
||||
extern FKeyBindings MenuBindings;
|
||||
|
||||
|
||||
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds);
|
||||
|
@ -95,4 +96,18 @@ void C_UnbindAll ();
|
|||
|
||||
extern const char *KeyNames[];
|
||||
|
||||
struct FKeyAction
|
||||
{
|
||||
FString mTitle;
|
||||
FString mAction;
|
||||
};
|
||||
|
||||
struct FKeySection
|
||||
{
|
||||
FString mTitle;
|
||||
FString mSection;
|
||||
TArray<FKeyAction> mActions;
|
||||
};
|
||||
extern TArray<FKeySection> KeySections;
|
||||
|
||||
#endif //__C_BINDINGS_H__
|
||||
|
|
|
@ -936,3 +936,4 @@ CCMD(currentpos)
|
|||
FIXED2FLOAT(mo->x), FIXED2FLOAT(mo->y), FIXED2FLOAT(mo->z), mo->angle/float(ANGLE_1), FIXED2FLOAT(mo->floorz), mo->Sector->sectornum, mo->Sector->lightlevel);
|
||||
}
|
||||
|
||||
|
||||
|
|
110
src/c_cvars.cpp
110
src/c_cvars.cpp
|
@ -1119,7 +1119,7 @@ void FFlagCVar::DoSet (UCVarValue value, ECVarType type)
|
|||
// exec scripts because all flags will base their changes off of the value of
|
||||
// the "master" cvar at the time the script was run, overriding any changes
|
||||
// another flag might have made to the same cvar earlier in the script.
|
||||
if ((ValueVar.Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback)
|
||||
if ((ValueVar.GetFlags() & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback)
|
||||
{
|
||||
if (netgame && !players[consoleplayer].settings_controller)
|
||||
{
|
||||
|
@ -1139,6 +1139,114 @@ void FFlagCVar::DoSet (UCVarValue value, ECVarType type)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Mask cvar implementation
|
||||
//
|
||||
// Similar to FFlagCVar but can have multiple bits
|
||||
//
|
||||
|
||||
FMaskCVar::FMaskCVar (const char *name, FIntCVar &realvar, DWORD bitval)
|
||||
: FBaseCVar (name, 0, NULL),
|
||||
ValueVar (realvar),
|
||||
BitVal (bitval)
|
||||
{
|
||||
int bit;
|
||||
|
||||
Flags &= ~CVAR_ISDEFAULT;
|
||||
|
||||
assert (bitval != 0);
|
||||
|
||||
bit = 0;
|
||||
while ((bitval & 1) == 0)
|
||||
{
|
||||
++bit;
|
||||
bitval >>= 1;
|
||||
}
|
||||
BitNum = bit;
|
||||
}
|
||||
|
||||
ECVarType FMaskCVar::GetRealType () const
|
||||
{
|
||||
return CVAR_Dummy;
|
||||
}
|
||||
|
||||
UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const
|
||||
{
|
||||
return FromInt ((ValueVar & BitVal) >> BitNum, type);
|
||||
}
|
||||
|
||||
UCVarValue FMaskCVar::GetFavoriteRep (ECVarType *type) const
|
||||
{
|
||||
UCVarValue ret;
|
||||
*type = CVAR_Int;
|
||||
ret.Int = (ValueVar & BitVal) >> BitNum;
|
||||
return ret;
|
||||
}
|
||||
|
||||
UCVarValue FMaskCVar::GetGenericRepDefault (ECVarType type) const
|
||||
{
|
||||
ECVarType dummy;
|
||||
UCVarValue def;
|
||||
def = ValueVar.GetFavoriteRepDefault (&dummy);
|
||||
return FromInt ((def.Int & BitVal) >> BitNum, type);
|
||||
}
|
||||
|
||||
UCVarValue FMaskCVar::GetFavoriteRepDefault (ECVarType *type) const
|
||||
{
|
||||
ECVarType dummy;
|
||||
UCVarValue def;
|
||||
def = ValueVar.GetFavoriteRepDefault (&dummy);
|
||||
def.Int = (def.Int & BitVal) >> BitNum;
|
||||
*type = CVAR_Int;
|
||||
return def;
|
||||
}
|
||||
|
||||
void FMaskCVar::SetGenericRepDefault (UCVarValue value, ECVarType type)
|
||||
{
|
||||
int val = ToInt(value, type) << BitNum;
|
||||
ECVarType dummy;
|
||||
UCVarValue def;
|
||||
def = ValueVar.GetFavoriteRepDefault (&dummy);
|
||||
def.Int &= ~BitVal;
|
||||
def.Int |= val;
|
||||
ValueVar.SetGenericRepDefault (def, CVAR_Int);
|
||||
}
|
||||
|
||||
void FMaskCVar::DoSet (UCVarValue value, ECVarType type)
|
||||
{
|
||||
int val = ToInt(value, type) << BitNum;
|
||||
|
||||
// Server cvars that get changed by this need to use a special message, because
|
||||
// changes are not processed until the next net update. This is a problem with
|
||||
// exec scripts because all flags will base their changes off of the value of
|
||||
// the "master" cvar at the time the script was run, overriding any changes
|
||||
// another flag might have made to the same cvar earlier in the script.
|
||||
if ((ValueVar.GetFlags() & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback)
|
||||
{
|
||||
if (netgame && !players[consoleplayer].settings_controller)
|
||||
{
|
||||
Printf ("Only setting controllers can change %s\n", Name);
|
||||
return;
|
||||
}
|
||||
// Ugh...
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
if (BitVal & (1<<i))
|
||||
{
|
||||
D_SendServerFlagChange (&ValueVar, i, !!(val & (1<<i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int vval = *ValueVar;
|
||||
vval &= ~BitVal;
|
||||
vval |= val;
|
||||
ValueVar = vval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
static int STACK_ARGS sortcvars (const void *a, const void *b)
|
||||
{
|
||||
|
|
|
@ -344,6 +344,30 @@ protected:
|
|||
int BitNum;
|
||||
};
|
||||
|
||||
class FMaskCVar : public FBaseCVar
|
||||
{
|
||||
public:
|
||||
FMaskCVar (const char *name, FIntCVar &realvar, uint32 bitval);
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
inline operator int () const { return (ValueVar & BitVal) >> BitNum; }
|
||||
inline int operator *() const { return (ValueVar & BitVal) >> BitNum; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
FIntCVar &ValueVar;
|
||||
uint32 BitVal;
|
||||
int BitNum;
|
||||
};
|
||||
|
||||
class FGUIDCVar : public FBaseCVar
|
||||
{
|
||||
public:
|
||||
|
|
39
src/d_gui.h
39
src/d_gui.h
|
@ -43,27 +43,34 @@ enum EGUIEvent
|
|||
EV_GUI_KeyRepeat, // same
|
||||
EV_GUI_KeyUp, // same
|
||||
EV_GUI_Char, // data1: translated character (for user text input), data2: alt down?
|
||||
EV_GUI_MouseMove,
|
||||
EV_GUI_LButtonDown,
|
||||
EV_GUI_LButtonUp,
|
||||
EV_GUI_LButtonDblClick,
|
||||
EV_GUI_MButtonDown,
|
||||
EV_GUI_MButtonUp,
|
||||
EV_GUI_MButtonDblClick,
|
||||
EV_GUI_RButtonDown,
|
||||
EV_GUI_RButtonUp,
|
||||
EV_GUI_RButtonDblClick,
|
||||
EV_GUI_WheelUp, // data3: shift/ctrl/alt
|
||||
EV_GUI_WheelDown, // "
|
||||
EV_GUI_WheelRight, // "
|
||||
EV_GUI_WheelLeft, // "
|
||||
EV_GUI_FirstMouseEvent,
|
||||
EV_GUI_MouseMove,
|
||||
EV_GUI_LButtonDown,
|
||||
EV_GUI_LButtonUp,
|
||||
EV_GUI_LButtonDblClick,
|
||||
EV_GUI_MButtonDown,
|
||||
EV_GUI_MButtonUp,
|
||||
EV_GUI_MButtonDblClick,
|
||||
EV_GUI_RButtonDown,
|
||||
EV_GUI_RButtonUp,
|
||||
EV_GUI_RButtonDblClick,
|
||||
EV_GUI_WheelUp, // data3: shift/ctrl/alt
|
||||
EV_GUI_WheelDown, // "
|
||||
EV_GUI_WheelRight, // "
|
||||
EV_GUI_WheelLeft, // "
|
||||
EV_GUI_BackButtonDown,
|
||||
EV_GUI_BackButtonUp,
|
||||
EV_GUI_FwdButtonDown,
|
||||
EV_GUI_FwdButtonUp,
|
||||
EV_GUI_LastMouseEvent,
|
||||
};
|
||||
|
||||
enum GUIKeyModifiers
|
||||
{
|
||||
GKM_SHIFT = 1,
|
||||
GKM_CTRL = 2,
|
||||
GKM_ALT = 4
|
||||
GKM_ALT = 4,
|
||||
GKM_LBUTTON = 8
|
||||
};
|
||||
|
||||
// Special codes for some GUI keys, including a few real ASCII codes.
|
||||
|
@ -100,7 +107,7 @@ enum ESpecialGUIKeys
|
|||
GK_ESCAPE = 27, // ASCII
|
||||
GK_FREE1 = 28,
|
||||
GK_FREE2 = 29,
|
||||
GK_FREE3 = 30,
|
||||
GK_BACK = 30, // browser back key
|
||||
GK_CESCAPE = 31 // color escape
|
||||
};
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ const IWADInfo IWADInfos[NUM_IWAD_TYPES] =
|
|||
{ "FreeDM", "FreeDM", MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx },
|
||||
{ "Blasphemer", "Blasphemer",MAKERGB(115,0,0), MAKERGB(0,0,0), GAME_Heretic, "mapinfo/heretic.txt" },
|
||||
{ "Chex(R) Quest", "Chex1", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex.txt" },
|
||||
{ "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex3.txt" },
|
||||
{ "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex3.txt", GI_NOTEXTCOLOR },
|
||||
{ "Action Doom 2: Urban Brawl", "UrbanBrawl",MAKERGB(168,168,0), MAKERGB(168,0,0), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx },
|
||||
{ "Harmony", "Harmony", MAKERGB(110,180,230), MAKERGB(69,79,126), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx },
|
||||
//{ "ZDoom Engine", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) },
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
#include "f_wipe.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_menu.h"
|
||||
#include "menu/menu.h"
|
||||
#include "c_console.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "i_system.h"
|
||||
|
@ -392,6 +392,18 @@ CVAR (Flag, sv_nofov, dmflags, DF_NO_FOV);
|
|||
CVAR (Flag, sv_noweaponspawn, dmflags, DF_NO_COOP_WEAPON_SPAWN);
|
||||
CVAR (Flag, sv_nocrouch, dmflags, DF_NO_CROUCH);
|
||||
CVAR (Flag, sv_allowcrouch, dmflags, DF_YES_CROUCH);
|
||||
CVAR (Flag, sv_cooploseinventory, dmflags, DF_COOP_LOSE_INVENTORY);
|
||||
CVAR (Flag, sv_cooplosekeys, dmflags, DF_COOP_LOSE_KEYS);
|
||||
CVAR (Flag, sv_cooploseweapons, dmflags, DF_COOP_LOSE_WEAPONS);
|
||||
CVAR (Flag, sv_cooplosearmor, dmflags, DF_COOP_LOSE_ARMOR);
|
||||
CVAR (Flag, sv_cooplosepowerups, dmflags, DF_COOP_LOSE_POWERUPS);
|
||||
CVAR (Flag, sv_cooploseammo, dmflags, DF_COOP_LOSE_AMMO);
|
||||
CVAR (Flag, sv_coophalveammo, dmflags, DF_COOP_HALVE_AMMO);
|
||||
|
||||
// Some (hopefully cleaner) interface to these settings.
|
||||
CVAR (Mask, sv_crouch, dmflags, DF_NO_CROUCH|DF_YES_CROUCH);
|
||||
CVAR (Mask, sv_jump, dmflags, DF_NO_JUMP|DF_YES_JUMP);
|
||||
CVAR (Mask, sv_fallingdamage, dmflags, DF_FORCE_FALLINGHX|DF_FORCE_FALLINGZD);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -462,7 +474,6 @@ CVAR (Flag, sv_disallowsuicide, dmflags2, DF2_NOSUICIDE);
|
|||
CVAR (Flag, sv_noautoaim, dmflags2, DF2_NOAUTOAIM);
|
||||
CVAR (Flag, sv_dontcheckammo, dmflags2, DF2_DONTCHECKAMMO);
|
||||
CVAR (Flag, sv_killbossmonst, dmflags2, DF2_KILLBOSSMONST);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CVAR compatflags
|
||||
|
@ -888,6 +899,8 @@ void D_DoomLoop ()
|
|||
// Clamp the timer to TICRATE until the playloop has been entered.
|
||||
r_NoInterpolate = true;
|
||||
|
||||
I_SetCursor(TexMan["cursor"]);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
|
@ -2077,6 +2090,7 @@ void D_DoomMain (void)
|
|||
// [GRB] Initialize player class list
|
||||
SetupPlayerClasses ();
|
||||
|
||||
|
||||
// [RH] Load custom key and weapon settings from WADs
|
||||
D_LoadWadSettings ();
|
||||
|
||||
|
@ -2146,7 +2160,7 @@ void D_DoomMain (void)
|
|||
bglobal.spawn_tries = 0;
|
||||
bglobal.wanted_botnum = bglobal.getspawned.Size();
|
||||
|
||||
Printf ("M_Init: Init miscellaneous info.\n");
|
||||
Printf ("M_Init: Init menus.\n");
|
||||
M_Init ();
|
||||
|
||||
Printf ("P_Init: Init Playloop state.\n");
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "m_menu.h"
|
||||
#include "menu/menu.h"
|
||||
#include "m_random.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
|
|
@ -54,6 +54,7 @@ enum
|
|||
APMETA_ColorRange, // skin color range
|
||||
APMETA_InvulMode,
|
||||
APMETA_HealingRadius,
|
||||
APMETA_Portrait,
|
||||
APMETA_Hexenarmor0,
|
||||
APMETA_Hexenarmor1,
|
||||
APMETA_Hexenarmor2,
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "m_argv.h"
|
||||
#include "po_man.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -298,6 +299,7 @@ static void MarkRoot()
|
|||
Mark(Args);
|
||||
Mark(screen);
|
||||
Mark(StatusBar);
|
||||
Mark(DMenu::CurrentMenu);
|
||||
DThinker::MarkRoots();
|
||||
FCanvasTextureInfo::Mark();
|
||||
Mark(DACSThinker::ActiveThinker);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include "f_finale.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_menu.h"
|
||||
#include "menu/menu.h"
|
||||
#include "m_random.h"
|
||||
#include "m_crc32.h"
|
||||
#include "i_system.h"
|
||||
|
@ -128,6 +128,8 @@ CUSTOM_CVAR (Int, displaynametags, 0, CVAR_ARCHIVE)
|
|||
}
|
||||
}
|
||||
|
||||
CVAR(Int, nametagcolor, CR_GOLD, CVAR_ARCHIVE)
|
||||
|
||||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_STARTUP;
|
||||
|
@ -326,7 +328,7 @@ CCMD (weapnext)
|
|||
if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
|
||||
{
|
||||
StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, SendItemUse->GetTag(),
|
||||
1.5f, 0.90f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' ));
|
||||
1.5f, 0.90f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' ));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +339,7 @@ CCMD (weapprev)
|
|||
if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
|
||||
{
|
||||
StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, SendItemUse->GetTag(),
|
||||
1.5f, 0.90f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' ));
|
||||
1.5f, 0.90f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' ));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,7 +370,7 @@ CCMD (invnext)
|
|||
}
|
||||
if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel)
|
||||
StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(),
|
||||
1.5f, 0.80f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
|
||||
1.5f, 0.80f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
|
||||
}
|
||||
who->player->inventorytics = 5*TICRATE;
|
||||
}
|
||||
|
@ -398,7 +400,7 @@ CCMD (invprev)
|
|||
}
|
||||
if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel)
|
||||
StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(),
|
||||
1.5f, 0.80f, 0, 0, CR_GOLD, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
|
||||
1.5f, 0.80f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('S','I','N','V'));
|
||||
}
|
||||
who->player->inventorytics = 5*TICRATE;
|
||||
}
|
||||
|
@ -897,7 +899,8 @@ bool G_Responder (event_t *ev)
|
|||
stricmp (cmd, "bumpgamma") &&
|
||||
stricmp (cmd, "screenshot")))
|
||||
{
|
||||
M_StartControlPanel (true, true);
|
||||
M_StartControlPanel(true);
|
||||
M_SetMenu(NAME_Mainmenu, -1);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
#include "m_png.h"
|
||||
#include "m_random.h"
|
||||
#include "version.h"
|
||||
#include "m_menu.h"
|
||||
#include "statnums.h"
|
||||
#include "sbarinfo.h"
|
||||
#include "r_translate.h"
|
||||
|
@ -78,6 +77,7 @@
|
|||
#include "d_net.h"
|
||||
#include "d_netinf.h"
|
||||
#include "v_palette.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
#include "gi.h"
|
||||
|
||||
|
@ -99,6 +99,7 @@ void STAT_WRITE(FILE *f);
|
|||
EXTERN_CVAR (Float, sv_gravity)
|
||||
EXTERN_CVAR (Float, sv_aircontrol)
|
||||
EXTERN_CVAR (Int, disableautosave)
|
||||
EXTERN_CVAR (String, playerclass)
|
||||
|
||||
#define SNAP_ID MAKE_ID('s','n','A','p')
|
||||
#define DSNP_ID MAKE_ID('d','s','N','p')
|
||||
|
@ -230,6 +231,15 @@ void G_DeferedInitNew (const char *mapname, int newskill)
|
|||
gameaction = ga_newgame2;
|
||||
}
|
||||
|
||||
void G_DeferedInitNew (FGameStartup *gs)
|
||||
{
|
||||
playerclass = gs->PlayerClass;
|
||||
d_mapname = AllEpisodes[gs->Episode].mEpisodeMap;
|
||||
d_skill = gs->Skill;
|
||||
CheckWarpTransMap (d_mapname, true);
|
||||
gameaction = ga_newgame2;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -486,6 +486,8 @@ void G_InitNew (const char *mapname, bool bTitleLevel);
|
|||
// A normal game starts at map 1,
|
||||
// but a warp test can start elsewhere
|
||||
void G_DeferedInitNew (const char *mapname, int skill = -1);
|
||||
struct FGameStartup;
|
||||
void G_DeferedInitNew (FGameStartup *gs);
|
||||
|
||||
void G_ExitLevel (int position, bool keepFacing);
|
||||
void G_SecretExitLevel (int position);
|
||||
|
@ -603,6 +605,16 @@ struct FSkillInfo
|
|||
extern TArray<FSkillInfo> AllSkills;
|
||||
extern int DefaultSkill;
|
||||
|
||||
struct FEpisode
|
||||
{
|
||||
FString mEpisodeName;
|
||||
FString mEpisodeMap;
|
||||
FString mPicName;
|
||||
char mShortcut;
|
||||
bool mNoSkill;
|
||||
};
|
||||
|
||||
extern TArray<FEpisode> AllEpisodes;
|
||||
|
||||
|
||||
#endif //__G_LEVEL_H__
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "g_level.h"
|
||||
#include "sc_man.h"
|
||||
#include "w_wad.h"
|
||||
#include "m_menu.h"
|
||||
#include "cmdlib.h"
|
||||
#include "v_video.h"
|
||||
#include "p_lnspec.h"
|
||||
|
@ -63,6 +62,8 @@ TArray<level_info_t> wadlevelinfos;
|
|||
level_info_t TheDefaultLevelInfo;
|
||||
static cluster_info_t TheDefaultClusterInfo;
|
||||
|
||||
TArray<FEpisode> AllEpisodes;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -1655,10 +1656,10 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo)
|
|||
|
||||
void FMapInfoParser::ParseEpisodeInfo ()
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
char map[9];
|
||||
char *pic = NULL;
|
||||
bool picisgfx = false; // Shut up, GCC!!!!
|
||||
FString pic;
|
||||
FString name;
|
||||
bool remove = false;
|
||||
char key = 0;
|
||||
bool noskill = false;
|
||||
|
@ -1697,15 +1698,13 @@ void FMapInfoParser::ParseEpisodeInfo ()
|
|||
{
|
||||
ParseAssign();
|
||||
sc.MustGetString ();
|
||||
ReplaceString (&pic, sc.String);
|
||||
picisgfx = false;
|
||||
name = sc.String;
|
||||
}
|
||||
else if (sc.Compare ("picname"))
|
||||
{
|
||||
ParseAssign();
|
||||
sc.MustGetString ();
|
||||
ReplaceString (&pic, sc.String);
|
||||
picisgfx = true;
|
||||
pic = sc.String;
|
||||
}
|
||||
else if (sc.Compare ("remove"))
|
||||
{
|
||||
|
@ -1751,9 +1750,9 @@ void FMapInfoParser::ParseEpisodeInfo ()
|
|||
}
|
||||
|
||||
|
||||
for (i = 0; i < EpiDef.numitems; ++i)
|
||||
for (i = 0; i < AllEpisodes.Size(); i++)
|
||||
{
|
||||
if (strncmp (EpisodeMaps[i], map, 8) == 0)
|
||||
if (AllEpisodes[i].mEpisodeMap.CompareNoCase(map) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1762,50 +1761,17 @@ void FMapInfoParser::ParseEpisodeInfo ()
|
|||
if (remove)
|
||||
{
|
||||
// If the remove property is given for an episode, remove it.
|
||||
if (i < EpiDef.numitems)
|
||||
{
|
||||
if (i+1 < EpiDef.numitems)
|
||||
{
|
||||
memmove (&EpisodeMaps[i], &EpisodeMaps[i+1],
|
||||
sizeof(EpisodeMaps[0])*(EpiDef.numitems - i - 1));
|
||||
memmove (&EpisodeMenu[i], &EpisodeMenu[i+1],
|
||||
sizeof(EpisodeMenu[0])*(EpiDef.numitems - i - 1));
|
||||
memmove (&EpisodeNoSkill[i], &EpisodeNoSkill[i+1],
|
||||
sizeof(EpisodeNoSkill[0])*(EpiDef.numitems - i - 1));
|
||||
}
|
||||
EpiDef.numitems--;
|
||||
}
|
||||
AllEpisodes.Delete(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pic == NULL)
|
||||
{
|
||||
pic = copystring (map);
|
||||
picisgfx = false;
|
||||
}
|
||||
FEpisode *epi = &AllEpisodes[AllEpisodes.Reserve(1)];
|
||||
|
||||
if (i == EpiDef.numitems)
|
||||
{
|
||||
if (EpiDef.numitems == MAX_EPISODES)
|
||||
{
|
||||
i = EpiDef.numitems - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = EpiDef.numitems++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] const_cast<char *>(EpisodeMenu[i].name);
|
||||
}
|
||||
|
||||
EpisodeMenu[i].name = pic;
|
||||
EpisodeMenu[i].alphaKey = tolower(key);
|
||||
EpisodeMenu[i].fulltext = !picisgfx;
|
||||
EpisodeNoSkill[i] = noskill;
|
||||
strncpy (EpisodeMaps[i], map, 8);
|
||||
EpisodeMaps[i][8] = 0;
|
||||
epi->mEpisodeMap = map;
|
||||
epi->mEpisodeName = name;
|
||||
epi->mPicName = pic;
|
||||
epi->mShortcut = tolower(key);
|
||||
epi->mNoSkill = noskill;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1818,12 +1784,7 @@ void FMapInfoParser::ParseEpisodeInfo ()
|
|||
|
||||
void ClearEpisodes()
|
||||
{
|
||||
for (int i = 0; i < EpiDef.numitems; ++i)
|
||||
{
|
||||
delete[] const_cast<char *>(EpisodeMenu[i].name);
|
||||
EpisodeMenu[i].name = NULL;
|
||||
}
|
||||
EpiDef.numitems = 0;
|
||||
AllEpisodes.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2004,7 +1965,7 @@ void G_ParseMapInfo (const char *basemapinfo)
|
|||
}
|
||||
EndSequences.ShrinkToFit ();
|
||||
|
||||
if (EpiDef.numitems == 0)
|
||||
if (AllEpisodes.Size() == 0)
|
||||
{
|
||||
I_FatalError ("You cannot use clearepisodes in a MAPINFO if you do not define any new episodes after it.");
|
||||
}
|
||||
|
|
15
src/gi.cpp
15
src/gi.cpp
|
@ -103,12 +103,11 @@ const char* GameInfoBoarders[] =
|
|||
do \
|
||||
{ \
|
||||
sc.MustGetToken(TK_StringConst); \
|
||||
if(strlen(sc.String) > length) \
|
||||
if(length > 0 && strlen(sc.String) > length) \
|
||||
{ \
|
||||
sc.ScriptError("Value for '%s' can not be longer than %d characters.", #key, length); \
|
||||
} \
|
||||
FName val = sc.String; \
|
||||
gameinfo.key.Push(val); \
|
||||
gameinfo.key[gameinfo.key.Reserve(1)] = sc.String; \
|
||||
} \
|
||||
while (sc.CheckToken(',')); \
|
||||
}
|
||||
|
@ -283,6 +282,16 @@ void FMapInfoParser::ParseGameInfo()
|
|||
GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle")
|
||||
GAMEINFOKEY_CSTRING(Endoom, "endoom", 8)
|
||||
GAMEINFOKEY_INT(player5start, "player5start")
|
||||
GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0)
|
||||
GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title")
|
||||
GAMEINFOKEY_STRING(mFontColor, "menufontcolor_label")
|
||||
GAMEINFOKEY_STRING(mFontColorValue, "menufontcolor_value")
|
||||
GAMEINFOKEY_STRING(mFontColorMore, "menufontcolor_action")
|
||||
GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header")
|
||||
GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight")
|
||||
GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection")
|
||||
GAMEINFOKEY_CSTRING(mBackButton, "menubackbutton", 8)
|
||||
|
||||
else
|
||||
{
|
||||
// ignore unkown keys.
|
||||
|
|
10
src/gi.h
10
src/gi.h
|
@ -46,6 +46,7 @@
|
|||
#define GI_COMPATSTAIRS 0x00000020 // same for stairbuilding
|
||||
#define GI_COMPATPOLY1 0x00000040 // Hexen's MAP36 needs old polyobject drawing
|
||||
#define GI_COMPATPOLY2 0x00000080 // so does HEXDD's MAP47
|
||||
#define GI_NOTEXTCOLOR 0x00000100
|
||||
|
||||
#include "gametype.h"
|
||||
|
||||
|
@ -109,6 +110,15 @@ struct gameinfo_t
|
|||
int defaultdropstyle;
|
||||
int player5start;
|
||||
DWORD pickupcolor;
|
||||
TArray<FString> quitmessages;
|
||||
FName mTitleColor;
|
||||
FName mFontColor;
|
||||
FName mFontColorValue;
|
||||
FName mFontColorMore;
|
||||
FName mFontColorHeader;
|
||||
FName mFontColorHighlight;
|
||||
FName mFontColorSelection;
|
||||
char mBackButton[9];
|
||||
|
||||
const char *GetFinalePage(unsigned int num) const;
|
||||
};
|
||||
|
|
146
src/keysections.cpp
Normal file
146
src/keysections.cpp
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
** keysections.cpp
|
||||
** Custom key bindings
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2009 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 "g_level.h"
|
||||
#include "d_player.h"
|
||||
#include "gi.h"
|
||||
#include "c_bind.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "gameconfigfile.h"
|
||||
|
||||
TArray<FKeySection> KeySections;
|
||||
|
||||
static void LoadKeys (const char *modname, bool dbl)
|
||||
{
|
||||
char section[64];
|
||||
|
||||
if (GameNames[gameinfo.gametype] == NULL)
|
||||
return;
|
||||
|
||||
mysnprintf (section, countof(section), "%s.%s%sBindings", GameNames[gameinfo.gametype], modname,
|
||||
dbl ? ".Double" : ".");
|
||||
|
||||
FKeyBindings *bindings = dbl? &DoubleBindings : &Bindings;
|
||||
if (GameConfig->SetSection (section))
|
||||
{
|
||||
const char *key, *value;
|
||||
while (GameConfig->NextInSection (key, value))
|
||||
{
|
||||
bindings->DoBind (key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DoSaveKeys (FConfigFile *config, const char *section, FKeySection *keysection, bool dbl)
|
||||
{
|
||||
config->SetSection (section, true);
|
||||
config->ClearCurrentSection ();
|
||||
FKeyBindings *bindings = dbl? &DoubleBindings : &Bindings;
|
||||
for (unsigned i = 0; i < keysection->mActions.Size(); ++i)
|
||||
{
|
||||
bindings->ArchiveBindings (config, keysection->mActions[i].mAction);
|
||||
}
|
||||
}
|
||||
|
||||
void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen)
|
||||
{
|
||||
for (unsigned i=0; i<KeySections.Size(); i++)
|
||||
{
|
||||
mysnprintf (subsection, sublen, "%s.Bindings", KeySections[i].mSection);
|
||||
DoSaveKeys (config, section, &KeySections[i], false);
|
||||
mysnprintf (subsection, sublen, "%s.DoubleBindings", KeySections[i].mSection);
|
||||
DoSaveKeys (config, section, &KeySections[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
static int CurrentKeySection = -1;
|
||||
|
||||
CCMD (addkeysection)
|
||||
{
|
||||
if (ParsingKeyConf)
|
||||
{
|
||||
if (argv.argc() != 3)
|
||||
{
|
||||
Printf ("Usage: addkeysection <menu section name> <ini name>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit the ini name to 32 chars
|
||||
if (strlen (argv[2]) > 32)
|
||||
argv[2][32] = 0;
|
||||
|
||||
for (unsigned i = 0; i < KeySections.Size(); i++)
|
||||
{
|
||||
if (KeySections[i].mTitle.CompareNoCase(argv[2] == 0))
|
||||
{
|
||||
CurrentKeySection = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CurrentKeySection = KeySections.Reserve(1);
|
||||
KeySections[CurrentKeySection].mTitle = argv[1];
|
||||
KeySections[CurrentKeySection].mSection = argv[2];
|
||||
// Load bindings for this section from the ini
|
||||
LoadKeys (argv[2], 0);
|
||||
LoadKeys (argv[2], 1);
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (addmenukey)
|
||||
{
|
||||
if (ParsingKeyConf)
|
||||
{
|
||||
if (argv.argc() != 3)
|
||||
{
|
||||
Printf ("Usage: addmenukey <description> <command>\n");
|
||||
return;
|
||||
}
|
||||
if (CurrentKeySection == -1 || CurrentKeySection >= (int)KeySections.Size())
|
||||
{
|
||||
Printf ("You must use addkeysection first.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FKeySection *sect = &KeySections[CurrentKeySection];
|
||||
|
||||
FKeyAction *act = §->mActions[sect->mActions.Reserve(1)];
|
||||
act->mTitle = argv[1];
|
||||
act->mAction = argv[2];
|
||||
}
|
||||
}
|
||||
|
|
@ -60,5 +60,6 @@ double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons);
|
|||
void I_GetAxes(float axes[NUM_JOYAXIS]);
|
||||
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks);
|
||||
IJoystickConfig *I_UpdateDeviceList();
|
||||
extern void UpdateJoystickMenu(IJoystickConfig *);
|
||||
|
||||
#endif
|
||||
|
|
4152
src/m_menu.cpp
4152
src/m_menu.cpp
File diff suppressed because it is too large
Load diff
280
src/m_menu.h
280
src/m_menu.h
|
@ -1,280 +0,0 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Menu widget stuff, episode selection and such.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __M_MENU_H__
|
||||
#define __M_MENU_H__
|
||||
|
||||
#include "c_cvars.h"
|
||||
|
||||
struct event_t;
|
||||
struct menu_t;
|
||||
//
|
||||
// MENUS
|
||||
//
|
||||
// Called by main loop,
|
||||
// saves config file and calls I_Quit when user exits.
|
||||
// Even when the menu is not displayed,
|
||||
// this can resize the view and change game parameters.
|
||||
// Does all the real work of the menu interaction.
|
||||
bool M_Responder (event_t *ev);
|
||||
|
||||
// Called by main loop,
|
||||
// only used for menu (skull cursor) animation.
|
||||
void M_Ticker (void);
|
||||
|
||||
// Called by main loop,
|
||||
// draws the menus directly into the screen buffer.
|
||||
void M_Drawer (void);
|
||||
|
||||
// Called by D_DoomMain, loads the config file.
|
||||
void M_Init (void);
|
||||
|
||||
void M_Deinit ();
|
||||
|
||||
// Called by intro code to force menu up upon a keypress,
|
||||
// does nothing if menu is already up.
|
||||
void M_StartControlPanel (bool makeSound, bool wantTop=false);
|
||||
|
||||
// Turns off the menu
|
||||
void M_ClearMenus ();
|
||||
|
||||
// [RH] Setup options menu
|
||||
bool M_StartOptionsMenu (void);
|
||||
|
||||
// [RH] Handle keys for options menu
|
||||
void M_OptResponder (event_t *ev);
|
||||
|
||||
// [RH] Draw options menu
|
||||
void M_OptDrawer (void);
|
||||
|
||||
// [RH] Initialize options menu
|
||||
void M_OptInit (void);
|
||||
|
||||
// [RH] Initialize the video modes menu
|
||||
void M_InitVideoModesMenu (void);
|
||||
|
||||
void M_SwitchMenu (struct menu_t *menu);
|
||||
|
||||
void M_PopMenuStack (void);
|
||||
|
||||
// [RH] Called whenever the display mode changes
|
||||
void M_RefreshModesList ();
|
||||
|
||||
void M_ActivateMenuInput ();
|
||||
void M_DeactivateMenuInput ();
|
||||
|
||||
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
|
||||
|
||||
//
|
||||
// MENU TYPEDEFS
|
||||
//
|
||||
typedef enum {
|
||||
whitetext,
|
||||
redtext,
|
||||
more,
|
||||
rightmore,
|
||||
safemore,
|
||||
rsafemore,
|
||||
joymore,
|
||||
slider,
|
||||
absslider,
|
||||
inverter,
|
||||
discrete,
|
||||
discretes,
|
||||
cdiscrete,
|
||||
ediscrete,
|
||||
control,
|
||||
screenres,
|
||||
bitflag,
|
||||
bitmask,
|
||||
listelement,
|
||||
nochoice,
|
||||
numberedmore,
|
||||
colorpicker,
|
||||
intslider,
|
||||
palettegrid,
|
||||
joy_sens,
|
||||
joy_slider,
|
||||
joy_map,
|
||||
joy_inverter,
|
||||
mapcontrol,
|
||||
} itemtype;
|
||||
|
||||
struct IJoystickConfig;
|
||||
void UpdateJoystickMenu(IJoystickConfig *selected);
|
||||
|
||||
// Yeargh! It's a monster!
|
||||
struct menuitem_t
|
||||
{
|
||||
itemtype type;
|
||||
const char *label;
|
||||
union {
|
||||
FBaseCVar *cvar;
|
||||
FIntCVar *intcvar;
|
||||
FGUIDCVar *guidcvar;
|
||||
FColorCVar *colorcvar;
|
||||
int selmode;
|
||||
float fval;
|
||||
int joyselection;
|
||||
} a;
|
||||
union {
|
||||
float min; /* aka numvalues aka invflag */
|
||||
float numvalues;
|
||||
float invflag;
|
||||
int key1;
|
||||
char *res1;
|
||||
int position;
|
||||
} b;
|
||||
union {
|
||||
float max;
|
||||
int key2;
|
||||
char *res2;
|
||||
void *extra;
|
||||
float discretecenter; // 1 to center or 2 to disable repeat (do I even use centered discretes?)
|
||||
} c;
|
||||
union {
|
||||
float step;
|
||||
char *res3;
|
||||
FBoolCVar *graycheck; // for drawing discrete items
|
||||
} d;
|
||||
union {
|
||||
struct value_t *values;
|
||||
struct valuestring_t *valuestrings;
|
||||
struct valueenum_t *enumvalues;
|
||||
char *command;
|
||||
void (*cfunc)(FBaseCVar *cvar, float newval);
|
||||
void (*mfunc)(void);
|
||||
void (*lfunc)(int);
|
||||
int highlight;
|
||||
int flagmask;
|
||||
int joyslidernum;
|
||||
} e;
|
||||
};
|
||||
|
||||
struct menu_t {
|
||||
const char *texttitle;
|
||||
int lastOn;
|
||||
int numitems;
|
||||
int indent;
|
||||
menuitem_t *items;
|
||||
int scrolltop;
|
||||
int scrollpos;
|
||||
int y;
|
||||
bool (*PreDraw)(void);
|
||||
bool DontDim;
|
||||
void (*EscapeHandler)(void);
|
||||
};
|
||||
|
||||
struct value_t {
|
||||
float value;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct valuestring_t {
|
||||
float value;
|
||||
FString name;
|
||||
};
|
||||
|
||||
struct valueenum_t {
|
||||
const char *value; // Value of cvar
|
||||
const char *name; // Name on menu
|
||||
};
|
||||
|
||||
struct oldmenuitem_t
|
||||
{
|
||||
// -1 = no cursor here, 1 = ok, 2 = arrows ok
|
||||
SBYTE status;
|
||||
BYTE fulltext; // [RH] Menu name is text, not a graphic
|
||||
|
||||
// hotkey in menu
|
||||
char alphaKey;
|
||||
|
||||
const char *name;
|
||||
|
||||
// choice = menu item #.
|
||||
// if status = 2,
|
||||
// choice=0:leftarrow,1:rightarrow
|
||||
void (*routine)(int choice);
|
||||
int textcolor;
|
||||
};
|
||||
|
||||
struct oldmenu_t
|
||||
{
|
||||
short numitems; // # of menu items
|
||||
oldmenuitem_t *menuitems; // menu items
|
||||
void (*routine)(void); // draw routine
|
||||
short x;
|
||||
short y; // x,y of menu
|
||||
short lastOn; // last item user was on in menu
|
||||
};
|
||||
|
||||
struct menustack_t
|
||||
{
|
||||
union {
|
||||
menu_t *newmenu;
|
||||
oldmenu_t *old;
|
||||
} menu;
|
||||
bool isNewStyle;
|
||||
bool drawSkull;
|
||||
};
|
||||
|
||||
enum EMenuKey
|
||||
{
|
||||
MKEY_Up,
|
||||
MKEY_Down,
|
||||
MKEY_Left,
|
||||
MKEY_Right,
|
||||
MKEY_PageUp,
|
||||
MKEY_PageDown,
|
||||
//----------------- Keys past here do not repeat.
|
||||
MKEY_Enter,
|
||||
MKEY_Back, // Back to previous menu
|
||||
MKEY_Clear, // Clear keybinding/flip player sprite preview
|
||||
|
||||
NUM_MKEYS
|
||||
};
|
||||
|
||||
void M_ButtonHandler(EMenuKey key, bool repeat);
|
||||
void M_OptButtonHandler(EMenuKey key, bool repeat);
|
||||
void M_DrawConText (int color, int x, int y, const char *str);
|
||||
|
||||
extern value_t YesNo[2];
|
||||
extern value_t NoYes[2];
|
||||
extern value_t OnOff[2];
|
||||
|
||||
extern menustack_t MenuStack[16];
|
||||
extern int MenuStackDepth;
|
||||
|
||||
extern bool OptionsActive;
|
||||
extern int skullAnimCounter;
|
||||
|
||||
extern menu_t *CurrentMenu;
|
||||
extern int CurrentItem;
|
||||
|
||||
#define MAX_EPISODES 8
|
||||
|
||||
extern oldmenuitem_t EpisodeMenu[MAX_EPISODES];
|
||||
extern bool EpisodeNoSkill[MAX_EPISODES];
|
||||
extern char EpisodeMaps[MAX_EPISODES][9];
|
||||
extern oldmenu_t EpiDef;
|
||||
|
||||
#endif
|
|
@ -85,8 +85,6 @@ CVAR(String, screenshot_type, "png", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
|||
CVAR(String, screenshot_dir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
EXTERN_CVAR(Bool, longsavemessages);
|
||||
|
||||
extern void FreeKeySections();
|
||||
|
||||
static long ParseCommandLine (const char *args, int *argc, char **argv);
|
||||
|
||||
//
|
||||
|
@ -420,7 +418,6 @@ void M_LoadDefaults ()
|
|||
{
|
||||
GameConfig = new FGameConfigFile;
|
||||
GameConfig->DoGlobalSetup ();
|
||||
atterm (FreeKeySections);
|
||||
atterm (M_SaveDefaultsFinal);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ void M_LoadDefaults ();
|
|||
bool M_SaveDefaults (const char *filename);
|
||||
void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen);
|
||||
|
||||
|
||||
// Prepends ~/.zdoom to path
|
||||
FString GetUserFile (const char *path);
|
||||
|
||||
|
|
3958
src/m_options.cpp
3958
src/m_options.cpp
File diff suppressed because it is too large
Load diff
357
src/menu/colorpickermenu.cpp
Normal file
357
src/menu/colorpickermenu.cpp
Normal file
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
** colorpickermenu.cpp
|
||||
** The color picker menu
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 <float.h>
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "w_wad.h"
|
||||
#include "sc_man.h"
|
||||
#include "v_font.h"
|
||||
#include "g_level.h"
|
||||
#include "d_player.h"
|
||||
#include "v_video.h"
|
||||
#include "gi.h"
|
||||
#include "i_system.h"
|
||||
#include "c_bind.h"
|
||||
#include "v_palette.h"
|
||||
#include "d_event.h"
|
||||
#include "d_gui.h"
|
||||
|
||||
#define NO_IMP
|
||||
#include "menu/optionmenuitems.h"
|
||||
|
||||
class DColorPickerMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DColorPickerMenu, DOptionMenu)
|
||||
|
||||
float mRed;
|
||||
float mGreen;
|
||||
float mBlue;
|
||||
|
||||
int mGridPosX;
|
||||
int mGridPosY;
|
||||
|
||||
int mStartItem;
|
||||
|
||||
FColorCVar *mCVar;
|
||||
|
||||
public:
|
||||
|
||||
DColorPickerMenu(DMenu *parent, const char *name, FOptionMenuDescriptor *desc, FColorCVar *cvar)
|
||||
{
|
||||
mStartItem = desc->mItems.Size();
|
||||
mRed = (float)RPART(DWORD(*cvar));
|
||||
mGreen = (float)GPART(DWORD(*cvar));
|
||||
mBlue = (float)BPART(DWORD(*cvar));
|
||||
mGridPosX = 0;
|
||||
mGridPosY = 0;
|
||||
mCVar = cvar;
|
||||
|
||||
// This menu uses some featurs that are hard to implement in an external control lump
|
||||
// so it creates its own list of menu items.
|
||||
desc->mItems.Resize(mStartItem+8);
|
||||
desc->mItems[mStartItem+0] = new FOptionMenuItemStaticText(name, false);
|
||||
desc->mItems[mStartItem+1] = new FOptionMenuItemStaticText(" ", false);
|
||||
desc->mItems[mStartItem+2] = new FOptionMenuSliderVar("Red", &mRed, 0, 255, 15, 0);
|
||||
desc->mItems[mStartItem+3] = new FOptionMenuSliderVar("Green", &mGreen, 0, 255, 15, 0);
|
||||
desc->mItems[mStartItem+4] = new FOptionMenuSliderVar("Blue", &mBlue, 0, 255, 15, 0);
|
||||
desc->mItems[mStartItem+5] = new FOptionMenuItemStaticText(" ", false);
|
||||
desc->mItems[mStartItem+6] = new FOptionMenuItemCommand("Undo changes", "undocolorpic");
|
||||
desc->mItems[mStartItem+7] = new FOptionMenuItemStaticText(" ", false);
|
||||
desc->mSelectedItem = mStartItem + 2;
|
||||
Init(parent, desc);
|
||||
desc->mIndent = 0;
|
||||
desc->CalcIndent();
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
if (mStartItem >= 0)
|
||||
{
|
||||
for(unsigned i=0;i<8;i++)
|
||||
{
|
||||
delete mDesc->mItems[mStartItem+i];
|
||||
mDesc->mItems.Resize(mStartItem);
|
||||
}
|
||||
UCVarValue val;
|
||||
val.Int = MAKERGB(int(mRed), int(mGreen), int(mBlue));
|
||||
if (mCVar != NULL) mCVar->SetGenericRep (val, CVAR_Int);
|
||||
mStartItem = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
mRed = (float)RPART(DWORD(*mCVar));
|
||||
mGreen = (float)GPART(DWORD(*mCVar));
|
||||
mBlue = (float)BPART(DWORD(*mCVar));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int &mSelectedItem = mDesc->mSelectedItem;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Down:
|
||||
if (mSelectedItem == mStartItem+6) // last valid item
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
mGridPosY = 0;
|
||||
// let it point to the last static item so that the super class code still has a valid item
|
||||
mSelectedItem = mStartItem+7;
|
||||
return true;
|
||||
}
|
||||
else if (mSelectedItem == mStartItem+7)
|
||||
{
|
||||
if (mGridPosY < 15)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
mGridPosY++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Up:
|
||||
if (mSelectedItem == mStartItem+7)
|
||||
{
|
||||
if (mGridPosY > 0)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
mGridPosY--;
|
||||
}
|
||||
else
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
mSelectedItem = mStartItem+6;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Left:
|
||||
if (mSelectedItem == mStartItem+7)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
if (--mGridPosX < 0) mGridPosX = 15;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Right:
|
||||
if (mSelectedItem == mStartItem+7)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
if (++mGridPosX > 15) mGridPosX = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mSelectedItem == mStartItem+7)
|
||||
{
|
||||
// Choose selected palette entry
|
||||
int index = mGridPosX + mGridPosY * 16;
|
||||
mRed = GPalette.BaseColors[index].r;
|
||||
mGreen = GPalette.BaseColors[index].g;
|
||||
mBlue = GPalette.BaseColors[index].b;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (mSelectedItem >= 0 && mSelectedItem < mStartItem+7)
|
||||
{
|
||||
if (mDesc->mItems[mDesc->mSelectedItem]->MenuEvent(mkey, fromcontroller)) return true;
|
||||
}
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool MouseEvent(int type, int mx, int my)
|
||||
{
|
||||
int olditem = mDesc->mSelectedItem;
|
||||
bool res = Super::MouseEvent(type, mx, my);
|
||||
|
||||
if (mDesc->mSelectedItem == -1 || mDesc->mSelectedItem == mStartItem+7)
|
||||
{
|
||||
int y = (-mDesc->mPosition + BigFont->GetHeight() + mDesc->mItems.Size() * OptionSettings.mLinespacing) * CleanYfac_1;
|
||||
int h = (screen->GetHeight() - y) / 16;
|
||||
int fh = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
int w = fh;
|
||||
int yy = y + 2 * CleanYfac_1;
|
||||
int indent = (screen->GetWidth() / 2);
|
||||
|
||||
if (h > fh) h = fh;
|
||||
else if (h < 4) return res; // no space to draw it.
|
||||
|
||||
int box_y = y - 2 * CleanYfac_1;
|
||||
int box_x = indent - 16*w;
|
||||
|
||||
if (mx >= box_x && mx < box_x + 16*w && my >= box_y && my < box_y + 16*h)
|
||||
{
|
||||
int cell_x = (mx - box_x) / w;
|
||||
int cell_y = (my - box_y) / h;
|
||||
|
||||
if (olditem != mStartItem+7 || cell_x != mGridPosX || cell_y != mGridPosY)
|
||||
{
|
||||
mGridPosX = cell_x;
|
||||
mGridPosY = cell_y;
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc->mSelectedItem = mStartItem+7;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
MenuEvent(MKEY_Enter, true);
|
||||
if (m_use_mouse == 2) mDesc->mSelectedItem = -1;
|
||||
}
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Drawer()
|
||||
{
|
||||
Super::Drawer();
|
||||
|
||||
if (mCVar == NULL) return;
|
||||
int y = (-mDesc->mPosition + BigFont->GetHeight() + mDesc->mItems.Size() * OptionSettings.mLinespacing) * CleanYfac_1;
|
||||
int h = (screen->GetHeight() - y) / 16;
|
||||
int fh = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
int w = fh;
|
||||
int yy = y;
|
||||
|
||||
if (h > fh) h = fh;
|
||||
else if (h < 4) return; // no space to draw it.
|
||||
|
||||
int indent = (screen->GetWidth() / 2);
|
||||
int p = 0;
|
||||
|
||||
for(int i = 0; i < 16; i++, y += h)
|
||||
{
|
||||
int box_x, box_y;
|
||||
int x1;
|
||||
|
||||
box_y = y - 2 * CleanYfac_1;
|
||||
box_x = indent - 16*w;
|
||||
for (x1 = 0; x1 < 16; ++x1, p++)
|
||||
{
|
||||
screen->Clear (box_x, box_y, box_x + w, box_y + h, p, 0);
|
||||
if ((mDesc->mSelectedItem == mStartItem+7) &&
|
||||
(/*p == CurrColorIndex ||*/ (i == mGridPosY && x1 == mGridPosX)))
|
||||
{
|
||||
int r, g, b;
|
||||
DWORD col;
|
||||
double blinky;
|
||||
if (i == mGridPosY && x1 == mGridPosX)
|
||||
{
|
||||
r = 255, g = 128, b = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 200, g = 200, b = 255;
|
||||
}
|
||||
// Make sure the cursors stand out against similar colors
|
||||
// by pulsing them.
|
||||
blinky = fabs(sin(I_MSTime()/1000.0)) * 0.5 + 0.5;
|
||||
col = MAKEARGB(255,int(r*blinky),int(g*blinky),int(b*blinky));
|
||||
|
||||
screen->Clear (box_x, box_y, box_x + w, box_y + 1, -1, col);
|
||||
screen->Clear (box_x, box_y + h-1, box_x + w, box_y + h, -1, col);
|
||||
screen->Clear (box_x, box_y, box_x + 1, box_y + h, -1, col);
|
||||
screen->Clear (box_x + w - 1, box_y, box_x + w, box_y + h, -1, col);
|
||||
}
|
||||
box_x += w;
|
||||
}
|
||||
}
|
||||
y = yy;
|
||||
DWORD newColor = MAKEARGB(255, int(mRed), int(mGreen), int(mBlue));
|
||||
DWORD oldColor = DWORD(*mCVar) | 0xFF000000;
|
||||
|
||||
int x = screen->GetWidth()*2/3;
|
||||
|
||||
screen->Clear (x, y, x + 48*CleanXfac_1, y + 48*CleanYfac_1, -1, oldColor);
|
||||
screen->Clear (x + 48*CleanXfac_1, y, x + 48*2*CleanXfac_1, y + 48*CleanYfac_1, -1, newColor);
|
||||
|
||||
y += 49*CleanYfac_1;
|
||||
screen->DrawText (SmallFont, CR_GRAY, x+(24-SmallFont->StringWidth("Old")/2)*CleanXfac_1, y,
|
||||
"Old", DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_WHITE, x+(48+24-SmallFont->StringWidth("New")/2)*CleanXfac_1, y,
|
||||
"New", DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(DColorPickerMenu)
|
||||
|
||||
CCMD(undocolorpic)
|
||||
{
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DColorPickerMenu)))
|
||||
{
|
||||
static_cast<DColorPickerMenu*>(DMenu::CurrentMenu)->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar)
|
||||
{
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Colorpickermenu);
|
||||
if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
|
||||
{
|
||||
return new DColorPickerMenu(parent, name, (FOptionMenuDescriptor*)(*desc), cvar);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
420
src/menu/joystickmenu.cpp
Normal file
420
src/menu/joystickmenu.cpp
Normal file
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
** joystickmenu.cpp
|
||||
** The joystick configuration menus
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "w_wad.h"
|
||||
#include "sc_man.h"
|
||||
#include "v_font.h"
|
||||
#include "g_level.h"
|
||||
#include "d_player.h"
|
||||
#include "v_video.h"
|
||||
#include "gi.h"
|
||||
#include "i_system.h"
|
||||
#include "c_bind.h"
|
||||
#include "v_palette.h"
|
||||
#include "d_event.h"
|
||||
#include "d_gui.h"
|
||||
#include "i_music.h"
|
||||
#include "m_joy.h"
|
||||
|
||||
#define NO_IMP
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
|
||||
static TArray<IJoystickConfig *> Joysticks;
|
||||
IJoystickConfig *SELECTED_JOYSTICK;
|
||||
|
||||
FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuSliderJoySensitivity : public FOptionMenuSliderBase
|
||||
{
|
||||
public:
|
||||
FOptionMenuSliderJoySensitivity(const char *label, double min, double max, double step, int showval)
|
||||
: FOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
}
|
||||
|
||||
double GetValue()
|
||||
{
|
||||
return SELECTED_JOYSTICK->GetSensitivity();
|
||||
}
|
||||
|
||||
void SetValue(double val)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetSensitivity(float(val));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuSliderJoyScale : public FOptionMenuSliderBase
|
||||
{
|
||||
int mAxis;
|
||||
int mNeg;
|
||||
|
||||
public:
|
||||
FOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval)
|
||||
: FOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
mAxis = axis;
|
||||
mNeg = 1;
|
||||
}
|
||||
|
||||
double GetValue()
|
||||
{
|
||||
double d = SELECTED_JOYSTICK->GetAxisScale(mAxis);
|
||||
mNeg = d < 0? -1:1;
|
||||
return d;
|
||||
}
|
||||
|
||||
void SetValue(double val)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetAxisScale(mAxis, float(val * mNeg));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuSliderJoyDeadZone : public FOptionMenuSliderBase
|
||||
{
|
||||
int mAxis;
|
||||
int mNeg;
|
||||
|
||||
public:
|
||||
FOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval)
|
||||
: FOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
mAxis = axis;
|
||||
mNeg = 1;
|
||||
}
|
||||
|
||||
double GetValue()
|
||||
{
|
||||
double d = SELECTED_JOYSTICK->GetAxisDeadZone(mAxis);
|
||||
mNeg = d < 0? -1:1;
|
||||
return d;
|
||||
}
|
||||
|
||||
void SetValue(double val)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetAxisDeadZone(mAxis, float(val * mNeg));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemJoyMap : public FOptionMenuItemOptionBase
|
||||
{
|
||||
int mAxis;
|
||||
public:
|
||||
|
||||
FOptionMenuItemJoyMap(const char *label, int axis, const char *values, int center)
|
||||
: FOptionMenuItemOptionBase(label, "none", values, NULL, center)
|
||||
{
|
||||
mAxis = axis;
|
||||
}
|
||||
|
||||
int GetSelection()
|
||||
{
|
||||
float f = (float)(int)SELECTED_JOYSTICK->GetAxisMap(mAxis);
|
||||
for(unsigned i=0;i<mValues->mValues.Size(); i++)
|
||||
{
|
||||
if (fabs(f - mValues->mValues[i].Value) < FLT_EPSILON)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SetSelection(int Selection)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetAxisMap(mAxis, (EJoyAxis)Selection);
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemInverter : public FOptionMenuItemOptionBase
|
||||
{
|
||||
int mAxis;
|
||||
public:
|
||||
|
||||
FOptionMenuItemInverter(const char *label, int axis, int center)
|
||||
: FOptionMenuItemOptionBase(label, "none", "YesNo", NULL, center)
|
||||
{
|
||||
mAxis = axis;
|
||||
}
|
||||
|
||||
int GetSelection()
|
||||
{
|
||||
float f = SELECTED_JOYSTICK->GetAxisScale(mAxis);
|
||||
return f > 0? 0:1;
|
||||
}
|
||||
|
||||
void SetSelection(int Selection)
|
||||
{
|
||||
float f = fabs(SELECTED_JOYSTICK->GetAxisScale(mAxis));
|
||||
if (Selection) f*=-1;
|
||||
SELECTED_JOYSTICK->SetAxisScale(mAxis, f);
|
||||
}
|
||||
};
|
||||
|
||||
class DJoystickConfigMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DJoystickConfigMenu, DOptionMenu)
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DJoystickConfigMenu)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Executes a CCMD, action is a CCMD name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemJoyConfigMenu : public FOptionMenuItemSubmenu
|
||||
{
|
||||
IJoystickConfig *mJoy;
|
||||
public:
|
||||
FOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy)
|
||||
: FOptionMenuItemSubmenu(label, "JoystickConfigMenu")
|
||||
{
|
||||
mJoy = joy;
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
UpdateJoystickConfigMenu(mJoy);
|
||||
return FOptionMenuItemSubmenu::Activate();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Joystick Menu
|
||||
*
|
||||
*=======================================*/
|
||||
|
||||
FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy)
|
||||
{
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_JoystickConfigMenu);
|
||||
if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
|
||||
{
|
||||
FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc;
|
||||
FOptionMenuItem *it;
|
||||
for(unsigned i=0;i<opt->mItems.Size();i++)
|
||||
{
|
||||
delete opt->mItems[i];
|
||||
opt->mItems.Clear();
|
||||
}
|
||||
opt->mTitle.Format("Configure %s", joy->GetName().GetChars());
|
||||
|
||||
if (joy == NULL)
|
||||
{
|
||||
it = new FOptionMenuItemStaticText("Invalid controller specified for menu", false);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
SELECTED_JOYSTICK = joy;
|
||||
|
||||
it = new FOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuItemStaticText(" ", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
if (joy->GetNumAxes() > 0)
|
||||
{
|
||||
it = new FOptionMenuItemStaticText("Axis Configuration", true);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
for (int i = 0; i < joy->GetNumAxes(); ++i)
|
||||
{
|
||||
it = new FOptionMenuItemStaticText(" ", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
it = new FOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuItemInverter("Invert", i, false);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it = new FOptionMenuItemStaticText("No configurable axes", false);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
}
|
||||
opt->mScrollPos = 0;
|
||||
opt->mSelectedItem = -1;
|
||||
opt->mIndent = 0;
|
||||
opt->mPosition = -25;
|
||||
opt->CalcIndent();
|
||||
return opt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UpdateJoystickMenu(IJoystickConfig *selected)
|
||||
{
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_JoystickOptions);
|
||||
if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
|
||||
{
|
||||
FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc;
|
||||
FOptionMenuItem *it;
|
||||
for(unsigned i=0;i<opt->mItems.Size();i++)
|
||||
{
|
||||
delete opt->mItems[i];
|
||||
opt->mItems.Clear();
|
||||
}
|
||||
|
||||
int i;
|
||||
int itemnum = -1;
|
||||
|
||||
I_GetJoysticks(Joysticks);
|
||||
if ((unsigned)itemnum >= Joysticks.Size())
|
||||
{
|
||||
itemnum = Joysticks.Size() - 1;
|
||||
}
|
||||
if (selected != NULL)
|
||||
{
|
||||
for (i = 0; (unsigned)i < Joysticks.Size(); ++i)
|
||||
{
|
||||
if (Joysticks[i] == selected)
|
||||
{
|
||||
itemnum = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Todo: Block joystick for changing this one.
|
||||
it = new FOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
#ifdef _WIN32
|
||||
it = new FOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
#endif
|
||||
|
||||
it = new FOptionMenuItemStaticText(" ", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
if (Joysticks.Size() == 0)
|
||||
{
|
||||
it = new FOptionMenuItemStaticText("No controllers detected", false);
|
||||
opt->mItems.Push(it);
|
||||
if (!use_joystick)
|
||||
{
|
||||
it = new FOptionMenuItemStaticText("Controller support must be", false);
|
||||
opt->mItems.Push(it);
|
||||
it = new FOptionMenuItemStaticText("enabled to detect any", false);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it = new FOptionMenuItemStaticText("Configure controllers:", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
for (int i = 0; i < (int)Joysticks.Size(); ++i)
|
||||
{
|
||||
it = new FOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]);
|
||||
opt->mItems.Push(it);
|
||||
if (i == itemnum) opt->mSelectedItem = opt->mItems.Size();
|
||||
}
|
||||
}
|
||||
if (opt->mSelectedItem >= (int)opt->mItems.Size())
|
||||
{
|
||||
opt->mSelectedItem = opt->mItems.Size() - 1;
|
||||
}
|
||||
|
||||
opt->CalcIndent();
|
||||
|
||||
// If the joystick config menu is open, close it if the device it's
|
||||
// open for is gone.
|
||||
for (i = 0; (unsigned)i < Joysticks.Size(); ++i)
|
||||
{
|
||||
if (Joysticks[i] == SELECTED_JOYSTICK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (int)Joysticks.Size())
|
||||
{
|
||||
SELECTED_JOYSTICK = NULL;
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DJoystickConfigMenu)))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
511
src/menu/listmenu.cpp
Normal file
511
src/menu/listmenu.cpp
Normal file
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
** 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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DListMenu::DListMenu(DMenu *parent, FListMenuDescriptor *desc)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mDesc = desc;
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
GC::WriteBarrier(this, parent);
|
||||
mDesc = desc;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItem *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 startedAt = mDesc->mSelectedItem;
|
||||
|
||||
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);
|
||||
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);
|
||||
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 (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 == 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
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItem::~FListMenuItem()
|
||||
{
|
||||
}
|
||||
|
||||
bool FListMenuItem::CheckCoordinate(int x, int y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void FListMenuItem::Ticker()
|
||||
{
|
||||
}
|
||||
|
||||
void FListMenuItem::Drawer(bool selected)
|
||||
{
|
||||
}
|
||||
|
||||
bool FListMenuItem::Selectable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void FListMenuItem::DrawSelector(int xofs, int yofs, FTextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((DMenu::MenuTime%8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
mXpos + xofs, mYpos + yofs, "\xd", DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture (TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
bool FListMenuItem::Activate()
|
||||
{
|
||||
return false; // cannot be activated
|
||||
}
|
||||
|
||||
FName FListMenuItem::GetAction(int *pparam)
|
||||
{
|
||||
return mAction;
|
||||
}
|
||||
|
||||
bool FListMenuItem::SetString(int i, const char *s)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FListMenuItem::GetString(int i, char *s, int len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FListMenuItem::SetValue(int i, int value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FListMenuItem::GetValue(int i, int *pvalue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void FListMenuItem::Enable(bool on)
|
||||
{
|
||||
mEnabled = on;
|
||||
}
|
||||
|
||||
bool FListMenuItem::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FListMenuItem::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FListMenuItem::CheckHotkey(int c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// static patch
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemStaticPatch::FListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered)
|
||||
: FListMenuItem(x, y)
|
||||
{
|
||||
mTexture = patch;
|
||||
mCentered = centered;
|
||||
}
|
||||
|
||||
void FListMenuItemStaticPatch::Drawer(bool selected)
|
||||
{
|
||||
int x = mXpos;
|
||||
FTexture *tex = TexMan(mTexture);
|
||||
if (mYpos >= 0)
|
||||
{
|
||||
if (mCentered) x -= tex->GetScaledWidth()/2;
|
||||
screen->DrawTexture (tex, x, mYpos, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1);
|
||||
if (mCentered) x -= (tex->GetScaledWidth()*CleanXfac)/2;
|
||||
screen->DrawTexture (tex, x, -mYpos*CleanYfac, DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// static text
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemStaticText::FListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered)
|
||||
: FListMenuItem(x, y)
|
||||
{
|
||||
mText = ncopystring(text);
|
||||
mFont = font;
|
||||
mColor = color;
|
||||
mCentered = centered;
|
||||
}
|
||||
|
||||
void FListMenuItemStaticText::Drawer(bool selected)
|
||||
{
|
||||
const char *text = mText;
|
||||
if (text != NULL)
|
||||
{
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
if (mYpos >= 0)
|
||||
{
|
||||
int x = mXpos;
|
||||
if (mCentered) x -= mFont->StringWidth(text)/2;
|
||||
screen->DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1);
|
||||
if (mCentered) x -= (mFont->StringWidth(text)*CleanXfac)/2;
|
||||
screen->DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FListMenuItemStaticText::~FListMenuItemStaticText()
|
||||
{
|
||||
if (mText != NULL) delete [] mText;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for selectable items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemSelectable::FListMenuItemSelectable(int x, int y, int height, FName action, int param)
|
||||
: FListMenuItem(x, y, action)
|
||||
{
|
||||
mHeight = height;
|
||||
mParam = param;
|
||||
mHotkey = 0;
|
||||
}
|
||||
|
||||
bool FListMenuItemSelectable::CheckCoordinate(int x, int y)
|
||||
{
|
||||
return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here
|
||||
}
|
||||
|
||||
bool FListMenuItemSelectable::Selectable()
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
bool FListMenuItemSelectable::Activate()
|
||||
{
|
||||
M_SetMenu(mAction, mParam);
|
||||
return true;
|
||||
}
|
||||
|
||||
FName FListMenuItemSelectable::GetAction(int *pparam)
|
||||
{
|
||||
if (pparam != NULL) *pparam = mParam;
|
||||
return mAction;
|
||||
}
|
||||
|
||||
bool FListMenuItemSelectable::CheckHotkey(int c)
|
||||
{
|
||||
return c == tolower(mHotkey);
|
||||
}
|
||||
|
||||
bool FListMenuItemSelectable::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == DMenu::MOUSE_Release)
|
||||
{
|
||||
if (DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// text item
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemText::FListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, FName child, int param)
|
||||
: FListMenuItemSelectable(x, y, height, child, param)
|
||||
{
|
||||
mText = ncopystring(text);
|
||||
mFont = font;
|
||||
mColor = color;
|
||||
mHotkey = hotkey;
|
||||
}
|
||||
|
||||
FListMenuItemText::~FListMenuItemText()
|
||||
{
|
||||
if (mText != NULL)
|
||||
{
|
||||
delete [] mText;
|
||||
}
|
||||
}
|
||||
|
||||
void FListMenuItemText::Drawer(bool selected)
|
||||
{
|
||||
const char *text = mText;
|
||||
if (text != NULL)
|
||||
{
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
screen->DrawText(mFont, mColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// patch item
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemPatch::FListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param)
|
||||
: FListMenuItemSelectable(x, y, height, child, param)
|
||||
{
|
||||
mHotkey = hotkey;
|
||||
mTexture = patch;
|
||||
}
|
||||
|
||||
void FListMenuItemPatch::Drawer(bool selected)
|
||||
{
|
||||
screen->DrawTexture (TexMan(mTexture), mXpos, mYpos, DTA_Clean, true, TAG_DONE);
|
||||
}
|
1165
src/menu/loadsavemenu.cpp
Normal file
1165
src/menu/loadsavemenu.cpp
Normal file
File diff suppressed because it is too large
Load diff
949
src/menu/menu.cpp
Normal file
949
src/menu/menu.cpp
Normal file
|
@ -0,0 +1,949 @@
|
|||
/*
|
||||
** menu.cpp
|
||||
** Menu base class and global interface
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "d_gui.h"
|
||||
#include "d_player.h"
|
||||
#include "g_level.h"
|
||||
#include "c_console.h"
|
||||
#include "c_bind.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_tick.h"
|
||||
#include "g_game.h"
|
||||
#include "c_cvars.h"
|
||||
#include "d_event.h"
|
||||
#include "v_video.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "gi.h"
|
||||
#include "i_input.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "gstrings.h"
|
||||
#include "r_main.h"
|
||||
#include "menu/menu.h"
|
||||
#include "textures/textures.h"
|
||||
|
||||
//
|
||||
// Todo: Move these elsewhere
|
||||
//
|
||||
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 (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE)
|
||||
CVAR(Int, m_use_mouse, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DMenu *DMenu::CurrentMenu;
|
||||
int DMenu::MenuTime;
|
||||
|
||||
FListMenuDescriptor *MainMenu;
|
||||
FGameStartup GameStartupInfo;
|
||||
EMenuState menuactive;
|
||||
bool M_DemoNoPlay;
|
||||
FButtonStatus MenuButtons[NUM_MKEYS];
|
||||
int MenuButtonTickers[NUM_MKEYS];
|
||||
bool MenuButtonOrigin[NUM_MKEYS];
|
||||
int BackbuttonTime;
|
||||
fixed_t BackbuttonAlpha;
|
||||
|
||||
|
||||
#define KEY_REPEAT_DELAY (TICRATE*5/12)
|
||||
#define KEY_REPEAT_RATE (3)
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// DMenu base class
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (DMenu)
|
||||
DECLARE_POINTER(mParentMenu)
|
||||
END_POINTERS
|
||||
|
||||
DMenu::DMenu(DMenu *parent)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
mMouseCapture = false;
|
||||
mBackbuttonSelected = false;
|
||||
GC::WriteBarrier(this, parent);
|
||||
}
|
||||
|
||||
bool DMenu::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_LButtonDown)
|
||||
{
|
||||
MouseEventBack(MOUSE_Click, ev->data1, ev->data2);
|
||||
if (MouseEvent(MOUSE_Click, ev->data1, ev->data2))
|
||||
{
|
||||
SetCapture();
|
||||
}
|
||||
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_MouseMove)
|
||||
{
|
||||
BackbuttonTime = BACKBUTTON_TIME;
|
||||
if (mMouseCapture || m_use_mouse == 1)
|
||||
{
|
||||
MouseEventBack(MOUSE_Move, ev->data1, ev->data2);
|
||||
return MouseEvent(MOUSE_Move, ev->data1, ev->data2);
|
||||
}
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_LButtonUp)
|
||||
{
|
||||
if (mMouseCapture)
|
||||
{
|
||||
ReleaseCapture();
|
||||
MouseEventBack(MOUSE_Release, ev->data1, ev->data2);
|
||||
return MouseEvent(MOUSE_Release, ev->data1, ev->data2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Back:
|
||||
{
|
||||
Close();
|
||||
S_Sound (CHAN_VOICE | CHAN_UI,
|
||||
DMenu::CurrentMenu != NULL? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMenu::Close ()
|
||||
{
|
||||
assert(DMenu::CurrentMenu == this);
|
||||
DMenu::CurrentMenu = mParentMenu;
|
||||
Destroy();
|
||||
if (DMenu::CurrentMenu != NULL)
|
||||
{
|
||||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_ClearMenus ();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMenu::MouseEventBack(int type, int x, int y)
|
||||
{
|
||||
if (m_show_backbutton >= 0)
|
||||
{
|
||||
FTexture *tex = TexMan[gameinfo.mBackButton];
|
||||
if (tex != NULL)
|
||||
{
|
||||
if (m_show_backbutton&1) x -= screen->GetWidth() - tex->GetScaledWidth() * CleanXfac;
|
||||
if (m_show_backbutton&2) y -= screen->GetHeight() - tex->GetScaledHeight() * CleanYfac;
|
||||
mBackbuttonSelected = (x >= 0 && x < tex->GetScaledWidth() * CleanXfac && y < tex->GetScaledHeight() * CleanYfac);
|
||||
if (mBackbuttonSelected && type == MOUSE_Release)
|
||||
{
|
||||
if (m_use_mouse == 2) mBackbuttonSelected = false;
|
||||
MenuEvent(MKEY_Back, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMenu::SetCapture()
|
||||
{
|
||||
if (!mMouseCapture)
|
||||
{
|
||||
mMouseCapture = true;
|
||||
I_SetMouseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void DMenu::ReleaseCapture()
|
||||
{
|
||||
if (mMouseCapture)
|
||||
{
|
||||
mMouseCapture = false;
|
||||
I_ReleaseMouseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMenu::Ticker ()
|
||||
{
|
||||
}
|
||||
|
||||
void DMenu::Drawer ()
|
||||
{
|
||||
if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
{
|
||||
FTexture *tex = TexMan[gameinfo.mBackButton];
|
||||
int w = tex->GetScaledWidth() * CleanXfac;
|
||||
int h = tex->GetScaledHeight() * CleanYfac;
|
||||
int x = (!(m_show_backbutton&1))? 0:screen->GetWidth() - w;
|
||||
int y = (!(m_show_backbutton&2))? 0:screen->GetHeight() - h;
|
||||
if (mBackbuttonSelected && (mMouseCapture || m_use_mouse == 1))
|
||||
{
|
||||
screen->DrawTexture(tex, x, y, DTA_CleanNoMove, true, DTA_ColorOverlay, MAKEARGB(40, 255,255,255), TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture(tex, x, y, DTA_CleanNoMove, true, DTA_Alpha, BackbuttonAlpha, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenu::DimAllowed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DMenu::TranslateKeyboardEvents()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_StartControlPanel (bool makeSound)
|
||||
{
|
||||
// intro might call this repeatedly
|
||||
if (DMenu::CurrentMenu != NULL)
|
||||
return;
|
||||
|
||||
ResetButtonStates ();
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
MenuButtons[i].ReleaseKey(0);
|
||||
}
|
||||
|
||||
C_HideConsole (); // [RH] Make sure console goes bye bye.
|
||||
menuactive = MENU_On;
|
||||
// Pause sound effects before we play the menu switch sound.
|
||||
// That way, it won't be paused.
|
||||
P_CheckTickerPaused ();
|
||||
|
||||
if (makeSound)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
BackbuttonTime = 0;
|
||||
BackbuttonAlpha = 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_ActivateMenu(DMenu *menu)
|
||||
{
|
||||
if (menuactive == MENU_Off) menuactive = MENU_On;
|
||||
if (DMenu::CurrentMenu != NULL) DMenu::CurrentMenu->ReleaseCapture();
|
||||
DMenu::CurrentMenu = menu;
|
||||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_SetMenu(FName menu, int param)
|
||||
{
|
||||
// some menus need some special treatment
|
||||
switch (menu)
|
||||
{
|
||||
case NAME_Episodemenu:
|
||||
// sent from the player class menu
|
||||
GameStartupInfo.Skill = -1;
|
||||
GameStartupInfo.Episode = -1;
|
||||
GameStartupInfo.PlayerClass =
|
||||
param == -1? "Random" : PlayerClasses[param].Type->Meta.GetMetaString (APMETA_DisplayName);
|
||||
break;
|
||||
|
||||
case NAME_Skillmenu:
|
||||
// sent from the episode menu
|
||||
|
||||
if ((gameinfo.flags & GI_SHAREWARE) && param > 0)
|
||||
{
|
||||
// Only Doom and Heretic have multi-episode shareware versions.
|
||||
if (gameinfo.gametype == GAME_Doom)
|
||||
{
|
||||
M_StartMessage(GStrings("SWSTRING"), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_StartMessage(GStrings("MNU_ONLYREGISTERED"), 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GameStartupInfo.Episode = param;
|
||||
M_StartupSkillMenu(&GameStartupInfo); // needs player class name from class menu (later)
|
||||
break;
|
||||
|
||||
case NAME_StartgameConfirm:
|
||||
{
|
||||
// sent from the skill menu for a skill that needs to be confirmed
|
||||
GameStartupInfo.Skill = param;
|
||||
|
||||
const char *msg = AllSkills[param].MustConfirmText;
|
||||
if (*msg==0) msg = GStrings("NIGHTMARE");
|
||||
M_StartMessage (msg, 0, NAME_Startgame);
|
||||
return;
|
||||
}
|
||||
|
||||
case NAME_Startgame:
|
||||
// sent either from skill menu or confirmation screen. Skill gets only set if sent from skill menu
|
||||
// Now we can finally start the game. Ugh...
|
||||
if (GameStartupInfo.Skill == -1) GameStartupInfo.Skill = param;
|
||||
|
||||
G_DeferedInitNew (&GameStartupInfo);
|
||||
if (gamestate == GS_FULLCONSOLE)
|
||||
{
|
||||
gamestate = GS_HIDECONSOLE;
|
||||
gameaction = ga_newgame;
|
||||
}
|
||||
M_ClearMenus ();
|
||||
return;
|
||||
|
||||
case NAME_Savegamemenu:
|
||||
if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer))
|
||||
{
|
||||
// cannot save outside the game.
|
||||
M_StartMessage (GStrings("SAVEDEAD"), 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// End of special checks
|
||||
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(menu);
|
||||
if (desc != NULL)
|
||||
{
|
||||
if ((*desc)->mNetgameMessage.IsNotEmpty() && netgame)
|
||||
{
|
||||
M_StartMessage((*desc)->mNetgameMessage, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*desc)->mType == MDESC_ListMenu)
|
||||
{
|
||||
FListMenuDescriptor *ld = static_cast<FListMenuDescriptor*>(*desc);
|
||||
if (ld->mAutoselect >= 0 && ld->mAutoselect < (int)ld->mItems.Size())
|
||||
{
|
||||
// recursively activate the autoselected item without ever creating this menu.
|
||||
ld->mItems[ld->mAutoselect]->Activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
const PClass *cls = ld->mClass == NULL? RUNTIME_CLASS(DListMenu) : ld->mClass;
|
||||
|
||||
DListMenu *newmenu = (DListMenu *)cls->CreateNew();
|
||||
newmenu->Init(DMenu::CurrentMenu, ld);
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
}
|
||||
else if ((*desc)->mType == MDESC_OptionsMenu)
|
||||
{
|
||||
FOptionMenuDescriptor *ld = static_cast<FOptionMenuDescriptor*>(*desc);
|
||||
const PClass *cls = ld->mClass == NULL? RUNTIME_CLASS(DOptionMenu) : ld->mClass;
|
||||
|
||||
DOptionMenu *newmenu = (DOptionMenu *)cls->CreateNew();
|
||||
newmenu->Init(DMenu::CurrentMenu, ld);
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
const PClass *menuclass = PClass::FindClass(menu);
|
||||
if (menuclass != NULL)
|
||||
{
|
||||
if (menuclass->IsDescendantOf(RUNTIME_CLASS(DMenu)))
|
||||
{
|
||||
DMenu *newmenu = (DMenu*)menuclass->CreateNew();
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars());
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool M_Responder (event_t *ev)
|
||||
{
|
||||
int ch = 0;
|
||||
bool keyup = false;
|
||||
int mkey = NUM_MKEYS;
|
||||
bool fromcontroller = true;
|
||||
|
||||
if (chatmodeon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
|
||||
{
|
||||
// There are a few input sources we are interested in:
|
||||
//
|
||||
// EV_KeyDown / EV_KeyUp : joysticks/gamepads/controllers
|
||||
// EV_GUI_KeyDown / EV_GUI_KeyUp : the keyboard
|
||||
// EV_GUI_Char : printable characters, which we want in string input mode
|
||||
//
|
||||
// This code previously listened for EV_GUI_KeyRepeat to handle repeating
|
||||
// in the menus, but that doesn't work with gamepads, so now we combine
|
||||
// the multiple inputs into buttons and handle the repetition manually.
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
fromcontroller = false;
|
||||
if (ev->subtype == EV_GUI_KeyRepeat)
|
||||
{
|
||||
// We do our own key repeat handling but still want to eat the
|
||||
// OS's repeated keys.
|
||||
return true;
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_BackButtonDown || ev->subtype == EV_GUI_BackButtonUp)
|
||||
{
|
||||
mkey = MKEY_Back;
|
||||
keyup = ev->subtype == EV_GUI_BackButtonUp;
|
||||
}
|
||||
else if (ev->subtype != EV_GUI_KeyDown && ev->subtype != EV_GUI_KeyUp)
|
||||
{
|
||||
// do we want mouse input?
|
||||
if (ev->subtype >= EV_GUI_FirstMouseEvent && ev->subtype <= EV_GUI_LastMouseEvent)
|
||||
{
|
||||
// FIXME: Mouse events in SDL code are mostly useless so mouse is
|
||||
// disabled until that code is fixed
|
||||
#ifdef _WIN32
|
||||
if (!m_use_mouse)
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// pass everything else on to the current menu
|
||||
return DMenu::CurrentMenu->Responder(ev);
|
||||
}
|
||||
else if (DMenu::CurrentMenu->TranslateKeyboardEvents())
|
||||
{
|
||||
ch = ev->data1;
|
||||
keyup = ev->subtype == EV_GUI_KeyUp;
|
||||
switch (ch)
|
||||
{
|
||||
case GK_BACK: mkey = MKEY_Back; break;
|
||||
case GK_ESCAPE: mkey = MKEY_Back; break;
|
||||
case GK_RETURN: mkey = MKEY_Enter; break;
|
||||
case GK_UP: mkey = MKEY_Up; break;
|
||||
case GK_DOWN: mkey = MKEY_Down; break;
|
||||
case GK_LEFT: mkey = MKEY_Left; break;
|
||||
case GK_RIGHT: mkey = MKEY_Right; break;
|
||||
case GK_BACKSPACE: mkey = MKEY_Clear; break;
|
||||
case GK_PGUP: mkey = MKEY_PageUp; break;
|
||||
case GK_PGDN: mkey = MKEY_PageDown; break;
|
||||
default:
|
||||
if (!keyup)
|
||||
{
|
||||
return DMenu::CurrentMenu->Responder(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ev->type == EV_KeyDown || ev->type == EV_KeyUp)
|
||||
{
|
||||
keyup = ev->type == EV_KeyUp;
|
||||
|
||||
ch = ev->data1;
|
||||
switch (ch)
|
||||
{
|
||||
case KEY_JOY1:
|
||||
case KEY_PAD_A:
|
||||
mkey = MKEY_Enter;
|
||||
break;
|
||||
|
||||
case KEY_JOY2:
|
||||
case KEY_PAD_B:
|
||||
mkey = MKEY_Back;
|
||||
break;
|
||||
|
||||
case KEY_JOY3:
|
||||
case KEY_PAD_X:
|
||||
mkey = MKEY_Clear;
|
||||
break;
|
||||
|
||||
case KEY_JOY5:
|
||||
case KEY_PAD_LSHOULDER:
|
||||
mkey = MKEY_PageUp;
|
||||
break;
|
||||
|
||||
case KEY_JOY6:
|
||||
case KEY_PAD_RSHOULDER:
|
||||
mkey = MKEY_PageDown;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_UP:
|
||||
case KEY_PAD_LTHUMB_UP:
|
||||
case KEY_JOYAXIS1MINUS:
|
||||
case KEY_JOYPOV1_UP:
|
||||
mkey = MKEY_Up;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_DOWN:
|
||||
case KEY_PAD_LTHUMB_DOWN:
|
||||
case KEY_JOYAXIS1PLUS:
|
||||
case KEY_JOYPOV1_DOWN:
|
||||
mkey = MKEY_Down;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_LEFT:
|
||||
case KEY_PAD_LTHUMB_LEFT:
|
||||
case KEY_JOYAXIS2MINUS:
|
||||
case KEY_JOYPOV1_LEFT:
|
||||
mkey = MKEY_Left;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_RIGHT:
|
||||
case KEY_PAD_LTHUMB_RIGHT:
|
||||
case KEY_JOYAXIS2PLUS:
|
||||
case KEY_JOYPOV1_RIGHT:
|
||||
mkey = MKEY_Right;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mkey != NUM_MKEYS)
|
||||
{
|
||||
if (keyup)
|
||||
{
|
||||
MenuButtons[mkey].ReleaseKey(ch);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
MenuButtons[mkey].PressKey(ch);
|
||||
MenuButtonOrigin[mkey] = fromcontroller;
|
||||
if (mkey <= MKEY_PageDown)
|
||||
{
|
||||
MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
|
||||
}
|
||||
DMenu::CurrentMenu->MenuEvent(mkey, fromcontroller);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return DMenu::CurrentMenu->Responder(ev) || !keyup;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ev->type == EV_KeyDown)
|
||||
{
|
||||
// Pop-up menu?
|
||||
if (ev->data1 == KEY_ESCAPE)
|
||||
{
|
||||
M_StartControlPanel(true);
|
||||
M_SetMenu(NAME_Mainmenu, -1);
|
||||
return true;
|
||||
}
|
||||
// If devparm is set, pressing F1 always takes a screenshot no matter
|
||||
// what it's bound to. (for those who don't bother to read the docs)
|
||||
if (devparm && ev->data1 == KEY_F1)
|
||||
{
|
||||
G_ScreenShot(NULL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_LButtonDown &&
|
||||
ConsoleState != c_down && m_use_mouse)
|
||||
{
|
||||
M_StartControlPanel(true);
|
||||
M_SetMenu(NAME_Mainmenu, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_Ticker (void)
|
||||
{
|
||||
DMenu::MenuTime++;
|
||||
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
|
||||
DMenu::CurrentMenu->Ticker();
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
if (MenuButtons[i].bDown)
|
||||
{
|
||||
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
||||
{
|
||||
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
||||
DMenu::CurrentMenu->MenuEvent(i, MenuButtonOrigin[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BackbuttonTime > 0)
|
||||
{
|
||||
if (BackbuttonAlpha < FRACUNIT) BackbuttonAlpha += FRACUNIT/10;
|
||||
BackbuttonTime--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BackbuttonAlpha > 0) BackbuttonAlpha -= FRACUNIT/10;
|
||||
if (BackbuttonAlpha < 0) BackbuttonAlpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_Drawer (void)
|
||||
{
|
||||
player_t *player = &players[consoleplayer];
|
||||
AActor *camera = player->camera;
|
||||
PalEntry fade = 0;
|
||||
|
||||
if (!screen->Accel2D && camera != NULL && (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL))
|
||||
{
|
||||
if (camera->player != NULL)
|
||||
{
|
||||
player = camera->player;
|
||||
}
|
||||
fade = PalEntry (BYTE(player->BlendA*255), BYTE(player->BlendR*255), BYTE(player->BlendG*255), BYTE(player->BlendB*255));
|
||||
}
|
||||
|
||||
|
||||
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
|
||||
{
|
||||
if (DMenu::CurrentMenu->DimAllowed()) screen->Dim(fade);
|
||||
DMenu::CurrentMenu->Drawer();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_ClearMenus ()
|
||||
{
|
||||
M_DemoNoPlay = false;
|
||||
if (DMenu::CurrentMenu != NULL)
|
||||
{
|
||||
DMenu::CurrentMenu->Destroy();
|
||||
DMenu::CurrentMenu = NULL;
|
||||
}
|
||||
BorderNeedRefresh = screen->GetPageCount ();
|
||||
menuactive = MENU_Off;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_Init (void)
|
||||
{
|
||||
M_ParseMenuDefs();
|
||||
M_CreateMenus();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// [RH] Most menus can now be accessed directly
|
||||
// through console commands.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (menu_main)
|
||||
{
|
||||
M_StartControlPanel(true);
|
||||
M_SetMenu(NAME_Mainmenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_load)
|
||||
{ // F3
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_Loadgamemenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_save)
|
||||
{ // F2
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_Savegamemenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_help)
|
||||
{ // F1
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_Readthismenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_game)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_Playerclassmenu, -1); // The playerclass menu is the first in the 'start game' chain
|
||||
}
|
||||
|
||||
CCMD (menu_options)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_Optionsmenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_player)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_Playermenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_messages)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_MessageOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_automap)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_AutomapOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_scoreboard)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_ScoreboardOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_mapcolors)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_MapColorMenu, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_keys)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_CustomizeControls, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_gameplay)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_GameplayOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_compatibility)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_CompatibilityOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_mouse)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_MouseOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_joystick)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_JoystickOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_sound)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_SoundOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_advsound)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_AdvSoundOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_modreplayer)
|
||||
{
|
||||
M_StartControlPanel(true);
|
||||
M_SetMenu(NAME_ModReplayerOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_display)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_VideoOptions, -1);
|
||||
}
|
||||
|
||||
CCMD (menu_video)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(NAME_VideoModeMenu, -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
CCMD (openmenu)
|
||||
{
|
||||
if (argv.argc() < 2)
|
||||
{
|
||||
Printf("Usage: openmenu \"menu_name\"");
|
||||
return;
|
||||
}
|
||||
M_StartControlPanel (true);
|
||||
M_SetMenu(argv[1], -1);
|
||||
}
|
||||
|
||||
//
|
||||
// Toggle messages on/off
|
||||
//
|
||||
CCMD (togglemessages)
|
||||
{
|
||||
if (show_messages)
|
||||
{
|
||||
Printf (128, "%s\n", GStrings("MSGOFF"));
|
||||
show_messages = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf (128, "%s\n", GStrings("MSGON"));
|
||||
show_messages = true;
|
||||
}
|
||||
}
|
||||
|
||||
EXTERN_CVAR (Int, screenblocks)
|
||||
|
||||
CCMD (sizedown)
|
||||
{
|
||||
screenblocks = screenblocks - 1;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
|
||||
CCMD (sizeup)
|
||||
{
|
||||
screenblocks = screenblocks + 1;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
|
||||
CCMD(menuconsole)
|
||||
{
|
||||
M_ClearMenus();
|
||||
C_ToggleConsole();
|
||||
}
|
||||
|
||||
CCMD(reset2defaults)
|
||||
{
|
||||
C_SetDefaultBindings ();
|
||||
C_SetCVarsToDefaults ();
|
||||
R_SetViewSize (screenblocks);
|
||||
}
|
||||
|
||||
CCMD(reset2saved)
|
||||
{
|
||||
GameConfig->DoGlobalSetup ();
|
||||
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
|
||||
R_SetViewSize (screenblocks);
|
||||
}
|
652
src/menu/menu.h
Normal file
652
src/menu/menu.h
Normal file
|
@ -0,0 +1,652 @@
|
|||
#ifndef __M_MENU_MENU_H__
|
||||
#define __M_MENU_MENU_H__
|
||||
|
||||
|
||||
|
||||
|
||||
#include "dobject.h"
|
||||
#include "lists.h"
|
||||
#include "d_player.h"
|
||||
#include "r_translate.h"
|
||||
#include "c_cvars.h"
|
||||
#include "v_font.h"
|
||||
#include "version.h"
|
||||
#include "textures/textures.h"
|
||||
|
||||
EXTERN_CVAR(Float, snd_menuvolume)
|
||||
EXTERN_CVAR(Int, m_use_mouse);
|
||||
|
||||
|
||||
struct event_t;
|
||||
class FTexture;
|
||||
class FFont;
|
||||
enum EColorRange;
|
||||
class FPlayerClass;
|
||||
class FKeyBindings;
|
||||
|
||||
enum EMenuKey
|
||||
{
|
||||
MKEY_Up,
|
||||
MKEY_Down,
|
||||
MKEY_Left,
|
||||
MKEY_Right,
|
||||
MKEY_PageUp,
|
||||
MKEY_PageDown,
|
||||
//----------------- Keys past here do not repeat.
|
||||
MKEY_Enter,
|
||||
MKEY_Back, // Back to previous menu
|
||||
MKEY_Clear, // Clear keybinding/flip player sprite preview
|
||||
NUM_MKEYS,
|
||||
|
||||
// These are not buttons but events sent from other menus
|
||||
|
||||
MKEY_Input, // Sent when input is confirmed
|
||||
MKEY_Abort, // Input aborted
|
||||
MKEY_MBYes,
|
||||
MKEY_MBNo,
|
||||
};
|
||||
|
||||
|
||||
struct FGameStartup
|
||||
{
|
||||
const char *PlayerClass;
|
||||
int Episode;
|
||||
int Skill;
|
||||
};
|
||||
|
||||
extern FGameStartup GameStartupInfo;
|
||||
|
||||
struct FSaveGameNode : public Node
|
||||
{
|
||||
char Title[SAVESTRINGSIZE];
|
||||
FString Filename;
|
||||
bool bOldVersion;
|
||||
bool bMissingWads;
|
||||
bool bNoDelete;
|
||||
|
||||
FSaveGameNode() { bNoDelete = false; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// menu descriptor. This is created from the menu definition lump
|
||||
// Items must be inserted in the order they are cycled through with the cursor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
enum EMenuDescriptorType
|
||||
{
|
||||
MDESC_ListMenu,
|
||||
MDESC_OptionsMenu,
|
||||
};
|
||||
|
||||
struct FMenuDescriptor
|
||||
{
|
||||
FName mMenuName;
|
||||
FString mNetgameMessage;
|
||||
int mType;
|
||||
|
||||
virtual ~FMenuDescriptor() {}
|
||||
};
|
||||
|
||||
class FListMenuItem;
|
||||
class FOptionMenuItem;
|
||||
|
||||
struct FListMenuDescriptor : public FMenuDescriptor
|
||||
{
|
||||
TDeletingArray<FListMenuItem *> mItems;
|
||||
int mSelectedItem;
|
||||
int mSelectOfsX;
|
||||
int mSelectOfsY;
|
||||
FTextureID mSelector;
|
||||
int mDisplayTop;
|
||||
int mXpos, mYpos;
|
||||
int mWLeft, mWRight;
|
||||
int mLinespacing; // needs to be stored for dynamically created menus
|
||||
int mAutoselect; // this can only be set by internal menu creation functions
|
||||
FFont *mFont;
|
||||
EColorRange mFontColor;
|
||||
EColorRange mFontColor2;
|
||||
const PClass *mClass;
|
||||
FMenuDescriptor *mRedirect; // used to redirect overlong skill and episode menus to option menu based alternatives
|
||||
};
|
||||
|
||||
struct FOptionMenuSettings
|
||||
{
|
||||
EColorRange mTitleColor;
|
||||
EColorRange mFontColor;
|
||||
EColorRange mFontColorValue;
|
||||
EColorRange mFontColorMore;
|
||||
EColorRange mFontColorHeader;
|
||||
EColorRange mFontColorHighlight;
|
||||
EColorRange mFontColorSelection;
|
||||
int mLinespacing;
|
||||
int mLabelOffset;
|
||||
};
|
||||
|
||||
struct FOptionMenuDescriptor : public FMenuDescriptor
|
||||
{
|
||||
TDeletingArray<FOptionMenuItem *> mItems;
|
||||
FString mTitle;
|
||||
int mSelectedItem;
|
||||
int mDrawTop;
|
||||
int mScrollTop;
|
||||
int mScrollPos;
|
||||
int mIndent;
|
||||
int mPosition;
|
||||
bool mDontDim;
|
||||
const PClass *mClass;
|
||||
|
||||
void CalcIndent();
|
||||
FOptionMenuItem *GetItem(FName name);
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef TMap<FName, FMenuDescriptor *> MenuDescriptorList;
|
||||
|
||||
extern FOptionMenuSettings OptionSettings;
|
||||
extern MenuDescriptorList MenuDescriptors;
|
||||
|
||||
#define CURSORSPACE (14 * CleanXfac_1)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
struct FMenuRect
|
||||
{
|
||||
int x, y;
|
||||
int width, height;
|
||||
|
||||
void set(int _x, int _y, int _w, int _h)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
width = _w;
|
||||
height = _h;
|
||||
}
|
||||
|
||||
bool inside(int _x, int _y)
|
||||
{
|
||||
return _x >= x && _x < x+width && _y >= y && _y < y+height;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class DMenu : public DObject
|
||||
{
|
||||
DECLARE_CLASS (DMenu, DObject)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
protected:
|
||||
bool mMouseCapture;
|
||||
bool mBackbuttonSelected;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MOUSE_Click,
|
||||
MOUSE_Move,
|
||||
MOUSE_Release
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BACKBUTTON_TIME = 4*TICRATE
|
||||
};
|
||||
|
||||
static DMenu *CurrentMenu;
|
||||
static int MenuTime;
|
||||
|
||||
TObjPtr<DMenu> mParentMenu;
|
||||
|
||||
DMenu(DMenu *parent = NULL);
|
||||
virtual bool Responder (event_t *ev);
|
||||
virtual bool MenuEvent (int mkey, bool fromcontroller);
|
||||
virtual void Ticker ();
|
||||
virtual void Drawer ();
|
||||
virtual bool DimAllowed ();
|
||||
virtual bool TranslateKeyboardEvents();
|
||||
virtual void Close();
|
||||
virtual bool MouseEvent(int type, int x, int y);
|
||||
bool MouseEventBack(int type, int x, int y);
|
||||
void SetCapture();
|
||||
void ReleaseCapture();
|
||||
bool HasCapture()
|
||||
{
|
||||
return mMouseCapture;
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FListMenuItem
|
||||
{
|
||||
protected:
|
||||
int mXpos, mYpos;
|
||||
FName mAction;
|
||||
|
||||
public:
|
||||
bool mEnabled;
|
||||
|
||||
FListMenuItem(int xpos = 0, int ypos = 0, FName action = NAME_None)
|
||||
{
|
||||
mXpos = xpos;
|
||||
mYpos = ypos;
|
||||
mAction = action;
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
virtual ~FListMenuItem();
|
||||
|
||||
virtual bool CheckCoordinate(int x, int y);
|
||||
virtual void Ticker();
|
||||
virtual void Drawer(bool selected);
|
||||
virtual bool Selectable();
|
||||
virtual bool Activate();
|
||||
virtual FName GetAction(int *pparam);
|
||||
virtual bool SetString(int i, const char *s);
|
||||
virtual bool GetString(int i, char *s, int len);
|
||||
virtual bool SetValue(int i, int value);
|
||||
virtual bool GetValue(int i, int *pvalue);
|
||||
virtual void Enable(bool on);
|
||||
virtual bool MenuEvent (int mkey, bool fromcontroller);
|
||||
virtual bool MouseEvent(int type, int x, int y);
|
||||
virtual bool CheckHotkey(int c);
|
||||
void DrawSelector(int xofs, int yofs, FTextureID tex);
|
||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||
int GetY() { return mYpos; }
|
||||
};
|
||||
|
||||
class FListMenuItemStaticPatch : public FListMenuItem
|
||||
{
|
||||
protected:
|
||||
FTextureID mTexture;
|
||||
bool mCentered;
|
||||
|
||||
public:
|
||||
FListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered);
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
class FListMenuItemStaticText : public FListMenuItem
|
||||
{
|
||||
protected:
|
||||
const char *mText;
|
||||
FFont *mFont;
|
||||
EColorRange mColor;
|
||||
bool mCentered;
|
||||
|
||||
public:
|
||||
FListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered);
|
||||
~FListMenuItemStaticText();
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// the player sprite window
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FListMenuItemPlayerDisplay : public FListMenuItem
|
||||
{
|
||||
FListMenuDescriptor *mOwner;
|
||||
FTexture *mBackdrop;
|
||||
FRemapTable mRemap;
|
||||
FPlayerClass *mPlayerClass;
|
||||
FState *mPlayerState;
|
||||
int mPlayerTics;
|
||||
bool mNoportrait;
|
||||
BYTE mRotation;
|
||||
BYTE mMode; // 0: automatic (used by class selection), 1: manual (used by player setup)
|
||||
BYTE mTranslate;
|
||||
int mSkin;
|
||||
int mRandomClass;
|
||||
int mRandomTimer;
|
||||
int mClassNum;
|
||||
|
||||
void SetPlayerClass(int classnum, bool force = false);
|
||||
bool UpdatePlayerClass();
|
||||
void UpdateRandomClass();
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
PDF_ROTATION = 0x10001,
|
||||
PDF_SKIN = 0x10002,
|
||||
PDF_CLASS = 0x10003,
|
||||
PDF_MODE = 0x10004,
|
||||
PDF_TRANSLATE = 0x10005,
|
||||
};
|
||||
|
||||
FListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action);
|
||||
~FListMenuItemPlayerDisplay();
|
||||
virtual void Ticker();
|
||||
virtual void Drawer(bool selected);
|
||||
bool SetValue(int i, int value);
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// selectable items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FListMenuItemSelectable : public FListMenuItem
|
||||
{
|
||||
protected:
|
||||
int mHotkey;
|
||||
int mHeight;
|
||||
int mParam;
|
||||
|
||||
public:
|
||||
FListMenuItemSelectable(int x, int y, int height, FName childmenu, int mParam = -1);
|
||||
bool CheckCoordinate(int x, int y);
|
||||
bool Selectable();
|
||||
bool CheckHotkey(int c);
|
||||
bool Activate();
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
FName GetAction(int *pparam);
|
||||
};
|
||||
|
||||
class FListMenuItemText : public FListMenuItemSelectable
|
||||
{
|
||||
const char *mText;
|
||||
FFont *mFont;
|
||||
EColorRange mColor;
|
||||
public:
|
||||
FListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, FName child, int param = 0);
|
||||
~FListMenuItemText();
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
class FListMenuItemPatch : public FListMenuItemSelectable
|
||||
{
|
||||
FTextureID mTexture;
|
||||
public:
|
||||
FListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0);
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FPlayerNameBox : public FListMenuItemSelectable
|
||||
{
|
||||
const char *mText;
|
||||
FFont *mFont;
|
||||
EColorRange mFontColor;
|
||||
int mFrameSize;
|
||||
char mPlayerName[MAXPLAYERNAME+1];
|
||||
char mEditName[MAXPLAYERNAME+2];
|
||||
bool mEntering;
|
||||
|
||||
void DrawBorder (int x, int y, int len);
|
||||
|
||||
public:
|
||||
|
||||
FPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action);
|
||||
~FPlayerNameBox();
|
||||
bool SetString(int i, const char *s);
|
||||
bool GetString(int i, char *s, int len);
|
||||
void Drawer(bool selected);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FValueTextItem : public FListMenuItemSelectable
|
||||
{
|
||||
TArray<FString> mSelections;
|
||||
const char *mText;
|
||||
int mSelection;
|
||||
FFont *mFont;
|
||||
EColorRange mFontColor;
|
||||
EColorRange mFontColor2;
|
||||
|
||||
public:
|
||||
|
||||
FValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values);
|
||||
~FValueTextItem();
|
||||
bool SetString(int i, const char *s);
|
||||
bool SetValue(int i, int value);
|
||||
bool GetValue(int i, int *pvalue);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FSliderItem : public FListMenuItemSelectable
|
||||
{
|
||||
const char *mText;
|
||||
FFont *mFont;
|
||||
EColorRange mFontColor;
|
||||
int mMinrange, mMaxrange;
|
||||
int mStep;
|
||||
int mSelection;
|
||||
|
||||
void DrawSlider (int x, int y);
|
||||
|
||||
public:
|
||||
|
||||
FSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step);
|
||||
~FSliderItem();
|
||||
bool SetValue(int i, int value);
|
||||
bool GetValue(int i, int *pvalue);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
void Drawer(bool selected);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// list menu class runs a menu described by a FListMenuDescriptor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DListMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DListMenu, DMenu)
|
||||
|
||||
protected:
|
||||
FListMenuDescriptor *mDesc;
|
||||
FListMenuItem *mFocusControl;
|
||||
|
||||
public:
|
||||
DListMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
|
||||
virtual void Init(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
|
||||
FListMenuItem *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(FListMenuItem *fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
}
|
||||
bool CheckFocus(FListMenuItem *fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItem : public FListMenuItem
|
||||
{
|
||||
protected:
|
||||
char *mLabel;
|
||||
bool mCentered;
|
||||
|
||||
void drawLabel(int indent, int y, EColorRange color, bool grayed = false);
|
||||
public:
|
||||
|
||||
FOptionMenuItem(const char *text, FName action = NAME_None, bool center = false)
|
||||
: FListMenuItem(0, 0, action)
|
||||
{
|
||||
mLabel = copystring(text);
|
||||
mCentered = center;
|
||||
}
|
||||
|
||||
~FOptionMenuItem();
|
||||
virtual bool CheckCoordinate(FOptionMenuDescriptor *desc, int x, int y);
|
||||
virtual int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected);
|
||||
virtual bool Selectable();
|
||||
virtual int GetIndent();
|
||||
virtual bool MouseEvent(int type, int x, int y);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
struct FOptionValues
|
||||
{
|
||||
struct Pair
|
||||
{
|
||||
double Value;
|
||||
FString TextValue;
|
||||
FString Text;
|
||||
};
|
||||
|
||||
TArray<Pair> mValues;
|
||||
};
|
||||
|
||||
typedef TMap< FName, FOptionValues* > FOptionMap;
|
||||
|
||||
extern FOptionMap OptionValues;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Option menu class runs a menu described by a FOptionMenuDescriptor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DOptionMenu, DMenu)
|
||||
|
||||
bool CanScrollUp;
|
||||
bool CanScrollDown;
|
||||
int VisBottom;
|
||||
FOptionMenuItem *mFocusControl;
|
||||
|
||||
protected:
|
||||
FOptionMenuDescriptor *mDesc;
|
||||
|
||||
public:
|
||||
FOptionMenuItem *GetItem(FName name);
|
||||
DOptionMenu(DMenu *parent = NULL, FOptionMenuDescriptor *desc = NULL);
|
||||
virtual void Init(DMenu *parent = NULL, FOptionMenuDescriptor *desc = NULL);
|
||||
bool Responder (event_t *ev);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void Ticker ();
|
||||
void Drawer ();
|
||||
const FOptionMenuDescriptor *GetDescriptor() const { return mDesc; }
|
||||
void SetFocus(FOptionMenuItem *fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
}
|
||||
bool CheckFocus(FOptionMenuItem *fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Input some text
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DTextEnterMenu : public DMenu
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DTextEnterMenu, DMenu)
|
||||
|
||||
char *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;
|
||||
|
||||
public:
|
||||
|
||||
DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int sizemode, bool showgrid);
|
||||
|
||||
void Drawer ();
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool Responder(event_t *ev);
|
||||
bool TranslateKeyboardEvents();
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct event_t;
|
||||
bool M_Responder (event_t *ev);
|
||||
void M_Ticker (void);
|
||||
void M_Drawer (void);
|
||||
void M_Init (void);
|
||||
void M_CreateMenus();
|
||||
void M_ActivateMenu(DMenu *menu);
|
||||
void M_ClearMenus ();
|
||||
void M_ParseMenuDefs();
|
||||
void M_StartupSkillMenu(FGameStartup *gs);
|
||||
void M_StartControlPanel (bool makeSound);
|
||||
void M_SetMenu(FName menu, int param = -1);
|
||||
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
|
||||
void M_StartMessage(const char *message, int messagemode, FName action = NAME_None);
|
||||
DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar);
|
||||
void M_RefreshModesList ();
|
||||
void M_InitVideoModesMenu ();
|
||||
|
||||
|
||||
#endif
|
1389
src/menu/menudef.cpp
Normal file
1389
src/menu/menudef.cpp
Normal file
File diff suppressed because it is too large
Load diff
366
src/menu/menuinput.cpp
Normal file
366
src/menu/menuinput.cpp
Normal file
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
** 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"
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(DTextEnterMenu)
|
||||
|
||||
#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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DTextEnterMenu::DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int sizemode, bool showgrid)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mEnterString = textbuffer;
|
||||
mEnterSize = maxlen;
|
||||
mEnterPos = (unsigned)strlen(textbuffer);
|
||||
mSizeMode = sizemode;
|
||||
mInputGridOkay = showgrid || m_showinputgrid;
|
||||
if (mEnterPos > 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;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::TranslateKeyboardEvents()
|
||||
{
|
||||
return mInputGridOkay;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
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 (mEnterPos < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString[mEnterPos] = (char)ev->data1;
|
||||
mEnterString[++mEnterPos] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
char ch = (char)ev->data1;
|
||||
if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b')
|
||||
{
|
||||
if (mEnterPos > 0)
|
||||
{
|
||||
mEnterPos--;
|
||||
mEnterString[mEnterPos] = 0;
|
||||
}
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
if (ch == GK_ESCAPE)
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->MenuEvent(MKEY_Abort, false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == '\r')
|
||||
{
|
||||
if (mEnterString[0])
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->MenuEvent(MKEY_Input, false);
|
||||
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 (MenuEvent(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->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 (mEnterPos > 0)
|
||||
{
|
||||
mEnterString[--mEnterPos] = 0;
|
||||
}
|
||||
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[0] != '\0')
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->MenuEvent(MKEY_Input, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ch == '\b') // bs
|
||||
{
|
||||
if (mEnterPos > 0)
|
||||
{
|
||||
mEnterString[--mEnterPos] = 0;
|
||||
}
|
||||
}
|
||||
else if (mEnterPos < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString[mEnterPos] = ch;
|
||||
mEnterString[++mEnterPos] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DTextEnterMenu::Drawer ()
|
||||
{
|
||||
mParentMenu->Drawer();
|
||||
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;
|
||||
FRemapTable *remap;
|
||||
|
||||
// The highlighted character is yellow; the rest are dark gray.
|
||||
color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY;
|
||||
remap = SmallFont->GetColorTranslation(color);
|
||||
|
||||
if (pic != NULL)
|
||||
{
|
||||
// Draw a normal character.
|
||||
screen->DrawTexture(pic, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding,
|
||||
DTA_Translation, remap,
|
||||
DTA_CleanNoMove, true,
|
||||
TAG_DONE);
|
||||
}
|
||||
else if (ch == ' ')
|
||||
{
|
||||
// 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();
|
||||
}
|
733
src/menu/messagebox.cpp
Normal file
733
src/menu/messagebox.cpp
Normal file
|
@ -0,0 +1,733 @@
|
|||
/*
|
||||
** messagebox.cpp
|
||||
** Confirmation, notification screns
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 "d_event.h"
|
||||
#include "d_gui.h"
|
||||
#include "v_video.h"
|
||||
#include "v_text.h"
|
||||
#include "d_main.h"
|
||||
#include "gstrings.h"
|
||||
#include "gi.h"
|
||||
#include "i_video.h"
|
||||
#include "st_start.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "g_game.h"
|
||||
|
||||
|
||||
extern FSaveGameNode *quickSaveSlot;
|
||||
|
||||
class DMessageBoxMenu : public DMenu
|
||||
{
|
||||
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 Destroy();
|
||||
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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::Init(DMenu *parent, const char *message, int messagemode, bool playsound)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::Destroy()
|
||||
{
|
||||
if (mMessage != NULL) V_FreeBrokenLines(mMessage);
|
||||
mMessage = NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
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->MenuEvent(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();
|
||||
//BorderNeedRefresh = screen->GetPageCount ();
|
||||
//SB_state = screen->GetPageCount ();
|
||||
|
||||
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) * 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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (menu_quit)
|
||||
{ // F10
|
||||
M_StartControlPanel (true);
|
||||
DMenu *newmenu = new DQuitMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DEndGameMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DEndGameMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DEndGameMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DEndGameMenu)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DEndGameMenu::DEndGameMenu(bool playsound)
|
||||
{
|
||||
int messageindex = gametic % gameinfo.quitmessages.Size();
|
||||
FString EndString = gameinfo.quitmessages[messageindex];
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
if(gameinfo.gametype == GAME_Chex)
|
||||
EndString = GStrings("CNETEND");
|
||||
else
|
||||
EndString = GStrings("NETEND");
|
||||
return;
|
||||
}
|
||||
|
||||
if(gameinfo.gametype == GAME_Chex)
|
||||
EndString = GStrings("CENDGAME");
|
||||
else
|
||||
EndString = GStrings("ENDGAME");
|
||||
|
||||
|
||||
Init(NULL, EndString, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DEndGameMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
M_ClearMenus ();
|
||||
D_StartTitle ();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (menu_endgame)
|
||||
{ // F7
|
||||
if (!usergame)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/invalid", snd_menuvolume, ATTN_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
//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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuickSaveMenu::DQuickSaveMenu(bool playsound)
|
||||
{
|
||||
FString tempstring;
|
||||
|
||||
if(gameinfo.gametype == GAME_Chex)
|
||||
tempstring.Format(GStrings("CQSPROMPT"), quickSaveSlot->Title);
|
||||
else
|
||||
tempstring.Format(GStrings("QSPROMPT"), quickSaveSlot->Title);
|
||||
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuickSaveMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
G_SaveGame (quickSaveSlot->Filename.GetChars(), quickSaveSlot->Title);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (quicksave)
|
||||
{ // F6
|
||||
if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer))
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/invalid", snd_menuvolume, ATTN_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
return;
|
||||
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
if (quickSaveSlot == NULL)
|
||||
{
|
||||
M_StartControlPanel(false);
|
||||
M_SetMenu(NAME_Savegamemenu);
|
||||
return;
|
||||
}
|
||||
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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuickLoadMenu::DQuickLoadMenu(bool playsound)
|
||||
{
|
||||
FString tempstring;
|
||||
|
||||
if(gameinfo.gametype == GAME_Chex)
|
||||
tempstring.Format(GStrings("CQLPROMPT"), quickSaveSlot->Title);
|
||||
else
|
||||
tempstring.Format(GStrings("QLPROMPT"), quickSaveSlot->Title);
|
||||
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuickLoadMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
G_LoadGame (quickSaveSlot->Filename.GetChars());
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (quickload)
|
||||
{ // F9
|
||||
M_StartControlPanel (true);
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
if(gameinfo.gametype == GAME_Chex)
|
||||
M_StartMessage (GStrings("CQLOADNET"), NULL);
|
||||
else
|
||||
M_StartMessage (GStrings("QLOADNET"), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quickSaveSlot == NULL)
|
||||
{
|
||||
M_StartControlPanel(false);
|
||||
// signal that whatever gets loaded should be the new quicksave
|
||||
quickSaveSlot = (FSaveGameNode *)1;
|
||||
M_SetMenu(NAME_Loadgamemenu);
|
||||
return;
|
||||
}
|
||||
DMenu *newmenu = new DQuickLoadMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_StartMessage(const char *message, int messagemode, FName action)
|
||||
{
|
||||
if (DMenu::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;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
591
src/menu/optionmenu.cpp
Normal file
591
src/menu/optionmenu.cpp
Normal file
|
@ -0,0 +1,591 @@
|
|||
/*
|
||||
** optionmenu.cpp
|
||||
** Handler class for the option menus and associated 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 "v_palette.h"
|
||||
#include "d_gui.h"
|
||||
#include "d_event.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "c_console.h"
|
||||
#include "c_cvars.h"
|
||||
#include "c_bind.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Draws a string in the console font, scaled to the 8x8 cells
|
||||
// used by the default console font.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_DrawConText (int color, int x, int y, const char *str)
|
||||
{
|
||||
int len = (int)strlen(str);
|
||||
|
||||
screen->DrawText (ConFont, color, x, y, str,
|
||||
DTA_CellX, 8 * CleanXfac_1,
|
||||
DTA_CellY, 8 * CleanYfac_1,
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Draw a slider. Set fracdigits negative to not display the current value numerically.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigits)
|
||||
{
|
||||
double range;
|
||||
|
||||
range = max - min;
|
||||
double ccur = clamp(cur, min, max) - min;
|
||||
|
||||
if (CleanXfac > CleanXfac_1)
|
||||
{
|
||||
M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12");
|
||||
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), y, "\x13");
|
||||
|
||||
if (fracdigits >= 0)
|
||||
{
|
||||
char textbuf[16];
|
||||
mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur);
|
||||
screen->DrawText(SmallFont, CR_DARKGRAY, x + (12*8 + 4) * CleanXfac_1, y, textbuf, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// On 320x200 we need a shorter slider
|
||||
M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x12");
|
||||
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), y, "\x13");
|
||||
|
||||
if (fracdigits >= 0)
|
||||
{
|
||||
char textbuf[16];
|
||||
mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur);
|
||||
screen->DrawText(SmallFont, CR_DARKGRAY, x + (7*8 + 4) * CleanXfac_1, y, textbuf, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(DOptionMenu)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DOptionMenu::DOptionMenu(DMenu *parent, FOptionMenuDescriptor *desc)
|
||||
: DMenu(parent)
|
||||
{
|
||||
CanScrollUp = false;
|
||||
CanScrollDown = false;
|
||||
VisBottom = 0;
|
||||
mFocusControl = NULL;
|
||||
Init(parent, desc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Init(DMenu *parent, FOptionMenuDescriptor *desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
GC::WriteBarrier(this, parent);
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc->mSelectedItem < 0)
|
||||
{
|
||||
// Go down to the first selectable item
|
||||
int i = -1;
|
||||
mDesc->mSelectedItem = -1;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
}
|
||||
while (!mDesc->mItems[i]->Selectable() && i < (int)mDesc->mItems.Size());
|
||||
if (i>=0) mDesc->mSelectedItem = i;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FOptionMenuItem *DOptionMenu::GetItem(FName name)
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mDesc->mItems[i]->GetAction(NULL);
|
||||
if (nm == name) return mDesc->mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_WheelUp)
|
||||
{
|
||||
if (mDesc->mScrollPos > 0)
|
||||
{
|
||||
mDesc->mScrollPos--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_WheelDown)
|
||||
{
|
||||
if (CanScrollDown)
|
||||
{
|
||||
mDesc->mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int startedAt = mDesc->mSelectedItem;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
do
|
||||
{
|
||||
--mDesc->mSelectedItem;
|
||||
|
||||
if (mDesc->mScrollPos > 0 &&
|
||||
mDesc->mSelectedItem == mDesc->mScrollTop + mDesc->mScrollPos)
|
||||
{
|
||||
mDesc->mScrollPos--;
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem < 0)
|
||||
{
|
||||
// Figure out how many lines of text fit on the menu
|
||||
int y = mDesc->mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc->mTitle.IsNotEmpty())
|
||||
{
|
||||
y = -y + BigFont->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
y *= CleanYfac_1;
|
||||
int rowheight = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
int maxitems = (screen->GetHeight() - rowheight - y) / rowheight + 1;
|
||||
|
||||
mDesc->mScrollPos = MAX (0, (int)mDesc->mItems.Size() - maxitems + mDesc->mScrollTop);
|
||||
mDesc->mSelectedItem = mDesc->mItems.Size()-1;
|
||||
}
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_Down:
|
||||
do
|
||||
{
|
||||
++mDesc->mSelectedItem;
|
||||
|
||||
if (CanScrollDown && mDesc->mSelectedItem == VisBottom)
|
||||
{
|
||||
mDesc->mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
if (mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
mDesc->mScrollPos = 0;
|
||||
}
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (mDesc->mScrollPos > 0)
|
||||
{
|
||||
mDesc->mScrollPos -= VisBottom - mDesc->mScrollPos - mDesc->mScrollTop;
|
||||
if (mDesc->mScrollPos < 0)
|
||||
{
|
||||
mDesc->mScrollPos = 0;
|
||||
}
|
||||
mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos + 1;
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable())
|
||||
{
|
||||
++mDesc->mSelectedItem;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (CanScrollDown)
|
||||
{
|
||||
int pagesize = VisBottom - mDesc->mScrollPos - mDesc->mScrollTop;
|
||||
mDesc->mScrollPos += pagesize;
|
||||
if (mDesc->mScrollPos + mDesc->mScrollTop + pagesize > (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mItems.Size() - mDesc->mScrollTop - pagesize;
|
||||
}
|
||||
mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos;
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable())
|
||||
{
|
||||
++mDesc->mSelectedItem;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// fall through to default
|
||||
default:
|
||||
if (mDesc->mSelectedItem >= 0 &&
|
||||
mDesc->mItems[mDesc->mSelectedItem]->MenuEvent(mkey, fromcontroller)) return true;
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem != startedAt)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
y = (y / CleanYfac_1) - mDesc->mDrawTop;
|
||||
|
||||
if (mFocusControl)
|
||||
{
|
||||
mFocusControl->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int yline = (y / OptionSettings.mLinespacing);
|
||||
if (yline >= mDesc->mScrollTop)
|
||||
{
|
||||
yline += mDesc->mScrollPos;
|
||||
}
|
||||
if ((unsigned)yline < mDesc->mItems.Size() && mDesc->mItems[yline]->Selectable())
|
||||
{
|
||||
if (yline != mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mSelectedItem = yline;
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc->mItems[yline]->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mDesc->mSelectedItem = -1;
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Ticker ()
|
||||
{
|
||||
Super::Ticker();
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
mDesc->mItems[i]->Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Drawer ()
|
||||
{
|
||||
int y = mDesc->mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc->mTitle.IsNotEmpty())
|
||||
{
|
||||
const char *tt = mDesc->mTitle;
|
||||
if (*tt == '$') tt = GStrings(tt+1);
|
||||
screen->DrawText (BigFont, OptionSettings.mTitleColor,
|
||||
(screen->GetWidth() - BigFont->StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1,
|
||||
tt, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
y = -y + BigFont->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
mDesc->mDrawTop = y;
|
||||
//int labelofs = OptionSettings.mLabelOffset * CleanXfac_1;
|
||||
//int cursorspace = 14 * CleanXfac_1;
|
||||
int fontheight = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
y *= CleanYfac_1;
|
||||
|
||||
int indent = mDesc->mIndent;
|
||||
if (indent > 280)
|
||||
{ // kludge for the compatibility options with their extremely long labels
|
||||
if (indent + 40 <= CleanWidth_1)
|
||||
{
|
||||
indent = (screen->GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = screen->GetWidth() - 40 * CleanXfac_1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = (indent - 160) * CleanXfac_1 + screen->GetWidth() / 2;
|
||||
}
|
||||
|
||||
int ytop = y + mDesc->mScrollTop * 8 * CleanYfac_1;
|
||||
int lastrow = screen->GetHeight() - SmallFont->GetHeight() * CleanYfac_1;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < mDesc->mItems.Size() && y <= lastrow; i++, y += fontheight)
|
||||
{
|
||||
// Don't scroll the uppermost items
|
||||
if (i == mDesc->mScrollTop)
|
||||
{
|
||||
i += mDesc->mScrollPos;
|
||||
if (i >= mDesc->mItems.Size()) break; // skipped beyond end of menu
|
||||
}
|
||||
int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, mDesc->mSelectedItem == i);
|
||||
if (cur_indent >= 0 && mDesc->mSelectedItem == i && mDesc->mItems[i]->Selectable())
|
||||
{
|
||||
if (((DMenu::MenuTime%8) < 6) || DMenu::CurrentMenu != this)
|
||||
{
|
||||
M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y-CleanYfac_1+OptionSettings.mLabelOffset, "\xd");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CanScrollUp = (mDesc->mScrollPos > 0);
|
||||
CanScrollDown = (i < mDesc->mItems.Size());
|
||||
VisBottom = i - 1;
|
||||
|
||||
if (CanScrollUp)
|
||||
{
|
||||
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop + OptionSettings.mLabelOffset, "\x1a");
|
||||
}
|
||||
if (CanScrollDown)
|
||||
{
|
||||
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1 + OptionSettings.mLabelOffset, "\x1b");
|
||||
}
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FOptionMenuItem::~FOptionMenuItem()
|
||||
{
|
||||
if (mLabel != NULL) delete [] mLabel;
|
||||
}
|
||||
|
||||
bool FOptionMenuItem::CheckCoordinate(FOptionMenuDescriptor *desc, int x, int y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
return indent;
|
||||
}
|
||||
|
||||
bool FOptionMenuItem::Selectable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FOptionMenuItem::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (Selectable() && type == DMenu::MOUSE_Release)
|
||||
{
|
||||
return DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int FOptionMenuItem::GetIndent()
|
||||
{
|
||||
return mCentered? 0 : SmallFont->StringWidth(mLabel);
|
||||
}
|
||||
|
||||
void FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)
|
||||
{
|
||||
const char *label = mLabel;
|
||||
if (*label == '$') label = GStrings(label+1);
|
||||
|
||||
int overlay = grayed? MAKEARGB(96,48,0,0) : 0;
|
||||
|
||||
int x;
|
||||
int w = SmallFont->StringWidth(label) * CleanXfac_1;
|
||||
if (!mCentered) x = indent - w;
|
||||
else x = (screen->GetWidth() - w) / 2;
|
||||
screen->DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FOptionMenuDescriptor::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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FOptionMenuItem *FOptionMenuDescriptor::GetItem(FName name)
|
||||
{
|
||||
for(unsigned i=0;i<mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mItems[i]->GetAction(NULL);
|
||||
if (nm == name) return mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class DGameplayMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DGameplayMenu, DOptionMenu)
|
||||
|
||||
public:
|
||||
DGameplayMenu()
|
||||
{}
|
||||
|
||||
void Drawer ()
|
||||
{
|
||||
Super::Drawer();
|
||||
|
||||
char text[64];
|
||||
mysnprintf(text, 64, "dmflags = %d dmflags2 = %d", *dmflags, *dmflags2);
|
||||
screen->DrawText (SmallFont, OptionSettings.mFontColorValue,
|
||||
(screen->GetWidth() - SmallFont->StringWidth (text) * CleanXfac_1) / 2, 0, text,
|
||||
DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DGameplayMenu)
|
||||
|
||||
class DCompatibilityMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DCompatibilityMenu, DOptionMenu)
|
||||
|
||||
public:
|
||||
DCompatibilityMenu()
|
||||
{}
|
||||
|
||||
void Drawer ()
|
||||
{
|
||||
Super::Drawer();
|
||||
|
||||
char text[64];
|
||||
mysnprintf(text, 64, "compatflags = %d", *compatflags);
|
||||
screen->DrawText (SmallFont, OptionSettings.mFontColorValue,
|
||||
(screen->GetWidth() - SmallFont->StringWidth (text) * CleanXfac_1) / 2, 0, text,
|
||||
DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DCompatibilityMenu)
|
916
src/menu/optionmenuitems.h
Normal file
916
src/menu/optionmenuitems.h
Normal file
|
@ -0,0 +1,916 @@
|
|||
/*
|
||||
** optionmenuitems.h
|
||||
** Control items for option menus
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
void M_DrawConText (int color, int x, int y, const char *str);
|
||||
void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigits);
|
||||
void M_SetVideoMode();
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// opens a submenu, action is a submenu name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemSubmenu : public FOptionMenuItem
|
||||
{
|
||||
int mParam;
|
||||
public:
|
||||
FOptionMenuItemSubmenu(const char *label, const char *menu, int param = 0)
|
||||
: FOptionMenuItem(label, menu)
|
||||
{
|
||||
mParam = param;
|
||||
}
|
||||
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColorMore);
|
||||
return indent;
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
M_SetMenu(mAction, mParam);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Executes a CCMD, action is a CCMD name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemCommand : public FOptionMenuItemSubmenu
|
||||
{
|
||||
public:
|
||||
FOptionMenuItemCommand(const char *label, const char *menu)
|
||||
: FOptionMenuItemSubmenu(label, menu)
|
||||
{
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
C_DoCommand(mAction);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Executes a CCMD after confirmation, action is a CCMD name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemSafeCommand : public FOptionMenuItemCommand
|
||||
{
|
||||
// action is a CCMD
|
||||
public:
|
||||
FOptionMenuItemSafeCommand(const char *label, const char *menu)
|
||||
: FOptionMenuItemCommand(label, menu)
|
||||
{
|
||||
}
|
||||
|
||||
bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_MBYes)
|
||||
{
|
||||
C_DoCommand(mAction);
|
||||
return true;
|
||||
}
|
||||
return FOptionMenuItemCommand::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
M_StartMessage("Do you really want to do this?", 0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Base class for option lists
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemOptionBase : public FOptionMenuItem
|
||||
{
|
||||
protected:
|
||||
// action is a CVAR
|
||||
FOptionValues *mValues;
|
||||
FBaseCVar *mGrayCheck;
|
||||
int mCenter;
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
OP_VALUES = 0x11001
|
||||
};
|
||||
|
||||
FOptionMenuItemOptionBase(const char *label, const char *menu, const char *values, const char *graycheck, int center)
|
||||
: FOptionMenuItem(label, menu)
|
||||
{
|
||||
FOptionValues **opt = OptionValues.CheckKey(values);
|
||||
if (opt != NULL)
|
||||
{
|
||||
mValues = *opt;
|
||||
}
|
||||
else
|
||||
{
|
||||
mValues = NULL;
|
||||
}
|
||||
mGrayCheck = (FBoolCVar*)FindCVar(graycheck, NULL);
|
||||
mCenter = center;
|
||||
}
|
||||
|
||||
bool SetString(int i, const char *newtext)
|
||||
{
|
||||
if (i == OP_VALUES)
|
||||
{
|
||||
FOptionValues **opt = OptionValues.CheckKey(newtext);
|
||||
if (opt != NULL)
|
||||
{
|
||||
mValues = *opt;
|
||||
int s = GetSelection();
|
||||
if (s >= (int)mValues->mValues.Size()) s = 0;
|
||||
SetSelection(s); // readjust the CVAR if its value is outside the range now
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
virtual int GetSelection() = 0;
|
||||
virtual void SetSelection(int Selection) = 0;
|
||||
|
||||
//=============================================================================
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
bool grayed = mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool);
|
||||
|
||||
if (mCenter)
|
||||
{
|
||||
indent = (screen->GetWidth() / 2);
|
||||
}
|
||||
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, grayed);
|
||||
|
||||
int overlay = grayed? MAKEARGB(96,48,0,0) : 0;
|
||||
const char *text;
|
||||
int Selection = GetSelection();
|
||||
if (Selection < 0)
|
||||
{
|
||||
text = "Unknown";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = mValues->mValues[Selection].Text;
|
||||
}
|
||||
screen->DrawText (SmallFont, OptionSettings.mFontColorValue, indent + CURSORSPACE, y,
|
||||
text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE);
|
||||
return indent;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mValues->mValues.Size() > 0)
|
||||
{
|
||||
int Selection = GetSelection();
|
||||
if (mkey == MKEY_Left)
|
||||
{
|
||||
if (Selection == -1) Selection = 0;
|
||||
else if (--Selection < 0) Selection = mValues->mValues.Size()-1;
|
||||
}
|
||||
else if (mkey == MKEY_Right || mkey == MKEY_Enter)
|
||||
{
|
||||
if (++Selection >= (int)mValues->mValues.Size()) Selection = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
SetSelection(Selection);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Selectable()
|
||||
{
|
||||
return !(mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Change a CVAR, action is the CVAR name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemOption : public FOptionMenuItemOptionBase
|
||||
{
|
||||
// action is a CVAR
|
||||
FBaseCVar *mCVar;
|
||||
public:
|
||||
|
||||
FOptionMenuItemOption(const char *label, const char *menu, const char *values, const char *graycheck, int center)
|
||||
: FOptionMenuItemOptionBase(label, menu, values, graycheck, center)
|
||||
{
|
||||
mCVar = FindCVar(mAction, NULL);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
int GetSelection()
|
||||
{
|
||||
int Selection = -1;
|
||||
if (mValues != NULL && mCVar != NULL && mValues->mValues.Size() > 0)
|
||||
{
|
||||
if (mValues->mValues[0].TextValue.IsEmpty())
|
||||
{
|
||||
UCVarValue cv = mCVar->GetGenericRep(CVAR_Float);
|
||||
for(unsigned i=0;i<mValues->mValues.Size(); i++)
|
||||
{
|
||||
if (fabs(cv.Float - mValues->mValues[i].Value) < FLT_EPSILON)
|
||||
{
|
||||
Selection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UCVarValue cv = mCVar->GetGenericRep(CVAR_String);
|
||||
for(unsigned i=0;i<mValues->mValues.Size(); i++)
|
||||
{
|
||||
if (mValues->mValues[i].TextValue.CompareNoCase(cv.String) == 0)
|
||||
{
|
||||
Selection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Selection;
|
||||
}
|
||||
|
||||
void SetSelection(int Selection)
|
||||
{
|
||||
UCVarValue value;
|
||||
if (mValues != NULL && mCVar != NULL && mValues->mValues.Size() > 0)
|
||||
{
|
||||
if (mValues->mValues[0].TextValue.IsEmpty())
|
||||
{
|
||||
value.Float = (float)mValues->mValues[Selection].Value;
|
||||
mCVar->SetGenericRep (value, CVAR_Float);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.String = mValues->mValues[Selection].TextValue.LockBuffer();
|
||||
mCVar->SetGenericRep (value, CVAR_String);
|
||||
mValues->mValues[Selection].TextValue.UnlockBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// This class is used to capture the key to be used as the new key binding
|
||||
// for a control item
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DEnterKey : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DEnterKey, DMenu)
|
||||
|
||||
int *pKey;
|
||||
|
||||
public:
|
||||
DEnterKey(DMenu *parent, int *keyptr)
|
||||
: DMenu(parent)
|
||||
{
|
||||
pKey = keyptr;
|
||||
SetMenuMessage(1);
|
||||
menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture...
|
||||
}
|
||||
|
||||
bool TranslateKeyboardEvents()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetMenuMessage(int which)
|
||||
{
|
||||
if (mParentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu)))
|
||||
{
|
||||
DOptionMenu *m = barrier_cast<DOptionMenu*>(mParentMenu);
|
||||
FListMenuItem *it = m->GetItem(NAME_Controlmessage);
|
||||
if (it != NULL)
|
||||
{
|
||||
it->SetValue(0, which);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_KeyDown)
|
||||
{
|
||||
*pKey = ev->data1;
|
||||
menuactive = MENU_On;
|
||||
SetMenuMessage(0);
|
||||
Close();
|
||||
mParentMenu->MenuEvent((ev->data1 == KEY_ESCAPE)? MKEY_Abort : MKEY_Input, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Drawer()
|
||||
{
|
||||
mParentMenu->Drawer();
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef NO_IMP
|
||||
IMPLEMENT_ABSTRACT_CLASS(DEnterKey)
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// // Edit a key binding, Action is the CCMD to bind
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemControl : public FOptionMenuItem
|
||||
{
|
||||
FKeyBindings *mBindings;
|
||||
int mInput;
|
||||
bool mWaiting;
|
||||
public:
|
||||
|
||||
FOptionMenuItemControl(const char *label, const char *menu, FKeyBindings *bindings)
|
||||
: FOptionMenuItem(label, menu)
|
||||
{
|
||||
mBindings = bindings;
|
||||
mWaiting = false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
drawLabel(indent, y, mWaiting? OptionSettings.mFontColorHighlight:
|
||||
(selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor));
|
||||
|
||||
char description[64];
|
||||
int Key1, Key2;
|
||||
|
||||
mBindings->GetKeysForCommand(mAction, &Key1, &Key2);
|
||||
C_NameKeys (description, Key1, Key2);
|
||||
if (description[0])
|
||||
{
|
||||
M_DrawConText(CR_WHITE, indent + CURSORSPACE, y-1+OptionSettings.mLabelOffset, description);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawText(SmallFont, CR_BLACK, indent + CURSORSPACE, y + OptionSettings.mLabelOffset, "---",
|
||||
DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
return indent;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Input)
|
||||
{
|
||||
mWaiting = false;
|
||||
mBindings->SetBind(mInput, mAction);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Clear)
|
||||
{
|
||||
mBindings->UnbindACommand(mAction);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Abort)
|
||||
{
|
||||
mWaiting = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
mWaiting = true;
|
||||
DMenu *input = new DEnterKey(DMenu::CurrentMenu, &mInput);
|
||||
M_ActivateMenu(input);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemStaticText : public FOptionMenuItem
|
||||
{
|
||||
EColorRange mColor;
|
||||
public:
|
||||
FOptionMenuItemStaticText(const char *label, bool header)
|
||||
: FOptionMenuItem(label, NAME_None, true)
|
||||
{
|
||||
mColor = header? OptionSettings.mFontColorHeader : OptionSettings.mFontColor;
|
||||
}
|
||||
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
drawLabel(indent, y, mColor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Selectable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemStaticTextSwitchable : public FOptionMenuItem
|
||||
{
|
||||
EColorRange mColor;
|
||||
FString mAltText;
|
||||
int mCurrent;
|
||||
|
||||
public:
|
||||
FOptionMenuItemStaticTextSwitchable(const char *label, const char *label2, FName action, bool header)
|
||||
: FOptionMenuItem(label, action, true)
|
||||
{
|
||||
mColor = header? OptionSettings.mFontColorHeader : OptionSettings.mFontColor;
|
||||
mAltText = label2;
|
||||
mCurrent = 0;
|
||||
}
|
||||
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
const char *txt = mCurrent? (const char*)mAltText : mLabel;
|
||||
int w = SmallFont->StringWidth(txt) * CleanXfac_1;
|
||||
int x = (screen->GetWidth() - w) / 2;
|
||||
screen->DrawText (SmallFont, mColor, x, y, txt, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SetValue(int i, int val)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mCurrent = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetString(int i, const char *newtext)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mAltText = newtext;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Selectable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuSliderBase : public FOptionMenuItem
|
||||
{
|
||||
// action is a CVAR
|
||||
double mMin, mMax, mStep;
|
||||
int mShowValue;
|
||||
int mDrawX;
|
||||
public:
|
||||
FOptionMenuSliderBase(const char *label, double min, double max, double step, int showval)
|
||||
: FOptionMenuItem(label, NAME_None)
|
||||
{
|
||||
mMin = min;
|
||||
mMax = max;
|
||||
mStep = step;
|
||||
mShowValue = showval;
|
||||
mDrawX = 0;
|
||||
}
|
||||
|
||||
virtual double GetValue() = 0;
|
||||
virtual void SetValue(double val) = 0;
|
||||
|
||||
//=============================================================================
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor);
|
||||
mDrawX = indent + CURSORSPACE;
|
||||
M_DrawSlider (mDrawX, y + OptionSettings.mLabelOffset, mMin, mMax, GetValue(), mShowValue);
|
||||
return indent;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
double value = GetValue();
|
||||
|
||||
if (mkey == MKEY_Left)
|
||||
{
|
||||
value -= mStep;
|
||||
}
|
||||
else if (mkey == MKEY_Right)
|
||||
{
|
||||
value += mStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
SetValue(clamp(value, mMin, mMax));
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
DOptionMenu *lm = static_cast<DOptionMenu*>(DMenu::CurrentMenu);
|
||||
if (type != DMenu::MOUSE_Click)
|
||||
{
|
||||
if (!lm->CheckFocus(this)) return false;
|
||||
}
|
||||
if (type == DMenu::MOUSE_Release)
|
||||
{
|
||||
lm->ReleaseFocus();
|
||||
}
|
||||
|
||||
int slide_left = mDrawX+8*CleanXfac_1;
|
||||
int slide_right = slide_left + 10*8*CleanXfac_1; // 12 char cells with 8 pixels each.
|
||||
|
||||
if (type == DMenu::MOUSE_Click)
|
||||
{
|
||||
if (x < slide_left || x >= slide_right) return true;
|
||||
}
|
||||
|
||||
x = clamp(x, slide_left, slide_right);
|
||||
double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left);
|
||||
if (v != GetValue())
|
||||
{
|
||||
SetValue(v);
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
if (type == DMenu::MOUSE_Click)
|
||||
{
|
||||
lm->SetFocus(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuSliderCVar : public FOptionMenuSliderBase
|
||||
{
|
||||
FBaseCVar *mCVar;
|
||||
public:
|
||||
FOptionMenuSliderCVar(const char *label, const char *menu, double min, double max, double step, int showval)
|
||||
: FOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
mCVar = FindCVar(menu, NULL);
|
||||
}
|
||||
|
||||
double GetValue()
|
||||
{
|
||||
if (mCVar != NULL)
|
||||
{
|
||||
return mCVar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetValue(double val)
|
||||
{
|
||||
if (mCVar != NULL)
|
||||
{
|
||||
UCVarValue value;
|
||||
value.Float = (float)val;
|
||||
mCVar->SetGenericRep(value, CVAR_Float);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuSliderVar : public FOptionMenuSliderBase
|
||||
{
|
||||
float *mPVal;
|
||||
public:
|
||||
|
||||
FOptionMenuSliderVar(const char *label, float *pVal, double min, double max, double step, int showval)
|
||||
: FOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
mPVal = pVal;
|
||||
}
|
||||
|
||||
double GetValue()
|
||||
{
|
||||
return *mPVal;
|
||||
}
|
||||
|
||||
void SetValue(double val)
|
||||
{
|
||||
*mPVal = (float)val;
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// // Edit a key binding, Action is the CCMD to bind
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class FOptionMenuItemColorPicker : public FOptionMenuItem
|
||||
{
|
||||
FColorCVar *mCVar;
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
CPF_RESET = 0x20001,
|
||||
};
|
||||
|
||||
FOptionMenuItemColorPicker(const char *label, const char *menu)
|
||||
: FOptionMenuItem(label, menu)
|
||||
{
|
||||
FBaseCVar *cv = FindCVar(menu, NULL);
|
||||
if (cv->GetRealType() == CVAR_Color)
|
||||
{
|
||||
mCVar = (FColorCVar*)cv;
|
||||
}
|
||||
else mCVar = NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor);
|
||||
|
||||
if (mCVar != NULL)
|
||||
{
|
||||
int box_x = indent + CURSORSPACE;
|
||||
int box_y = y + OptionSettings.mLabelOffset * CleanYfac_1 / 2;
|
||||
screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + (SmallFont->GetHeight() - 1) * CleanYfac_1,
|
||||
-1, (uint32)*mCVar | 0xff000000);
|
||||
}
|
||||
return indent;
|
||||
}
|
||||
|
||||
bool SetValue(int i, int v)
|
||||
{
|
||||
if (i == CPF_RESET && mCVar != NULL)
|
||||
{
|
||||
mCVar->ResetToDefault();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
if (mCVar != NULL)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
DMenu *picker = StartPickerMenu(DMenu::CurrentMenu, mLabel, mCVar);
|
||||
if (picker != NULL)
|
||||
{
|
||||
M_ActivateMenu(picker);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class FOptionMenuScreenResolutionLine : public FOptionMenuItem
|
||||
{
|
||||
FString mResTexts[3];
|
||||
int mSelection;
|
||||
int mHighlight;
|
||||
int mMaxValid;
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
SRL_INDEX = 0x30000,
|
||||
SRL_SELECTION = 0x30003,
|
||||
SRL_HIGHLIGHT = 0x30004,
|
||||
};
|
||||
|
||||
FOptionMenuScreenResolutionLine(const char *action)
|
||||
: FOptionMenuItem("", action)
|
||||
{
|
||||
mSelection = 0;
|
||||
mHighlight = -1;
|
||||
}
|
||||
|
||||
bool SetValue(int i, int v)
|
||||
{
|
||||
if (i == SRL_SELECTION)
|
||||
{
|
||||
mSelection = v;
|
||||
return true;
|
||||
}
|
||||
else if (i == SRL_HIGHLIGHT)
|
||||
{
|
||||
mHighlight = v;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetValue(int i, int *v)
|
||||
{
|
||||
if (i == SRL_SELECTION)
|
||||
{
|
||||
*v = mSelection;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetString(int i, const char *newtext)
|
||||
{
|
||||
if (i >= SRL_INDEX && i <= SRL_INDEX+2)
|
||||
{
|
||||
mResTexts[i-SRL_INDEX] = newtext;
|
||||
if (mResTexts[0].IsEmpty()) mMaxValid = -1;
|
||||
else if (mResTexts[1].IsEmpty()) mMaxValid = 0;
|
||||
else if (mResTexts[2].IsEmpty()) mMaxValid = 1;
|
||||
else mMaxValid = 2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetString(int i, char *s, int len)
|
||||
{
|
||||
if (i >= SRL_INDEX && i <= SRL_INDEX+2)
|
||||
{
|
||||
strncpy(s, mResTexts[i-SRL_INDEX], len-1);
|
||||
s[len-1] = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Left)
|
||||
{
|
||||
if (--mSelection < 0) mSelection = mMaxValid;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Right)
|
||||
{
|
||||
if (++mSelection > mMaxValid) mSelection = 0;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int colwidth = screen->GetWidth() / 3;
|
||||
mSelection = x / colwidth;
|
||||
return FOptionMenuItem::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
M_SetVideoMode();
|
||||
return true;
|
||||
}
|
||||
|
||||
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
int colwidth = screen->GetWidth() / 3;
|
||||
EColorRange color;
|
||||
|
||||
for (int x = 0; x < 3; x++)
|
||||
{
|
||||
if (selected && mSelection == x)
|
||||
color = OptionSettings.mFontColorSelection;
|
||||
else if (x == mHighlight)
|
||||
color = OptionSettings.mFontColorHighlight;
|
||||
else
|
||||
color = OptionSettings.mFontColorValue;
|
||||
|
||||
screen->DrawText (SmallFont, color, colwidth * x + 20 * CleanXfac_1, y, mResTexts[x], DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
return colwidth * mSelection + 20 * CleanXfac_1 - CURSORSPACE;
|
||||
}
|
||||
|
||||
bool Selectable()
|
||||
{
|
||||
return mMaxValid >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef NO_IMP
|
||||
CCMD(am_restorecolors)
|
||||
{
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu)))
|
||||
{
|
||||
DOptionMenu *m = (DOptionMenu*)DMenu::CurrentMenu;
|
||||
const FOptionMenuDescriptor *desc = m->GetDescriptor();
|
||||
// Find the color cvars by scanning the MapColors menu.
|
||||
for (unsigned i = 0; i < desc->mItems.Size(); ++i)
|
||||
{
|
||||
desc->mItems[i]->SetValue(FOptionMenuItemColorPicker::CPF_RESET, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
561
src/menu/playerdisplay.cpp
Normal file
561
src/menu/playerdisplay.cpp
Normal file
|
@ -0,0 +1,561 @@
|
|||
/*
|
||||
** playerdisplay.cpp
|
||||
** The player display for the player setup and class selection screen
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 "doomtype.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_player.h"
|
||||
#include "tables.h"
|
||||
#include "m_fixed.h"
|
||||
#include "templates.h"
|
||||
#include "menu/menu.h"
|
||||
#include "colormatcher.h"
|
||||
#include "textures/textures.h"
|
||||
#include "w_wad.h"
|
||||
#include "v_font.h"
|
||||
#include "v_video.h"
|
||||
#include "g_level.h"
|
||||
#include "gi.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_state.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Used by the player display
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
struct FBackdropTexture : public FTexture
|
||||
{
|
||||
public:
|
||||
FBackdropTexture();
|
||||
|
||||
const BYTE *GetColumn(unsigned int column, const Span **spans_out);
|
||||
const BYTE *GetPixels();
|
||||
void Unload();
|
||||
bool CheckModified();
|
||||
|
||||
protected:
|
||||
BYTE Pixels[144*160];
|
||||
static const Span DummySpan[2];
|
||||
int LastRenderTic;
|
||||
|
||||
angle_t time1, time2, time3, time4;
|
||||
angle_t t1ang, t2ang, z1ang, z2ang;
|
||||
|
||||
void Render();
|
||||
};
|
||||
|
||||
|
||||
|
||||
// A 32x32 cloud rendered with Photoshop, plus some other filters
|
||||
static BYTE pattern1[1024] =
|
||||
{
|
||||
5, 9, 7,10, 9,15, 9, 7, 8,10, 5, 3, 5, 7, 9, 8,14, 8, 4, 7, 8, 9, 5, 7,14, 7, 0, 7,13,13, 9, 6,
|
||||
2, 7, 9, 7, 7,10, 8, 8,11,10, 6, 7,10, 7, 5, 6, 6, 4, 7,13,15,16,11,15,11, 8, 0, 4,13,22,17,11,
|
||||
5, 9, 9, 7, 9,10, 4, 3, 6, 7, 8, 6, 5, 4, 2, 2, 1, 4, 6,11,15,15,14,13,17, 9, 5, 9,11,12,17,20,
|
||||
9,16, 9, 8,12,13, 7, 3, 7, 9, 5, 4, 2, 5, 5, 5, 7,11, 6, 7, 6,13,17,10,10, 9,12,17,14,12,16,15,
|
||||
15,13, 5, 3, 9,10, 4,10,12,12, 7, 9, 8, 8, 8,10, 7, 6, 5, 5, 5, 6,11, 9, 3,13,16,18,21,16,23,18,
|
||||
23,13, 0, 0, 0, 0, 0,12,18,14,15,16,13, 7, 7, 5, 9, 6, 6, 8, 4, 0, 0, 0, 0,14,19,17,14,20,21,25,
|
||||
19,20,14,13, 7, 5,13,19,14,13,17,15,14, 7, 3, 5, 6,11, 7, 7, 8, 8,10, 9, 9,18,17,15,14,15,18,16,
|
||||
16,29,24,23,18, 9,17,20,11, 5,12,15,15,12, 6, 3, 4, 6, 7,10,13,18,18,19,16,12,17,19,23,16,14,14,
|
||||
9,18,20,26,19, 5,18,18,10, 5,12,15,14,17,11, 6,11, 9,10,13,10,20,24,20,21,20,14,18,15,22,20,19,
|
||||
0, 6,16,18, 8, 7,15,18,10,13,17,17,13,11,15,11,19,12,13,10, 4,15,19,21,21,24,14, 9,17,20,24,17,
|
||||
18,17, 7, 7,16,21,22,15, 5,14,20,14,13,21,13, 8,12,14, 7, 8,11,15,13,11,16,17, 7, 5,12,17,19,14,
|
||||
25,23,17,16,23,18,15, 7, 0, 6,11, 6,11,15,11, 7,12, 7, 4,10,16,13, 7, 7,15,13, 9,15,21,14, 5, 0,
|
||||
18,22,21,21,21,22,12, 6,14,20,15, 6,10,19,13, 8, 7, 3, 7,12,14,16, 9,12,22,15,12,18,24,19,17, 9,
|
||||
0,15,18,21,17,25,14,13,19,21,21,11, 6,13,16,16,12,10,12,11,13,20,14,13,18,13, 9,15,16,25,31,20,
|
||||
5,20,24,16, 7,14,14,11,18,19,19, 6, 0, 5,11,14,17,16,19,14,15,21,19,15,14,14, 8, 0, 7,24,18,16,
|
||||
9,17,15, 7, 6,14,12, 7,14,16,11, 4, 7, 6,13,16,15,13,12,20,21,20,21,17,18,26,14, 0,13,23,21,11,
|
||||
9,12,18,11,15,21,13, 8,13,13,10, 7,13, 8, 8,19,13, 7, 4,15,19,18,14,12,14,15, 8, 6,16,22,22,15,
|
||||
9,17,14,19,15,14,15, 9,11, 9, 6, 8,14,13,13,12, 5, 0, 0, 6,12,13, 7, 7, 9, 7, 0,12,21,16,15,18,
|
||||
15,16,18,11, 6, 8,15, 9, 2, 0, 5,10,10,16, 9, 0, 4,12,15, 9,12, 9, 7, 7,12, 7, 0, 6,12, 6, 9,13,
|
||||
12,19,15,14,11, 7, 8, 9,12,10, 5, 5, 7,12,12,10,14,16,16,11, 8,12,10,12,10, 8,10,10,14,12,16,16,
|
||||
16,17,20,22,12,15,12,14,19,11, 6, 5,10,13,17,17,21,19,15, 9, 6, 9,15,18,10,10,18,14,20,15,16,17,
|
||||
11,19,19,18,19,14,17,13,12,12, 7,11,18,17,16,15,19,19,10, 2, 0, 8,15,12, 8,11,12,10,19,20,19,19,
|
||||
6,14,18,13,13,16,16,12, 5, 8,10,12,10,13,18,12, 9,10, 7, 6, 5,11, 8, 6, 7,13,16,13,10,15,20,14,
|
||||
0, 5,12,12, 4, 0, 9,16, 9,10,12, 8, 0, 9,13, 9, 0, 2, 4, 7,10, 6, 7, 3, 4,11,16,18,10,11,21,21,
|
||||
16,13,11,15, 8, 0, 5, 9, 8, 7, 6, 3, 0, 9,17, 9, 0, 0, 0, 3, 5, 4, 3, 5, 7,15,16,16,17,14,22,22,
|
||||
24,14,15,12, 9, 0, 5,10, 8, 4, 7,12,10,11,12, 7, 6, 8, 6, 5, 7, 8, 8,11,13,10,15,14,12,18,20,16,
|
||||
16,17,17,18,12, 9,12,16,10, 5, 6,20,13,15, 8, 4, 8, 9, 8, 7, 9,11,12,17,16,16,11,10, 9,10, 5, 0,
|
||||
0,14,18,18,15,16,14, 9,10, 9, 9,15,14,10, 4, 6,10, 8, 8, 7,10, 9,10,16,18,10, 0, 0, 7,12,10, 8,
|
||||
0,14,19,14, 9,11,11, 8, 8,10,15, 9,10, 7, 4,10,13, 9, 7, 5, 5, 7, 7, 7,13,13, 5, 5,14,22,18,16,
|
||||
0,10,14,10, 3, 6, 5, 6, 8, 9, 8, 9, 5, 9, 8, 9, 6, 8, 8, 8, 1, 0, 0, 0, 9,17,12,12,17,19,20,13,
|
||||
6,11,17,11, 5, 5, 8,10, 6, 5, 6, 6, 3, 7, 9, 7, 6, 8,12,10, 4, 8, 6, 6,11,16,16,15,16,17,17,16,
|
||||
11, 9,10,10, 5, 6,12,10, 5, 1, 6,10, 5, 3, 3, 5, 4, 7,15,10, 7,13, 7, 8,15,11,15,15,15, 8,11,15,
|
||||
};
|
||||
|
||||
// Just a 32x32 cloud rendered with the standard Photoshop filter
|
||||
static BYTE pattern2[1024] =
|
||||
{
|
||||
9, 9, 8, 8, 8, 8, 6, 6,13,13,11,21,19,21,23,18,23,24,19,19,24,17,18,12, 9,14, 8,12,12, 5, 8, 6,
|
||||
11,10, 6, 7, 8, 8, 9,13,10,11,17,15,23,22,23,22,20,26,27,26,17,21,20,14,12, 8,11, 8,11, 7, 8, 7,
|
||||
6, 9,13,13,10, 9,13, 7,12,13,16,19,16,20,22,25,22,25,27,22,21,23,15,10,14,14,15,13,12, 8,12, 6,
|
||||
6, 7,12,12,12,16, 9,12,12,15,16,11,21,24,19,24,23,26,28,27,26,21,14,15, 7, 7,10,15,12,11,10, 9,
|
||||
7,14,11,16,12,18,16,14,16,14,11,14,15,21,23,17,20,18,26,24,27,18,20,11,11,14,10,17,17,10, 6,10,
|
||||
13, 9,14,10,13,11,14,15,18,15,15,12,19,19,20,18,22,20,19,22,19,19,19,20,17,15,15,11,16,14,10, 8,
|
||||
13,16,12,16,17,19,17,18,15,19,14,18,15,14,15,17,21,19,23,18,23,22,18,18,17,15,15,16,12,12,15,10,
|
||||
10,12,14,10,16,11,18,15,21,20,20,17,18,19,16,19,14,20,19,14,19,25,22,21,22,24,18,12, 9, 9, 8, 6,
|
||||
10,10,13, 9,15,13,20,19,22,18,18,17,17,21,21,13,13,12,19,18,16,17,27,26,22,23,20,17,12,11, 8, 9,
|
||||
7,13,14,15,11,13,18,22,19,23,23,20,22,24,21,14,12,16,17,19,18,18,22,18,24,23,19,17,16,14, 8, 7,
|
||||
12,12, 8, 8,16,20,26,25,28,28,22,29,23,22,21,18,13,16,15,15,20,17,25,24,19,17,17,17,15,10, 8, 9,
|
||||
7,12,15,11,17,20,25,25,25,29,30,31,28,26,18,16,17,18,20,21,22,20,23,19,18,19,10,16,16,11,11, 8,
|
||||
5, 6, 8,14,14,17,17,21,27,23,27,31,27,22,23,21,19,19,21,19,20,19,17,22,13,17,12,15,10,10,12, 6,
|
||||
8, 9, 8,14,15,16,15,18,27,26,23,25,23,22,18,21,20,17,19,20,20,16,20,14,15,13,12, 8, 8, 7,11,13,
|
||||
7, 6,11,11,11,13,15,22,25,24,26,22,24,26,23,18,24,24,20,18,20,16,17,12,12,12,10, 8,11, 9, 6, 8,
|
||||
9,10, 9, 6, 5,14,16,19,17,21,26,20,23,19,19,17,20,21,26,25,23,21,17,13,12, 5,13,11, 7,12,10,12,
|
||||
6, 5, 4,10,11, 9,10,13,17,20,20,18,23,26,27,20,21,24,20,19,24,20,18,10,11, 3, 6,13, 9, 6, 8, 8,
|
||||
1, 2, 2,11,13,13,11,16,16,16,19,21,20,23,22,28,21,20,19,18,23,16,18, 7, 5, 9, 7, 6, 5,10, 8, 8,
|
||||
0, 0, 6, 9,11,15,12,12,19,18,19,26,22,24,26,30,23,22,22,16,20,19,12,12, 3, 4, 6, 5, 4, 7, 2, 4,
|
||||
2, 0, 0, 7,11, 8,14,13,15,21,26,28,25,24,27,26,23,24,22,22,15,17,12, 8,10, 7, 7, 4, 0, 5, 0, 1,
|
||||
1, 2, 0, 1, 9,14,13,10,19,24,22,29,30,28,30,30,31,23,24,19,17,14,13, 8, 8, 8, 1, 4, 0, 0, 0, 3,
|
||||
5, 2, 4, 2, 9, 8, 8, 8,18,23,20,27,30,27,31,25,28,30,28,24,24,15,11,14,10, 3, 4, 3, 0, 0, 1, 3,
|
||||
9, 3, 4, 3, 5, 6, 8,13,14,23,21,27,28,27,28,27,27,29,30,24,22,23,13,15, 8, 6, 2, 0, 4, 3, 4, 1,
|
||||
6, 5, 5, 3, 9, 3, 6,14,13,16,23,26,28,23,30,31,28,29,26,27,21,20,15,15,13, 9, 1, 0, 2, 0, 5, 8,
|
||||
8, 4, 3, 7, 2, 0,10, 7,10,14,21,21,29,28,25,27,30,28,25,24,27,22,19,13,10, 5, 0, 0, 0, 0, 0, 7,
|
||||
7, 6, 7, 0, 2, 2, 5, 6,15,11,19,24,22,29,27,31,30,30,31,28,23,18,14,14, 7, 5, 0, 0, 1, 0, 1, 0,
|
||||
5, 5, 5, 0, 0, 4, 5,11, 7,10,13,20,21,21,28,31,28,30,26,28,25,21, 9,12, 3, 3, 0, 2, 2, 2, 0, 1,
|
||||
3, 3, 0, 2, 0, 3, 5, 3,11,11,16,19,19,27,26,26,30,27,28,26,23,22,16, 6, 2, 2, 3, 2, 0, 2, 4, 0,
|
||||
0, 0, 0, 3, 3, 1, 0, 4, 5, 9,11,16,24,20,28,26,28,24,28,25,22,21,16, 5, 7, 5, 7, 3, 2, 3, 3, 6,
|
||||
0, 0, 2, 0, 2, 0, 4, 3, 8,12, 9,17,16,23,23,27,27,22,26,22,21,21,13,14, 5, 3, 7, 3, 2, 4, 6, 1,
|
||||
2, 5, 6, 4, 0, 1, 5, 8, 7, 6,15,17,22,20,24,28,23,25,20,21,18,16,13,15,13,10, 8, 5, 5, 9, 3, 7,
|
||||
7, 7, 0, 5, 1, 6, 7, 9,12, 9,12,21,22,25,24,22,23,25,24,18,24,22,17,13,10, 9,10, 9, 6,11, 6, 5,
|
||||
};
|
||||
|
||||
const FTexture::Span FBackdropTexture::DummySpan[2] = { { 0, 160 }, { 0, 0 } };
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FBackdropTexture::FBackdropTexture()
|
||||
{
|
||||
Width = 144;
|
||||
Height = 160;
|
||||
WidthBits = 8;
|
||||
HeightBits = 8;
|
||||
WidthMask = 255;
|
||||
LastRenderTic = 0;
|
||||
|
||||
time1 = ANGLE_1*180;
|
||||
time2 = ANGLE_1*56;
|
||||
time3 = ANGLE_1*99;
|
||||
time4 = ANGLE_1*1;
|
||||
t1ang = ANGLE_90;
|
||||
t2ang = 0;
|
||||
z1ang = 0;
|
||||
z2ang = ANGLE_90/2;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool FBackdropTexture::CheckModified()
|
||||
{
|
||||
return LastRenderTic != gametic;
|
||||
}
|
||||
|
||||
void FBackdropTexture::Unload()
|
||||
{
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
const BYTE *FBackdropTexture::GetColumn(unsigned int column, const Span **spans_out)
|
||||
{
|
||||
if (LastRenderTic != gametic)
|
||||
{
|
||||
Render();
|
||||
}
|
||||
column = clamp(column, 0u, 143u);
|
||||
if (spans_out != NULL)
|
||||
{
|
||||
*spans_out = DummySpan;
|
||||
}
|
||||
return Pixels + column*160;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
const BYTE *FBackdropTexture::GetPixels()
|
||||
{
|
||||
if (LastRenderTic != gametic)
|
||||
{
|
||||
Render();
|
||||
}
|
||||
return Pixels;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// This is one plasma and two rotozoomers. I think it turned out quite awesome.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FBackdropTexture::Render()
|
||||
{
|
||||
BYTE *from;
|
||||
int width, height, pitch;
|
||||
|
||||
width = 160;
|
||||
height = 144;
|
||||
pitch = width;
|
||||
|
||||
int x, y;
|
||||
|
||||
const angle_t a1add = ANGLE_1/2;
|
||||
const angle_t a2add = ANGLE_MAX-ANGLE_1;
|
||||
const angle_t a3add = ANGLE_1*5/7;
|
||||
const angle_t a4add = ANGLE_MAX-ANGLE_1*4/3;
|
||||
|
||||
const angle_t t1add = ANGLE_MAX-ANGLE_1*2;
|
||||
const angle_t t2add = ANGLE_MAX-ANGLE_1*3+ANGLE_1/6;
|
||||
const angle_t t3add = ANGLE_1*16/7;
|
||||
const angle_t t4add = ANGLE_MAX-ANGLE_1*2/3;
|
||||
const angle_t x1add = 5<<ANGLETOFINESHIFT;
|
||||
const angle_t x2add = ANGLE_MAX-(13<<ANGLETOFINESHIFT);
|
||||
const angle_t z1add = 3<<ANGLETOFINESHIFT;
|
||||
const angle_t z2add = 4<<ANGLETOFINESHIFT;
|
||||
|
||||
angle_t a1, a2, a3, a4;
|
||||
fixed_t c1, c2, c3, c4;
|
||||
DWORD tx, ty, tc, ts;
|
||||
DWORD ux, uy, uc, us;
|
||||
DWORD ltx, lty, lux, luy;
|
||||
|
||||
from = Pixels;
|
||||
|
||||
a3 = time3;
|
||||
a4 = time4;
|
||||
|
||||
fixed_t z1 = (finecosine[z2ang>>ANGLETOFINESHIFT]>>2)+FRACUNIT/2;
|
||||
fixed_t z2 = (finecosine[z1ang>>ANGLETOFINESHIFT]>>2)+FRACUNIT*3/4;
|
||||
|
||||
tc = MulScale5 (finecosine[t1ang>>ANGLETOFINESHIFT], z1);
|
||||
ts = MulScale5 (finesine[t1ang>>ANGLETOFINESHIFT], z1);
|
||||
uc = MulScale5 (finecosine[t2ang>>ANGLETOFINESHIFT], z2);
|
||||
us = MulScale5 (finesine[t2ang>>ANGLETOFINESHIFT], z2);
|
||||
|
||||
ltx = -width/2*tc;
|
||||
lty = -width/2*ts;
|
||||
lux = -width/2*uc;
|
||||
luy = -width/2*us;
|
||||
|
||||
for (y = 0; y < height; ++y)
|
||||
{
|
||||
a1 = time1;
|
||||
a2 = time2;
|
||||
c3 = finecosine[a3>>ANGLETOFINESHIFT];
|
||||
c4 = finecosine[a4>>ANGLETOFINESHIFT];
|
||||
tx = ltx - (y-height/2)*ts;
|
||||
ty = lty + (y-height/2)*tc;
|
||||
ux = lux - (y-height/2)*us;
|
||||
uy = luy + (y-height/2)*uc;
|
||||
for (x = 0; x < width; ++x)
|
||||
{
|
||||
c1 = finecosine[a1>>ANGLETOFINESHIFT];
|
||||
c2 = finecosine[a2>>ANGLETOFINESHIFT];
|
||||
from[x] = ((c1 + c2 + c3 + c4) >> (FRACBITS+3-7)) + 128 // plasma
|
||||
+ pattern1[(tx>>27)+((ty>>22)&992)] // rotozoomer 1
|
||||
+ pattern2[(ux>>27)+((uy>>22)&992)]; // rotozoomer 2
|
||||
tx += tc;
|
||||
ty += ts;
|
||||
ux += uc;
|
||||
uy += us;
|
||||
a1 += a1add;
|
||||
a2 += a2add;
|
||||
}
|
||||
a3 += a3add;
|
||||
a4 += a4add;
|
||||
from += pitch;
|
||||
}
|
||||
|
||||
time1 += t1add;
|
||||
time2 += t2add;
|
||||
time3 += t3add;
|
||||
time4 += t4add;
|
||||
t1ang += x1add;
|
||||
t2ang += x2add;
|
||||
z1ang += z1add;
|
||||
z2ang += z2add;
|
||||
|
||||
LastRenderTic = gametic;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemPlayerDisplay::FListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action)
|
||||
: FListMenuItem(x, y, action)
|
||||
{
|
||||
mOwner = menu;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
int r = c1.r + c2.r * i / 255;
|
||||
int g = c1.g + c2.g * i / 255;
|
||||
int b = c1.b + c2.b * i / 255;
|
||||
mRemap.Remap[i] = ColorMatcher.Pick (r, g, b);
|
||||
mRemap.Palette[i] = PalEntry(255, r, g, b);
|
||||
}
|
||||
mBackdrop = new FBackdropTexture;
|
||||
mPlayerClass = NULL;
|
||||
mPlayerState = NULL;
|
||||
mNoportrait = np;
|
||||
mMode = 0;
|
||||
mRotation = 0;
|
||||
mTranslate = false;
|
||||
mSkin = 0;
|
||||
mRandomClass = 0;
|
||||
mRandomTimer = 0;
|
||||
mClassNum = -1;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FListMenuItemPlayerDisplay::~FListMenuItemPlayerDisplay()
|
||||
{
|
||||
delete mBackdrop;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FListMenuItemPlayerDisplay::UpdateRandomClass()
|
||||
{
|
||||
if (--mRandomTimer < 0)
|
||||
{
|
||||
if (++mRandomClass >= (int)PlayerClasses.Size ()) mRandomClass = 0;
|
||||
mPlayerClass = &PlayerClasses[mRandomClass];
|
||||
mPlayerState = GetDefaultByType (mPlayerClass->Type)->SeeState;
|
||||
mPlayerTics = mPlayerState->GetTics();
|
||||
mRandomTimer = 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force)
|
||||
{
|
||||
if (classnum < 0 || classnum >= (int)PlayerClasses.Size ())
|
||||
{
|
||||
if (mClassNum != -1)
|
||||
{
|
||||
mClassNum = -1;
|
||||
mRandomTimer = 0;
|
||||
UpdateRandomClass();
|
||||
}
|
||||
}
|
||||
else if (mPlayerClass != &PlayerClasses[classnum] || force)
|
||||
{
|
||||
mPlayerClass = &PlayerClasses[classnum];
|
||||
mPlayerState = GetDefaultByType (mPlayerClass->Type)->SeeState;
|
||||
mPlayerTics = mPlayerState->GetTics();
|
||||
mClassNum = classnum;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool FListMenuItemPlayerDisplay::UpdatePlayerClass()
|
||||
{
|
||||
int classnum;
|
||||
FName seltype = mOwner->mItems[mOwner->mSelectedItem]->GetAction(&classnum);
|
||||
|
||||
if (seltype != NAME_Episodemenu) return false;
|
||||
if (PlayerClasses.Size() == 0) return false;
|
||||
|
||||
SetPlayerClass(classnum);
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool FListMenuItemPlayerDisplay::SetValue(int i, int value)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case PDF_MODE:
|
||||
mMode = value;
|
||||
return true;
|
||||
|
||||
case PDF_ROTATION:
|
||||
mRotation = value;
|
||||
return true;
|
||||
|
||||
case PDF_TRANSLATE:
|
||||
mTranslate = value;
|
||||
|
||||
case PDF_CLASS:
|
||||
SetPlayerClass(value, true);
|
||||
break;
|
||||
|
||||
case PDF_SKIN:
|
||||
mSkin = value;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FListMenuItemPlayerDisplay::Ticker()
|
||||
{
|
||||
if (mClassNum < 0) UpdateRandomClass();
|
||||
|
||||
if (mPlayerState != NULL && mPlayerState->GetTics () != -1 && mPlayerState->GetNextState () != NULL)
|
||||
{
|
||||
if (--mPlayerTics <= 0)
|
||||
{
|
||||
mPlayerState = mPlayerState->GetNextState();
|
||||
mPlayerTics = mPlayerState->GetTics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FListMenuItemPlayerDisplay::Drawer(bool selected)
|
||||
{
|
||||
if (mMode == 0 && !UpdatePlayerClass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const char *portrait = mPlayerClass->Type->Meta.GetMetaString(APMETA_Portrait);
|
||||
|
||||
if (portrait != NULL && !mNoportrait)
|
||||
{
|
||||
FTextureID texid = TexMan.CheckForTexture(portrait, FTexture::TEX_MiscPatch);
|
||||
if (texid.isValid())
|
||||
{
|
||||
FTexture *tex = TexMan(texid);
|
||||
if (tex != NULL)
|
||||
{
|
||||
screen->DrawTexture (tex, mXpos, mYpos, DTA_Clean, true, TAG_DONE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1);
|
||||
int y = (mYpos - 100) * CleanYfac + (SCREENHEIGHT>>1);
|
||||
|
||||
screen->DrawTexture (mBackdrop, x, y - 1,
|
||||
DTA_DestWidth, 72 * CleanXfac,
|
||||
DTA_DestHeight, 80 * CleanYfac,
|
||||
DTA_Translation, &mRemap,
|
||||
DTA_Masked, true,
|
||||
TAG_DONE);
|
||||
|
||||
V_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1);
|
||||
|
||||
spriteframe_t *sprframe;
|
||||
fixed_t scaleX, scaleY;
|
||||
|
||||
if (mSkin == 0)
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[mPlayerState->sprite].spriteframes + mPlayerState->GetFrame()];
|
||||
scaleX = GetDefaultByType(mPlayerClass->Type)->scaleX;
|
||||
scaleY = GetDefaultByType(mPlayerClass->Type)->scaleY;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[skins[mSkin].sprite].spriteframes + mPlayerState->GetFrame()];
|
||||
scaleX = skins[mSkin].ScaleX;
|
||||
scaleY = skins[mSkin].ScaleY;
|
||||
}
|
||||
|
||||
if (sprframe != NULL)
|
||||
{
|
||||
FTexture *tex = TexMan(sprframe->Texture[mRotation]);
|
||||
if (tex != NULL && tex->UseType != FTexture::TEX_Null)
|
||||
{
|
||||
FRemapTable *trans = NULL;
|
||||
if (mTranslate) trans = translationtables[TRANSLATION_Players](MAXPLAYERS);
|
||||
screen->DrawTexture (tex,
|
||||
x + 36*CleanXfac, y + 71*CleanYfac,
|
||||
DTA_DestWidth, MulScale16 (tex->GetWidth() * CleanXfac, scaleX),
|
||||
DTA_DestHeight, MulScale16 (tex->GetHeight() * CleanYfac, scaleY),
|
||||
DTA_Translation, trans,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1142
src/menu/playermenu.cpp
Normal file
1142
src/menu/playermenu.cpp
Normal file
File diff suppressed because it is too large
Load diff
154
src/menu/readthis.cpp
Normal file
154
src/menu/readthis.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
** 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 "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)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Read This Menus
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DReadThisMenu::DReadThisMenu(DMenu *parent)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mScreen = 1;
|
||||
mInfoTic = gametic;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DReadThisMenu::Drawer()
|
||||
{
|
||||
FTexture *tex = NULL, *prevpic = NULL;
|
||||
fixed_t alpha;
|
||||
|
||||
// Did the mapper choose a custom help page via MAPINFO?
|
||||
if ((level.info != NULL) && level.info->f1[0] != 0)
|
||||
{
|
||||
tex = TexMan.FindTexture(level.info->f1);
|
||||
mScreen = 1;
|
||||
}
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
tex = TexMan[gameinfo.infoPages[mScreen-1].GetChars()];
|
||||
}
|
||||
|
||||
if (mScreen > 1)
|
||||
{
|
||||
prevpic = TexMan[gameinfo.infoPages[mScreen-2].GetChars()];
|
||||
}
|
||||
|
||||
alpha = MIN<fixed_t> (Scale (gametic - mInfoTic, OPAQUE, TICRATE/3), OPAQUE);
|
||||
if (alpha < OPAQUE && prevpic != NULL)
|
||||
{
|
||||
screen->DrawTexture (prevpic, 0, 0,
|
||||
DTA_DestWidth, screen->GetWidth(),
|
||||
DTA_DestHeight, screen->GetHeight(),
|
||||
TAG_DONE);
|
||||
}
|
||||
screen->DrawTexture (tex, 0, 0,
|
||||
DTA_DestWidth, screen->GetWidth(),
|
||||
DTA_DestHeight, screen->GetHeight(),
|
||||
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->f1[0] != 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;
|
||||
}
|
||||
|
442
src/menu/videomenu.cpp
Normal file
442
src/menu/videomenu.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
** videomenu.cpp
|
||||
** The video modes menu
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** 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 <float.h>
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "w_wad.h"
|
||||
#include "sc_man.h"
|
||||
#include "v_font.h"
|
||||
#include "g_level.h"
|
||||
#include "d_player.h"
|
||||
#include "v_video.h"
|
||||
#include "gi.h"
|
||||
#include "i_system.h"
|
||||
#include "c_bind.h"
|
||||
#include "v_palette.h"
|
||||
#include "d_event.h"
|
||||
#include "d_gui.h"
|
||||
#include "i_music.h"
|
||||
#include "m_joy.h"
|
||||
#include "sbar.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#define NO_IMP
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Video Modes Menu
|
||||
*
|
||||
*=======================================*/
|
||||
static void BuildModesList (int hiwidth, int hiheight, int hi_id);
|
||||
static bool GetSelectedSize (int *width, int *height);
|
||||
static void SetModesMenu (int w, int h, int bits);
|
||||
FOptionMenuDescriptor *GetVideoModeMenu();
|
||||
|
||||
extern bool setmodeneeded;
|
||||
extern int NewWidth, NewHeight, NewBits;
|
||||
extern int DisplayBits;
|
||||
|
||||
EXTERN_CVAR (Int, vid_defwidth)
|
||||
EXTERN_CVAR (Int, vid_defheight)
|
||||
EXTERN_CVAR (Int, vid_defbits)
|
||||
EXTERN_CVAR (Bool, fullscreen)
|
||||
EXTERN_CVAR (Bool, vid_tft) // Defined below
|
||||
|
||||
int testingmode; // Holds time to revert to old mode
|
||||
int OldWidth, OldHeight, OldBits;
|
||||
static FIntCVar DummyDepthCvar (NULL, 0, 0);
|
||||
static BYTE BitTranslate[32];
|
||||
|
||||
CUSTOM_CVAR (Int, menu_screenratios, 0, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0 || self > 4)
|
||||
{
|
||||
self = 3;
|
||||
}
|
||||
else if (self == 4 && !vid_tft)
|
||||
{
|
||||
self = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildModesList (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR (Bool, vid_tft, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
FOptionMenuDescriptor *opt = GetVideoModeMenu();
|
||||
if (opt != NULL)
|
||||
{
|
||||
FOptionMenuItem *it = opt->GetItem("menu_screenratios");
|
||||
if (it != NULL)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
it->SetString(FOptionMenuItemOptionBase::OP_VALUES, "RatiosTFT");
|
||||
}
|
||||
else
|
||||
{
|
||||
it->SetString(FOptionMenuItemOptionBase::OP_VALUES, "Ratios");
|
||||
}
|
||||
}
|
||||
}
|
||||
setsizeneeded = true;
|
||||
if (StatusBar != NULL)
|
||||
{
|
||||
StatusBar->ScreenSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DVideoModeMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DVideoModeMenu, DOptionMenu)
|
||||
|
||||
public:
|
||||
|
||||
DVideoModeMenu()
|
||||
{
|
||||
SetModesMenu (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
|
||||
}
|
||||
|
||||
bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if ((mkey == MKEY_Up || mkey == MKEY_Down) && mDesc->mSelectedItem >= 0 &&
|
||||
mDesc->mSelectedItem < (int)mDesc->mItems.Size())
|
||||
{
|
||||
int sel;
|
||||
bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, &sel);
|
||||
bool res = Super::MenuEvent(mkey, fromcontroller);
|
||||
if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, sel);
|
||||
return res;
|
||||
}
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
bool Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown &&
|
||||
(ev->data1 == 't' || ev->data1 == 'T'))
|
||||
{
|
||||
if (!GetSelectedSize (&NewWidth, &NewHeight))
|
||||
{
|
||||
NewWidth = SCREENWIDTH;
|
||||
NewHeight = SCREENHEIGHT;
|
||||
}
|
||||
OldWidth = SCREENWIDTH;
|
||||
OldHeight = SCREENHEIGHT;
|
||||
OldBits = DisplayBits;
|
||||
NewBits = BitTranslate[DummyDepthCvar];
|
||||
setmodeneeded = true;
|
||||
testingmode = I_GetTime(false) + 5 * TICRATE;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
SetModesMenu (NewWidth, NewHeight, NewBits);
|
||||
return true;
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DVideoModeMenu)
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FOptionMenuDescriptor *GetVideoModeMenu()
|
||||
{
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_VideoModeMenu);
|
||||
if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
|
||||
{
|
||||
return (FOptionMenuDescriptor *)*desc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Set some stuff up for the video modes menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
|
||||
{
|
||||
char strtemp[32];
|
||||
int i, c;
|
||||
int width, height, showbits;
|
||||
bool letterbox=false;
|
||||
int ratiomatch;
|
||||
|
||||
if (menu_screenratios >= 0 && menu_screenratios <= 4 && menu_screenratios != 3)
|
||||
{
|
||||
ratiomatch = menu_screenratios;
|
||||
}
|
||||
else
|
||||
{
|
||||
ratiomatch = -1;
|
||||
}
|
||||
showbits = BitTranslate[DummyDepthCvar];
|
||||
|
||||
if (Video != NULL)
|
||||
{
|
||||
Video->StartModeIterator (showbits, screen->IsFullscreen());
|
||||
}
|
||||
|
||||
FOptionMenuDescriptor *opt = GetVideoModeMenu();
|
||||
if (opt != NULL)
|
||||
{
|
||||
for (i = NAME_res_0; i<= NAME_res_9; i++)
|
||||
{
|
||||
FOptionMenuItem *it = opt->GetItem((ENamedName)i);
|
||||
if (it != NULL)
|
||||
{
|
||||
it->SetValue(FOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, -1);
|
||||
for (c = 0; c < 3; c++)
|
||||
{
|
||||
bool haveMode = false;
|
||||
|
||||
if (Video != NULL)
|
||||
{
|
||||
while ((haveMode = Video->NextMode (&width, &height, &letterbox)) &&
|
||||
(ratiomatch >= 0 && CheckRatio (width, height) != ratiomatch))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (haveMode)
|
||||
{
|
||||
if (width == hiwidth && height == hiheight)
|
||||
{
|
||||
it->SetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, c);
|
||||
it->SetValue(FOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, c);
|
||||
}
|
||||
|
||||
mysnprintf (strtemp, countof(strtemp), "%dx%d%s", width, height, letterbox?TEXTCOLOR_BROWN" LB":"");
|
||||
it->SetString(FOptionMenuScreenResolutionLine::SRL_INDEX+c, strtemp);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->SetString(FOptionMenuScreenResolutionLine::SRL_INDEX+c, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_RestoreMode ()
|
||||
{
|
||||
NewWidth = OldWidth;
|
||||
NewHeight = OldHeight;
|
||||
NewBits = OldBits;
|
||||
setmodeneeded = true;
|
||||
testingmode = 0;
|
||||
SetModesMenu (OldWidth, OldHeight, OldBits);
|
||||
}
|
||||
|
||||
void M_SetDefaultMode ()
|
||||
{
|
||||
// Make current resolution the default
|
||||
vid_defwidth = SCREENWIDTH;
|
||||
vid_defheight = SCREENHEIGHT;
|
||||
vid_defbits = DisplayBits;
|
||||
testingmode = 0;
|
||||
SetModesMenu (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_RefreshModesList ()
|
||||
{
|
||||
BuildModesList (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
|
||||
}
|
||||
|
||||
void M_InitVideoModesMenu ()
|
||||
{
|
||||
int dummy1, dummy2;
|
||||
size_t currval = 0;
|
||||
|
||||
M_RefreshModesList();
|
||||
|
||||
for (unsigned int i = 1; i <= 32 && currval < countof(BitTranslate); i++)
|
||||
{
|
||||
Video->StartModeIterator (i, screen->IsFullscreen());
|
||||
if (Video->NextMode (&dummy1, &dummy2, NULL))
|
||||
{
|
||||
BitTranslate[currval++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* It doesn't look like this can be anything but DISPLAY_Both, regardless of any other settings.
|
||||
switch (Video->GetDisplayType ())
|
||||
{
|
||||
case DISPLAY_FullscreenOnly:
|
||||
case DISPLAY_WindowOnly:
|
||||
// todo: gray out fullscreen option
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static bool GetSelectedSize (int *width, int *height)
|
||||
{
|
||||
FOptionMenuDescriptor *opt = GetVideoModeMenu();
|
||||
if (opt != NULL)
|
||||
{
|
||||
int line = opt->mSelectedItem;
|
||||
int hsel;
|
||||
FOptionMenuItem *it = opt->mItems[line];
|
||||
if (it->GetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, &hsel))
|
||||
{
|
||||
char buffer[32];
|
||||
char *breakpt;
|
||||
if (it->GetString(FOptionMenuScreenResolutionLine::SRL_INDEX+hsel, buffer, sizeof(buffer)))
|
||||
{
|
||||
*width = strtol (buffer, &breakpt, 10);
|
||||
*height = strtol (breakpt+1, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_SetVideoMode()
|
||||
{
|
||||
if (!GetSelectedSize (&NewWidth, &NewHeight))
|
||||
{
|
||||
NewWidth = SCREENWIDTH;
|
||||
NewHeight = SCREENHEIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
testingmode = 1;
|
||||
setmodeneeded = true;
|
||||
NewBits = BitTranslate[DummyDepthCvar];
|
||||
}
|
||||
SetModesMenu (NewWidth, NewHeight, NewBits);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static int FindBits (int bits)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 22; i++)
|
||||
{
|
||||
if (BitTranslate[i] == bits)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetModesMenu (int w, int h, int bits)
|
||||
{
|
||||
DummyDepthCvar = FindBits (bits);
|
||||
|
||||
FOptionMenuDescriptor *opt = GetVideoModeMenu();
|
||||
if (opt != NULL)
|
||||
{
|
||||
FOptionMenuItem *it;
|
||||
if (testingmode <= 1)
|
||||
{
|
||||
it = opt->GetItem(NAME_VMEnterText);
|
||||
if (it != NULL) it->SetValue(0, 0);
|
||||
it = opt->GetItem(NAME_VMTestText);
|
||||
if (it != NULL) it->SetValue(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
it = opt->GetItem(NAME_VMTestText);
|
||||
if (it != NULL) it->SetValue(0, 1);
|
||||
it = opt->GetItem(NAME_VMEnterText);
|
||||
if (it != NULL)
|
||||
{
|
||||
char strtemp[64];
|
||||
mysnprintf (strtemp, countof(strtemp), "TESTING %dx%dx%d", w, h, bits);
|
||||
it->SetValue(0, 1);
|
||||
it->SetString(0, strtemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
BuildModesList (w, h, bits);
|
||||
}
|
|
@ -465,3 +465,64 @@ xx(Dialog)
|
|||
xx(Ifitem)
|
||||
xx(Choice)
|
||||
xx(Link)
|
||||
|
||||
// Special menus
|
||||
xx(Mainmenu)
|
||||
xx(Episodemenu)
|
||||
xx(Playerclassmenu)
|
||||
xx(HexenDefaultPlayerclassmenu)
|
||||
xx(Skillmenu)
|
||||
xx(Startgame)
|
||||
xx(StartgameConfirm)
|
||||
xx(Loadgamemenu)
|
||||
xx(Savegamemenu)
|
||||
xx(Readthismenu)
|
||||
xx(Optionsmenu)
|
||||
xx(Quitmenu)
|
||||
xx(Savemenu)
|
||||
xx(Playermenu)
|
||||
|
||||
xx(Playerbox)
|
||||
xx(Team)
|
||||
xx(Color)
|
||||
xx(Red)
|
||||
xx(Green)
|
||||
xx(Blue)
|
||||
xx(Class)
|
||||
xx(Skin)
|
||||
xx(Gender)
|
||||
xx(Autoaim)
|
||||
xx(Switch)
|
||||
xx(Playerdisplay)
|
||||
xx(Controlmessage)
|
||||
xx(Crosshairs)
|
||||
xx(Colorpickermenu)
|
||||
xx(Mididevices)
|
||||
xx(CustomizeControls)
|
||||
xx(MessageOptions)
|
||||
xx(AutomapOptions)
|
||||
xx(ScoreboardOptions)
|
||||
xx(MapColorMenu)
|
||||
xx(GameplayOptions)
|
||||
xx(CompatibilityOptions)
|
||||
xx(MouseOptions)
|
||||
xx(JoystickOptions)
|
||||
xx(SoundOptions)
|
||||
xx(AdvSoundOptions)
|
||||
xx(ModReplayerOptions)
|
||||
xx(VideoOptions)
|
||||
xx(JoystickConfigMenu)
|
||||
xx(VMEnterText)
|
||||
xx(VMTestText)
|
||||
xx(VideoModeMenu)
|
||||
xx(res_0)
|
||||
xx(res_1)
|
||||
xx(res_2)
|
||||
xx(res_3)
|
||||
xx(res_4)
|
||||
xx(res_5)
|
||||
xx(res_6)
|
||||
xx(res_7)
|
||||
xx(res_8)
|
||||
xx(res_9)
|
||||
xx(AlwaysRun)
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_menu.h"
|
||||
#include "v_text.h"
|
||||
#include "v_video.h"
|
||||
#include "m_random.h"
|
||||
|
@ -56,11 +55,13 @@
|
|||
#include "d_net.h"
|
||||
#include "g_level.h"
|
||||
#include "d_event.h"
|
||||
#include "d_gui.h"
|
||||
#include "doomstat.h"
|
||||
#include "c_console.h"
|
||||
#include "sbar.h"
|
||||
#include "farchive.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
// The conversations as they exist inside a SCRIPTxx lump.
|
||||
struct Response
|
||||
|
@ -112,9 +113,8 @@ typedef TMap<FName, int> FDialogueMap; // maps actor class names to dialogue
|
|||
static FStrifeTypeMap StrifeTypes;
|
||||
static FDialogueIDMap DialogueRoots;
|
||||
static FDialogueMap ClassRoots;
|
||||
static int ConversationMenuY;
|
||||
|
||||
static menu_t ConversationMenu;
|
||||
static TArray<menuitem_t> ConversationItems;
|
||||
static int ConversationPauseTic;
|
||||
static bool ShowGold;
|
||||
|
||||
|
@ -123,13 +123,11 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeaker
|
|||
static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeakerType);
|
||||
static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses);
|
||||
static bool DrawConversationMenu ();
|
||||
static void PickConversationReply ();
|
||||
static void PickConversationReply (int replyindex);
|
||||
static void CleanupConversationMenu ();
|
||||
static void ConversationMenuEscaped ();
|
||||
static void TerminalResponse (const char *str);
|
||||
|
||||
static FStrifeDialogueNode *CurNode, *PrevNode;
|
||||
static FBrokenLines *DialogueLines;
|
||||
static FStrifeDialogueNode *PrevNode;
|
||||
|
||||
#define NUM_RANDOM_LINES 10
|
||||
#define NUM_RANDOM_GOODBYES 3
|
||||
|
@ -233,7 +231,6 @@ void P_FreeStrifeConversations ()
|
|||
DialogueRoots.Clear();
|
||||
ClassRoots.Clear();
|
||||
|
||||
CurNode = NULL;
|
||||
PrevNode = NULL;
|
||||
}
|
||||
|
||||
|
@ -541,10 +538,6 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
reply->ItemCheck[k].Amount = rsp->Count[k];
|
||||
}
|
||||
|
||||
// ReplyLines is calculated when the menu is shown. It is just Reply
|
||||
// with word wrap turned on.
|
||||
reply->ReplyLines = NULL;
|
||||
|
||||
// If the first item check has a positive amount required, then
|
||||
// add that to the reply string. Otherwise, use the reply as-is.
|
||||
if (rsp->Count[0] > 0)
|
||||
|
@ -615,7 +608,6 @@ FStrifeDialogueReply::~FStrifeDialogueReply ()
|
|||
if (Reply != NULL) delete[] Reply;
|
||||
if (QuickYes != NULL) delete[] QuickYes;
|
||||
if (QuickNo != NULL) delete[] QuickNo;
|
||||
if (ReplyLines != NULL) V_FreeBrokenLines (ReplyLines);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -703,6 +695,372 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
|
|||
else if (self > 1.f) self = 1.f;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// The conversation menu
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
class DConversationMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DConversationMenu, DMenu)
|
||||
|
||||
FString mSpeaker;
|
||||
FBrokenLines *mDialogueLines;
|
||||
TArray<FString> mResponseLines;
|
||||
TArray<unsigned int> mResponses;
|
||||
bool mShowGold;
|
||||
FStrifeDialogueNode *mCurNode;
|
||||
int mYpos;
|
||||
|
||||
public:
|
||||
static int mSelection;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DConversationMenu(FStrifeDialogueNode *CurNode)
|
||||
{
|
||||
menuactive = MENU_OnNoPause;
|
||||
mCurNode = CurNode;
|
||||
mDialogueLines = NULL;
|
||||
mShowGold = false;
|
||||
|
||||
// Format the speaker's message.
|
||||
const char * toSay = CurNode->Dialogue;
|
||||
if (strncmp (toSay, "RANDOM_", 7) == 0)
|
||||
{
|
||||
FString dlgtext;
|
||||
|
||||
dlgtext.Format("TXT_%s_%02d", toSay, 1+(pr_randomspeech() % NUM_RANDOM_LINES));
|
||||
toSay = GStrings[dlgtext];
|
||||
if (toSay == NULL)
|
||||
{
|
||||
toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle string table replacement
|
||||
if (toSay[0] == '$')
|
||||
{
|
||||
toSay = GStrings(toSay + 1);
|
||||
}
|
||||
}
|
||||
if (toSay == NULL)
|
||||
{
|
||||
toSay = ".";
|
||||
}
|
||||
mDialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay);
|
||||
|
||||
FStrifeDialogueReply *reply;
|
||||
int i,j;
|
||||
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
||||
{
|
||||
if (reply->Reply == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
mShowGold |= reply->NeedsGold;
|
||||
|
||||
const char *ReplyText = reply->Reply;
|
||||
if (ReplyText[0] == '$')
|
||||
{
|
||||
ReplyText = GStrings(ReplyText + 1);
|
||||
}
|
||||
FBrokenLines *ReplyLines = V_BreakLines (SmallFont, 320-50-10, ReplyText);
|
||||
|
||||
mResponses.Push(mResponseLines.Size());
|
||||
for (j = 0; ReplyLines[j].Width >= 0; ++j)
|
||||
{
|
||||
mResponseLines.Push(ReplyLines[j].Text);
|
||||
}
|
||||
++i;
|
||||
V_FreeBrokenLines (ReplyLines);
|
||||
}
|
||||
char goodbye[25];
|
||||
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1+(pr_randomspeech() % NUM_RANDOM_GOODBYES));
|
||||
const char *goodbyestr = GStrings[goodbye];
|
||||
if (goodbyestr == NULL) goodbyestr = "Bye.";
|
||||
mResponses.Push(mResponseLines.Size());
|
||||
mResponseLines.Push(FString(goodbyestr));
|
||||
|
||||
// Determine where the top of the reply list should be positioned.
|
||||
i = OptionSettings.mLinespacing;
|
||||
mYpos = MIN<int> (140, 192 - mResponseLines.Size() * i);
|
||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
||||
{ }
|
||||
i = 44 + i * 10;
|
||||
if (mYpos - 100 < i - screen->GetHeight() / CleanYfac / 2)
|
||||
{
|
||||
mYpos = i - screen->GetHeight() / CleanYfac / 2 + 100;
|
||||
}
|
||||
ConversationMenuY = mYpos;
|
||||
//ConversationMenu.indent = 50;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
V_FreeBrokenLines(mDialogueLines);
|
||||
mDialogueLines = NULL;
|
||||
I_SetMusicVolume (1.f);
|
||||
}
|
||||
|
||||
bool DimAllowed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Up)
|
||||
{
|
||||
if (--mSelection < 0) mSelection = mResponses.Size() - 1;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Down)
|
||||
{
|
||||
if (++mSelection >= (int)mResponses.Size()) mSelection = 0;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
if ((unsigned)mSelection >= mResponses.Size())
|
||||
{
|
||||
Net_WriteByte(DEM_CONVCLOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send dialogue and reply numbers across the wire.
|
||||
assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size());
|
||||
assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode);
|
||||
Net_WriteByte(DEM_CONVREPLY);
|
||||
Net_WriteWord(mCurNode->ThisNodeNum);
|
||||
Net_WriteByte(mSelection);
|
||||
}
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = SmallFont->GetHeight();
|
||||
|
||||
// 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 >= 24 && x <= 320-24 && y >= mYpos && y < mYpos + fh * (int)mResponseLines.Size())
|
||||
{
|
||||
sel = (y - mYpos) / fh;
|
||||
for(unsigned i=0;i<mResponses.Size(); i++)
|
||||
{
|
||||
if ((int)mResponses[i] > sel)
|
||||
{
|
||||
sel = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sel != -1 && sel != mSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_Char && ev->data1 >= '0' && ev->data1 <= '9')
|
||||
{ // Activate an item of type numberedmore (dialogue only)
|
||||
mSelection = ev->data1 == '0' ? 10 : ev->data1 - '0';
|
||||
return MenuEvent(MKEY_Enter, false);
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// DrawConversationMenu
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void Drawer()
|
||||
{
|
||||
const char *speakerName;
|
||||
int i, x, y, linesize;
|
||||
int width, fontheight;
|
||||
int labelofs;
|
||||
|
||||
player_t *cp = &players[consoleplayer];
|
||||
|
||||
assert (mDialogueLines != NULL);
|
||||
assert (mCurNode != NULL);
|
||||
|
||||
FStrifeDialogueNode *CurNode = mCurNode;
|
||||
|
||||
if (CurNode == NULL)
|
||||
{
|
||||
Close ();
|
||||
return;
|
||||
}
|
||||
|
||||
// [CW] Freeze the game depending on MAPINFO options.
|
||||
if (ConversationPauseTic < gametic && !multiplayer && !(level.flags2 & LEVEL2_CONV_SINGLE_UNFREEZE))
|
||||
{
|
||||
menuactive = MENU_On;
|
||||
}
|
||||
|
||||
if (CurNode->Backdrop.isValid())
|
||||
{
|
||||
screen->DrawTexture (TexMan(CurNode->Backdrop), 0, 0, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
x = 16 * screen->GetWidth() / 320;
|
||||
y = 16 * screen->GetHeight() / 200;
|
||||
linesize = 10 * CleanYfac;
|
||||
|
||||
// Who is talking to you?
|
||||
if (CurNode->SpeakerName != NULL)
|
||||
{
|
||||
speakerName = CurNode->SpeakerName;
|
||||
}
|
||||
else
|
||||
{
|
||||
speakerName = cp->ConversationNPC->GetTag("Person");
|
||||
}
|
||||
|
||||
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
||||
if (!CurNode->Backdrop.isValid())
|
||||
{
|
||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
||||
{ }
|
||||
screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200,
|
||||
308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320,
|
||||
speakerName == NULL ? linesize * i + 6 * CleanYfac
|
||||
: linesize * i + 6 * CleanYfac + linesize * 3/2);
|
||||
}
|
||||
|
||||
// Dim the screen behind the PC's choices.
|
||||
|
||||
screen->Dim (0, 0.45f, (24-160) * CleanXfac + screen->GetWidth()/2,
|
||||
(mYpos - 2 - 100) * CleanYfac + screen->GetHeight()/2,
|
||||
272 * CleanXfac,
|
||||
MIN<int>(mResponseLines.Size() * OptionSettings.mLinespacing + 4, 200 - mYpos) * CleanYfac);
|
||||
|
||||
if (speakerName != NULL)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_WHITE, x, y, speakerName,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
y += linesize * 3 / 2;
|
||||
}
|
||||
x = 24 * screen->GetWidth() / 320;
|
||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, x, y, mDialogueLines[i].Text,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
y += linesize;
|
||||
}
|
||||
|
||||
if (ShowGold)
|
||||
{
|
||||
AInventory *coin = cp->ConversationPC->FindInventory (RUNTIME_CLASS(ACoin));
|
||||
char goldstr[32];
|
||||
|
||||
mysnprintf (goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0);
|
||||
screen->DrawText (SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon),
|
||||
3, 190, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE);
|
||||
screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon),
|
||||
2, 189, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
|
||||
y = mYpos;
|
||||
labelofs = OptionSettings.mLabelOffset;
|
||||
y -= labelofs;
|
||||
fontheight = OptionSettings.mLinespacing;
|
||||
|
||||
int response = 0;
|
||||
for (i = 0; i < (int)mResponseLines.Size(); i++, y += fontheight)
|
||||
{
|
||||
width = SmallFont->StringWidth(mResponseLines[i]);
|
||||
x = 64;
|
||||
|
||||
screen->DrawText (SmallFont, CR_GREEN, x, y, mResponseLines[i], DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (i == mResponses[response])
|
||||
{
|
||||
char tbuf[16];
|
||||
|
||||
response++;
|
||||
mysnprintf (tbuf, countof(tbuf), "%d.", response);
|
||||
x = 50 - SmallFont->StringWidth (tbuf);
|
||||
screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (response == mSelection+1)
|
||||
{
|
||||
int color = ((DMenu::MenuTime%8) < 4) || DMenu::CurrentMenu != this ? CR_RED:CR_GREY;
|
||||
|
||||
x = (50 + 3 - 160) * CleanXfac + screen->GetWidth() / 2;
|
||||
int yy = (y-1+labelofs - 100) * CleanYfac + screen->GetHeight() / 2;
|
||||
screen->DrawText (ConFont, color, x, yy, "\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(DConversationMenu)
|
||||
int DConversationMenu::mSelection; // needs to be preserved if the same dialogue is restarted
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_StartConversation
|
||||
|
@ -714,10 +1072,7 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
|
|||
void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveangle)
|
||||
{
|
||||
AActor *oldtarget;
|
||||
FStrifeDialogueReply *reply;
|
||||
menuitem_t item;
|
||||
const char *toSay;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
// Make sure this is actually a player.
|
||||
if (pc->player == NULL) return;
|
||||
|
@ -798,102 +1153,19 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
|
|||
S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
// Set up the menu
|
||||
::CurNode = CurNode; // only set the global variable for the consoleplayer
|
||||
ConversationMenu.PreDraw = DrawConversationMenu;
|
||||
ConversationMenu.EscapeHandler = ConversationMenuEscaped;
|
||||
DConversationMenu *cmenu = new DConversationMenu(CurNode);
|
||||
|
||||
// Format the speaker's message.
|
||||
toSay = CurNode->Dialogue;
|
||||
if (strncmp (toSay, "RANDOM_", 7) == 0)
|
||||
{
|
||||
FString dlgtext;
|
||||
|
||||
dlgtext.Format("TXT_%s_%02d", toSay, 1+(pr_randomspeech() % NUM_RANDOM_LINES));
|
||||
toSay = GStrings[dlgtext];
|
||||
if (toSay == NULL)
|
||||
{
|
||||
toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle string table replacement
|
||||
if (toSay[0] == '$')
|
||||
{
|
||||
toSay = GStrings(toSay + 1);
|
||||
}
|
||||
}
|
||||
if (toSay == NULL)
|
||||
{
|
||||
toSay = ".";
|
||||
}
|
||||
DialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay);
|
||||
|
||||
// Fill out the possible choices
|
||||
ShowGold = false;
|
||||
item.type = numberedmore;
|
||||
item.e.mfunc = PickConversationReply;
|
||||
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
||||
{
|
||||
if (reply->Reply == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ShowGold |= reply->NeedsGold;
|
||||
reply->ReplyLines = V_BreakLines (SmallFont, 320-50-10, reply->Reply);
|
||||
for (j = 0; reply->ReplyLines[j].Width >= 0; ++j)
|
||||
{
|
||||
item.label = reply->ReplyLines[j].Text.LockBuffer();
|
||||
// handle string table replacement
|
||||
if (item.label[0] == '$')
|
||||
{
|
||||
item.label = GStrings(item.label + 1);
|
||||
}
|
||||
|
||||
item.b.position = j == 0 ? i : 0;
|
||||
item.c.extra = reply;
|
||||
ConversationItems.Push (item);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
char goodbye[25];
|
||||
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1+(pr_randomspeech() % NUM_RANDOM_GOODBYES));
|
||||
item.label = (char*)GStrings[goodbye];
|
||||
if (item.label == NULL) item.label = "Bye.";
|
||||
item.b.position = i;
|
||||
item.c.extra = NULL;
|
||||
ConversationItems.Push (item);
|
||||
|
||||
// Determine where the top of the reply list should be positioned.
|
||||
i = (gameinfo.gametype & GAME_Raven) ? 9 : 8;
|
||||
ConversationMenu.y = MIN<int> (140, 192 - ConversationItems.Size() * i);
|
||||
for (i = 0; DialogueLines[i].Width >= 0; ++i)
|
||||
{ }
|
||||
i = 44 + i * 10;
|
||||
if (ConversationMenu.y - 100 < i - screen->GetHeight() / CleanYfac / 2)
|
||||
{
|
||||
ConversationMenu.y = i - screen->GetHeight() / CleanYfac / 2 + 100;
|
||||
}
|
||||
ConversationMenu.indent = 50;
|
||||
|
||||
// Finish setting up the menu
|
||||
ConversationMenu.items = &ConversationItems[0];
|
||||
ConversationMenu.numitems = ConversationItems.Size();
|
||||
if (CurNode != PrevNode)
|
||||
{ // Only reset the selection if showing a different menu.
|
||||
ConversationMenu.lastOn = 0;
|
||||
DConversationMenu::mSelection = 0;
|
||||
PrevNode = CurNode;
|
||||
}
|
||||
ConversationMenu.DontDim = true;
|
||||
|
||||
// And open the menu
|
||||
M_StartControlPanel (false);
|
||||
OptionsActive = true;
|
||||
menuactive = MENU_OnNoPause;
|
||||
M_ActivateMenu(cmenu);
|
||||
ConversationPauseTic = gametic + 20;
|
||||
|
||||
M_SwitchMenu (&ConversationMenu);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -921,193 +1193,6 @@ void P_ResumeConversation ()
|
|||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// DrawConversationMenu
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
static bool DrawConversationMenu ()
|
||||
{
|
||||
const char *speakerName;
|
||||
int i, x, y, linesize;
|
||||
int width, fontheight;
|
||||
menuitem_t *item;
|
||||
int labelofs;
|
||||
|
||||
player_t *cp = &players[consoleplayer];
|
||||
|
||||
assert (DialogueLines != NULL);
|
||||
assert (CurNode != NULL);
|
||||
|
||||
if (CurNode == NULL)
|
||||
{
|
||||
M_ClearMenus ();
|
||||
return true;
|
||||
}
|
||||
|
||||
// [CW] Freeze the game depending on MAPINFO options.
|
||||
if (ConversationPauseTic < gametic && !multiplayer && !(level.flags2 & LEVEL2_CONV_SINGLE_UNFREEZE))
|
||||
{
|
||||
menuactive = MENU_On;
|
||||
}
|
||||
|
||||
if (CurNode->Backdrop.isValid())
|
||||
{
|
||||
screen->DrawTexture (TexMan(CurNode->Backdrop), 0, 0, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
x = 16 * screen->GetWidth() / 320;
|
||||
y = 16 * screen->GetHeight() / 200;
|
||||
linesize = 10 * CleanYfac;
|
||||
|
||||
// Who is talking to you?
|
||||
if (CurNode->SpeakerName != NULL)
|
||||
{
|
||||
speakerName = CurNode->SpeakerName;
|
||||
}
|
||||
else
|
||||
{
|
||||
speakerName = cp->ConversationNPC->GetTag("Person");
|
||||
}
|
||||
|
||||
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
||||
if (!CurNode->Backdrop.isValid())
|
||||
{
|
||||
for (i = 0; DialogueLines[i].Width >= 0; ++i)
|
||||
{ }
|
||||
screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200,
|
||||
308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320,
|
||||
speakerName == NULL ? linesize * i + 6 * CleanYfac
|
||||
: linesize * i + 6 * CleanYfac + linesize * 3/2);
|
||||
}
|
||||
|
||||
// Dim the screen behind the PC's choices.
|
||||
screen->Dim (0, 0.45f, (24-160) * CleanXfac + screen->GetWidth()/2,
|
||||
(ConversationMenu.y - 2 - 100) * CleanYfac + screen->GetHeight()/2,
|
||||
272 * CleanXfac,
|
||||
MIN(ConversationMenu.numitems * (gameinfo.gametype & GAME_Raven ? 9 : 8) + 4,
|
||||
200 - ConversationMenu.y) * CleanYfac);
|
||||
|
||||
if (speakerName != NULL)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_WHITE, x, y, speakerName,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
y += linesize * 3 / 2;
|
||||
}
|
||||
x = 24 * screen->GetWidth() / 320;
|
||||
for (i = 0; DialogueLines[i].Width >= 0; ++i)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, x, y, DialogueLines[i].Text,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
y += linesize;
|
||||
}
|
||||
|
||||
if (ShowGold)
|
||||
{
|
||||
AInventory *coin = cp->ConversationPC->FindInventory (RUNTIME_CLASS(ACoin));
|
||||
char goldstr[32];
|
||||
|
||||
mysnprintf (goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0);
|
||||
screen->DrawText (SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon),
|
||||
3, 190, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE);
|
||||
screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon),
|
||||
2, 189, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
|
||||
y = CurrentMenu->y;
|
||||
|
||||
if (gameinfo.gametype & GAME_Raven)
|
||||
{
|
||||
labelofs = 2;
|
||||
y -= 2;
|
||||
fontheight = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
labelofs = 0;
|
||||
fontheight = 8;
|
||||
}
|
||||
for (i = 0; i < CurrentMenu->numitems; i++, y += fontheight)
|
||||
{
|
||||
item = CurrentMenu->items + i;
|
||||
|
||||
width = SmallFont->StringWidth(item->label);
|
||||
x = CurrentMenu->indent + 14;
|
||||
|
||||
screen->DrawText (SmallFont, CR_GREEN, x, y, item->label, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (item->b.position != 0)
|
||||
{
|
||||
char tbuf[16];
|
||||
|
||||
mysnprintf (tbuf, countof(tbuf), "%d.", item->b.position);
|
||||
x = CurrentMenu->indent - SmallFont->StringWidth (tbuf);
|
||||
screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
|
||||
if (i == CurrentItem &&
|
||||
(skullAnimCounter < 6 || menuactive == MENU_WaitKey))
|
||||
{
|
||||
int x = (CurrentMenu->indent + 3 - 160) * CleanXfac + screen->GetWidth() / 2;
|
||||
int yy = (y-1+labelofs - 100) * CleanYfac + screen->GetHeight() / 2;
|
||||
screen->DrawText (ConFont, CR_RED, x, yy, "\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// PickConversationReply
|
||||
//
|
||||
// Run only on the local machine with the conversation menu up.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
static void PickConversationReply ()
|
||||
{
|
||||
FStrifeDialogueReply *reply = (FStrifeDialogueReply *)ConversationItems[ConversationMenu.lastOn].c.extra;
|
||||
FStrifeDialogueReply *replyscan;
|
||||
int replynum = 0;
|
||||
|
||||
assert(CurNode->ThisNodeNum >= 0 && CurNode->ThisNodeNum < 65536);
|
||||
assert(StrifeDialogues[CurNode->ThisNodeNum] == CurNode);
|
||||
|
||||
// Determine reply number for netcode.
|
||||
if (reply == NULL)
|
||||
{
|
||||
replyscan = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (replyscan = CurNode->Children; replyscan != NULL && replyscan != reply; ++replynum, replyscan = replyscan->Next)
|
||||
{ }
|
||||
}
|
||||
|
||||
M_ClearMenus ();
|
||||
if (replyscan == NULL)
|
||||
{
|
||||
Net_WriteByte(DEM_CONVCLOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send dialogue and reply numbers across the wire.
|
||||
assert(replynum < 256);
|
||||
Net_WriteByte(DEM_CONVREPLY);
|
||||
Net_WriteWord(CurNode->ThisNodeNum);
|
||||
Net_WriteByte(replynum);
|
||||
}
|
||||
CleanupConversationMenu ();
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// HandleReply
|
||||
|
@ -1307,27 +1392,6 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
|||
|
||||
void CleanupConversationMenu ()
|
||||
{
|
||||
FStrifeDialogueReply *reply;
|
||||
|
||||
if (CurNode != NULL)
|
||||
{
|
||||
for (reply = CurNode->Children; reply != NULL; reply = reply->Next)
|
||||
{
|
||||
if (reply->ReplyLines != NULL)
|
||||
{
|
||||
V_FreeBrokenLines (reply->ReplyLines);
|
||||
reply->ReplyLines = NULL;
|
||||
}
|
||||
}
|
||||
CurNode = NULL;
|
||||
}
|
||||
if (DialogueLines != NULL)
|
||||
{
|
||||
V_FreeBrokenLines (DialogueLines);
|
||||
DialogueLines = NULL;
|
||||
}
|
||||
ConversationItems.Clear ();
|
||||
I_SetMusicVolume (1.f);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -1408,7 +1472,7 @@ static void TerminalResponse (const char *str)
|
|||
// their dialogue screen. I think most other conversations use this
|
||||
// only as a response for terminating the dialogue.
|
||||
StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, str,
|
||||
float(CleanWidth/2) + 0.4f, float(ConversationMenu.y - 110 + CleanHeight/2), CleanWidth, -CleanHeight,
|
||||
float(CleanWidth/2) + 0.4f, float(ConversationMenuY - 110 + CleanHeight/2), CleanWidth, -CleanHeight,
|
||||
CR_UNTRANSLATED, 3, 1), MAKE_ID('T','A','L','K'));
|
||||
}
|
||||
else
|
||||
|
|
|
@ -48,8 +48,6 @@ struct FStrifeDialogueReply
|
|||
char *LogString;
|
||||
char *QuickNo;
|
||||
bool NeedsGold;
|
||||
|
||||
FBrokenLines *ReplyLines;
|
||||
};
|
||||
|
||||
extern TArray<FStrifeDialogueNode *> StrifeDialogues;
|
||||
|
|
|
@ -1961,7 +1961,7 @@ void R_DrawBorder (int x1, int y1, int x2, int y2)
|
|||
int BorderNeedRefresh;
|
||||
|
||||
void V_MarkRect (int x, int y, int width, int height);
|
||||
void M_DrawFrame (int x, int y, int width, int height);
|
||||
void V_DrawFrame (int x, int y, int width, int height);
|
||||
|
||||
void R_DrawViewBorder (void)
|
||||
{
|
||||
|
@ -1982,7 +1982,7 @@ void R_DrawViewBorder (void)
|
|||
R_DrawBorder (viewwindowx + viewwidth, viewwindowy, SCREENWIDTH, viewheight + viewwindowy);
|
||||
R_DrawBorder (0, viewwindowy + viewheight, SCREENWIDTH, ST_Y);
|
||||
|
||||
M_DrawFrame (viewwindowx, viewwindowy, viewwidth, viewheight);
|
||||
V_DrawFrame (viewwindowx, viewwindowy, viewwidth, viewheight);
|
||||
V_MarkRect (0, 0, SCREENWIDTH, ST_Y);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,14 @@ static void I_CheckGUICapture ()
|
|||
}
|
||||
}
|
||||
|
||||
void I_SetMouseCapture()
|
||||
{
|
||||
}
|
||||
|
||||
void I_ReleaseMouseCapture()
|
||||
{
|
||||
}
|
||||
|
||||
static void CenterMouse ()
|
||||
{
|
||||
SDL_WarpMouse (screen->GetWidth()/2, screen->GetHeight()/2);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
void I_PutInClipboard (const char *str);
|
||||
FString I_GetFromClipboard (bool use_primary_selection);
|
||||
void I_SetMouseCapture();
|
||||
void I_ReleaseMouseCapture();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -778,3 +778,8 @@ unsigned int I_MakeRNGSeed()
|
|||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool I_SetCursor(FTexture *cursorpic)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -128,6 +128,8 @@ bool I_WriteIniFailed ();
|
|||
unsigned int I_MSTime (void);
|
||||
unsigned int I_FPSTime();
|
||||
|
||||
class FTexture;
|
||||
bool I_SetCursor(FTexture *);
|
||||
|
||||
// Directory searching routines
|
||||
|
||||
|
|
|
@ -37,13 +37,14 @@
|
|||
#include "doomdef.h"
|
||||
|
||||
class FileReader;
|
||||
struct FOptionValues;
|
||||
|
||||
//
|
||||
// MUSIC I/O
|
||||
//
|
||||
void I_InitMusic ();
|
||||
void I_ShutdownMusic ();
|
||||
void I_BuildMIDIMenuList (struct value_t **values, float *numValues);
|
||||
void I_BuildMIDIMenuList (FOptionValues *);
|
||||
void I_UpdateMusic ();
|
||||
|
||||
// Volume.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "templates.h"
|
||||
#include "v_text.h"
|
||||
#include "m_menu.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
static DWORD nummididevices;
|
||||
static bool nummididevicesset;
|
||||
|
@ -71,50 +71,43 @@ void I_ShutdownMusicWin32 ()
|
|||
}
|
||||
}
|
||||
|
||||
void I_BuildMIDIMenuList (struct value_t **outValues, float *numValues)
|
||||
{
|
||||
if (*outValues == NULL)
|
||||
{
|
||||
int count = 4 + nummididevices;
|
||||
value_t *values;
|
||||
UINT id;
|
||||
int p = 0;
|
||||
|
||||
*outValues = values = new value_t[count];
|
||||
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
values[p].name = "FluidSynth";
|
||||
values[p].value = -5.0;
|
||||
++p;
|
||||
#define NUM_DEF_DEVICES 4
|
||||
#else
|
||||
#define NUM_DEF_DEVICES 3
|
||||
#endif
|
||||
values[p].name = "OPL Synth Emulation";
|
||||
values[p].value = -3.0;
|
||||
++p;
|
||||
values[p].name = "TiMidity++";
|
||||
values[p].value = -2.0;
|
||||
++p;
|
||||
values[p].name = "FMOD";
|
||||
values[p].value = -1.0;
|
||||
++p;
|
||||
for (id = 0; id < nummididevices; ++id)
|
||||
void I_BuildMIDIMenuList (FOptionValues *opt)
|
||||
{
|
||||
int p;
|
||||
FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)];
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
pair[0].Text = "FluidSynth";
|
||||
pair[0].Value = -5.0;
|
||||
p = 1;
|
||||
#else
|
||||
p = 0;
|
||||
#endif
|
||||
pair[p].Text = "OPL Synth Emulation";
|
||||
pair[p].Value = -3.0;
|
||||
pair[p+1].Text = "TiMidity++";
|
||||
pair[p+1].Value = -2.0;
|
||||
pair[p+2].Text = "FMOD";
|
||||
pair[p+2].Value = -1.0;
|
||||
|
||||
|
||||
for (DWORD id = 0; id < nummididevices; ++id)
|
||||
{
|
||||
MIDIOUTCAPS caps;
|
||||
MMRESULT res;
|
||||
|
||||
res = midiOutGetDevCaps (id, &caps, sizeof(caps));
|
||||
assert(res == MMSYSERR_NOERROR);
|
||||
if (res == MMSYSERR_NOERROR)
|
||||
{
|
||||
MIDIOUTCAPS caps;
|
||||
MMRESULT res;
|
||||
|
||||
res = midiOutGetDevCaps (id, &caps, sizeof(caps));
|
||||
assert(res == MMSYSERR_NOERROR);
|
||||
if (res == MMSYSERR_NOERROR)
|
||||
{
|
||||
size_t len = strlen (caps.szPname) + 1;
|
||||
char *name = new char[len];
|
||||
|
||||
memcpy (name, caps.szPname, len);
|
||||
values[p].name = name;
|
||||
values[p].value = (float)id;
|
||||
++p;
|
||||
}
|
||||
pair = &opt->mValues[opt->mValues.Reserve(1)];
|
||||
pair->Text = caps.szPname;
|
||||
pair->Value = (float)id;
|
||||
}
|
||||
*numValues = float(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,31 +188,28 @@ CUSTOM_CVAR(Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
self = -1;
|
||||
}
|
||||
|
||||
void I_BuildMIDIMenuList (struct value_t **outValues, float *numValues)
|
||||
{
|
||||
if (*outValues == NULL)
|
||||
{
|
||||
value_t *values;
|
||||
int p = 0;
|
||||
|
||||
*outValues = values = new value_t[4];
|
||||
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
values[p].name = "FluidSynth";
|
||||
values[p].value = -5.0;
|
||||
++p;
|
||||
#define NUM_DEF_DEVICES 4
|
||||
#else
|
||||
#define NUM_DEF_DEVICES 3
|
||||
#endif
|
||||
values[p].name = "OPL Synth Emulation";
|
||||
values[p].value = -3.0;
|
||||
++p;
|
||||
values[p].name = "TiMidity++";
|
||||
values[p].value = -2.0;
|
||||
++p;
|
||||
values[p].name = "FMOD";
|
||||
values[p].value = -1.0;
|
||||
++p;
|
||||
*numValues = float(p);
|
||||
}
|
||||
void I_BuildMIDIMenuList (FOptionValues *opt)
|
||||
{
|
||||
int p;
|
||||
FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)];
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
pair[0].Text = "FluidSynth";
|
||||
pair[0].Value = -5.0;
|
||||
p = 1;
|
||||
#else
|
||||
p = 0;
|
||||
#endif
|
||||
pair[p].Text = "OPL Synth Emulation";
|
||||
pair[p].Value = -3.0;
|
||||
pair[p+1].Text = "TiMidity++";
|
||||
pair[p+1].Value = -2.0;
|
||||
pair[p+2].Text = "FMOD";
|
||||
pair[p+2].Value = -1.0;
|
||||
}
|
||||
|
||||
CCMD (snd_listmididevices)
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
Width = w;
|
||||
Height = h;
|
||||
data = new BYTE[4*w*h];
|
||||
memset(data, 0, 4*w*h);
|
||||
FreeBuffer = true;
|
||||
ClipRect.x = ClipRect.y = 0;
|
||||
ClipRect.width = w;
|
||||
|
|
|
@ -189,7 +189,7 @@ protected:
|
|||
|
||||
private:
|
||||
void CheckForHacks ();
|
||||
void ParsePatch(FScanner &sc, TexPart & part);
|
||||
void ParsePatch(FScanner &sc, TexPart & part, bool silent);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -970,7 +970,7 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent)
|
||||
{
|
||||
FString patchname;
|
||||
sc.MustGetString();
|
||||
|
@ -1011,7 +1011,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
|||
}
|
||||
if (part.Texture == NULL)
|
||||
{
|
||||
Printf("Unknown patch '%s' in texture '%s'\n", sc.String, Name);
|
||||
if (!silent) Printf("Unknown patch '%s' in texture '%s'\n", sc.String, Name);
|
||||
}
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
|
@ -1164,6 +1164,14 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
|||
bComplex |= (part.op != OP_COPY);
|
||||
bTranslucentPatches = bComplex;
|
||||
}
|
||||
else if (sc.Compare("useoffsets"))
|
||||
{
|
||||
if (part.Texture != NULL)
|
||||
{
|
||||
part.OriginX -= part.Texture->LeftOffset;
|
||||
part.OriginY -= part.Texture->TopOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Mirror & 2)
|
||||
|
@ -1187,10 +1195,23 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||
{
|
||||
TArray<TexPart> parts;
|
||||
bool bSilent = false;
|
||||
|
||||
bMultiPatch = true;
|
||||
sc.SetCMode(true);
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("optional"))
|
||||
{
|
||||
bSilent = true;
|
||||
sc.MustGetString();
|
||||
if (sc.Compare(","))
|
||||
{
|
||||
// this is not right. Apparently a texture named 'optional' is being defined right now...
|
||||
sc.UnGet();
|
||||
sc.String = "optional";
|
||||
bSilent = false;
|
||||
}
|
||||
}
|
||||
uppercopy(Name, sc.String);
|
||||
Name[8] = 0;
|
||||
sc.MustGetStringName(",");
|
||||
|
@ -1231,7 +1252,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
else if (sc.Compare("Patch"))
|
||||
{
|
||||
TexPart part;
|
||||
ParsePatch(sc, part);
|
||||
ParsePatch(sc, part, bSilent);
|
||||
if (part.Texture != NULL) parts.Push(part);
|
||||
part.Texture = NULL;
|
||||
part.Translation = NULL;
|
||||
|
|
|
@ -2182,6 +2182,15 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY_PREFIX(player, portrait, S, PlayerPawn)
|
||||
{
|
||||
PROP_STRING_PARM(val, 0);
|
||||
info->Class->Meta.SetMetaString (APMETA_Portrait, val);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "r_translate.h"
|
||||
#include "doomstat.h"
|
||||
#include "v_palette.h"
|
||||
#include "gi.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
@ -1351,3 +1352,35 @@ bool DCanvas::ClipBox (int &x, int &y, int &w, int &h, const BYTE *&src, const i
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Draw a frame around the specified area using the view border
|
||||
// frame graphics. The border is drawn outside the area, not in it.
|
||||
void V_DrawFrame (int left, int top, int width, int height)
|
||||
{
|
||||
FTexture *p;
|
||||
const gameborder_t *border = gameinfo.border;
|
||||
// Sanity check for incomplete gameinfo
|
||||
if (border == NULL)
|
||||
return;
|
||||
int offset = border->offset;
|
||||
int right = left + width;
|
||||
int bottom = top + height;
|
||||
|
||||
// Draw top and bottom sides.
|
||||
p = TexMan[border->t];
|
||||
screen->FlatFill(left, top - p->GetHeight(), right, top, p, true);
|
||||
p = TexMan[border->b];
|
||||
screen->FlatFill(left, bottom, right, bottom + p->GetHeight(), p, true);
|
||||
|
||||
// Draw left and right sides.
|
||||
p = TexMan[border->l];
|
||||
screen->FlatFill(left - p->GetWidth(), top, left, bottom, p, true);
|
||||
p = TexMan[border->r];
|
||||
screen->FlatFill(right, top, right + p->GetWidth(), bottom, p, true);
|
||||
|
||||
// Draw beveled corners.
|
||||
screen->DrawTexture (TexMan[border->tl], left-offset, top-offset, TAG_DONE);
|
||||
screen->DrawTexture (TexMan[border->tr], left+width, top-offset, TAG_DONE);
|
||||
screen->DrawTexture (TexMan[border->bl], left-offset, top+height, TAG_DONE);
|
||||
screen->DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE);
|
||||
}
|
|
@ -2043,6 +2043,15 @@ void V_InitFontColors ()
|
|||
|
||||
while ((lump = Wads.FindLump ("TEXTCOLO", &lastlump)) != -1)
|
||||
{
|
||||
if (gameinfo.flags & GI_NOTEXTCOLOR)
|
||||
{
|
||||
// Chex3 contains a bad TEXTCOLO lump, probably to force all text to be green.
|
||||
// This renders the Gray, Gold, Red and Yellow color range inoperable, some of
|
||||
// which are used by the menu. So we have no choice but to skip this lump so that
|
||||
// all colors work properly.
|
||||
// The text colors should be the end user's choice anyway.
|
||||
if (Wads.GetLumpFile(lump) == 1) continue;
|
||||
}
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
|
|
|
@ -118,6 +118,21 @@ CUSTOM_CVAR (Float, Gamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
}
|
||||
}
|
||||
|
||||
CCMD (bumpgamma)
|
||||
{
|
||||
// [RH] Gamma correction tables are now generated
|
||||
// on the fly for *any* gamma level.
|
||||
// Q: What are reasonable limits to use here?
|
||||
|
||||
float newgamma = Gamma + 0.1f;
|
||||
|
||||
if (newgamma > 3.0)
|
||||
newgamma = 1.0;
|
||||
|
||||
Gamma = newgamma;
|
||||
Printf ("Gamma correction level %g\n", *Gamma);
|
||||
}
|
||||
|
||||
|
||||
/****************************/
|
||||
/* Palette management stuff */
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "m_argv.h"
|
||||
#include "m_bbox.h"
|
||||
#include "m_swap.h"
|
||||
#include "m_menu.h"
|
||||
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
|
@ -63,6 +62,7 @@
|
|||
#include "colormatcher.h"
|
||||
#include "v_palette.h"
|
||||
#include "r_sky.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS (DCanvas)
|
||||
|
|
|
@ -412,6 +412,7 @@ public:
|
|||
virtual void WipeEndScreen();
|
||||
virtual bool WipeDo(int ticks);
|
||||
virtual void WipeCleanup();
|
||||
virtual int GetPixelDoubling() const { return 1; }
|
||||
|
||||
uint32 GetLastFPS() const { return LastCount; }
|
||||
|
||||
|
@ -489,6 +490,7 @@ FString V_GetColorStringByName (const char *name);
|
|||
|
||||
// Tries to get color by name, then by string
|
||||
int V_GetColor (const DWORD *palette, const char *str);
|
||||
void V_DrawFrame (int left, int top, int width, int height);
|
||||
|
||||
#if defined(X86_ASM) || defined(X64_ASM)
|
||||
extern "C" void ASM_PatchPitch (void);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "win32iface.h"
|
||||
#include "m_menu.h"
|
||||
#include "templates.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "cmdlib.h"
|
||||
|
@ -236,8 +235,6 @@ protected:
|
|||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
extern void UpdateJoystickMenu();
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
@ -246,7 +243,6 @@ static void MapAxis(FIntCVar &var, int num);
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern menu_t JoystickMenu;
|
||||
extern LPDIRECTINPUT8 g_pdi;
|
||||
extern HWND Window;
|
||||
|
||||
|
|
|
@ -86,7 +86,6 @@
|
|||
#include "i_input.h"
|
||||
#include "v_video.h"
|
||||
#include "i_sound.h"
|
||||
#include "m_menu.h"
|
||||
#include "g_game.h"
|
||||
#include "d_main.h"
|
||||
#include "d_gui.h"
|
||||
|
@ -145,6 +144,7 @@ extern HWND EAXEditWindow;
|
|||
EXTERN_CVAR (String, language)
|
||||
EXTERN_CVAR (Bool, lookstrafe)
|
||||
EXTERN_CVAR (Bool, use_joystick)
|
||||
EXTERN_CVAR (Bool, use_mouse)
|
||||
|
||||
static int WheelDelta;
|
||||
extern bool CursorState;
|
||||
|
@ -191,6 +191,16 @@ static void I_CheckGUICapture ()
|
|||
}
|
||||
}
|
||||
|
||||
void I_SetMouseCapture()
|
||||
{
|
||||
SetCapture(Window);
|
||||
}
|
||||
|
||||
void I_ReleaseMouseCapture()
|
||||
{
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
bool GUIWndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||
{
|
||||
event_t ev = { EV_GUI_Event };
|
||||
|
@ -228,28 +238,29 @@ bool GUIWndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESU
|
|||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_PRIOR: ev.data1 = GK_PGUP; break;
|
||||
case VK_NEXT: ev.data1 = GK_PGDN; break;
|
||||
case VK_END: ev.data1 = GK_END; break;
|
||||
case VK_HOME: ev.data1 = GK_HOME; break;
|
||||
case VK_LEFT: ev.data1 = GK_LEFT; break;
|
||||
case VK_RIGHT: ev.data1 = GK_RIGHT; break;
|
||||
case VK_UP: ev.data1 = GK_UP; break;
|
||||
case VK_DOWN: ev.data1 = GK_DOWN; break;
|
||||
case VK_DELETE: ev.data1 = GK_DEL; break;
|
||||
case VK_ESCAPE: ev.data1 = GK_ESCAPE; break;
|
||||
case VK_F1: ev.data1 = GK_F1; break;
|
||||
case VK_F2: ev.data1 = GK_F2; break;
|
||||
case VK_F3: ev.data1 = GK_F3; break;
|
||||
case VK_F4: ev.data1 = GK_F4; break;
|
||||
case VK_F5: ev.data1 = GK_F5; break;
|
||||
case VK_F6: ev.data1 = GK_F6; break;
|
||||
case VK_F7: ev.data1 = GK_F7; break;
|
||||
case VK_F8: ev.data1 = GK_F8; break;
|
||||
case VK_F9: ev.data1 = GK_F9; break;
|
||||
case VK_F10: ev.data1 = GK_F10; break;
|
||||
case VK_F11: ev.data1 = GK_F11; break;
|
||||
case VK_F12: ev.data1 = GK_F12; break;
|
||||
case VK_PRIOR: ev.data1 = GK_PGUP; break;
|
||||
case VK_NEXT: ev.data1 = GK_PGDN; break;
|
||||
case VK_END: ev.data1 = GK_END; break;
|
||||
case VK_HOME: ev.data1 = GK_HOME; break;
|
||||
case VK_LEFT: ev.data1 = GK_LEFT; break;
|
||||
case VK_RIGHT: ev.data1 = GK_RIGHT; break;
|
||||
case VK_UP: ev.data1 = GK_UP; break;
|
||||
case VK_DOWN: ev.data1 = GK_DOWN; break;
|
||||
case VK_DELETE: ev.data1 = GK_DEL; break;
|
||||
case VK_ESCAPE: ev.data1 = GK_ESCAPE; break;
|
||||
case VK_F1: ev.data1 = GK_F1; break;
|
||||
case VK_F2: ev.data1 = GK_F2; break;
|
||||
case VK_F3: ev.data1 = GK_F3; break;
|
||||
case VK_F4: ev.data1 = GK_F4; break;
|
||||
case VK_F5: ev.data1 = GK_F5; break;
|
||||
case VK_F6: ev.data1 = GK_F6; break;
|
||||
case VK_F7: ev.data1 = GK_F7; break;
|
||||
case VK_F8: ev.data1 = GK_F8; break;
|
||||
case VK_F9: ev.data1 = GK_F9; break;
|
||||
case VK_F10: ev.data1 = GK_F10; break;
|
||||
case VK_F11: ev.data1 = GK_F11; break;
|
||||
case VK_F12: ev.data1 = GK_F12; break;
|
||||
case VK_BROWSER_BACK: ev.data1 = GK_BACK; break;
|
||||
}
|
||||
if (ev.data1 != 0)
|
||||
{
|
||||
|
@ -278,6 +289,9 @@ bool GUIWndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESU
|
|||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONDOWN:
|
||||
case WM_XBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
if (message >= WM_LBUTTONDOWN && message <= WM_LBUTTONDBLCLK)
|
||||
{
|
||||
ev.subtype = message - WM_LBUTTONDOWN + EV_GUI_LButtonDown;
|
||||
|
@ -290,11 +304,35 @@ bool GUIWndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESU
|
|||
{
|
||||
ev.subtype = message - WM_MBUTTONDOWN + EV_GUI_MButtonDown;
|
||||
}
|
||||
D_PostEvent(&ev);
|
||||
else if (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONUP)
|
||||
{
|
||||
ev.subtype = message - WM_XBUTTONDOWN + EV_GUI_BackButtonDown;
|
||||
if (GET_XBUTTON_WPARAM(wParam) == 2)
|
||||
{
|
||||
ev.subtype += EV_GUI_FwdButtonDown - EV_GUI_BackButtonDown;
|
||||
}
|
||||
else if (GET_XBUTTON_WPARAM(wParam) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (message == WM_MOUSEMOVE)
|
||||
{
|
||||
ev.subtype = EV_GUI_MouseMove;
|
||||
}
|
||||
ev.data1 = LOWORD(lParam) >> screen->GetPixelDoubling();
|
||||
ev.data2 = HIWORD(lParam) >> screen->GetPixelDoubling();
|
||||
|
||||
if (wParam & MK_SHIFT) ev.data3 |= GKM_SHIFT;
|
||||
if (wParam & MK_CONTROL) ev.data3 |= GKM_CTRL;
|
||||
if (GetKeyState(VK_MENU) & 0x8000) ev.data3 |= GKM_ALT;
|
||||
|
||||
if (use_mouse) D_PostEvent(&ev);
|
||||
return true;
|
||||
|
||||
// Note: If the mouse is grabbed, it sends the mouse wheel events itself.
|
||||
case WM_MOUSEWHEEL:
|
||||
if (!use_mouse) return false;
|
||||
if (wParam & MK_SHIFT) ev.data3 |= GKM_SHIFT;
|
||||
if (wParam & MK_CONTROL) ev.data3 |= GKM_CTRL;
|
||||
if (GetKeyState(VK_MENU) & 0x8000) ev.data3 |= GKM_ALT;
|
||||
|
@ -385,6 +423,15 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
return result;
|
||||
}
|
||||
|
||||
if ((gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL) && message == WM_LBUTTONDOWN)
|
||||
{
|
||||
if (GUIWndProcHook(hWnd, message, wParam, lParam, &result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
|
@ -425,6 +472,10 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
SetCursor(NULL); // turn off window cursor
|
||||
return TRUE; // Prevent Windows from setting cursor to window class cursor
|
||||
}
|
||||
else
|
||||
{
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#include "doomtype.h"
|
||||
#include "doomdef.h"
|
||||
|
||||
void I_SetMouseCapture();
|
||||
void I_ReleaseMouseCapture();
|
||||
|
||||
bool I_InitInput (void *hwnd);
|
||||
void I_ShutdownInput ();
|
||||
void I_PutInClipboard (const char *str);
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
#ifdef _MSC_VER
|
||||
// Turn off "conversion from 'LONG_PTR' to 'LONG', possible loss of data"
|
||||
// generated by SetClassLongPtr().
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
|
@ -22,6 +17,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "win32iface.h"
|
||||
#include "rawinput.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -265,18 +261,17 @@ void I_CheckNativeMouse(bool preferNative)
|
|||
|
||||
if (!windowed)
|
||||
{
|
||||
want_native = false;
|
||||
// ungrab mouse when in the menu with mouse control on.
|
||||
want_native = m_use_mouse && (menuactive == MENU_On || menuactive == MENU_OnNoPause);
|
||||
}
|
||||
else
|
||||
{
|
||||
want_native =
|
||||
(GetForegroundWindow() != Window) ||
|
||||
!CaptureMode_InGame() ||
|
||||
GUICapture ||
|
||||
paused ||
|
||||
preferNative ||
|
||||
!use_mouse ||
|
||||
demoplayback;
|
||||
((!m_use_mouse || menuactive != MENU_WaitKey) &&
|
||||
(!CaptureMode_InGame() || GUICapture || paused || demoplayback));
|
||||
}
|
||||
|
||||
//Printf ("%d %d %d\n", wantNative, preferNative, NativeMouse);
|
||||
|
@ -592,7 +587,7 @@ void FRawMouse::Ungrab()
|
|||
|
||||
bool FRawMouse::ProcessRawInput(RAWINPUT *raw, int code)
|
||||
{
|
||||
if (!Grabbed || raw->header.dwType != RIM_TYPEMOUSE)
|
||||
if (!Grabbed || raw->header.dwType != RIM_TYPEMOUSE || !use_mouse)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -806,7 +801,7 @@ void FDInputMouse::ProcessInput()
|
|||
dx = 0;
|
||||
dy = 0;
|
||||
|
||||
if (!Grabbed)
|
||||
if (!Grabbed || !use_mouse)
|
||||
return;
|
||||
|
||||
event_t ev = { 0 };
|
||||
|
@ -948,7 +943,7 @@ void FWin32Mouse::ProcessInput()
|
|||
POINT pt;
|
||||
int x, y;
|
||||
|
||||
if (!Grabbed || !GetCursorPos(&pt))
|
||||
if (!Grabbed || !use_mouse || !GetCursorPos(&pt))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1006,6 +1001,11 @@ bool FWin32Mouse::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (!use_mouse)
|
||||
{
|
||||
// all following messages should only be processed if the mouse is in use
|
||||
return false;
|
||||
}
|
||||
else if (message == WM_MOUSEWHEEL)
|
||||
{
|
||||
WheelMoved(0, (SHORT)HIWORD(wParam));
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "win32iface.h"
|
||||
#include "m_menu.h"
|
||||
#include "templates.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "cmdlib.h"
|
||||
|
|
|
@ -83,9 +83,17 @@
|
|||
#include "doomstat.h"
|
||||
#include "v_palette.h"
|
||||
#include "stats.h"
|
||||
#include "r_data.h"
|
||||
#include "textures/bitmap.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conversion from 'LONG_PTR' to 'LONG', possible loss of data"
|
||||
// generated by SetClassLongPtr().
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
@ -108,6 +116,11 @@ static int I_WaitForTicEvent(int prevtic);
|
|||
static void I_FreezeTimeEventDriven(bool frozen);
|
||||
static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2);
|
||||
|
||||
static HCURSOR CreateCompatibleCursor(FTexture *cursorpic);
|
||||
static HCURSOR CreateAlphaCursor(FTexture *cursorpic);
|
||||
static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP color_mask);
|
||||
static void DestroyCustomCursor();
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
EXTERN_CVAR(String, language);
|
||||
|
@ -158,6 +171,8 @@ static WadStuff *WadList;
|
|||
static int NumWads;
|
||||
static int DefaultWad;
|
||||
|
||||
static HCURSOR CustomCursor;
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1175,6 +1190,208 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
|||
return defaultiwad;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// I_SetCursor
|
||||
//
|
||||
// Returns true if the cursor was successfully changed.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool I_SetCursor(FTexture *cursorpic)
|
||||
{
|
||||
HCURSOR cursor;
|
||||
|
||||
// Must be no larger than 32x32.
|
||||
if (cursorpic->GetWidth() > 32 || cursorpic->GetHeight() > 32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cursor = CreateAlphaCursor(cursorpic);
|
||||
if (cursor == NULL)
|
||||
{
|
||||
cursor = CreateCompatibleCursor(cursorpic);
|
||||
}
|
||||
if (cursor == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Replace the existing cursor with the new one.
|
||||
if (CustomCursor != NULL)
|
||||
{
|
||||
DestroyCursor(CustomCursor);
|
||||
}
|
||||
CustomCursor = cursor;
|
||||
atterm(DestroyCustomCursor);
|
||||
SetClassLongPtr(Window, GCLP_HCURSOR, (LONG_PTR)cursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CreateCompatibleCursor
|
||||
//
|
||||
// Creates a cursor with a 1-bit alpha channel.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static HCURSOR CreateCompatibleCursor(FTexture *cursorpic)
|
||||
{
|
||||
int picwidth = cursorpic->GetWidth();
|
||||
int picheight = cursorpic->GetHeight();
|
||||
|
||||
// Create bitmap masks for the cursor from the texture.
|
||||
HDC dc = GetDC(NULL);
|
||||
if (dc == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
HDC and_mask_dc = CreateCompatibleDC(dc);
|
||||
HDC xor_mask_dc = CreateCompatibleDC(dc);
|
||||
HBITMAP and_mask = CreateCompatibleBitmap(dc, 32, 32);
|
||||
HBITMAP xor_mask = CreateCompatibleBitmap(dc, 32, 32);
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
SelectObject(and_mask_dc, and_mask);
|
||||
SelectObject(xor_mask_dc, xor_mask);
|
||||
|
||||
// Initialize with an invisible cursor.
|
||||
SelectObject(and_mask_dc, GetStockObject(WHITE_PEN));
|
||||
SelectObject(and_mask_dc, GetStockObject(WHITE_BRUSH));
|
||||
Rectangle(and_mask_dc, 0, 0, 32, 32);
|
||||
SelectObject(xor_mask_dc, GetStockObject(BLACK_PEN));
|
||||
SelectObject(xor_mask_dc, GetStockObject(BLACK_BRUSH));
|
||||
Rectangle(xor_mask_dc, 0, 0, 32, 32);
|
||||
|
||||
FBitmap bmp;
|
||||
const BYTE *pixels;
|
||||
|
||||
bmp.Create(picwidth, picheight);
|
||||
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
|
||||
pixels = bmp.GetPixels();
|
||||
|
||||
// Copy color data from the source texture to the cursor bitmaps.
|
||||
for (int y = 0; y < picheight; ++y)
|
||||
{
|
||||
for (int x = 0; x < picwidth; ++x)
|
||||
{
|
||||
const BYTE *bgra = &pixels[x*4 + y*bmp.GetPitch()];
|
||||
if (bgra[3] != 0)
|
||||
{
|
||||
SetPixelV(and_mask_dc, x, y, RGB(0,0,0));
|
||||
SetPixelV(xor_mask_dc, x, y, RGB(bgra[2], bgra[1], bgra[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
DeleteDC(and_mask_dc);
|
||||
DeleteDC(xor_mask_dc);
|
||||
|
||||
// Create the cursor from the bitmaps.
|
||||
return CreateBitmapCursor(cursorpic->LeftOffset, cursorpic->TopOffset, and_mask, xor_mask);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CreateAlphaCursor
|
||||
//
|
||||
// Creates a cursor with a full alpha channel.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static HCURSOR CreateAlphaCursor(FTexture *cursorpic)
|
||||
{
|
||||
HDC dc;
|
||||
BITMAPV5HEADER bi;
|
||||
HBITMAP color, mono;
|
||||
void *bits;
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.bV5Size = sizeof(bi);
|
||||
bi.bV5Width = 32;
|
||||
bi.bV5Height = 32;
|
||||
bi.bV5Planes = 1;
|
||||
bi.bV5BitCount = 32;
|
||||
bi.bV5Compression = BI_BITFIELDS;
|
||||
bi.bV5RedMask = 0x00FF0000;
|
||||
bi.bV5GreenMask = 0x0000FF00;
|
||||
bi.bV5BlueMask = 0x000000FF;
|
||||
bi.bV5AlphaMask = 0xFF000000;
|
||||
|
||||
dc = GetDC(NULL);
|
||||
if (dc == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the DIB section with an alpha channel.
|
||||
color = CreateDIBSection(dc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
if (color == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create an empty mask bitmap, since CreateIconIndirect requires this.
|
||||
mono = CreateBitmap(32, 32, 1, 1, NULL);
|
||||
if (mono == NULL)
|
||||
{
|
||||
DeleteObject(color);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy cursor to the color bitmap. Note that GDI bitmaps are upside down compared
|
||||
// to normal conventions, so we create the FBitmap pointing at the last row and use
|
||||
// a negative pitch so that CopyTrueColorPixels will use GDI's orientation.
|
||||
FBitmap bmp((BYTE *)bits + 31*32*4, -32*4, 32, 32);
|
||||
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
|
||||
|
||||
return CreateBitmapCursor(cursorpic->LeftOffset, cursorpic->TopOffset, mono, color);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CreateBitmapCursor
|
||||
//
|
||||
// Create the cursor from the bitmaps. Deletes the bitmaps before returning.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP color_mask)
|
||||
{
|
||||
ICONINFO iconinfo =
|
||||
{
|
||||
FALSE, // fIcon
|
||||
xhot, // xHotspot
|
||||
yhot, // yHotspot
|
||||
and_mask, // hbmMask
|
||||
color_mask // hbmColor
|
||||
};
|
||||
HCURSOR cursor = CreateIconIndirect(&iconinfo);
|
||||
|
||||
// Delete the bitmaps.
|
||||
DeleteObject(and_mask);
|
||||
DeleteObject(color_mask);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DestroyCustomCursor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void DestroyCustomCursor()
|
||||
{
|
||||
if (CustomCursor != NULL)
|
||||
{
|
||||
DestroyCursor(CustomCursor);
|
||||
CustomCursor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// I_WriteIniFailed
|
||||
|
|
|
@ -114,6 +114,10 @@ void STACK_ARGS I_FatalError (const char *error, ...) GCCPRINTF(1,2);
|
|||
void atterm (void (*func)(void));
|
||||
void popterm ();
|
||||
|
||||
// Set the mouse cursor. The texture must be 32x32.
|
||||
class FTexture;
|
||||
bool I_SetCursor(FTexture *cursor);
|
||||
|
||||
// Repaint the pre-game console
|
||||
void I_PaintConsole (void);
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "win32iface.h"
|
||||
#include "m_menu.h"
|
||||
#include "templates.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "cmdlib.h"
|
||||
|
|
|
@ -372,6 +372,7 @@ private:
|
|||
void EndLineBatch();
|
||||
void EndBatch();
|
||||
void CopyNextFrontBuffer();
|
||||
int GetPixelDoubling() const { return PixelDoubling; }
|
||||
|
||||
D3DCAPS9 DeviceCaps;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ ACTOR ClericPlayer : PlayerPawn
|
|||
Player.HealRadiusType "Health"
|
||||
Player.Hexenarmor 10, 10, 25, 5, 20
|
||||
Player.StartItem "CWeapMace"
|
||||
Player.Portrait "P_CWALK1"
|
||||
Player.WeaponSlot 1, CWeapMace
|
||||
Player.WeaponSlot 2, CWeapStaff
|
||||
Player.WeaponSlot 3, CWeapFlame
|
||||
|
|
|
@ -23,6 +23,7 @@ ACTOR FighterPlayer : PlayerPawn
|
|||
Player.StartItem "FWeapFist"
|
||||
Player.ForwardMove 1.08, 1.2
|
||||
Player.SideMove 1.125, 1.475
|
||||
Player.Portrait "P_FWALK1"
|
||||
Player.WeaponSlot 1, FWeapFist
|
||||
Player.WeaponSlot 2, FWeapAxe
|
||||
Player.WeaponSlot 3, FWeapHammer
|
||||
|
|
|
@ -25,6 +25,7 @@ ACTOR MagePlayer : PlayerPawn
|
|||
Player.StartItem "MWeapWand"
|
||||
Player.ForwardMove 0.88, 0.92
|
||||
Player.SideMove 0.875, 0.925
|
||||
Player.Portrait "P_MWALK1"
|
||||
Player.WeaponSlot 1, MWeapWand
|
||||
Player.WeaponSlot 2, MWeapFrost
|
||||
Player.WeaponSlot 3, MWeapLightning
|
||||
|
|
|
@ -101,6 +101,85 @@ pic PTN1A0 tics 3
|
|||
pic PTN1B0 tics 3
|
||||
pic PTN1C0 tics 3
|
||||
|
||||
// Hexen's player portraits
|
||||
texture optional P_FWALK1
|
||||
pic P_FWALK1 tics 8
|
||||
pic P_FWALK2 tics 8
|
||||
pic P_FWALK3 tics 8
|
||||
pic P_FWALK4 tics 8
|
||||
|
||||
texture optional P_CWALK1
|
||||
pic P_CWALK1 tics 8
|
||||
pic P_CWALK2 tics 8
|
||||
pic P_CWALK3 tics 8
|
||||
pic P_CWALK4 tics 8
|
||||
|
||||
texture optional P_MWALK1
|
||||
pic P_MWALK1 tics 8
|
||||
pic P_MWALK2 tics 8
|
||||
pic P_MWALK3 tics 8
|
||||
pic P_MWALK4 tics 8
|
||||
|
||||
// Heretic's menu skulls
|
||||
texture optional M_SKL00
|
||||
pic M_SKL00 tics 3
|
||||
pic M_SKL01 tics 3
|
||||
pic M_SKL02 tics 3
|
||||
pic M_SKL03 tics 3
|
||||
pic M_SKL04 tics 3
|
||||
pic M_SKL05 tics 3
|
||||
pic M_SKL06 tics 3
|
||||
pic M_SKL07 tics 3
|
||||
pic M_SKL08 tics 3
|
||||
pic M_SKL09 tics 3
|
||||
pic M_SKL10 tics 3
|
||||
pic M_SKL11 tics 3
|
||||
pic M_SKL12 tics 3
|
||||
pic M_SKL13 tics 3
|
||||
pic M_SKL14 tics 3
|
||||
pic M_SKL15 tics 3
|
||||
pic M_SKL16 tics 3
|
||||
pic M_SKL17 tics 3
|
||||
|
||||
texture optional M_SKL01
|
||||
pic M_SKL17 tics 3
|
||||
pic M_SKL16 tics 3
|
||||
pic M_SKL15 tics 3
|
||||
pic M_SKL14 tics 3
|
||||
pic M_SKL13 tics 3
|
||||
pic M_SKL12 tics 3
|
||||
pic M_SKL11 tics 3
|
||||
pic M_SKL10 tics 3
|
||||
pic M_SKL09 tics 3
|
||||
pic M_SKL08 tics 3
|
||||
pic M_SKL07 tics 3
|
||||
pic M_SKL06 tics 3
|
||||
pic M_SKL05 tics 3
|
||||
pic M_SKL04 tics 3
|
||||
pic M_SKL03 tics 3
|
||||
pic M_SKL02 tics 3
|
||||
pic M_SKL01 tics 3
|
||||
pic M_SKL00 tics 3
|
||||
|
||||
// Hexen's Fire Bulls
|
||||
texture optional FBULA0
|
||||
pic FBULA0 tics 5
|
||||
pic FBULB0 tics 5
|
||||
pic FBULC0 tics 5
|
||||
pic FBULD0 tics 5
|
||||
pic FBULE0 tics 5
|
||||
pic FBULF0 tics 5
|
||||
pic FBULG0 tics 5
|
||||
|
||||
texture optional FBULB0
|
||||
pic FBULC0 tics 5
|
||||
pic FBULD0 tics 5
|
||||
pic FBULE0 tics 5
|
||||
pic FBULF0 tics 5
|
||||
pic FBULG0 tics 5
|
||||
pic FBULA0 tics 5
|
||||
pic FBULB0 tics 5
|
||||
|
||||
// The Wings of Wrath are not included, because they stop spinning when
|
||||
// you stop flying, so they can't be a simple animation.
|
||||
|
||||
|
|
BIN
wadsrc/static/graphics/cursor.png
Normal file
BIN
wadsrc/static/graphics/cursor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 B |
BIN
wadsrc/static/graphics/m_back_d.png
Normal file
BIN
wadsrc/static/graphics/m_back_d.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 204 B |
BIN
wadsrc/static/graphics/m_back_h.png
Normal file
BIN
wadsrc/static/graphics/m_back_h.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 213 B |
BIN
wadsrc/static/graphics/m_back_s.png
Normal file
BIN
wadsrc/static/graphics/m_back_s.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 235 B |
BIN
wadsrc/static/graphics/m_back_x.png
Normal file
BIN
wadsrc/static/graphics/m_back_x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 B |
|
@ -1559,6 +1559,8 @@ MNU_DELETESG = "Do you really want to delete the savegame\n";
|
|||
|
||||
MNU_ONLYREGISTERED = "ONLY AVAILABLE IN THE REGISTERED VERSION";
|
||||
|
||||
MNU_EPISODE = "Select Episode";
|
||||
|
||||
// Bloodbath announcer
|
||||
|
||||
BBA_BONED = "%k boned %o like a fish";
|
||||
|
|
|
@ -43,6 +43,15 @@ gameinfo
|
|||
player5start = 4001
|
||||
drawreadthis = true
|
||||
pickupcolor = "d6 ba 45"
|
||||
quitmessages = "$QUITMSG", "$QUITMSG23", "$QUITMSG24", "$QUITMSG25", "$QUITMSG26", "$QUITMSG27", "$QUITMSG28", "$QUITMSG29"
|
||||
menufontcolor_title = "GREEN"
|
||||
menufontcolor_label = "UNTRANSLATED"
|
||||
menufontcolor_value = "GRAY"
|
||||
menufontcolor_action = "GRAY"
|
||||
menufontcolor_header = "YELLOW"
|
||||
menufontcolor_highlight = "BLUE"
|
||||
menufontcolor_selection = "GOLD"
|
||||
menubackbutton = "M_BACK_H"
|
||||
}
|
||||
|
||||
skill baby
|
||||
|
|
|
@ -14,6 +14,7 @@ gameinfo
|
|||
borderflat = "FLOOR7_2"
|
||||
drawreadthis = true
|
||||
intermissionmusic = "$MUSIC_INTER"
|
||||
quitmessages = "$QUITMSG", "$QUITMSG1", "$QUITMSG2", "$QUITMSG3", "$QUITMSG4", "$QUITMSG5", "$QUITMSG6", "$QUITMSG7"
|
||||
}
|
||||
|
||||
clearepisodes
|
||||
|
|
|
@ -41,6 +41,17 @@ gameinfo
|
|||
endoom = "ENDOOM"
|
||||
player5start = 4001
|
||||
pickupcolor = "d6 ba 45"
|
||||
quitmessages = "$QUITMSG", "$QUITMSG1", "$QUITMSG2", "$QUITMSG3", "$QUITMSG4", "$QUITMSG5", "$QUITMSG6", "$QUITMSG7",
|
||||
"$QUITMSG8", "$QUITMSG9", "$QUITMSG10", "$QUITMSG11", "$QUITMSG12", "$QUITMSG13", "$QUITMSG14"
|
||||
|
||||
menufontcolor_title = "RED"
|
||||
menufontcolor_label = "UNTRANSLATED"
|
||||
menufontcolor_value = "GRAY"
|
||||
menufontcolor_action = "GRAY"
|
||||
menufontcolor_header = "GOLD"
|
||||
menufontcolor_highlight = "YELLOW"
|
||||
menufontcolor_selection = "BRICK"
|
||||
menubackbutton = "M_BACK_D"
|
||||
}
|
||||
|
||||
skill baby
|
||||
|
|
|
@ -42,6 +42,15 @@ gameinfo
|
|||
endoom = "ENDTEXT"
|
||||
player5start = 4001
|
||||
pickupcolor = "d6 ba 45"
|
||||
quitmessages = "$*RAVENQUITMSG"
|
||||
menufontcolor_title = "UNTRANSLATED"
|
||||
menufontcolor_label = "GREEN"
|
||||
menufontcolor_value = "UNTRANSLATED"
|
||||
menufontcolor_action = "UNTRANSLATED"
|
||||
menufontcolor_header = "GOLD"
|
||||
menufontcolor_highlight = "YELLOW"
|
||||
menufontcolor_selection = "DARKGREEN"
|
||||
menubackbutton = "M_BACK_H"
|
||||
}
|
||||
|
||||
skill baby
|
||||
|
|
|
@ -40,6 +40,15 @@ gameinfo
|
|||
defaultdropstyle = 1
|
||||
player5start = 9100
|
||||
pickupcolor = "d6 ba 45"
|
||||
quitmessages = "$*RAVENQUITMSG"
|
||||
menufontcolor_title = "UNTRANSLATED"
|
||||
menufontcolor_label = "RED"
|
||||
menufontcolor_value = "UNTRANSLATED"
|
||||
menufontcolor_action = "UNTRANSLATED"
|
||||
menufontcolor_header = "GOLD"
|
||||
menufontcolor_highlight = "YELLOW"
|
||||
menufontcolor_selection = "BRICK"
|
||||
menubackbutton = "M_BACK_X"
|
||||
}
|
||||
|
||||
skill baby
|
||||
|
|
|
@ -43,6 +43,15 @@ gameinfo
|
|||
endoom = "ENDSTRF"
|
||||
player5start = 5
|
||||
pickupcolor = "d6 ba 45"
|
||||
quitmessages = "$QUITMSG", "$QUITMSG15", "$QUITMSG16", "$QUITMSG17", "$QUITMSG18", "$QUITMSG19", "$QUITMSG20", "$QUITMSG21", "$QUITMSG22"
|
||||
menufontcolor_title = "UNTRANSLATED"
|
||||
menufontcolor_label = "UNTRANSLATED"
|
||||
menufontcolor_value = "GRAY"
|
||||
menufontcolor_action = "GRAY"
|
||||
menufontcolor_header = "RED"
|
||||
menufontcolor_highlight = "GREEN"
|
||||
menufontcolor_selection = "GOLD"
|
||||
menubackbutton = "M_BACK_S"
|
||||
}
|
||||
|
||||
skill baby
|
||||
|
|
1333
wadsrc/static/menudef.txt
Normal file
1333
wadsrc/static/menudef.txt
Normal file
File diff suppressed because it is too large
Load diff
72
wadsrc/static/textures.txt
Normal file
72
wadsrc/static/textures.txt
Normal file
|
@ -0,0 +1,72 @@
|
|||
|
||||
Graphic optional P_FWALK1, 112, 136
|
||||
{
|
||||
Patch "M_FBOX", 0, 0
|
||||
Patch "M_FWALK1", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_FWALK2, 112, 136
|
||||
{
|
||||
Patch "M_FBOX", 0, 0
|
||||
Patch "M_FWALK2", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_FWALK3, 112, 136
|
||||
{
|
||||
Patch "M_FBOX", 0, 0
|
||||
Patch "M_FWALK3", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_FWALK4, 112, 136
|
||||
{
|
||||
Patch "M_FBOX", 0, 0
|
||||
Patch "M_FWALK4", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_CWALK1, 112, 136
|
||||
{
|
||||
Patch "M_CBOX", 0, 0
|
||||
Patch "M_CWALK1", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_CWALK2, 112, 136
|
||||
{
|
||||
Patch "M_CBOX", 0, 0
|
||||
Patch "M_CWALK2", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_CWALK3, 112, 136
|
||||
{
|
||||
Patch "M_CBOX", 0, 0
|
||||
Patch "M_CWALK3", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_CWALK4, 112, 136
|
||||
{
|
||||
Patch "M_CBOX", 0, 0
|
||||
Patch "M_CWALK4", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_MWALK1, 112, 136
|
||||
{
|
||||
Patch "M_MBOX", 0, 0
|
||||
Patch "M_MWALK1", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_MWALK2, 112, 136
|
||||
{
|
||||
Patch "M_MBOX", 0, 0
|
||||
Patch "M_MWALK2", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_MWALK3, 112, 136
|
||||
{
|
||||
Patch "M_MBOX", 0, 0
|
||||
Patch "M_MWALK3", 24, 12 { useoffsets }
|
||||
}
|
||||
|
||||
Graphic optional P_MWALK4, 112, 136
|
||||
{
|
||||
Patch "M_MBOX", 0, 0
|
||||
Patch "M_MWALK4", 24, 12 { useoffsets }
|
||||
}
|
826
zdoom.vcproj
826
zdoom.vcproj
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue