mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-17 00:51:49 +00:00
This commit is contained in:
commit
8c176575c8
64 changed files with 5349 additions and 4585 deletions
|
@ -914,7 +914,6 @@ set( FASTMATH_PCH_SOURCES
|
|||
SkylineBinPack.cpp
|
||||
intermission/intermission.cpp
|
||||
intermission/intermission_parse.cpp
|
||||
menu/colorpickermenu.cpp
|
||||
menu/joystickmenu.cpp
|
||||
menu/listmenu.cpp
|
||||
menu/loadsavemenu.cpp
|
||||
|
@ -923,7 +922,6 @@ set( FASTMATH_PCH_SOURCES
|
|||
menu/menuinput.cpp
|
||||
menu/messagebox.cpp
|
||||
menu/optionmenu.cpp
|
||||
menu/playerdisplay.cpp
|
||||
menu/playermenu.cpp
|
||||
menu/readthis.cpp
|
||||
menu/videomenu.cpp
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "i_system.h"
|
||||
#include "d_event.h"
|
||||
#include "w_wad.h"
|
||||
#include "templates.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -261,11 +262,27 @@ static const char *ConfigKeyName(int keynum)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FKeyBindings, SetBind)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings);
|
||||
PARAM_INT(k);
|
||||
PARAM_STRING(cmd);
|
||||
self->SetBind(k, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void C_NameKeys (char *str, int first, int second)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
*str = 0;
|
||||
if (second == first) second = 0;
|
||||
if (first)
|
||||
{
|
||||
c++;
|
||||
|
@ -284,6 +301,16 @@ void C_NameKeys (char *str, int first, int second)
|
|||
*str = '\0';
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FKeyBindings, NameKeys)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(k1);
|
||||
PARAM_INT(k2);
|
||||
char buffer[120];
|
||||
C_NameKeys(buffer, k1, k2);
|
||||
ACTION_RETURN_STRING(buffer);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -445,6 +472,17 @@ int FKeyBindings::GetKeysForCommand (const char *cmd, int *first, int *second)
|
|||
return c;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FKeyBindings, GetKeysForCommand)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings);
|
||||
PARAM_STRING(cmd);
|
||||
int k1, k2, c;
|
||||
self->GetKeysForCommand(cmd.GetChars(), &k1, &k2);
|
||||
if (numret > 0) ret[0].SetInt(k1);
|
||||
if (numret > 1) ret[1].SetInt(k2);
|
||||
return MIN(numret, 2);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -464,6 +502,14 @@ void FKeyBindings::UnbindACommand (const char *str)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FKeyBindings, UnbindACommand)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings);
|
||||
PARAM_STRING(cmd);
|
||||
self->UnbindACommand(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -1336,6 +1336,14 @@ DEFINE_ACTION_FUNCTION(_Console, HideConsole)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Console, Printf)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
FString s = FStringFormat(param, defaultparam, numparam, ret, numret);
|
||||
Printf("%s\n", s.GetChars());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
|
||||
{
|
||||
int data1 = ev->data1;
|
||||
|
|
|
@ -192,7 +192,7 @@ DEFINE_ACTION_FUNCTION(_CVar, GetFloat)
|
|||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
auto v = self->GetGenericRep(CVAR_Float);
|
||||
ACTION_RETURN_FLOAT(v.Int);
|
||||
ACTION_RETURN_FLOAT(v.Float);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, GetString)
|
||||
|
@ -202,6 +202,36 @@ DEFINE_ACTION_FUNCTION(_CVar, GetString)
|
|||
ACTION_RETURN_STRING(v.String);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, SetInt)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
PARAM_INT(val);
|
||||
UCVarValue v;
|
||||
v.Int = val;
|
||||
self->SetGenericRep(v, CVAR_Int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, SetFloat)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
PARAM_FLOAT(val);
|
||||
UCVarValue v;
|
||||
v.Float = val;
|
||||
self->SetGenericRep(v, CVAR_Float);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, SetString)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
PARAM_STRING(val);
|
||||
UCVarValue v;
|
||||
v.String = val.GetChars();
|
||||
self->SetGenericRep(v, CVAR_String);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FBaseCVar::ToBool (UCVarValue value, ECVarType type)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -643,6 +673,12 @@ void FBaseCVar::DisableCallbacks ()
|
|||
m_UseCallback = false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, GetRealType)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
ACTION_RETURN_INT(self->GetRealType());
|
||||
}
|
||||
|
||||
//
|
||||
// Boolean cvar implementation
|
||||
//
|
||||
|
@ -1082,6 +1118,13 @@ void FBaseCVar::ResetToDefault ()
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, ResetToDefault)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
self->ResetToDefault();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Flag cvar implementation
|
||||
//
|
||||
|
@ -1487,6 +1530,13 @@ FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev)
|
|||
return var;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_CVar, FindCVar)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(name);
|
||||
ACTION_RETURN_POINTER(FindCVar(name, nullptr));
|
||||
}
|
||||
|
||||
FBaseCVar *FindCVarSub (const char *var_name, int namelen)
|
||||
{
|
||||
FBaseCVar *var;
|
||||
|
|
|
@ -662,6 +662,14 @@ void C_DoCommand (const char *cmd, int keynum)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Console, DoCommand)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(cmd);
|
||||
C_DoCommand(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AddCommandString (char *cmd, int keynum)
|
||||
{
|
||||
char *brkpt;
|
||||
|
|
|
@ -614,16 +614,16 @@ int strbin (char *str)
|
|||
case '6':
|
||||
case '7':
|
||||
c = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
c <<= 3;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
p++;
|
||||
if (*p >= '0' && *p <= '7')
|
||||
c += *p-'0';
|
||||
c = (c << 3) + *p - '0';
|
||||
else
|
||||
{
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*str++ = c;
|
||||
break;
|
||||
|
@ -717,16 +717,16 @@ FString strbin1 (const char *start)
|
|||
case '6':
|
||||
case '7':
|
||||
c = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
c <<= 3;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
p++;
|
||||
if (*p >= '0' && *p <= '7')
|
||||
c += *p-'0';
|
||||
c = (c << 3) + *p - '0';
|
||||
else
|
||||
{
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
result << c;
|
||||
break;
|
||||
|
|
|
@ -2293,7 +2293,7 @@ static int PatchStrings (int dummy)
|
|||
holdstring.StripRight();
|
||||
if (holdstring.Len() > 0 && holdstring[holdstring.Len()-1] == '\\')
|
||||
{
|
||||
holdstring.Truncate((long)holdstring.Len()-1);
|
||||
holdstring.Truncate(holdstring.Len()-1);
|
||||
Line2 = igets ();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -2520,7 +2520,10 @@ void D_DoomMain (void)
|
|||
|
||||
// Create replacements for dehacked pickups
|
||||
FinishDehPatch();
|
||||
|
||||
|
||||
if (!batchrun) Printf("M_Init: Init menus.\n");
|
||||
M_Init();
|
||||
|
||||
// clean up the compiler symbols which are not needed any longer.
|
||||
RemoveUnusedSymbols();
|
||||
|
||||
|
@ -2538,9 +2541,6 @@ void D_DoomMain (void)
|
|||
bglobal.spawn_tries = 0;
|
||||
bglobal.wanted_botnum = bglobal.getspawned.Size();
|
||||
|
||||
if (!batchrun) Printf ("M_Init: Init menus.\n");
|
||||
M_Init ();
|
||||
|
||||
if (!batchrun) Printf ("P_Init: Init Playloop state.\n");
|
||||
StartScreen->LoadingStatus ("Init game engine", 0x3f);
|
||||
AM_StaticInit();
|
||||
|
@ -2827,3 +2827,10 @@ void FStartupScreen::NetMessage(char const *,...) {}
|
|||
void FStartupScreen::NetDone(void) {}
|
||||
bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; }
|
||||
|
||||
DEFINE_FIELD_X(InputEvent, event_t, type)
|
||||
DEFINE_FIELD_X(InputEvent, event_t, subtype)
|
||||
DEFINE_FIELD_X(InputEvent, event_t, data1)
|
||||
DEFINE_FIELD_X(InputEvent, event_t, data2)
|
||||
DEFINE_FIELD_X(InputEvent, event_t, data3)
|
||||
DEFINE_FIELD_X(InputEvent, event_t, x)
|
||||
DEFINE_FIELD_X(InputEvent, event_t, y)
|
||||
|
|
|
@ -204,6 +204,7 @@ enum EObjectFlags
|
|||
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
||||
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
||||
OF_Released = 1 << 12, // Object was released from the GC system and should not be processed by GC function
|
||||
OF_Abstract = 1 << 13, // Marks a class that cannot be created with CreateNew
|
||||
};
|
||||
|
||||
template<class T> class TObjPtr;
|
||||
|
|
|
@ -1985,7 +1985,7 @@ void PDynArray::DestroyValue(void *addr) const
|
|||
|
||||
void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
|
||||
{
|
||||
memset((char*)base + offset, 0, sizeof(FArray)); // same as constructing an empty array.
|
||||
if (base != nullptr) memset((char*)base + offset, 0, sizeof(FArray)); // same as constructing an empty array.
|
||||
if (special != nullptr)
|
||||
{
|
||||
special->Push(std::make_pair(this, offset));
|
||||
|
@ -3047,6 +3047,10 @@ DObject *PClass::CreateNew() const
|
|||
else
|
||||
memset (mem, 0, Size);
|
||||
|
||||
if (ConstructNative == nullptr)
|
||||
{
|
||||
I_Error("Attempt to instantiate abstract class %s.", TypeName.GetChars());
|
||||
}
|
||||
ConstructNative (mem);
|
||||
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
|
||||
InitializeSpecials(mem, Defaults);
|
||||
|
@ -3165,8 +3169,7 @@ void PClass::InitializeDefaults()
|
|||
{
|
||||
// Copy parent values from the parent defaults.
|
||||
assert(ParentClass != nullptr);
|
||||
ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults);
|
||||
|
||||
if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults);
|
||||
for (const PField *field : Fields)
|
||||
{
|
||||
if (!(field->Flags & VARF_Native))
|
||||
|
|
|
@ -101,7 +101,7 @@ EXTERN_CVAR (Float, snd_musicvolume) // maximum volume for music
|
|||
// Status flags for refresh.
|
||||
//
|
||||
|
||||
enum EMenuState
|
||||
enum EMenuState : int
|
||||
{
|
||||
MENU_Off, // Menu is closed
|
||||
MENU_On, // Menu is opened
|
||||
|
|
|
@ -2307,7 +2307,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
|
||||
WriteZip(filename, savegame_filenames, savegame_content);
|
||||
|
||||
M_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
|
||||
savegameManager.NotifyNewSave (filename.GetChars(), description, okForQuicksave);
|
||||
|
||||
// delete the JSON buffers we created just above. Everything else will
|
||||
// either still be needed or taken care of automatically.
|
||||
|
|
|
@ -589,7 +589,7 @@ bool FMapInfoParser::ParseLookupName(FString &dest)
|
|||
}
|
||||
while (sc.CheckString(","));
|
||||
// strip off the last newline
|
||||
dest.Truncate(long(dest.Len()-1));
|
||||
dest.Truncate(dest.Len()-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
** 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)
|
||||
|
||||
public:
|
||||
|
||||
float mRed;
|
||||
float mGreen;
|
||||
float mBlue;
|
||||
|
||||
int mGridPosX;
|
||||
int mGridPosY;
|
||||
|
||||
int mStartItem;
|
||||
|
||||
FColorCVar *mCVar;
|
||||
|
||||
DColorPickerMenu(DMenu *parent, const char *name, DOptionMenuDescriptor *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 DOptionMenuItemStaticText(name, false);
|
||||
desc->mItems[mStartItem+1] = new DOptionMenuItemStaticText(" ", false);
|
||||
desc->mItems[mStartItem+2] = new DOptionMenuSliderVar("Red", &mRed, 0, 255, 15, 0);
|
||||
desc->mItems[mStartItem+3] = new DOptionMenuSliderVar("Green", &mGreen, 0, 255, 15, 0);
|
||||
desc->mItems[mStartItem+4] = new DOptionMenuSliderVar("Blue", &mBlue, 0, 255, 15, 0);
|
||||
desc->mItems[mStartItem+5] = new DOptionMenuItemStaticText(" ", false);
|
||||
desc->mItems[mStartItem+6] = new DOptionMenuItemCommand("Undo changes", "undocolorpic");
|
||||
desc->mItems[mStartItem+7] = new DOptionMenuItemStaticText(" ", false);
|
||||
for (auto &p : desc->mItems)
|
||||
{
|
||||
GC::WriteBarrier(p);
|
||||
}
|
||||
desc->mSelectedItem = mStartItem + 2;
|
||||
Init(parent, desc);
|
||||
desc->mIndent = 0;
|
||||
desc->CalcIndent();
|
||||
}
|
||||
|
||||
void OnDestroy() override
|
||||
{
|
||||
if (mStartItem >= 0)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DColorPickerMenu, true, false)
|
||||
|
||||
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)
|
||||
{
|
||||
DMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Colorpickermenu);
|
||||
if (desc != NULL && (*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor)))
|
||||
{
|
||||
return new DColorPickerMenu(parent, name, (DOptionMenuDescriptor*)(*desc), cvar);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_FIELD(DColorPickerMenu, mRed);
|
||||
DEFINE_FIELD(DColorPickerMenu, mGreen);
|
||||
DEFINE_FIELD(DColorPickerMenu, mBlue);
|
||||
DEFINE_FIELD(DColorPickerMenu, mGridPosX);
|
||||
DEFINE_FIELD(DColorPickerMenu, mGridPosY);
|
||||
DEFINE_FIELD(DColorPickerMenu, mStartItem);
|
||||
DEFINE_FIELD(DColorPickerMenu, mCVar);
|
|
@ -51,220 +51,79 @@
|
|||
#include "i_music.h"
|
||||
#include "m_joy.h"
|
||||
|
||||
#define NO_IMP
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
|
||||
static TArray<IJoystickConfig *> Joysticks;
|
||||
IJoystickConfig *SELECTED_JOYSTICK;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetCurrentJoystickConfig)
|
||||
{
|
||||
ACTION_RETURN_POINTER(SELECTED_JOYSTICK);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, GetSensitivity)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
ACTION_RETURN_FLOAT(self->GetSensitivity());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, SetSensitivity)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_FLOAT(sens);
|
||||
self->SetSensitivity((float)sens);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisScale)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_INT(axis);
|
||||
ACTION_RETURN_FLOAT(self->GetAxisScale(axis));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisScale)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_INT(axis);
|
||||
PARAM_FLOAT(sens);
|
||||
self->SetAxisScale(axis, (float)sens);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisDeadZone)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_INT(axis);
|
||||
ACTION_RETURN_FLOAT(self->GetAxisDeadZone(axis));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisDeadZone)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_INT(axis);
|
||||
PARAM_FLOAT(dz);
|
||||
self->SetAxisDeadZone(axis, (float)dz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisMap)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_INT(axis);
|
||||
ACTION_RETURN_INT(self->GetAxisMap(axis));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
|
||||
PARAM_INT(axis);
|
||||
PARAM_INT(map);
|
||||
self->SetAxisMap(axis, (EJoyAxis)map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuSliderJoySensitivity : public DOptionMenuSliderBase
|
||||
{
|
||||
public:
|
||||
DOptionMenuSliderJoySensitivity(const char *label, double min, double max, double step, int showval)
|
||||
: DOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
}
|
||||
|
||||
double GetSliderValue()
|
||||
{
|
||||
return SELECTED_JOYSTICK->GetSensitivity();
|
||||
}
|
||||
|
||||
void SetSliderValue(double val)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetSensitivity(float(val));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuSliderJoyScale : public DOptionMenuSliderBase
|
||||
{
|
||||
int mAxis;
|
||||
int mNeg;
|
||||
|
||||
public:
|
||||
DOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval)
|
||||
: DOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
mAxis = axis;
|
||||
mNeg = 1;
|
||||
}
|
||||
|
||||
double GetSliderValue()
|
||||
{
|
||||
double d = SELECTED_JOYSTICK->GetAxisScale(mAxis);
|
||||
mNeg = d < 0? -1:1;
|
||||
return d;
|
||||
}
|
||||
|
||||
void SetSliderValue(double val)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetAxisScale(mAxis, float(val * mNeg));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuSliderJoyDeadZone : public DOptionMenuSliderBase
|
||||
{
|
||||
int mAxis;
|
||||
int mNeg;
|
||||
|
||||
public:
|
||||
DOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval)
|
||||
: DOptionMenuSliderBase(label, min, max, step, showval)
|
||||
{
|
||||
mAxis = axis;
|
||||
mNeg = 1;
|
||||
}
|
||||
|
||||
double GetSliderValue()
|
||||
{
|
||||
double d = SELECTED_JOYSTICK->GetAxisDeadZone(mAxis);
|
||||
mNeg = d < 0? -1:1;
|
||||
return d;
|
||||
}
|
||||
|
||||
void SetSliderValue(double val)
|
||||
{
|
||||
SELECTED_JOYSTICK->SetAxisDeadZone(mAxis, float(val * mNeg));
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuItemJoyMap : public DOptionMenuItemOptionBase
|
||||
{
|
||||
int mAxis;
|
||||
public:
|
||||
|
||||
DOptionMenuItemJoyMap(const char *label, int axis, const char *values, int center)
|
||||
: DOptionMenuItemOptionBase(label, "none", values, NULL, center)
|
||||
{
|
||||
mAxis = axis;
|
||||
}
|
||||
|
||||
int GetSelection()
|
||||
{
|
||||
double f = SELECTED_JOYSTICK->GetAxisMap(mAxis);
|
||||
FOptionValues **opt = OptionValues.CheckKey(mValues);
|
||||
if (opt != NULL && *opt != NULL)
|
||||
{
|
||||
// Map from joystick axis to menu selection.
|
||||
for(unsigned i = 0; i < (*opt)->mValues.Size(); i++)
|
||||
{
|
||||
if (fabs(f - (*opt)->mValues[i].Value) < FLT_EPSILON)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SetSelection(int selection)
|
||||
{
|
||||
FOptionValues **opt = OptionValues.CheckKey(mValues);
|
||||
// Map from menu selection to joystick axis.
|
||||
if (opt == NULL || *opt == NULL || (unsigned)selection >= (*opt)->mValues.Size())
|
||||
{
|
||||
selection = JOYAXIS_None;
|
||||
}
|
||||
else
|
||||
{
|
||||
selection = (int)(*opt)->mValues[selection].Value;
|
||||
}
|
||||
SELECTED_JOYSTICK->SetAxisMap(mAxis, (EJoyAxis)selection);
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuItemInverter : public DOptionMenuItemOptionBase
|
||||
{
|
||||
int mAxis;
|
||||
public:
|
||||
|
||||
DOptionMenuItemInverter(const char *label, int axis, int center)
|
||||
: DOptionMenuItemOptionBase(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 = fabsf(SELECTED_JOYSTICK->GetAxisScale(mAxis));
|
||||
if (Selection) f*=-1;
|
||||
SELECTED_JOYSTICK->SetAxisScale(mAxis, f);
|
||||
}
|
||||
};
|
||||
|
||||
class DJoystickConfigMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DJoystickConfigMenu, DOptionMenu)
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DJoystickConfigMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Executes a CCMD, action is a CCMD name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuItemJoyConfigMenu : public DOptionMenuItemSubmenu
|
||||
{
|
||||
DECLARE_CLASS(DOptionMenuItemJoyConfigMenu, DOptionMenuItemSubmenu)
|
||||
IJoystickConfig *mJoy;
|
||||
public:
|
||||
DOptionMenuItemJoyConfigMenu(const char *label = nullptr, IJoystickConfig *joy = nullptr)
|
||||
: DOptionMenuItemSubmenu(label, "JoystickConfigMenu")
|
||||
{
|
||||
mJoy = joy;
|
||||
}
|
||||
|
||||
bool Activate()
|
||||
{
|
||||
UpdateJoystickConfigMenu(mJoy);
|
||||
return DOptionMenuItemSubmenu::Activate();
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DOptionMenuItemJoyConfigMenu, false, false)
|
||||
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Joystick Menu
|
||||
|
@ -277,12 +136,12 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy)
|
|||
if (desc != NULL && (*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor)))
|
||||
{
|
||||
DOptionMenuDescriptor *opt = (DOptionMenuDescriptor *)*desc;
|
||||
DOptionMenuItem *it;
|
||||
DMenuItemBase *it;
|
||||
opt->mItems.Clear();
|
||||
if (joy == NULL)
|
||||
{
|
||||
opt->mTitle = "Configure Controller";
|
||||
it = new DOptionMenuItemStaticText("Invalid controller specified for menu", false);
|
||||
it = CreateOptionMenuItemStaticText("Invalid controller specified for menu", false);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
else
|
||||
|
@ -291,34 +150,34 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy)
|
|||
|
||||
SELECTED_JOYSTICK = joy;
|
||||
|
||||
it = new DOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3);
|
||||
it = CreateOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuItemStaticText(" ", false);
|
||||
it = CreateOptionMenuItemStaticText(" ", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
if (joy->GetNumAxes() > 0)
|
||||
{
|
||||
it = new DOptionMenuItemStaticText("Axis Configuration", true);
|
||||
it = CreateOptionMenuItemStaticText("Axis Configuration", true);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
for (int i = 0; i < joy->GetNumAxes(); ++i)
|
||||
{
|
||||
it = new DOptionMenuItemStaticText(" ", false);
|
||||
it = CreateOptionMenuItemStaticText(" ", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
it = new DOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false);
|
||||
it = CreateOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3);
|
||||
it = CreateOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuItemInverter("Invert", i, false);
|
||||
it = CreateOptionMenuItemInverter("Invert", i, false);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3);
|
||||
it = CreateOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it = new DOptionMenuItemStaticText("No configurable axes", false);
|
||||
it = CreateOptionMenuItemStaticText("No configurable axes", false);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +203,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
if (desc != NULL && (*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor)))
|
||||
{
|
||||
DOptionMenuDescriptor *opt = (DOptionMenuDescriptor *)*desc;
|
||||
DOptionMenuItem *it;
|
||||
DMenuItemBase *it;
|
||||
opt->mItems.Clear();
|
||||
|
||||
int i;
|
||||
|
@ -368,40 +227,40 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
}
|
||||
|
||||
// Todo: Block joystick for changing this one.
|
||||
it = new DOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false);
|
||||
it = CreateOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
#ifdef _WIN32
|
||||
it = new DOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false);
|
||||
it = CreateOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false);
|
||||
it = CreateOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false);
|
||||
it = CreateOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false);
|
||||
opt->mItems.Push(it);
|
||||
#endif
|
||||
|
||||
it = new DOptionMenuItemStaticText(" ", false);
|
||||
it = CreateOptionMenuItemStaticText(" ", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
if (Joysticks.Size() == 0)
|
||||
{
|
||||
it = new DOptionMenuItemStaticText("No controllers detected", false);
|
||||
it = CreateOptionMenuItemStaticText("No controllers detected", false);
|
||||
opt->mItems.Push(it);
|
||||
if (!use_joystick)
|
||||
{
|
||||
it = new DOptionMenuItemStaticText("Controller support must be", false);
|
||||
it = CreateOptionMenuItemStaticText("Controller support must be", false);
|
||||
opt->mItems.Push(it);
|
||||
it = new DOptionMenuItemStaticText("enabled to detect any", false);
|
||||
it = CreateOptionMenuItemStaticText("enabled to detect any", false);
|
||||
opt->mItems.Push(it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it = new DOptionMenuItemStaticText("Configure controllers:", false);
|
||||
it = CreateOptionMenuItemStaticText("Configure controllers:", false);
|
||||
opt->mItems.Push(it);
|
||||
|
||||
for (int i = 0; i < (int)Joysticks.Size(); ++i)
|
||||
{
|
||||
it = new DOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]);
|
||||
it = CreateOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]);
|
||||
opt->mItems.Push(it);
|
||||
if (i == itemnum) opt->mSelectedItem = opt->mItems.Size();
|
||||
}
|
||||
|
@ -429,7 +288,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
if (i == (int)Joysticks.Size())
|
||||
{
|
||||
SELECTED_JOYSTICK = NULL;
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DJoystickConfigMenu)))
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf("JoystickConfigMenu"))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
}
|
||||
|
|
|
@ -278,309 +278,4 @@ void DListMenu::Drawer ()
|
|||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DMenuItemBase, true, false)
|
||||
|
||||
bool DMenuItemBase::CheckCoordinate(int x, int y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::Ticker()
|
||||
{
|
||||
}
|
||||
|
||||
void DMenuItemBase::Drawer(bool selected)
|
||||
{
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Selectable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((DMenu::MenuTime%8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture (TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Activate()
|
||||
{
|
||||
return false; // cannot be activated
|
||||
}
|
||||
|
||||
FName DMenuItemBase::GetAction(int *pparam)
|
||||
{
|
||||
return mAction;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::SetString(int i, const char *s)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::GetString(int i, char *s, int len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::SetValue(int i, int value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::GetValue(int i, int *pvalue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::Enable(bool on)
|
||||
{
|
||||
mEnabled = on;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenuItemBase, MenuEvent)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenuItemBase);
|
||||
PARAM_INT(key);
|
||||
PARAM_BOOL(fromcontroller);
|
||||
ACTION_RETURN_BOOL(self->MenuEvent(key, fromcontroller));
|
||||
}
|
||||
|
||||
|
||||
bool DMenuItemBase::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckHotkey(int c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetWidth()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// static patch
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DListMenuItemStaticPatch, false, false)
|
||||
|
||||
DListMenuItemStaticPatch::DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered)
|
||||
: DMenuItemBase(x, y)
|
||||
{
|
||||
mTexture = patch;
|
||||
mCentered = centered;
|
||||
}
|
||||
|
||||
void DListMenuItemStaticPatch::Drawer(bool selected)
|
||||
{
|
||||
if (!mTexture.Exists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DListMenuItemStaticText, false, false)
|
||||
|
||||
DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered)
|
||||
: DMenuItemBase(x, y)
|
||||
{
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mColor = color;
|
||||
mCentered = centered;
|
||||
}
|
||||
|
||||
void DListMenuItemStaticText::Drawer(bool selected)
|
||||
{
|
||||
if (mText.IsNotEmpty())
|
||||
{
|
||||
const char *text = mText;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for selectable items
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DListMenuItemSelectable, false, false)
|
||||
|
||||
DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName action, int param)
|
||||
: DMenuItemBase(x, y, action)
|
||||
{
|
||||
mHeight = height;
|
||||
mParam = param;
|
||||
mHotkey = 0;
|
||||
}
|
||||
|
||||
bool DListMenuItemSelectable::CheckCoordinate(int x, int y)
|
||||
{
|
||||
return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here
|
||||
}
|
||||
|
||||
bool DListMenuItemSelectable::Selectable()
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
bool DListMenuItemSelectable::Activate()
|
||||
{
|
||||
M_SetMenu(mAction, mParam);
|
||||
return true;
|
||||
}
|
||||
|
||||
FName DListMenuItemSelectable::GetAction(int *pparam)
|
||||
{
|
||||
if (pparam != NULL) *pparam = mParam;
|
||||
return mAction;
|
||||
}
|
||||
|
||||
bool DListMenuItemSelectable::CheckHotkey(int c)
|
||||
{
|
||||
return c == tolower(mHotkey);
|
||||
}
|
||||
|
||||
bool DListMenuItemSelectable::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == DMenu::MOUSE_Release)
|
||||
{
|
||||
if (NULL != DMenu::CurrentMenu && DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// text item
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DListMenuItemText, false, false)
|
||||
|
||||
DListMenuItemText::DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param)
|
||||
: DListMenuItemSelectable(x, y, height, child, param)
|
||||
{
|
||||
mText = ncopystring(text);
|
||||
mFont = font;
|
||||
mColor = color;
|
||||
mColorSelected = color2;
|
||||
mHotkey = hotkey;
|
||||
}
|
||||
|
||||
void DListMenuItemText::OnDestroy()
|
||||
{
|
||||
if (mText != NULL)
|
||||
{
|
||||
delete [] mText;
|
||||
}
|
||||
}
|
||||
|
||||
void DListMenuItemText::Drawer(bool selected)
|
||||
{
|
||||
const char *text = mText;
|
||||
if (text != NULL)
|
||||
{
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
screen->DrawText(mFont, selected ? mColorSelected : mColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
int DListMenuItemText::GetWidth()
|
||||
{
|
||||
const char *text = mText;
|
||||
if (text != NULL)
|
||||
{
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
return mFont->StringWidth(text);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// patch item
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DListMenuItemPatch, false, false)
|
||||
|
||||
DListMenuItemPatch::DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param)
|
||||
: DListMenuItemSelectable(x, y, height, child, param)
|
||||
{
|
||||
mHotkey = hotkey;
|
||||
mTexture = patch;
|
||||
}
|
||||
|
||||
void DListMenuItemPatch::Drawer(bool selected)
|
||||
{
|
||||
screen->DrawTexture (TexMan(mTexture), mXpos, mYpos, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
|
||||
int DListMenuItemPatch::GetWidth()
|
||||
{
|
||||
return mTexture.isValid()
|
||||
? TexMan[mTexture]->GetScaledWidth()
|
||||
: 0;
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS(DMenuItemBase, false, false)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -70,8 +70,19 @@ CVAR(Int, m_use_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DMenu *DMenu::CurrentMenu;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu)
|
||||
{
|
||||
ACTION_RETURN_OBJECT(DMenu::CurrentMenu);
|
||||
}
|
||||
|
||||
int DMenu::MenuTime;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, MenuTime)
|
||||
{
|
||||
ACTION_RETURN_INT(DMenu::MenuTime);
|
||||
}
|
||||
|
||||
FGameStartup GameStartupInfo;
|
||||
EMenuState menuactive;
|
||||
bool M_DemoNoPlay;
|
||||
|
@ -82,6 +93,8 @@ int BackbuttonTime;
|
|||
float BackbuttonAlpha;
|
||||
static bool MenuEnabled = true;
|
||||
|
||||
void M_InitVideoModes();
|
||||
|
||||
|
||||
#define KEY_REPEAT_DELAY (TICRATE*5/12)
|
||||
#define KEY_REPEAT_RATE (3)
|
||||
|
@ -96,6 +109,14 @@ IMPLEMENT_CLASS(DMenuDescriptor, false, false)
|
|||
IMPLEMENT_CLASS(DListMenuDescriptor, false, false)
|
||||
IMPLEMENT_CLASS(DOptionMenuDescriptor, false, false)
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenuDescriptor, GetDescriptor)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(name);
|
||||
DMenuDescriptor **desc = MenuDescriptors.CheckKey(name);
|
||||
auto retn = desc ? *desc : nullptr;
|
||||
ACTION_RETURN_OBJECT(retn);
|
||||
}
|
||||
|
||||
size_t DListMenuDescriptor::PropagateMark()
|
||||
{
|
||||
|
@ -180,6 +201,26 @@ bool DMenu::Responder (event_t *ev)
|
|||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, Responder)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_POINTER(ev, event_t);
|
||||
ACTION_RETURN_BOOL(self->Responder(ev));
|
||||
}
|
||||
|
||||
bool DMenu::CallResponder(event_t *ev)
|
||||
{
|
||||
IFVIRTUAL(DMenu, Responder)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, ev};
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
else return Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -337,6 +378,24 @@ void DMenu::Ticker ()
|
|||
{
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, Ticker)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
self->Drawer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DMenu::CallTicker()
|
||||
{
|
||||
IFVIRTUAL(DMenu, Ticker)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
else Drawer();
|
||||
}
|
||||
|
||||
|
||||
void DMenu::Drawer ()
|
||||
{
|
||||
if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
|
@ -375,6 +434,20 @@ void DMenu::CallDrawer()
|
|||
else Drawer();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, Close)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
self->Close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_NAME(name);
|
||||
ACTION_RETURN_OBJECT(self->GetItem(name));
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool DMenu::DimAllowed()
|
||||
|
@ -384,6 +457,14 @@ bool DMenu::DimAllowed()
|
|||
|
||||
bool DMenu::TranslateKeyboardEvents()
|
||||
{
|
||||
IFVIRTUAL(DMenu, TranslateKeyboardEvents)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -433,6 +514,13 @@ void M_ActivateMenu(DMenu *menu)
|
|||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
M_ActivateMenu(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -500,6 +588,11 @@ void M_SetMenu(FName menu, int param)
|
|||
M_StartMessage (GStrings("SAVEDEAD"), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
case NAME_VideoModeMenu:
|
||||
M_InitVideoModes();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// End of special checks
|
||||
|
@ -533,10 +626,14 @@ void M_SetMenu(FName menu, int param)
|
|||
else if ((*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor)))
|
||||
{
|
||||
DOptionMenuDescriptor *ld = static_cast<DOptionMenuDescriptor*>(*desc);
|
||||
const PClass *cls = ld->mClass == nullptr? RUNTIME_CLASS(DOptionMenu) : ld->mClass;
|
||||
const PClass *cls = ld->mClass == nullptr? PClass::FindClass("OptionMenu") : ld->mClass;
|
||||
|
||||
DOptionMenu *newmenu = (DOptionMenu *)cls->CreateNew();
|
||||
newmenu->Init(DMenu::CurrentMenu, ld);
|
||||
DMenu *newmenu = (DMenu*)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init)
|
||||
{
|
||||
VMValue params[3] = { newmenu, DMenu::CurrentMenu, ld };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0);
|
||||
}
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
return;
|
||||
|
@ -559,6 +656,14 @@ void M_SetMenu(FName menu, int param)
|
|||
M_ClearMenus();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, SetMenu)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(menu);
|
||||
PARAM_INT(mparam);
|
||||
M_SetMenu(menu, mparam);
|
||||
return 0;
|
||||
}
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -612,7 +717,7 @@ bool M_Responder (event_t *ev)
|
|||
}
|
||||
|
||||
// pass everything else on to the current menu
|
||||
return DMenu::CurrentMenu->Responder(ev);
|
||||
return DMenu::CurrentMenu->CallResponder(ev);
|
||||
}
|
||||
else if (DMenu::CurrentMenu->TranslateKeyboardEvents())
|
||||
{
|
||||
|
@ -633,7 +738,7 @@ bool M_Responder (event_t *ev)
|
|||
default:
|
||||
if (!keyup)
|
||||
{
|
||||
return DMenu::CurrentMenu->Responder(ev);
|
||||
return DMenu::CurrentMenu->CallResponder(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -720,7 +825,7 @@ bool M_Responder (event_t *ev)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return DMenu::CurrentMenu->Responder(ev) || !keyup;
|
||||
return DMenu::CurrentMenu->CallResponder(ev) || !keyup;
|
||||
}
|
||||
else if (MenuEnabled)
|
||||
{
|
||||
|
@ -764,7 +869,7 @@ void M_Ticker (void)
|
|||
DMenu::MenuTime++;
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
DMenu::CurrentMenu->Ticker();
|
||||
DMenu::CurrentMenu->CallTicker();
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
|
@ -773,7 +878,7 @@ void M_Ticker (void)
|
|||
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
||||
{
|
||||
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
||||
DMenu::CurrentMenu->MenuEvent(i, MenuButtonOrigin[i]);
|
||||
DMenu::CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1071,10 +1176,23 @@ CCMD(reset2saved)
|
|||
}
|
||||
|
||||
|
||||
// This really should be in the script but we can't do scripted CCMDs yet.
|
||||
CCMD(undocolorpic)
|
||||
{
|
||||
if (DMenu::CurrentMenu != NULL)
|
||||
{
|
||||
IFVIRTUALPTR(DMenu::CurrentMenu, DMenu, ResetColor)
|
||||
{
|
||||
VMValue params[] = { (DObject*)DMenu::CurrentMenu };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//native void OptionMenuDescriptor.CalcIndent();
|
||||
//native OptionMenuItem OptionMenuDescriptor.GetItem(Name iname);
|
||||
//native void OptionMenuItem.drawLabel(int indent, int y, EColorRange color, bool grayed = false);
|
||||
|
||||
|
||||
|
||||
DEFINE_FIELD(DMenu, mParentMenu)
|
||||
|
||||
DEFINE_FIELD(DMenuDescriptor, mMenuName)
|
||||
DEFINE_FIELD(DMenuDescriptor, mNetgameMessage)
|
||||
|
@ -1085,6 +1203,23 @@ DEFINE_FIELD(DMenuItemBase, mYpos)
|
|||
DEFINE_FIELD(DMenuItemBase, mAction)
|
||||
DEFINE_FIELD(DMenuItemBase, mEnabled)
|
||||
|
||||
DEFINE_FIELD(DListMenuDescriptor, mItems)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectedItem)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectOfsX)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectOfsY)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelector)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mDisplayTop)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mXpos)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mYpos)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mWLeft)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mWRight)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mLinespacing)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mAutoselect)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mFont)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mFontColor)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mFontColor2)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mCenter)
|
||||
|
||||
DEFINE_FIELD(DOptionMenuDescriptor, mItems)
|
||||
DEFINE_FIELD(DOptionMenuDescriptor, mTitle)
|
||||
DEFINE_FIELD(DOptionMenuDescriptor, mSelectedItem)
|
||||
|
@ -1095,15 +1230,6 @@ DEFINE_FIELD(DOptionMenuDescriptor, mIndent)
|
|||
DEFINE_FIELD(DOptionMenuDescriptor, mPosition)
|
||||
DEFINE_FIELD(DOptionMenuDescriptor, mDontDim)
|
||||
|
||||
DEFINE_FIELD(DOptionMenuItem, mLabel)
|
||||
DEFINE_FIELD(DOptionMenuItem, mCentered)
|
||||
|
||||
DEFINE_FIELD(DOptionMenu, CanScrollUp)
|
||||
DEFINE_FIELD(DOptionMenu, CanScrollDown)
|
||||
DEFINE_FIELD(DOptionMenu, VisBottom)
|
||||
DEFINE_FIELD(DOptionMenu, mFocusControl)
|
||||
DEFINE_FIELD(DOptionMenu, mDesc)
|
||||
|
||||
DEFINE_FIELD(FOptionMenuSettings, mTitleColor)
|
||||
DEFINE_FIELD(FOptionMenuSettings, mFontColor)
|
||||
DEFINE_FIELD(FOptionMenuSettings, mFontColorValue)
|
||||
|
@ -1112,3 +1238,380 @@ DEFINE_FIELD(FOptionMenuSettings, mFontColorHeader)
|
|||
DEFINE_FIELD(FOptionMenuSettings, mFontColorHighlight)
|
||||
DEFINE_FIELD(FOptionMenuSettings, mFontColorSelection)
|
||||
DEFINE_FIELD(FOptionMenuSettings, mLinespacing)
|
||||
|
||||
|
||||
struct IJoystickConfig;
|
||||
DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemStaticText");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(name), v };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuSliderVar(const char *name, int index, double min, double max, double step, int showval)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemSliderVar");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(name), index, min, max, step, showval };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemCommand(const char * label, FName cmd)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemCommand");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), cmd.GetIndex() };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemOption(const char * label, FName cmd, FName values, FBaseCVar *graycheck, bool center)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemOption");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), cmd.GetIndex(), values.GetIndex(), graycheck, center };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemJoyConfigMenu");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), joy };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemJoyMap(const char *label, int axis, FName values, bool center)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemJoyMap");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), axis, values.GetIndex(), center };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double min, double max, double step, int showval)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuSliderJoySensitivity");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), min, max, step, showval };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuSliderJoyScale");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), min, max, step, showval };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemInverter");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), axis, center };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuSliderJoyDeadZone");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), min, max, step, showval };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemSubmenu");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), cmd.GetIndex(), center };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings)
|
||||
{
|
||||
auto c = PClass::FindClass("OptionMenuItemControl");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, FString(label), cmd.GetIndex(), bindings };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param)
|
||||
{
|
||||
auto c = PClass::FindClass("ListMenuItemPatchItem");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, x, y, height, tex.GetIndex(), FString(char(hotkey)), command.GetIndex(), param };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("InitDirect", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param)
|
||||
{
|
||||
auto c = PClass::FindClass("ListMenuItemTextItem");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, x, y, height, FString(char(hotkey)), text, font, int(color1.d), int(color2.d), command.GetIndex(), param };
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("InitDirect", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckCoordinate(int x, int y)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, CheckCoordinate)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, x, y };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::Ticker()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Ticker)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DMenuItemBase::Drawer(bool selected)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Drawer)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, selected };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Selectable()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Selectable)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Activate()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Activate)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
FName DMenuItemBase::GetAction(int *pparam)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetAction)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval[2];
|
||||
VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]);
|
||||
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
|
||||
return ENamedName(retval[0]);
|
||||
}
|
||||
return NAME_None;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::SetString(int i, const char *s)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, SetString)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, i, FString(s) };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::GetString(int i, char *s, int len)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetString)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, i };
|
||||
int retval;
|
||||
FString retstr;
|
||||
VMReturn ret[2]; ret[0].IntAt(&retval); ret[1].StringAt(&retstr);
|
||||
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
|
||||
strncpy(s, retstr, len);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DMenuItemBase::SetValue(int i, int value)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, SetValue)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, i, value };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::GetValue(int i, int *pvalue)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetValue)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, i };
|
||||
int retval[2];
|
||||
VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]);
|
||||
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
|
||||
*pvalue = retval[1];
|
||||
return !!retval[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DMenuItemBase::Enable(bool on)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Enable)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, on };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, MenuEvent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, mkey, fromcontroller };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, MouseEvent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, x, y };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckHotkey(int c)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, CheckHotkey)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, c };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetWidth()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetWidth)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetIndent()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetIndent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Draw)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, desc, y, indent, selected };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((DMenu::MenuTime % 8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture(TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
407
src/menu/menu.h
407
src/menu/menu.h
|
@ -22,6 +22,7 @@ class FFont;
|
|||
enum EColorRange : int;
|
||||
class FPlayerClass;
|
||||
class FKeyBindings;
|
||||
struct FBrokenLines;
|
||||
|
||||
enum EMenuKey
|
||||
{
|
||||
|
@ -66,7 +67,37 @@ struct FSaveGameNode
|
|||
FSaveGameNode() { bNoDelete = false; }
|
||||
};
|
||||
|
||||
struct SavegameManager
|
||||
{
|
||||
TArray<FSaveGameNode*> SaveGames;
|
||||
int LastSaved = -1;
|
||||
int LastAccessed = -1;
|
||||
int WindowSize = 0;
|
||||
FSaveGameNode *quickSaveSlot = nullptr;
|
||||
|
||||
FileReader *currentSavePic = nullptr;
|
||||
TArray<char> SavePicData;
|
||||
|
||||
FTexture *SavePic = nullptr;
|
||||
FBrokenLines *SaveComment = nullptr;
|
||||
|
||||
void ClearSaveGames();
|
||||
int InsertSaveNode(FSaveGameNode *node);
|
||||
int RemoveSaveSlot(int index);
|
||||
void ReadSaveStrings();
|
||||
void NotifyNewSave(const char *file, const char *title, bool okForQuicksave);
|
||||
void LoadSavegame(int Selected);
|
||||
void DoSave(int Selected, const char *savegamestring);
|
||||
void DeleteEntry(int Selected);
|
||||
void ExtractSaveData(int index);
|
||||
void UnloadSaveData();
|
||||
void ClearSaveStuff();
|
||||
bool DrawSavePic(int x, int y, int w, int h);
|
||||
void SetFileInfo(int Selected);
|
||||
|
||||
};
|
||||
|
||||
extern SavegameManager savegameManager;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -87,7 +118,6 @@ public:
|
|||
};
|
||||
|
||||
class DMenuItemBase;
|
||||
class DOptionMenuItem;
|
||||
|
||||
class DListMenuDescriptor : public DMenuDescriptor
|
||||
{
|
||||
|
@ -145,7 +175,7 @@ class DOptionMenuDescriptor : public DMenuDescriptor
|
|||
DECLARE_CLASS(DOptionMenuDescriptor, DMenuDescriptor)
|
||||
|
||||
public:
|
||||
TArray<DOptionMenuItem *> mItems;
|
||||
TArray<DMenuItemBase *> mItems;
|
||||
FString mTitle;
|
||||
int mSelectedItem;
|
||||
int mDrawTop;
|
||||
|
@ -156,7 +186,7 @@ public:
|
|||
bool mDontDim;
|
||||
|
||||
void CalcIndent();
|
||||
DOptionMenuItem *GetItem(FName name);
|
||||
DMenuItemBase *GetItem(FName name);
|
||||
void Reset()
|
||||
{
|
||||
// Reset the default settings (ignore all other values in the struct)
|
||||
|
@ -239,12 +269,20 @@ public:
|
|||
virtual void Ticker ();
|
||||
virtual void Drawer ();
|
||||
virtual bool DimAllowed ();
|
||||
virtual bool TranslateKeyboardEvents();
|
||||
bool TranslateKeyboardEvents();
|
||||
virtual void Close();
|
||||
virtual bool MouseEvent(int type, int x, int y);
|
||||
|
||||
virtual void SetFocus(DMenuItemBase *fc) {}
|
||||
virtual bool CheckFocus(DMenuItemBase *fc) { return false; }
|
||||
virtual void ReleaseFocus() {}
|
||||
|
||||
virtual DMenuItemBase *GetItem(FName name) { return nullptr; }
|
||||
|
||||
bool CallResponder(event_t *ev);
|
||||
bool CallMenuEvent(int mkey, bool fromcontroller);
|
||||
bool CallMouseEvent(int type, int x, int y);
|
||||
void CallTicker();
|
||||
void CallDrawer();
|
||||
|
||||
bool MouseEventBack(int type, int x, int y);
|
||||
|
@ -267,256 +305,35 @@ class DMenuItemBase : public DObject
|
|||
DECLARE_CLASS(DMenuItemBase, DObject)
|
||||
public:
|
||||
int mXpos, mYpos;
|
||||
FName mAction;
|
||||
|
||||
FNameNoInit mAction;
|
||||
bool mEnabled;
|
||||
|
||||
DMenuItemBase(int xpos = 0, int ypos = 0, FName action = NAME_None)
|
||||
{
|
||||
mXpos = xpos;
|
||||
mYpos = ypos;
|
||||
mAction = action;
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
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);
|
||||
virtual int GetWidth();
|
||||
void DrawSelector(int xofs, int yofs, FTextureID tex);
|
||||
bool CheckCoordinate(int x, int y);
|
||||
void Ticker();
|
||||
void Drawer(bool selected);
|
||||
bool Selectable();
|
||||
bool Activate();
|
||||
FName GetAction(int *pparam);
|
||||
bool SetString(int i, const char *s);
|
||||
bool GetString(int i, char *s, int len);
|
||||
bool SetValue(int i, int value);
|
||||
bool GetValue(int i, int *pvalue);
|
||||
void Enable(bool on);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
bool CheckHotkey(int c);
|
||||
int GetWidth();
|
||||
int GetIndent();
|
||||
int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected);
|
||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||
int GetY() { return mYpos; }
|
||||
int GetX() { return mXpos; }
|
||||
void SetX(int x) { mXpos = x; }
|
||||
|
||||
void DrawSelector(int xofs, int yofs, FTextureID tex);
|
||||
|
||||
};
|
||||
|
||||
class DListMenuItemStaticPatch : public DMenuItemBase
|
||||
{
|
||||
DECLARE_CLASS(DListMenuItemStaticPatch, DMenuItemBase)
|
||||
protected:
|
||||
FTextureID mTexture;
|
||||
bool mCentered;
|
||||
|
||||
DListMenuItemStaticPatch() {}
|
||||
public:
|
||||
DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered);
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
class DListMenuItemStaticText : public DMenuItemBase
|
||||
{
|
||||
DECLARE_CLASS(DListMenuItemStaticText, DMenuItemBase)
|
||||
protected:
|
||||
FString mText;
|
||||
FFont *mFont;
|
||||
EColorRange mColor;
|
||||
bool mCentered;
|
||||
|
||||
DListMenuItemStaticText() {}
|
||||
public:
|
||||
DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered);
|
||||
void Drawer(bool selected);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// the player sprite window
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DListMenuItemPlayerDisplay : public DMenuItemBase
|
||||
{
|
||||
DECLARE_CLASS(DListMenuItemPlayerDisplay, DMenuItemBase)
|
||||
|
||||
DListMenuDescriptor *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();
|
||||
void UpdateTranslation();
|
||||
|
||||
DListMenuItemPlayerDisplay() {}
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
PDF_ROTATION = 0x10001,
|
||||
PDF_SKIN = 0x10002,
|
||||
PDF_CLASS = 0x10003,
|
||||
PDF_MODE = 0x10004,
|
||||
PDF_TRANSLATE = 0x10005,
|
||||
};
|
||||
|
||||
DListMenuItemPlayerDisplay(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action);
|
||||
void OnDestroy() override;
|
||||
virtual void Ticker();
|
||||
virtual void Drawer(bool selected);
|
||||
bool SetValue(int i, int value);
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// selectable items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DListMenuItemSelectable : public DMenuItemBase
|
||||
{
|
||||
DECLARE_CLASS(DListMenuItemSelectable, DMenuItemBase)
|
||||
protected:
|
||||
int mHotkey;
|
||||
int mHeight;
|
||||
int mParam;
|
||||
|
||||
DListMenuItemSelectable() {}
|
||||
public:
|
||||
DListMenuItemSelectable(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 DListMenuItemText : public DListMenuItemSelectable
|
||||
{
|
||||
DECLARE_CLASS(DListMenuItemText, DListMenuItemSelectable)
|
||||
const char *mText;
|
||||
FFont *mFont;
|
||||
EColorRange mColor;
|
||||
EColorRange mColorSelected;
|
||||
|
||||
DListMenuItemText() {}
|
||||
public:
|
||||
DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0);
|
||||
void OnDestroy() override;
|
||||
void Drawer(bool selected);
|
||||
int GetWidth();
|
||||
};
|
||||
|
||||
class DListMenuItemPatch : public DListMenuItemSelectable
|
||||
{
|
||||
DECLARE_CLASS(DListMenuItemPatch, DListMenuItemSelectable)
|
||||
FTextureID mTexture;
|
||||
|
||||
DListMenuItemPatch() {}
|
||||
public:
|
||||
DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0);
|
||||
void Drawer(bool selected);
|
||||
int GetWidth();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DPlayerNameBox : public DListMenuItemSelectable
|
||||
{
|
||||
DECLARE_CLASS(DPlayerNameBox, DListMenuItemSelectable)
|
||||
FString 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);
|
||||
|
||||
DPlayerNameBox() {}
|
||||
public:
|
||||
|
||||
DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action);
|
||||
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 DValueTextItem : public DListMenuItemSelectable
|
||||
{
|
||||
DECLARE_CLASS(DValueTextItem, DListMenuItemSelectable)
|
||||
TArray<FString> mSelections;
|
||||
FString mText;
|
||||
int mSelection;
|
||||
FFont *mFont;
|
||||
EColorRange mFontColor;
|
||||
EColorRange mFontColor2;
|
||||
|
||||
DValueTextItem() {}
|
||||
public:
|
||||
|
||||
DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values);
|
||||
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 DSliderItem : public DListMenuItemSelectable
|
||||
{
|
||||
DECLARE_CLASS(DSliderItem, DListMenuItemSelectable)
|
||||
FString mText;
|
||||
FFont *mFont;
|
||||
EColorRange mFontColor;
|
||||
int mMinrange, mMaxrange;
|
||||
int mStep;
|
||||
int mSelection;
|
||||
|
||||
void DrawSlider (int x, int y);
|
||||
|
||||
DSliderItem() {}
|
||||
public:
|
||||
|
||||
DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step);
|
||||
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 DListMenuDescriptor
|
||||
|
@ -556,34 +373,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenuItem : public DMenuItemBase
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DOptionMenuItem, DMenuItemBase)
|
||||
public:
|
||||
FString mLabel;
|
||||
bool mCentered;
|
||||
|
||||
void drawLabel(int indent, int y, EColorRange color, bool grayed = false);
|
||||
|
||||
DOptionMenuItem(const char *text = nullptr, FName action = NAME_None, bool center = false)
|
||||
: DMenuItemBase(0, 0, action)
|
||||
{
|
||||
mLabel = text;
|
||||
mCentered = center;
|
||||
}
|
||||
|
||||
virtual int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected);
|
||||
virtual bool Selectable();
|
||||
virtual int GetIndent();
|
||||
virtual bool MouseEvent(int type, int x, int y);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -606,50 +395,6 @@ typedef TMap< FName, FOptionValues* > FOptionMap;
|
|||
extern FOptionMap OptionValues;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Option menu class runs a menu described by a DOptionMenuDescriptor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DOptionMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DOptionMenu, DMenu)
|
||||
HAS_OBJECT_POINTERS;
|
||||
|
||||
public: // needs to be public for script access
|
||||
bool CanScrollUp;
|
||||
bool CanScrollDown;
|
||||
int VisBottom;
|
||||
DOptionMenuItem *mFocusControl;
|
||||
DOptionMenuDescriptor *mDesc;
|
||||
|
||||
//public:
|
||||
DOptionMenuItem *GetItem(FName name);
|
||||
DOptionMenu(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL);
|
||||
virtual void Init(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL);
|
||||
int FirstSelectable();
|
||||
bool Responder (event_t *ev);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void Ticker ();
|
||||
void Drawer ();
|
||||
const DOptionMenuDescriptor *GetDescriptor() const { return mDesc; }
|
||||
void SetFocus(DOptionMenuItem *fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
}
|
||||
bool CheckFocus(DOptionMenuItem *fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Input some text
|
||||
|
@ -660,7 +405,8 @@ class DTextEnterMenu : public DMenu
|
|||
{
|
||||
DECLARE_ABSTRACT_CLASS(DTextEnterMenu, DMenu)
|
||||
|
||||
char *mEnterString;
|
||||
public:
|
||||
FString mEnterString;
|
||||
unsigned int mEnterSize;
|
||||
unsigned int mEnterPos;
|
||||
int mSizeMode; // 1: size is length in chars. 2: also check string width
|
||||
|
@ -672,17 +418,15 @@ class DTextEnterMenu : public DMenu
|
|||
// [TP]
|
||||
bool AllowColors;
|
||||
|
||||
public:
|
||||
|
||||
// [TP] Added allowcolors
|
||||
DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false);
|
||||
DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false);
|
||||
|
||||
void Drawer ();
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool Responder(event_t *ev);
|
||||
bool TranslateKeyboardEvents();
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
|
||||
FString GetText();
|
||||
};
|
||||
|
||||
|
||||
|
@ -702,7 +446,6 @@ void M_StartupSkillMenu(FGameStartup *gs);
|
|||
int M_GetDefaultSkill();
|
||||
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 ();
|
||||
|
@ -710,4 +453,20 @@ void M_InitVideoModesMenu ();
|
|||
void M_MarkMenus();
|
||||
|
||||
|
||||
struct IJoystickConfig;
|
||||
DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v);
|
||||
DMenuItemBase * CreateOptionMenuSliderVar(const char *name, int index, double min, double max, double step, int showval);
|
||||
DMenuItemBase * CreateOptionMenuItemCommand(const char * label, FName cmd);
|
||||
DMenuItemBase * CreateOptionMenuItemOption(const char * label, FName cmd, FName values, FBaseCVar *graycheck, bool center);
|
||||
DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center);
|
||||
DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings);
|
||||
DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy);
|
||||
DMenuItemBase * CreateOptionMenuItemJoyMap(const char *label, int axis, FName values, bool center);
|
||||
DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double min, double max, double step, int showval);
|
||||
DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval);
|
||||
DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center);
|
||||
DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval);
|
||||
DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param);
|
||||
DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
#include "i_sound.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
|
||||
void ClearSaveGames();
|
||||
|
||||
|
@ -65,6 +65,71 @@ bool mustPrintErrors;
|
|||
|
||||
void I_BuildALDeviceList(FOptionValues *opt);
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FOptionValues, GetCount)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(grp);
|
||||
int cnt = 0;
|
||||
FOptionValues **pGrp = OptionValues.CheckKey(grp);
|
||||
if (pGrp != nullptr)
|
||||
{
|
||||
cnt = (*pGrp)->mValues.Size();
|
||||
}
|
||||
ACTION_RETURN_INT(cnt);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FOptionValues, GetValue)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(grp);
|
||||
PARAM_UINT(index);
|
||||
double val = 0;
|
||||
FOptionValues **pGrp = OptionValues.CheckKey(grp);
|
||||
if (pGrp != nullptr)
|
||||
{
|
||||
if (index < (*pGrp)->mValues.Size())
|
||||
{
|
||||
val = (*pGrp)->mValues[index].Value;
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_FLOAT(val);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FOptionValues, GetTextValue)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(grp);
|
||||
PARAM_UINT(index);
|
||||
FString val;
|
||||
FOptionValues **pGrp = OptionValues.CheckKey(grp);
|
||||
if (pGrp != nullptr)
|
||||
{
|
||||
if (index < (*pGrp)->mValues.Size())
|
||||
{
|
||||
val = (*pGrp)->mValues[index].TextValue;
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_STRING(val);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FOptionValues, GetText)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(grp);
|
||||
PARAM_UINT(index);
|
||||
FString val;
|
||||
FOptionValues **pGrp = OptionValues.CheckKey(grp);
|
||||
if (pGrp != nullptr)
|
||||
{
|
||||
if (index < (*pGrp)->mValues.Size())
|
||||
{
|
||||
val = (*pGrp)->mValues[index].Text;
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_STRING(val);
|
||||
}
|
||||
|
||||
|
||||
static void DeinitMenus()
|
||||
{
|
||||
{
|
||||
|
@ -81,7 +146,7 @@ static void DeinitMenus()
|
|||
MenuDescriptors.Clear();
|
||||
OptionValues.Clear();
|
||||
DMenu::CurrentMenu = nullptr;
|
||||
ClearSaveGames();
|
||||
savegameManager.ClearSaveGames();
|
||||
}
|
||||
|
||||
static FTextureID GetMenuTexture(const char* const name)
|
||||
|
@ -269,87 +334,6 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
sc.MustGetNumber();
|
||||
desc->mWRight = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("StaticPatch") || sc.Compare("StaticPatchCentered"))
|
||||
{
|
||||
bool centered = sc.Compare("StaticPatchCentered");
|
||||
sc.MustGetNumber();
|
||||
int x = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int y = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FTextureID tex = GetMenuTexture(sc.String);
|
||||
|
||||
DMenuItemBase *it = new DListMenuItemStaticPatch(x, y, tex, centered);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered"))
|
||||
{
|
||||
bool centered = sc.Compare("StaticTextCentered");
|
||||
sc.MustGetNumber();
|
||||
int x = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int y = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
EColorRange cr = desc->mFontColor;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetString();
|
||||
cr = V_FindFontColor(sc.String);
|
||||
if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated")) cr = desc->mFontColor;
|
||||
}
|
||||
DMenuItemBase *it = new DListMenuItemStaticText(x, y, label, desc->mFont, cr, centered);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("PatchItem"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FTextureID tex = GetMenuTexture(sc.String);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
int hotkey = sc.String[0];
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FName action = sc.String;
|
||||
int param = 0;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
param = sc.Number;
|
||||
}
|
||||
|
||||
DMenuItemBase *it = new DListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param);
|
||||
desc->mItems.Push(it);
|
||||
desc->mYpos += desc->mLinespacing;
|
||||
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
|
||||
}
|
||||
else if (sc.Compare("TextItem"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString text = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
int hotkey = sc.String[0];
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FName action = sc.String;
|
||||
int param = 0;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
param = sc.Number;
|
||||
}
|
||||
|
||||
DMenuItemBase *it = new DListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param);
|
||||
desc->mItems.Push(it);
|
||||
desc->mYpos += desc->mLinespacing;
|
||||
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
|
||||
|
||||
}
|
||||
else if (sc.Compare("Font"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
|
@ -376,90 +360,134 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
sc.MustGetString();
|
||||
desc->mNetgameMessage = sc.String;
|
||||
}
|
||||
else if (sc.Compare("PlayerDisplay"))
|
||||
{
|
||||
bool noportrait = false;
|
||||
FName action = NAME_None;
|
||||
sc.MustGetNumber();
|
||||
int x = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int y = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
PalEntry c1 = V_GetColor(nullptr, sc);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
PalEntry c2 = V_GetColor(nullptr, sc);
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
noportrait = !!sc.Number;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetString();
|
||||
action = sc.String;
|
||||
}
|
||||
}
|
||||
DListMenuItemPlayerDisplay *it = new DListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("PlayerNameBox"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString text = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int ofs = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DMenuItemBase *it = new DPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String);
|
||||
desc->mItems.Push(it);
|
||||
desc->mYpos += desc->mLinespacing;
|
||||
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
|
||||
}
|
||||
else if (sc.Compare("ValueText"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString text = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FName action = sc.String;
|
||||
FName values;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetString();
|
||||
values = sc.String;
|
||||
}
|
||||
DMenuItemBase *it = new DValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values);
|
||||
desc->mItems.Push(it);
|
||||
desc->mYpos += desc->mLinespacing;
|
||||
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
|
||||
}
|
||||
else if (sc.Compare("Slider"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString text = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString action = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int min = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int max = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
int step = sc.Number;
|
||||
DMenuItemBase *it = new DSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step);
|
||||
desc->mItems.Push(it);
|
||||
desc->mYpos += desc->mLinespacing;
|
||||
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
||||
bool success = false;
|
||||
FStringf buildname("ListMenuItem%s", sc.String);
|
||||
PClass *cls = PClass::FindClass(buildname);
|
||||
if (cls != nullptr && cls->IsDescendantOf("ListMenuItem"))
|
||||
{
|
||||
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", false));
|
||||
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
|
||||
{
|
||||
auto &args = func->Variants[0].Proto->ArgumentTypes;
|
||||
TArray<VMValue> params;
|
||||
int start = 1;
|
||||
|
||||
params.Push(0);
|
||||
if (args.Size() > 1 && args[1] == NewPointer(PClass::FindClass("ListMenuDescriptor")))
|
||||
{
|
||||
params.Push(desc);
|
||||
start = 2;
|
||||
}
|
||||
auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr));
|
||||
|
||||
for (unsigned i = start; i < args.Size(); i++)
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (args[i] == TypeString)
|
||||
{
|
||||
params.Push(FString(sc.String));
|
||||
}
|
||||
else if (args[i] == TypeName)
|
||||
{
|
||||
params.Push(FName(sc.String).GetIndex());
|
||||
}
|
||||
else if (args[i] == TypeColor)
|
||||
{
|
||||
params.Push(V_GetColor(nullptr, sc));
|
||||
}
|
||||
else if (args[i] == TypeFont)
|
||||
{
|
||||
auto f = FFont::FindFont(sc.String);
|
||||
if (f == nullptr)
|
||||
{
|
||||
sc.ScriptError("Unknown font %s", sc.String);
|
||||
}
|
||||
params.Push(f);
|
||||
}
|
||||
else if (args[i] == TypeTextureID)
|
||||
{
|
||||
auto f = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
|
||||
if (!f.isValid())
|
||||
{
|
||||
sc.ScriptError("Unknown texture %s", sc.String);
|
||||
}
|
||||
params.Push(f.GetIndex());
|
||||
}
|
||||
else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||
{
|
||||
char *endp;
|
||||
int v = (int)strtoll(sc.String, &endp, 0);
|
||||
if (*endp != 0)
|
||||
{
|
||||
// special check for font color ranges.
|
||||
v = V_FindFontColor(sc.String);
|
||||
if (v == CR_UNTRANSLATED && !sc.Compare("untranslated"))
|
||||
{
|
||||
// todo: check other data types that may get used.
|
||||
sc.ScriptError("Integer expected, got %s", sc.String);
|
||||
}
|
||||
}
|
||||
if (args[i] == TypeBool) v = !!v;
|
||||
params.Push(v);
|
||||
}
|
||||
else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat)))
|
||||
{
|
||||
char *endp;
|
||||
double v = strtod(sc.String, &endp);
|
||||
if (*endp != 0)
|
||||
{
|
||||
sc.ScriptError("Float expected, got %s", sc.String);
|
||||
}
|
||||
params.Push(v);
|
||||
}
|
||||
else if (args[i] == TypeCVar)
|
||||
{
|
||||
auto cv = FindCVar(sc.String, nullptr);
|
||||
if (cv == nullptr && *sc.String)
|
||||
{
|
||||
sc.ScriptError("Unknown CVar %s", sc.String);
|
||||
}
|
||||
params.Push(cv);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Invalid parameter type %s for menu item", args[i]->DescriptiveName());
|
||||
}
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
if (i == args.Size() - 1)
|
||||
{
|
||||
sc.ScriptError("Too many parameters for %s", cls->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < args.Size() - 1 && !(func->Variants[0].ArgFlags[i + 1] & VARF_Optional))
|
||||
{
|
||||
sc.ScriptError("Insufficient parameters for %s", cls->TypeName.GetChars());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew();
|
||||
params[0] = item;
|
||||
GlobalVMStack.Call(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0);
|
||||
desc->mItems.Push((DMenuItemBase*)item);
|
||||
|
||||
if (cls->IsDescendantOf("ListMenuItemSelectable"))
|
||||
{
|
||||
desc->mYpos += desc->mLinespacing;
|
||||
if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size() - 1;
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &p : desc->mItems)
|
||||
|
@ -642,21 +670,6 @@ static void ParseOptionSettings(FScanner &sc)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
static EColorRange ParseOptionColor(FScanner &sc, DOptionMenuDescriptor *desc)
|
||||
{
|
||||
EColorRange cr = OptionSettings.mFontColor;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetString();
|
||||
cr = V_FindFontColor(sc.String);
|
||||
if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated") && isdigit(sc.String[0]))
|
||||
{
|
||||
if (strtoll(sc.String, nullptr, 0)) cr = OptionSettings.mFontColorHeader;
|
||||
}
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
|
||||
{
|
||||
sc.MustGetStringName("{");
|
||||
|
@ -687,7 +700,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
|
|||
{
|
||||
sc.MustGetString();
|
||||
const PClass *cls = PClass::FindClass(sc.String);
|
||||
if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(DOptionMenu)))
|
||||
if (cls == nullptr || !cls->IsDescendantOf("OptionMenu"))
|
||||
{
|
||||
sc.ScriptError("Unknown menu class '%s'", sc.String);
|
||||
}
|
||||
|
@ -718,198 +731,108 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
|
|||
sc.MustGetNumber();
|
||||
desc->mIndent = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("Submenu"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DOptionMenuItem *it = new DOptionMenuItemSubmenu(label, sc.String);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("Option"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString cvar = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString values = sc.String;
|
||||
FString check;
|
||||
int center = 0;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (*sc.String != 0) check = sc.String;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
center = sc.Number;
|
||||
}
|
||||
}
|
||||
DOptionMenuItem *it = new DOptionMenuItemOption(label, cvar, values, check, center);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("Command"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DOptionMenuItem *it = new DOptionMenuItemCommand(label, sc.String);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("SafeCommand"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString command = sc.String;
|
||||
FString prompt;
|
||||
// Check for optional custom prompt
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetString();
|
||||
prompt = sc.String;
|
||||
}
|
||||
DOptionMenuItem *it = new DOptionMenuItemSafeCommand(label, command, prompt);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("Control") || sc.Compare("MapControl"))
|
||||
{
|
||||
bool map = sc.Compare("MapControl");
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DOptionMenuItem *it = new DOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("ColorPicker"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DOptionMenuItem *it = new DOptionMenuItemColorPicker(label, sc.String);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("StaticText"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
EColorRange cr = ParseOptionColor(sc, desc);
|
||||
DOptionMenuItem *it = new DOptionMenuItemStaticText(label, cr);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("StaticTextSwitchable"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString label2 = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FName action = sc.String;
|
||||
EColorRange cr = ParseOptionColor(sc, desc);
|
||||
DOptionMenuItem *it = new DOptionMenuItemStaticTextSwitchable(label, label2, action, cr);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("Slider"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString text = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
FString action = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetFloat();
|
||||
double min = sc.Float;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetFloat();
|
||||
double max = sc.Float;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetFloat();
|
||||
double step = sc.Float;
|
||||
int showvalue = 1;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
showvalue = sc.Number;
|
||||
}
|
||||
DOptionMenuItem *it = new DOptionMenuSliderCVar(text, action, min, max, step, showvalue);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
else if (sc.Compare("screenresolution"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
DOptionMenuItem *it = new DOptionMenuScreenResolutionLine(sc.String);
|
||||
desc->mItems.Push(it);
|
||||
}
|
||||
// [TP] -- Text input widget
|
||||
else if ( sc.Compare( "TextField" ))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName( "," );
|
||||
sc.MustGetString();
|
||||
FString cvar = sc.String;
|
||||
FString check;
|
||||
|
||||
if ( sc.CheckString( "," ))
|
||||
{
|
||||
sc.MustGetString();
|
||||
check = sc.String;
|
||||
}
|
||||
|
||||
DOptionMenuItem* it = new DOptionMenuTextField( label, cvar, check );
|
||||
desc->mItems.Push( it );
|
||||
}
|
||||
// [TP] -- Number input widget
|
||||
else if ( sc.Compare( "NumberField" ))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FString label = sc.String;
|
||||
sc.MustGetStringName( "," );
|
||||
sc.MustGetString();
|
||||
FString cvar = sc.String;
|
||||
float minimum = 0.0f;
|
||||
float maximum = 100.0f;
|
||||
float step = 1.0f;
|
||||
FString check;
|
||||
|
||||
if ( sc.CheckString( "," ))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
minimum = (float) sc.Float;
|
||||
sc.MustGetStringName( "," );
|
||||
sc.MustGetFloat();
|
||||
maximum = (float) sc.Float;
|
||||
|
||||
if ( sc.CheckString( "," ))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
step = (float) sc.Float;
|
||||
|
||||
if ( sc.CheckString( "," ))
|
||||
{
|
||||
sc.MustGetString();
|
||||
check = sc.String;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOptionMenuItem* it = new DOptionMenuNumberField( label, cvar,
|
||||
minimum, maximum, step, check );
|
||||
desc->mItems.Push( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
||||
bool success = false;
|
||||
FStringf buildname("OptionMenuItem%s", sc.String);
|
||||
// Handle one special case: MapControl maps to Control with one parameter different
|
||||
PClass *cls = PClass::FindClass(buildname);
|
||||
if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem"))
|
||||
{
|
||||
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", false));
|
||||
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
|
||||
{
|
||||
auto &args = func->Variants[0].Proto->ArgumentTypes;
|
||||
TArray<VMValue> params;
|
||||
|
||||
params.Push(0);
|
||||
auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr));
|
||||
for (unsigned i = 1; i < args.Size(); i++)
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (args[i] == TypeString)
|
||||
{
|
||||
params.Push(FString(sc.String));
|
||||
}
|
||||
else if (args[i] == TypeName)
|
||||
{
|
||||
params.Push(FName(sc.String).GetIndex());
|
||||
}
|
||||
else if (args[i] == TypeColor)
|
||||
{
|
||||
params.Push(V_GetColor(nullptr, sc));
|
||||
}
|
||||
else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||
{
|
||||
char *endp;
|
||||
int v = (int)strtoll(sc.String, &endp, 0);
|
||||
if (*endp != 0)
|
||||
{
|
||||
// special check for font color ranges.
|
||||
v = V_FindFontColor(sc.String);
|
||||
if (v == CR_UNTRANSLATED && !sc.Compare("untranslated"))
|
||||
{
|
||||
// todo: check other data types that may get used.
|
||||
sc.ScriptError("Integer expected, got %s", sc.String);
|
||||
}
|
||||
// Color ranges need to be marked for option menu items to support an older feature where a boolean number could be passed instead.
|
||||
v |= 0x12340000;
|
||||
}
|
||||
if (args[i] == TypeBool) v = !!v;
|
||||
params.Push(v);
|
||||
}
|
||||
else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat)))
|
||||
{
|
||||
char *endp;
|
||||
double v = strtod(sc.String, &endp);
|
||||
if (*endp != 0)
|
||||
{
|
||||
sc.ScriptError("Float expected, got %s", sc.String);
|
||||
}
|
||||
params.Push(v);
|
||||
}
|
||||
else if (args[i] == TypeCVar)
|
||||
{
|
||||
auto cv = FindCVar(sc.String, nullptr);
|
||||
if (cv == nullptr && *sc.String)
|
||||
{
|
||||
sc.ScriptError("Unknown CVar %s", sc.String);
|
||||
}
|
||||
params.Push(cv);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Invalid parameter type %s for menu item", args[i]->DescriptiveName());
|
||||
}
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
if (i == args.Size() - 1)
|
||||
{
|
||||
sc.ScriptError("Too many parameters for %s", cls->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < args.Size() - 1 && !(func->Variants[0].ArgFlags[i + 1] & VARF_Optional))
|
||||
{
|
||||
sc.ScriptError("Insufficient parameters for %s", cls->TypeName.GetChars());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew();
|
||||
params[0] = item;
|
||||
GlobalVMStack.Call(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0);
|
||||
desc->mItems.Push((DMenuItemBase*)item);
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &p : desc->mItems)
|
||||
|
@ -1077,12 +1000,11 @@ static void BuildEpisodeMenu()
|
|||
if (AllEpisodes[i].mPicName.IsNotEmpty())
|
||||
{
|
||||
FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName);
|
||||
it = new DListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut,
|
||||
tex, NAME_Skillmenu, i);
|
||||
it = CreateListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, tex, NAME_Skillmenu, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
it = new DListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut,
|
||||
it = CreateListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut,
|
||||
AllEpisodes[i].mEpisodeName, ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i);
|
||||
}
|
||||
ld->mItems.Push(it);
|
||||
|
@ -1118,7 +1040,7 @@ static void BuildEpisodeMenu()
|
|||
GC::WriteBarrier(od);
|
||||
for(unsigned i = 0; i < AllEpisodes.Size(); i++)
|
||||
{
|
||||
DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i);
|
||||
auto it = CreateOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i);
|
||||
od->mItems.Push(it);
|
||||
GC::WriteBarrier(od, it);
|
||||
}
|
||||
|
@ -1175,7 +1097,7 @@ static void BuildPlayerclassMenu()
|
|||
if (numclassitems <= 1)
|
||||
{
|
||||
// create a dummy item that auto-chooses the default class.
|
||||
DListMenuItemText *it = new DListMenuItemText(0, 0, 0, 'p', "player",
|
||||
auto it = CreateListMenuItemText(0, 0, 0, 'p', "player",
|
||||
ld->mFont,ld->mFontColor, ld->mFontColor2, NAME_Episodemenu, -1000);
|
||||
ld->mAutoselect = ld->mItems.Push(it);
|
||||
success = true;
|
||||
|
@ -1201,7 +1123,7 @@ static void BuildPlayerclassMenu()
|
|||
const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type);
|
||||
if (pname != nullptr)
|
||||
{
|
||||
DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
|
||||
auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
|
||||
pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, i);
|
||||
ld->mItems.Push(it);
|
||||
ld->mYpos += ld->mLinespacing;
|
||||
|
@ -1211,7 +1133,7 @@ static void BuildPlayerclassMenu()
|
|||
}
|
||||
if (n > 1 && !gameinfo.norandomplayerclass)
|
||||
{
|
||||
DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r',
|
||||
auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r',
|
||||
"$MNU_RANDOM", ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, -1);
|
||||
ld->mItems.Push(it);
|
||||
}
|
||||
|
@ -1220,7 +1142,7 @@ static void BuildPlayerclassMenu()
|
|||
const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type);
|
||||
if (pname != nullptr)
|
||||
{
|
||||
DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
|
||||
auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
|
||||
pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, 0);
|
||||
ld->mItems.Push(it);
|
||||
}
|
||||
|
@ -1257,13 +1179,13 @@ static void BuildPlayerclassMenu()
|
|||
const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type);
|
||||
if (pname != nullptr)
|
||||
{
|
||||
DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(pname, "Episodemenu", i);
|
||||
auto it = CreateOptionMenuItemSubmenu(pname, "Episodemenu", i);
|
||||
od->mItems.Push(it);
|
||||
GC::WriteBarrier(od, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu("Random", "Episodemenu", -1);
|
||||
auto it = CreateOptionMenuItemSubmenu("Random", "Episodemenu", -1);
|
||||
od->mItems.Push(it);
|
||||
GC::WriteBarrier(od, it);
|
||||
}
|
||||
|
@ -1344,14 +1266,14 @@ static void InitKeySections()
|
|||
for (unsigned i = 0; i < KeySections.Size(); i++)
|
||||
{
|
||||
FKeySection *sect = &KeySections[i];
|
||||
DOptionMenuItem *item = new DOptionMenuItemStaticText(" ", false);
|
||||
DMenuItemBase *item = CreateOptionMenuItemStaticText(" ", false);
|
||||
menu->mItems.Push(item);
|
||||
item = new DOptionMenuItemStaticText(sect->mTitle, true);
|
||||
item = CreateOptionMenuItemStaticText(sect->mTitle, true);
|
||||
menu->mItems.Push(item);
|
||||
for (unsigned j = 0; j < sect->mActions.Size(); j++)
|
||||
{
|
||||
FKeyAction *act = §->mActions[j];
|
||||
item = new DOptionMenuItemControl(act->mTitle, act->mAction, &Bindings);
|
||||
item = CreateOptionMenuItemControl(act->mTitle, act->mAction, &Bindings);
|
||||
menu->mItems.Push(item);
|
||||
}
|
||||
}
|
||||
|
@ -1481,13 +1403,13 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
if (skill.PicName.Len() != 0 && pItemText == nullptr)
|
||||
{
|
||||
FTextureID tex = GetMenuTexture(skill.PicName);
|
||||
li = new DListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
|
||||
li = CreateListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
EColorRange color = (EColorRange)skill.GetTextColor();
|
||||
if (color == CR_UNTRANSLATED) color = ld->mFontColor;
|
||||
li = new DListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut,
|
||||
li = CreateListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut,
|
||||
pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i);
|
||||
}
|
||||
ld->mItems.Push(li);
|
||||
|
@ -1532,7 +1454,7 @@ fail:
|
|||
for(unsigned int i = 0; i < AllSkills.Size(); i++)
|
||||
{
|
||||
FSkillInfo &skill = AllSkills[i];
|
||||
DOptionMenuItem *li;
|
||||
DMenuItemBase *li;
|
||||
// Using a different name for skills that must be confirmed makes handling this easier.
|
||||
const char *action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
|
||||
"StartgameConfirm" : "Startgame";
|
||||
|
@ -1542,7 +1464,7 @@ fail:
|
|||
{
|
||||
pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass);
|
||||
}
|
||||
li = new DOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i);
|
||||
li = CreateOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i);
|
||||
od->mItems.Push(li);
|
||||
GC::WriteBarrier(od, li);
|
||||
if (!done)
|
||||
|
|
|
@ -61,6 +61,8 @@ static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] =
|
|||
|
||||
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DEFINE_FIELD(DTextEnterMenu, mInputGridOkay)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -68,15 +70,14 @@ CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
//=============================================================================
|
||||
|
||||
// [TP] Added allowcolors
|
||||
DTextEnterMenu::DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
|
||||
DTextEnterMenu::DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mEnterString = textbuffer;
|
||||
mEnterSize = maxlen;
|
||||
mEnterPos = (unsigned)strlen(textbuffer);
|
||||
mEnterSize = maxlen < 0 ? UINT_MAX : unsigned(maxlen);
|
||||
mSizeMode = sizemode;
|
||||
mInputGridOkay = showgrid || m_showinputgrid;
|
||||
if (mEnterPos > 0)
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
InputGridX = INPUTGRID_WIDTH - 1;
|
||||
InputGridY = INPUTGRID_HEIGHT - 1;
|
||||
|
@ -96,11 +97,18 @@ DTextEnterMenu::DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::TranslateKeyboardEvents()
|
||||
FString DTextEnterMenu::GetText()
|
||||
{
|
||||
return mInputGridOkay;
|
||||
return mEnterString;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -115,21 +123,19 @@ bool DTextEnterMenu::Responder(event_t *ev)
|
|||
if (ev->subtype == EV_GUI_Char)
|
||||
{
|
||||
mInputGridOkay = false;
|
||||
if (mEnterPos < mEnterSize &&
|
||||
if (mEnterString.Len() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString[mEnterPos] = (char)ev->data1;
|
||||
mEnterString[++mEnterPos] = 0;
|
||||
mEnterString.AppendFormat("%c", (char)ev->data1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
char ch = (char)ev->data1;
|
||||
if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b')
|
||||
{
|
||||
if (mEnterPos > 0)
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterPos--;
|
||||
mEnterString[mEnterPos] = 0;
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_KeyDown)
|
||||
|
@ -143,15 +149,15 @@ bool DTextEnterMenu::Responder(event_t *ev)
|
|||
}
|
||||
else if (ch == '\r')
|
||||
{
|
||||
if (mEnterString[0])
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
// [TP] If we allow color codes, colorize the string now.
|
||||
if (AllowColors)
|
||||
strbin(mEnterString);
|
||||
mEnterString = strbin1(mEnterString);
|
||||
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->CallMenuEvent(MKEY_Input, false);
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -245,9 +251,9 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
|||
return true;
|
||||
|
||||
case MKEY_Clear:
|
||||
if (mEnterPos > 0)
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString[--mEnterPos] = 0;
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
|
@ -258,7 +264,7 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
|||
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
|
||||
if (ch == 0) // end
|
||||
{
|
||||
if (mEnterString[0] != '\0')
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
|
@ -268,16 +274,15 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
|||
}
|
||||
else if (ch == '\b') // bs
|
||||
{
|
||||
if (mEnterPos > 0)
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString[--mEnterPos] = 0;
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
}
|
||||
else if (mEnterPos < mEnterSize &&
|
||||
else if (mEnterString.Len() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString[mEnterPos] = ch;
|
||||
mEnterString[++mEnterPos] = 0;
|
||||
mEnterString += char(ch);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -368,4 +373,24 @@ void DTextEnterMenu::Drawer ()
|
|||
}
|
||||
}
|
||||
Super::Drawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DTextEnterMenu, Open)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(parent, DMenu);
|
||||
PARAM_STRING(text);
|
||||
PARAM_INT(maxlen);
|
||||
PARAM_INT(sizemode);
|
||||
PARAM_BOOL(fromcontroller);
|
||||
auto m = new DTextEnterMenu(parent, text.GetChars(), maxlen, sizemode, fromcontroller, false);
|
||||
M_ActivateMenu(m);
|
||||
ACTION_RETURN_OBJECT(m);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DTextEnterMenu, GetText)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DTextEnterMenu);
|
||||
ACTION_RETURN_STRING(self->GetText());
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "g_game.h"
|
||||
|
||||
|
||||
extern FSaveGameNode *quickSaveSlot;
|
||||
EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd]
|
||||
|
||||
class DMessageBoxMenu : public DMenu
|
||||
|
@ -549,7 +548,7 @@ DQuickSaveMenu::DQuickSaveMenu(bool playsound)
|
|||
{
|
||||
FString tempstring;
|
||||
|
||||
tempstring.Format(GStrings("QSPROMPT"), quickSaveSlot->Title);
|
||||
tempstring.Format(GStrings("QSPROMPT"), savegameManager.quickSaveSlot->Title);
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
|
@ -563,7 +562,7 @@ void DQuickSaveMenu::HandleResult(bool res)
|
|||
{
|
||||
if (res)
|
||||
{
|
||||
G_SaveGame (quickSaveSlot->Filename.GetChars(), quickSaveSlot->Title);
|
||||
G_SaveGame (savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
|
@ -591,7 +590,7 @@ CCMD (quicksave)
|
|||
if (gamestate != GS_LEVEL)
|
||||
return;
|
||||
|
||||
if (quickSaveSlot == NULL)
|
||||
if (savegameManager.quickSaveSlot == NULL)
|
||||
{
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
M_StartControlPanel(false);
|
||||
|
@ -602,7 +601,7 @@ CCMD (quicksave)
|
|||
// [mxd]. Just save the game, no questions asked.
|
||||
if (!saveloadconfirmation)
|
||||
{
|
||||
G_SaveGame(quickSaveSlot->Filename.GetChars(), quickSaveSlot->Title);
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -645,7 +644,7 @@ DQuickLoadMenu::DQuickLoadMenu(bool playsound)
|
|||
{
|
||||
FString tempstring;
|
||||
|
||||
tempstring.Format(GStrings("QLPROMPT"), quickSaveSlot->Title);
|
||||
tempstring.Format(GStrings("QLPROMPT"), savegameManager.quickSaveSlot->Title);
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
|
@ -659,7 +658,7 @@ void DQuickLoadMenu::HandleResult(bool res)
|
|||
{
|
||||
if (res)
|
||||
{
|
||||
G_LoadGame (quickSaveSlot->Filename.GetChars());
|
||||
G_LoadGame (savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
|
@ -685,11 +684,11 @@ CCMD (quickload)
|
|||
return;
|
||||
}
|
||||
|
||||
if (quickSaveSlot == NULL)
|
||||
if (savegameManager.quickSaveSlot == NULL)
|
||||
{
|
||||
M_StartControlPanel(true);
|
||||
// signal that whatever gets loaded should be the new quicksave
|
||||
quickSaveSlot = (FSaveGameNode *)1;
|
||||
savegameManager.quickSaveSlot = (FSaveGameNode *)1;
|
||||
M_SetMenu(NAME_Loadgamemenu);
|
||||
return;
|
||||
}
|
||||
|
@ -697,7 +696,7 @@ CCMD (quickload)
|
|||
// [mxd]. Just load the game, no questions asked.
|
||||
if (!saveloadconfirmation)
|
||||
{
|
||||
G_LoadGame(quickSaveSlot->Filename.GetChars());
|
||||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -725,3 +724,12 @@ void M_StartMessage(const char *message, int messagemode, FName action)
|
|||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, StartMessage)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(msg);
|
||||
PARAM_INT(mode);
|
||||
PARAM_NAME_DEF(action);
|
||||
M_StartMessage(msg, mode, action);
|
||||
return 0;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
** Handler class for the option menus and associated items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -49,485 +49,12 @@
|
|||
#include "menu/menu.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Draws a string in the console font, scaled to the 8x8 cells
|
||||
// used by the default console font.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void M_DrawConText (int color, int x, int y, const char *str)
|
||||
{
|
||||
screen->DrawText (ConFont, color, x, y, str,
|
||||
DTA_CellX, 8 * CleanXfac_1,
|
||||
DTA_CellY, 8 * CleanYfac_1,
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS(DOptionMenu, false, false)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DOptionMenu)
|
||||
IMPLEMENT_POINTER(mFocusControl)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DOptionMenu::DOptionMenu(DMenu *parent, DOptionMenuDescriptor *desc)
|
||||
: DMenu(parent)
|
||||
{
|
||||
CanScrollUp = false;
|
||||
CanScrollDown = false;
|
||||
VisBottom = 0;
|
||||
mFocusControl = NULL;
|
||||
Init(parent, desc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Init(DMenu *parent, DOptionMenuDescriptor *desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
GC::WriteBarrier(this, parent);
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc->mSelectedItem == -1) mDesc->mSelectedItem = FirstSelectable();
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int DOptionMenu::FirstSelectable()
|
||||
{
|
||||
if (mDesc != NULL)
|
||||
{
|
||||
// Go down to the first selectable item
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
}
|
||||
while (i < (int)mDesc->mItems.Size() && !mDesc->mItems[i]->Selectable());
|
||||
if (i>=0 && i < (int)mDesc->mItems.Size()) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DOptionMenuItem, true, false)
|
||||
|
||||
|
||||
DOptionMenuItem *DOptionMenu::GetItem(FName name)
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mDesc->mItems[i]->GetAction(NULL);
|
||||
if (nm == name) return mDesc->mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_WheelUp)
|
||||
{
|
||||
int scrollamt = MIN(2, mDesc->mScrollPos);
|
||||
mDesc->mScrollPos -= scrollamt;
|
||||
return true;
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_WheelDown)
|
||||
{
|
||||
if (CanScrollDown)
|
||||
{
|
||||
if (VisBottom < (int)(mDesc->mItems.Size()-2))
|
||||
{
|
||||
mDesc->mScrollPos += 2;
|
||||
VisBottom += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc->mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int startedAt = mDesc->mSelectedItem;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (mDesc->mSelectedItem == -1)
|
||||
{
|
||||
mDesc->mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
--mDesc->mSelectedItem;
|
||||
|
||||
if (mDesc->mScrollPos > 0 &&
|
||||
mDesc->mSelectedItem <= mDesc->mScrollTop + mDesc->mScrollPos)
|
||||
{
|
||||
mDesc->mScrollPos = MAX(mDesc->mSelectedItem - mDesc->mScrollTop - 1, 0);
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem < 0)
|
||||
{
|
||||
// Figure out how many lines of text fit on the menu
|
||||
int y = mDesc->mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc->mTitle.IsNotEmpty())
|
||||
{
|
||||
y = -y + BigFont->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
y *= CleanYfac_1;
|
||||
int rowheight = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
int maxitems = (screen->GetHeight() - rowheight - y) / rowheight + 1;
|
||||
|
||||
mDesc->mScrollPos = MAX (0, (int)mDesc->mItems.Size() - maxitems + mDesc->mScrollTop);
|
||||
mDesc->mSelectedItem = mDesc->mItems.Size()-1;
|
||||
}
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_Down:
|
||||
if (mDesc->mSelectedItem == -1)
|
||||
{
|
||||
mDesc->mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
++mDesc->mSelectedItem;
|
||||
|
||||
if (CanScrollDown && mDesc->mSelectedItem == VisBottom)
|
||||
{
|
||||
mDesc->mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
if (mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
if (startedAt == -1)
|
||||
{
|
||||
mDesc->mSelectedItem = -1;
|
||||
mDesc->mScrollPos = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
mDesc->mScrollPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (mDesc->mScrollPos > 0)
|
||||
{
|
||||
mDesc->mScrollPos -= VisBottom - mDesc->mScrollPos - mDesc->mScrollTop;
|
||||
if (mDesc->mScrollPos < 0)
|
||||
{
|
||||
mDesc->mScrollPos = 0;
|
||||
}
|
||||
if (mDesc->mSelectedItem != -1)
|
||||
{
|
||||
mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos + 1;
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable())
|
||||
{
|
||||
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc->mScrollPos > mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (CanScrollDown)
|
||||
{
|
||||
int pagesize = VisBottom - mDesc->mScrollPos - mDesc->mScrollTop;
|
||||
mDesc->mScrollPos += pagesize;
|
||||
if (mDesc->mScrollPos + mDesc->mScrollTop + pagesize > (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mItems.Size() - mDesc->mScrollTop - pagesize;
|
||||
}
|
||||
if (mDesc->mSelectedItem != -1)
|
||||
{
|
||||
mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos;
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable())
|
||||
{
|
||||
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size())
|
||||
{
|
||||
mDesc->mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc->mScrollPos > mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mScrollPos = mDesc->mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// fall through to default
|
||||
default:
|
||||
if (mDesc->mSelectedItem >= 0 &&
|
||||
mDesc->mItems[mDesc->mSelectedItem]->MenuEvent(mkey, fromcontroller)) return true;
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem != startedAt)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DOptionMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
y = (y / CleanYfac_1) - mDesc->mDrawTop;
|
||||
|
||||
if (mFocusControl)
|
||||
{
|
||||
mFocusControl->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int yline = (y / OptionSettings.mLinespacing);
|
||||
if (yline >= mDesc->mScrollTop)
|
||||
{
|
||||
yline += mDesc->mScrollPos;
|
||||
}
|
||||
if ((unsigned)yline < mDesc->mItems.Size() && mDesc->mItems[yline]->Selectable())
|
||||
{
|
||||
if (yline != mDesc->mSelectedItem)
|
||||
{
|
||||
mDesc->mSelectedItem = yline;
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc->mItems[yline]->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mDesc->mSelectedItem = -1;
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Ticker ()
|
||||
{
|
||||
Super::Ticker();
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
mDesc->mItems[i]->Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenu::Drawer ()
|
||||
{
|
||||
int y = mDesc->mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc->mTitle.IsNotEmpty())
|
||||
{
|
||||
const char *tt = mDesc->mTitle;
|
||||
if (*tt == '$') tt = GStrings(tt+1);
|
||||
screen->DrawText (BigFont, OptionSettings.mTitleColor,
|
||||
(screen->GetWidth() - BigFont->StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1,
|
||||
tt, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
y = -y + BigFont->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
mDesc->mDrawTop = y;
|
||||
int fontheight = OptionSettings.mLinespacing * CleanYfac_1;
|
||||
y *= CleanYfac_1;
|
||||
|
||||
int indent = mDesc->mIndent;
|
||||
if (indent > 280)
|
||||
{ // kludge for the compatibility options with their extremely long labels
|
||||
if (indent + 40 <= CleanWidth_1)
|
||||
{
|
||||
indent = (screen->GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = screen->GetWidth() - 40 * CleanXfac_1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = (indent - 160) * CleanXfac_1 + screen->GetWidth() / 2;
|
||||
}
|
||||
|
||||
int ytop = y + mDesc->mScrollTop * 8 * CleanYfac_1;
|
||||
int lastrow = screen->GetHeight() - SmallFont->GetHeight() * CleanYfac_1;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < mDesc->mItems.Size() && y <= lastrow; i++, y += fontheight)
|
||||
{
|
||||
// Don't scroll the uppermost items
|
||||
if ((int)i == mDesc->mScrollTop)
|
||||
{
|
||||
i += mDesc->mScrollPos;
|
||||
if (i >= mDesc->mItems.Size()) break; // skipped beyond end of menu
|
||||
}
|
||||
bool isSelected = mDesc->mSelectedItem == (int)i;
|
||||
int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, isSelected);
|
||||
if (cur_indent >= 0 && isSelected && mDesc->mItems[i]->Selectable())
|
||||
{
|
||||
if (((DMenu::MenuTime%8) < 6) || DMenu::CurrentMenu != this)
|
||||
{
|
||||
M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CanScrollUp = (mDesc->mScrollPos > 0);
|
||||
CanScrollDown = (i < mDesc->mItems.Size());
|
||||
VisBottom = i - 1;
|
||||
|
||||
if (CanScrollUp)
|
||||
{
|
||||
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a");
|
||||
}
|
||||
if (CanScrollDown)
|
||||
{
|
||||
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b");
|
||||
}
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int DOptionMenuItem::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
return indent;
|
||||
}
|
||||
|
||||
bool DOptionMenuItem::Selectable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DOptionMenuItem::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (Selectable() && type == DMenu::MOUSE_Release)
|
||||
{
|
||||
return DMenu::CurrentMenu->CallMenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DOptionMenuItem::GetIndent()
|
||||
{
|
||||
if (mCentered)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const char *label = mLabel.GetChars();
|
||||
if (*label == '$') label = GStrings(label+1);
|
||||
return SmallFont->StringWidth(label);
|
||||
}
|
||||
|
||||
void DOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)
|
||||
{
|
||||
const char *label = mLabel.GetChars();
|
||||
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 DOptionMenuDescriptor::CalcIndent()
|
||||
{
|
||||
// calculate the menu indent
|
||||
|
@ -541,13 +68,20 @@ void DOptionMenuDescriptor::CalcIndent()
|
|||
mIndent = widest + 4;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuDescriptor, CalcIndent)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DOptionMenuDescriptor);
|
||||
self->CalcIndent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DOptionMenuItem *DOptionMenuDescriptor::GetItem(FName name)
|
||||
DMenuItemBase *DOptionMenuDescriptor::GetItem(FName name)
|
||||
{
|
||||
for(unsigned i=0;i<mItems.Size(); i++)
|
||||
{
|
||||
|
@ -557,49 +91,3 @@ DOptionMenuItem *DOptionMenuDescriptor::GetItem(FName name)
|
|||
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, false, false)
|
||||
|
||||
class DCompatibilityMenu : public DOptionMenu
|
||||
{
|
||||
DECLARE_CLASS(DCompatibilityMenu, DOptionMenu)
|
||||
|
||||
public:
|
||||
DCompatibilityMenu()
|
||||
{}
|
||||
|
||||
void Drawer ()
|
||||
{
|
||||
Super::Drawer();
|
||||
|
||||
char text[64];
|
||||
mysnprintf(text, 64, "compatflags = %d compatflags2 = %d", *compatflags, *compatflags2);
|
||||
screen->DrawText (SmallFont, OptionSettings.mFontColorValue,
|
||||
(screen->GetWidth() - SmallFont->StringWidth (text) * CleanXfac_1) / 2, 0, text,
|
||||
DTA_CleanNoMove_1, true, TAG_DONE);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DCompatibilityMenu, false, false)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,320 +0,0 @@
|
|||
/*
|
||||
** 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 "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"
|
||||
#include "r_data/r_translate.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DListMenuItemPlayerDisplay, false, false)
|
||||
DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action)
|
||||
: DMenuItemBase(x, y, action)
|
||||
{
|
||||
mOwner = menu;
|
||||
|
||||
FRemapTable *bdremap = translationtables[TRANSLATION_Players][MAXPLAYERS + 1];
|
||||
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;
|
||||
bdremap->Remap[i] = ColorMatcher.Pick (r, g, b);
|
||||
bdremap->Palette[i] = PalEntry(255, r, g, b);
|
||||
}
|
||||
auto id = TexMan.CheckForTexture("PlayerBackdrop", FTexture::TEX_MiscPatch);
|
||||
mBackdrop = TexMan[id];
|
||||
mPlayerClass = NULL;
|
||||
mPlayerState = NULL;
|
||||
mNoportrait = np;
|
||||
mMode = 0;
|
||||
mRotation = 0;
|
||||
mTranslate = false;
|
||||
mSkin = 0;
|
||||
mRandomClass = 0;
|
||||
mRandomTimer = 0;
|
||||
mClassNum = -1;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenuItemPlayerDisplay::OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenuItemPlayerDisplay::UpdateRandomClass()
|
||||
{
|
||||
if (--mRandomTimer < 0)
|
||||
{
|
||||
if (++mRandomClass >= (int)PlayerClasses.Size ()) mRandomClass = 0;
|
||||
mPlayerClass = &PlayerClasses[mRandomClass];
|
||||
mPlayerState = GetDefaultByType (mPlayerClass->Type)->SeeState;
|
||||
if (mPlayerState == NULL)
|
||||
{ // No see state, so try spawn state.
|
||||
mPlayerState = GetDefaultByType (mPlayerClass->Type)->SpawnState;
|
||||
}
|
||||
mPlayerTics = mPlayerState != NULL ? mPlayerState->GetTics() : -1;
|
||||
mRandomTimer = 6;
|
||||
|
||||
// Since the newly displayed class may used a different translation
|
||||
// range than the old one, we need to update the translation, too.
|
||||
UpdateTranslation();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenuItemPlayerDisplay::UpdateTranslation()
|
||||
{
|
||||
int PlayerColor = players[consoleplayer].userinfo.GetColor();
|
||||
int PlayerSkin = players[consoleplayer].userinfo.GetSkin();
|
||||
int PlayerColorset = players[consoleplayer].userinfo.GetColorSet();
|
||||
|
||||
if (mPlayerClass != NULL)
|
||||
{
|
||||
PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(mPlayerClass - &PlayerClasses[0]));
|
||||
R_GetPlayerTranslation(PlayerColor, GetColorSet(mPlayerClass->Type, PlayerColorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenuItemPlayerDisplay::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;
|
||||
if (mPlayerState == NULL)
|
||||
{ // No see state, so try spawn state.
|
||||
mPlayerState = GetDefaultByType (mPlayerClass->Type)->SpawnState;
|
||||
}
|
||||
mPlayerTics = mPlayerState != NULL ? mPlayerState->GetTics() : -1;
|
||||
mClassNum = classnum;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenuItemPlayerDisplay::UpdatePlayerClass()
|
||||
{
|
||||
if (mOwner->mSelectedItem >= 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenuItemPlayerDisplay::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 DListMenuItemPlayerDisplay::Ticker()
|
||||
{
|
||||
if (mClassNum < 0) UpdateRandomClass();
|
||||
|
||||
if (mPlayerState != NULL && mPlayerState->GetTics () != -1 && mPlayerState->GetNextState () != NULL)
|
||||
{
|
||||
if (--mPlayerTics <= 0)
|
||||
{
|
||||
mPlayerState = mPlayerState->GetNextState();
|
||||
mPlayerTics = mPlayerState->GetTics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenuItemPlayerDisplay::Drawer(bool selected)
|
||||
{
|
||||
if (mMode == 0 && !UpdatePlayerClass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FName portrait = ((APlayerPawn*)GetDefaultByType(mPlayerClass->Type))->Portrait;
|
||||
|
||||
if (portrait != NAME_None && !mNoportrait)
|
||||
{
|
||||
FTextureID texid = TexMan.CheckForTexture(portrait.GetChars(), 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_TranslationIndex, TRANSLATION(TRANSLATION_Players, MAXPLAYERS + 1),
|
||||
DTA_Masked, true,
|
||||
TAG_DONE);
|
||||
|
||||
V_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1);
|
||||
|
||||
spriteframe_t *sprframe = NULL;
|
||||
DVector2 Scale;
|
||||
|
||||
if (mPlayerState != NULL)
|
||||
{
|
||||
if (mSkin == 0)
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[mPlayerState->sprite].spriteframes + mPlayerState->GetFrame()];
|
||||
Scale = GetDefaultByType(mPlayerClass->Type)->Scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[skins[mSkin].sprite].spriteframes + mPlayerState->GetFrame()];
|
||||
Scale = skins[mSkin].Scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (sprframe != NULL)
|
||||
{
|
||||
FTexture *tex = TexMan(sprframe->Texture[mRotation]);
|
||||
if (tex != NULL && tex->UseType != FTexture::TEX_Null)
|
||||
{
|
||||
int trans = mTranslate? TRANSLATION(TRANSLATION_Players, MAXPLAYERS) : 0;
|
||||
screen->DrawTexture (tex,
|
||||
x + 36*CleanXfac, y + 71*CleanYfac,
|
||||
DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * Scale.X,
|
||||
DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * Scale.Y,
|
||||
DTA_TranslationIndex, trans,
|
||||
DTA_FlipX, sprframe->Flip & (1 << mRotation),
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,428 +55,6 @@ EXTERN_CVAR (Float, autoaim)
|
|||
EXTERN_CVAR(Bool, neverswitchonpickup)
|
||||
EXTERN_CVAR (Bool, cl_run)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Player's name
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DPlayerNameBox, false, false)
|
||||
|
||||
DPlayerNameBox::DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action)
|
||||
: DListMenuItemSelectable(x, y, height, action)
|
||||
{
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mFontColor = color;
|
||||
mFrameSize = frameofs;
|
||||
mPlayerName[0] = 0;
|
||||
mEntering = false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DPlayerNameBox::SetString(int i, const char *s)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
strncpy(mPlayerName, s, MAXPLAYERNAME);
|
||||
mPlayerName[MAXPLAYERNAME] = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DPlayerNameBox::GetString(int i, char *s, int len)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
strncpy(s, mPlayerName, len);
|
||||
s[len] = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// [RH] Width of the border is variable
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerNameBox::DrawBorder (int x, int y, int len)
|
||||
{
|
||||
FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)];
|
||||
FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)];
|
||||
FTexture *right = TexMan[TexMan.CheckForTexture("M_LSRGHT", FTexture::TEX_MiscPatch)];
|
||||
if (left != NULL && right != NULL && mid != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
screen->DrawTexture (left, x-8, y+7, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
screen->DrawTexture (mid, x, y+7, DTA_Clean, true, TAG_DONE);
|
||||
x += 8;
|
||||
}
|
||||
|
||||
screen->DrawTexture (right, x, y+7, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
FTexture *slot = TexMan[TexMan.CheckForTexture("M_FSLOT", FTexture::TEX_MiscPatch)];
|
||||
if (slot != NULL)
|
||||
{
|
||||
screen->DrawTexture (slot, x, y+1, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->Clear(x, y, x + len, y + SmallFont->GetHeight() * 3/2, -1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerNameBox::Drawer(bool selected)
|
||||
{
|
||||
const char *text = mText;
|
||||
if (text != NULL)
|
||||
{
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
|
||||
// Draw player name box
|
||||
int x = mXpos + mFont->StringWidth(text) + 16 + mFrameSize;
|
||||
DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1);
|
||||
if (!mEntering)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t l = strlen(mEditName);
|
||||
mEditName[l] = SmallFont->GetCursor();
|
||||
mEditName[l+1] = 0;
|
||||
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, x + mFrameSize, mYpos, mEditName,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
|
||||
mEditName[l] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DPlayerNameBox::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
strcpy(mEditName, mPlayerName);
|
||||
mEntering = true;
|
||||
DMenu *input = new DTextEnterMenu(DMenu::CurrentMenu, mEditName, MAXPLAYERNAME, 2, fromcontroller);
|
||||
M_ActivateMenu(input);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Input)
|
||||
{
|
||||
strcpy(mPlayerName, mEditName);
|
||||
mEntering = false;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Abort)
|
||||
{
|
||||
mEntering = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DValueTextItem, false, false)
|
||||
|
||||
DValueTextItem::DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values)
|
||||
: DListMenuItemSelectable(x, y, height, action)
|
||||
{
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mFontColor = color;
|
||||
mFontColor2 = valuecolor;
|
||||
mSelection = 0;
|
||||
if (values != NAME_None)
|
||||
{
|
||||
FOptionValues **opt = OptionValues.CheckKey(values);
|
||||
if (opt != NULL)
|
||||
{
|
||||
for(unsigned i=0;i<(*opt)->mValues.Size(); i++)
|
||||
{
|
||||
SetString(i, (*opt)->mValues[i].Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DValueTextItem::SetString(int i, const char *s)
|
||||
{
|
||||
// should actually use the index...
|
||||
FString str = s;
|
||||
if (i==0) mSelections.Clear();
|
||||
mSelections.Push(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DValueTextItem::SetValue(int i, int value)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mSelection = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DValueTextItem::GetValue(int i, int *pvalue)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
*pvalue = mSelection;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DValueTextItem::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mSelections.Size() > 1)
|
||||
{
|
||||
if (mkey == MKEY_Left)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
if (--mSelection < 0) mSelection = mSelections.Size() - 1;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Right || mkey == MKEY_Enter)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
if (++mSelection >= (int)mSelections.Size()) mSelection = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (mkey == MKEY_Enter); // needs to eat enter keys so that Activate won't get called
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DValueTextItem::Drawer(bool selected)
|
||||
{
|
||||
const char *text = mText;
|
||||
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
int x = mXpos + mFont->StringWidth(text) + 8;
|
||||
if (mSelections.Size() > 0)
|
||||
{
|
||||
const char *mOptValue = mSelections[mSelection];
|
||||
if (*mOptValue == '$') mOptValue = GStrings(mOptValue + 1);
|
||||
screen->DrawText(mFont, mFontColor2, x, mYpos, mOptValue, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DSliderItem, false, false)
|
||||
|
||||
DSliderItem::DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step)
|
||||
: DListMenuItemSelectable(x, y, height, action)
|
||||
{
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mFontColor = color;
|
||||
mSelection = 0;
|
||||
mMinrange = min;
|
||||
mMaxrange = max;
|
||||
mStep = step;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DSliderItem::SetValue(int i, int value)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mSelection = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSliderItem::GetValue(int i, int *pvalue)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
*pvalue = mSelection;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DSliderItem::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Left)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
if ((mSelection -= mStep) < mMinrange) mSelection = mMinrange;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Right || mkey == MKEY_Enter)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
if ((mSelection += mStep) > mMaxrange) mSelection = mMaxrange;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DSliderItem::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
DListMenu *lm = static_cast<DListMenu*>(DMenu::CurrentMenu);
|
||||
if (type != DMenu::MOUSE_Click)
|
||||
{
|
||||
if (!lm->CheckFocus(this)) return false;
|
||||
}
|
||||
if (type == DMenu::MOUSE_Release)
|
||||
{
|
||||
lm->ReleaseFocus();
|
||||
}
|
||||
|
||||
int slide_left = SmallFont->StringWidth ("Green") + 8 + mXpos;
|
||||
int slide_right = slide_left + 12*8; // 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);
|
||||
int v = mMinrange + Scale(x - slide_left, mMaxrange - mMinrange, slide_right - slide_left);
|
||||
if (v != mSelection)
|
||||
{
|
||||
mSelection = v;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
if (type == DMenu::MOUSE_Click)
|
||||
{
|
||||
lm->SetFocus(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DSliderItem::DrawSlider (int x, int y)
|
||||
{
|
||||
int range = mMaxrange - mMinrange;
|
||||
int cur = mSelection - mMinrange;
|
||||
|
||||
x = (x - 160) * CleanXfac + screen->GetWidth() / 2;
|
||||
y = (y - 100) * CleanYfac + screen->GetHeight() / 2;
|
||||
|
||||
screen->DrawText (ConFont, CR_WHITE, x, y,
|
||||
"\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
screen->DrawText (ConFont, CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y,
|
||||
"\x13",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DSliderItem::Drawer(bool selected)
|
||||
{
|
||||
const char *text = mText;
|
||||
|
||||
if (*text == '$') text = GStrings(text+1);
|
||||
screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
int x = SmallFont->StringWidth ("Green") + 8 + mXpos;
|
||||
int x2 = SmallFont->StringWidth (text) + 8 + mXpos;
|
||||
DrawSlider (MAX(x2, x), mYpos);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -524,6 +102,14 @@ IMPLEMENT_CLASS(DPlayerMenu, false, false)
|
|||
//
|
||||
//
|
||||
//=============================================================================
|
||||
enum EPDFlags
|
||||
{
|
||||
ListMenuItemPlayerDisplay_PDF_ROTATION = 0x10001,
|
||||
ListMenuItemPlayerDisplay_PDF_SKIN = 0x10002,
|
||||
ListMenuItemPlayerDisplay_PDF_CLASS = 0x10003,
|
||||
ListMenuItemPlayerDisplay_PDF_MODE = 0x10004,
|
||||
ListMenuItemPlayerDisplay_PDF_TRANSLATE = 0x10005,
|
||||
};
|
||||
|
||||
void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc)
|
||||
{
|
||||
|
@ -536,14 +122,14 @@ void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc)
|
|||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, 0);
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_MODE, 1);
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_TRANSLATE, 1);
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_ROTATION, 0);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_MODE, 1);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_TRANSLATE, 1);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
|
||||
if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) &&
|
||||
players[consoleplayer].userinfo.GetPlayerClassNum() != -1)
|
||||
{
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, players[consoleplayer].userinfo.GetSkin());
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, players[consoleplayer].userinfo.GetSkin());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -658,7 +244,7 @@ bool DPlayerMenu::Responder (event_t *ev)
|
|||
DMenuItemBase *li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, mRotation);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_ROTATION, mRotation);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -812,7 +398,7 @@ void DPlayerMenu::UpdateSkins()
|
|||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, skin);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, skin);
|
||||
}
|
||||
}
|
||||
UpdateTranslation();
|
||||
|
@ -908,7 +494,7 @@ void DPlayerMenu::ClassChanged (DMenuItemBase *li)
|
|||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -939,7 +525,7 @@ void DPlayerMenu::SkinChanged (DMenuItemBase *li)
|
|||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, sel);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, sel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,10 +54,6 @@
|
|||
#include "sbar.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#define NO_IMP
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Video Modes Menu
|
||||
|
@ -101,19 +97,21 @@ CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE)
|
|||
|
||||
CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
const int OptionMenuItemOptionBase_OP_VALUES = 0x11001;
|
||||
|
||||
DOptionMenuDescriptor *opt = GetVideoModeMenu();
|
||||
if (opt != NULL)
|
||||
{
|
||||
DOptionMenuItem *it = opt->GetItem("menu_screenratios");
|
||||
DMenuItemBase *it = opt->GetItem("menu_screenratios");
|
||||
if (it != NULL)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
it->SetString(DOptionMenuItemOptionBase::OP_VALUES, "RatiosTFT");
|
||||
it->SetString(OptionMenuItemOptionBase_OP_VALUES, "RatiosTFT");
|
||||
}
|
||||
else
|
||||
{
|
||||
it->SetString(DOptionMenuItemOptionBase::OP_VALUES, "Ratios");
|
||||
it->SetString(OptionMenuItemOptionBase_OP_VALUES, "Ratios");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,61 +129,16 @@ CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
class DVideoModeMenu : public DOptionMenu
|
||||
struct OptionMenuItemScreenResolution // temporary workaround
|
||||
{
|
||||
DECLARE_CLASS(DVideoModeMenu, DOptionMenu)
|
||||
|
||||
public:
|
||||
|
||||
DVideoModeMenu()
|
||||
enum EValues
|
||||
{
|
||||
SetModesMenu (screen->VideoWidth, screen->VideoHeight, 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(DOptionMenuScreenResolutionLine::SRL_SELECTION, &sel);
|
||||
bool res = Super::MenuEvent(mkey, fromcontroller);
|
||||
if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(DOptionMenuScreenResolutionLine::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 = screen->VideoWidth;
|
||||
NewHeight = screen->VideoHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
OldWidth = screen->VideoWidth;
|
||||
OldHeight = screen->VideoHeight;
|
||||
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);
|
||||
}
|
||||
SRL_INDEX = 0x30000,
|
||||
SRL_SELECTION = 0x30003,
|
||||
SRL_HIGHLIGHT = 0x30004,
|
||||
};
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DVideoModeMenu, false, false)
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -236,10 +189,10 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
|
|||
{
|
||||
for (i = NAME_res_0; i<= NAME_res_9; i++)
|
||||
{
|
||||
DOptionMenuItem *it = opt->GetItem((ENamedName)i);
|
||||
DMenuItemBase *it = opt->GetItem((ENamedName)i);
|
||||
if (it != NULL)
|
||||
{
|
||||
it->SetValue(DOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, -1);
|
||||
it->SetValue(OptionMenuItemScreenResolution::SRL_HIGHLIGHT, -1);
|
||||
for (c = 0; c < 3; c++)
|
||||
{
|
||||
bool haveMode = false;
|
||||
|
@ -260,16 +213,16 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
|
|||
{
|
||||
if (width == hiwidth && height == hiheight)
|
||||
{
|
||||
it->SetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, c);
|
||||
it->SetValue(DOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, c);
|
||||
it->SetValue(OptionMenuItemScreenResolution::SRL_SELECTION, c);
|
||||
it->SetValue(OptionMenuItemScreenResolution::SRL_HIGHLIGHT, c);
|
||||
}
|
||||
|
||||
mysnprintf (strtemp, countof(strtemp), "%dx%d%s", width, height, letterbox?TEXTCOLOR_BROWN" LB":"");
|
||||
it->SetString(DOptionMenuScreenResolutionLine::SRL_INDEX+c, strtemp);
|
||||
it->SetString(OptionMenuItemScreenResolution::SRL_INDEX+c, strtemp);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->SetString(DOptionMenuScreenResolutionLine::SRL_INDEX+c, "");
|
||||
it->SetString(OptionMenuItemScreenResolution::SRL_INDEX+c, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,12 +312,12 @@ static bool GetSelectedSize (int *width, int *height)
|
|||
{
|
||||
int line = opt->mSelectedItem;
|
||||
int hsel;
|
||||
DOptionMenuItem *it = opt->mItems[line];
|
||||
if (it->GetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, &hsel))
|
||||
DMenuItemBase *it = opt->mItems[line];
|
||||
if (it->GetValue(OptionMenuItemScreenResolution::SRL_SELECTION, &hsel))
|
||||
{
|
||||
char buffer[32];
|
||||
char *breakpt;
|
||||
if (it->GetString(DOptionMenuScreenResolutionLine::SRL_INDEX+hsel, buffer, sizeof(buffer)))
|
||||
if (it->GetString(OptionMenuItemScreenResolution::SRL_INDEX+hsel, buffer, sizeof(buffer)))
|
||||
{
|
||||
*width = (int)strtoll (buffer, &breakpt, 10);
|
||||
*height = (int)strtoll (breakpt+1, NULL, 10);
|
||||
|
@ -375,6 +328,27 @@ static bool GetSelectedSize (int *width, int *height)
|
|||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DVideoModeMenu, SetSelectedSize)
|
||||
{
|
||||
if (!GetSelectedSize (&NewWidth, &NewHeight))
|
||||
{
|
||||
NewWidth = screen->VideoWidth;
|
||||
NewHeight = screen->VideoHeight;
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
OldWidth = screen->VideoWidth;
|
||||
OldHeight = screen->VideoHeight;
|
||||
OldBits = DisplayBits;
|
||||
NewBits = BitTranslate[DummyDepthCvar];
|
||||
setmodeneeded = true;
|
||||
testingmode = I_GetTime(false) + 5 * TICRATE;
|
||||
SetModesMenu (NewWidth, NewHeight, NewBits);
|
||||
ACTION_RETURN_BOOL(true);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -397,6 +371,11 @@ void M_SetVideoMode()
|
|||
SetModesMenu (NewWidth, NewHeight, NewBits);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, SetVideoMode)
|
||||
{
|
||||
M_SetVideoMode();
|
||||
return 0;
|
||||
}
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -423,7 +402,7 @@ static void SetModesMenu (int w, int h, int bits)
|
|||
DOptionMenuDescriptor *opt = GetVideoModeMenu();
|
||||
if (opt != NULL)
|
||||
{
|
||||
DOptionMenuItem *it;
|
||||
DMenuItemBase *it;
|
||||
if (testingmode <= 1)
|
||||
{
|
||||
it = opt->GetItem(NAME_VMEnterText);
|
||||
|
@ -448,3 +427,8 @@ static void SetModesMenu (int w, int h, int bits)
|
|||
}
|
||||
BuildModesList (w, h, bits);
|
||||
}
|
||||
|
||||
void M_InitVideoModes()
|
||||
{
|
||||
SetModesMenu (screen->VideoWidth, screen->VideoHeight, DisplayBits);
|
||||
}
|
|
@ -51,6 +51,40 @@ FStateLabelStorage StateLabels;
|
|||
// actor. States are archived by recording the actor they belong
|
||||
// to and the index into that actor's list of states.
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// This wraps everything needed to get a current sprite from a state into
|
||||
// one single script function.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FState);
|
||||
PARAM_INT(rotation);
|
||||
PARAM_INT_DEF(skin);
|
||||
PARAM_FLOAT_DEF(scalex);
|
||||
PARAM_FLOAT_DEF(scaley);
|
||||
|
||||
spriteframe_t *sprframe;
|
||||
if (skin == 0)
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[self->sprite].spriteframes + self->GetFrame()];
|
||||
}
|
||||
else
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[skins[skin].sprite].spriteframes + self->GetFrame()];
|
||||
scalex = skins[skin].Scale.X;
|
||||
scaley = skins[skin].Scale.Y;
|
||||
}
|
||||
if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex());
|
||||
if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation)));
|
||||
if (numret > 2) ret[2].SetVector2(DVector2(scalex, scaley));
|
||||
return MIN(3, numret);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find the actor that a state belongs to.
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "virtual.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "r_data/r_translate.h"
|
||||
|
||||
static FRandom pr_skullpop ("SkullPop");
|
||||
|
||||
|
@ -142,6 +143,13 @@ bool FPlayerClass::CheckSkin (int skin)
|
|||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FPlayerClass, CheckSkin)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FPlayerClass);
|
||||
PARAM_INT(skin);
|
||||
ACTION_RETURN_BOOL(self->CheckSkin(skin));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// GetDisplayName
|
||||
|
@ -3342,3 +3350,7 @@ DEFINE_FIELD_X(PlayerInfo, player_t, cmd)
|
|||
DEFINE_FIELD_X(PlayerInfo, player_t, original_cmd)
|
||||
DEFINE_FIELD_X(PlayerInfo, player_t, userinfo)
|
||||
DEFINE_FIELD_X(PlayerInfo, player_t, weapons)
|
||||
|
||||
DEFINE_FIELD(FPlayerClass, Type)
|
||||
DEFINE_FIELD(FPlayerClass, Flags)
|
||||
DEFINE_FIELD(FPlayerClass, Skins)
|
||||
|
|
|
@ -740,8 +740,6 @@ void R_InitTranslationTables ()
|
|||
}
|
||||
// The menu player also gets a separate translation table
|
||||
PushIdentityTable(TRANSLATION_Players);
|
||||
// This one is for the backdrop in the menu
|
||||
PushIdentityTable(TRANSLATION_Players);
|
||||
|
||||
// The three standard translations from Doom or Heretic (seven for Strife),
|
||||
// plus the generic ice translation.
|
||||
|
@ -1200,6 +1198,33 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer
|
|||
R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_UINT(tgroup);
|
||||
PARAM_UINT(tnum);
|
||||
PARAM_UINT(pnum);
|
||||
PARAM_POINTER(cls, FPlayerClass);
|
||||
|
||||
if (pnum >= MAXPLAYERS || tgroup >= NUM_TRANSLATION_TABLES || tnum >= translationtables[tgroup].Size())
|
||||
{
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
auto self = &players[pnum];
|
||||
int PlayerColor = self->userinfo.GetColor();
|
||||
int PlayerSkin = self->userinfo.GetSkin();
|
||||
int PlayerColorset = self->userinfo.GetColorSet();
|
||||
|
||||
if (cls != nullptr)
|
||||
{
|
||||
PlayerSkin = R_FindSkin(skins[PlayerSkin].name, int(cls - &PlayerClasses[0]));
|
||||
R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset),
|
||||
&skins[PlayerSkin], translationtables[tgroup][tnum]);
|
||||
}
|
||||
ACTION_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
@ -1307,3 +1332,29 @@ void R_ParseTrnslate()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct FTranslation
|
||||
{
|
||||
PalEntry colors[256];
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Translation, AddTranslation)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FTranslation);
|
||||
|
||||
FRemapTable NewTranslation;
|
||||
memcpy(&NewTranslation.Palette[0], self->colors, 256 * sizeof(PalEntry));
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
NewTranslation.Remap[i] = ColorMatcher.Pick(self->colors[i]);
|
||||
}
|
||||
int trans = NewTranslation.StoreTranslation(TRANSLATION_Custom);
|
||||
ACTION_RETURN_INT(trans);
|
||||
}
|
||||
|
||||
|
|
|
@ -142,8 +142,6 @@ std2:
|
|||
'true' { RET(TK_True); }
|
||||
'false' { RET(TK_False); }
|
||||
'none' { RET(TK_None); }
|
||||
'new' { RET(TK_New); }
|
||||
'instanceof' { RET(TK_InstanceOf); }
|
||||
'auto' { RET(TK_Auto); }
|
||||
'exec' { RET(TK_Exec); }
|
||||
'property' { RET(TK_Property); }
|
||||
|
|
|
@ -81,7 +81,6 @@ xx(TK_ForEach, "'foreach'")
|
|||
xx(TK_True, "'true'")
|
||||
xx(TK_False, "'false'")
|
||||
xx(TK_None, "'none'")
|
||||
xx(TK_New, "'new'")
|
||||
xx(TK_InstanceOf, "'instanceof'")
|
||||
xx(TK_Auto, "'auto'")
|
||||
xx(TK_Exec, "'exec'")
|
||||
|
|
|
@ -154,6 +154,7 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
|||
{
|
||||
if (ReturnProto->ReturnTypes[i] != proto->ReturnTypes[i])
|
||||
{ // Incompatible
|
||||
Printf("Return type %s mismatch with %s\n", ReturnProto->ReturnTypes[i]->DescriptiveName(), proto->ReturnTypes[i]->DescriptiveName());
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
|
@ -2455,7 +2456,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
|||
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
||||
assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
|
||||
assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType());
|
||||
|
||||
ExpEmit pointer = Base->Emit(build);
|
||||
Address = pointer;
|
||||
|
@ -2973,6 +2974,12 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!left->ValueType || !right->ValueType)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "ValueType not set");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (left->IsVector() || right->IsVector())
|
||||
{
|
||||
|
@ -3551,6 +3558,16 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
|||
goto error;
|
||||
}
|
||||
}
|
||||
else if (left->IsPointer() && static_cast<PPointer*>(left->ValueType)->PointedType == right->ValueType)
|
||||
{
|
||||
bool writable;
|
||||
if (!right->RequestAddress(ctx, &writable)) goto error;
|
||||
}
|
||||
else if (right->IsPointer() && static_cast<PPointer*>(right->ValueType)->PointedType == left->ValueType)
|
||||
{
|
||||
bool writable;
|
||||
if (!left->RequestAddress(ctx, &writable)) goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error;
|
||||
|
@ -5052,7 +5069,6 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
|
|||
|
||||
ExpEmit FxNew::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
assert(ValueType == val->ValueType);
|
||||
ExpEmit from = val->Emit(build);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_POINTER);
|
||||
|
@ -10150,6 +10166,8 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
ScriptPosition.Message(MSG_OPTERROR,
|
||||
"Unknown class name '%s' of type '%s'",
|
||||
clsname.GetChars(), desttype->TypeName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "r_sky.h"
|
||||
#include "v_font.h"
|
||||
#include "v_video.h"
|
||||
#include "c_bind.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
static TArray<FPropertyInfo*> properties;
|
||||
|
@ -754,6 +755,10 @@ void InitThingdef()
|
|||
sectorportalstruct->Size = sizeof(FSectorPortal);
|
||||
sectorportalstruct->Align = alignof(FSectorPortal);
|
||||
|
||||
auto playerclassstruct = NewNativeStruct("PlayerClass", nullptr);
|
||||
playerclassstruct->Size = sizeof(FPlayerClass);
|
||||
playerclassstruct->Align = alignof(FPlayerClass);
|
||||
|
||||
// set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well...
|
||||
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
|
||||
sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native);
|
||||
|
@ -789,6 +794,16 @@ void InitThingdef()
|
|||
PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(aacf);
|
||||
|
||||
auto plrcls = NewPointer(NewResizableArray(playerclassstruct), false);
|
||||
PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf);
|
||||
|
||||
auto bindcls = NewNativeStruct("KeyBindings", nullptr);
|
||||
PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(binding);
|
||||
binding = new PField("AutomapBindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&AutomapBindings);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(binding);
|
||||
|
||||
// set up a variable for the DEH data
|
||||
PStruct *dstruct = NewNativeStruct("DehInfo", nullptr);
|
||||
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
|
||||
|
@ -867,6 +882,9 @@ void InitThingdef()
|
|||
fieldptr = new PField("CleanHeight_1", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanHeight_1);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
fieldptr = new PField("menuactive", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&menuactive);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
fieldptr = new PField("OptionMenuSettings", NewStruct("FOptionMenuSettings", nullptr), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&OptionSettings);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
|
@ -994,7 +1012,7 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Replace)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static FString FStringFormat(VM_ARGS)
|
||||
FString FStringFormat(VM_ARGS)
|
||||
{
|
||||
assert(param[0].Type == REGT_STRING);
|
||||
FString fmtstring = param[0].s().GetChars();
|
||||
|
|
|
@ -1213,6 +1213,6 @@ class PFunction;
|
|||
VMFunction *FindVMFunction(PClass *cls, const char *name);
|
||||
#define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name);
|
||||
|
||||
|
||||
FString FStringFormat(VM_ARGS);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -785,8 +785,11 @@ begin:
|
|||
OP(NEW_K):
|
||||
OP(NEW):
|
||||
{
|
||||
PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[C] : konsta[C].v);
|
||||
reg.a[B] = cls->CreateNew();
|
||||
b = B;
|
||||
PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[b] : konsta[b].v);
|
||||
if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
|
||||
reg.a[a] = cls->CreateNew();
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,8 +70,8 @@ xx(SS, ss, RPRSKI, SS_R, 4, REGT_INT), // store string
|
|||
xx(SS_R, ss, RPRSRI, NOP, 0, 0),
|
||||
xx(SP, sp, RPRPKI, SP_R, 4, REGT_INT), // store pointer
|
||||
xx(SP_R, sp, RPRPRI, NOP, 0, 0),
|
||||
xx(SO, sp, RPRPKI, SO_R, 4, REGT_INT), // store object pointer with write barrier (only needed for non thinkers and non types
|
||||
xx(SO_R, sp, RPRPRI, NOP, 0, 0),
|
||||
xx(SO, so, RPRPKI, SO_R, 4, REGT_INT), // store object pointer with write barrier (only needed for non thinkers and non types)
|
||||
xx(SO_R, so, RPRPRI, NOP, 0, 0),
|
||||
xx(SV2, sv2, RPRVKI, SV2_R, 4, REGT_INT), // store vector2
|
||||
xx(SV2_R, sv2, RPRVRI, NOP, 0, 0),
|
||||
xx(SV3, sv3, RPRVKI, SV3_R, 4, REGT_INT), // store vector3
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
}
|
||||
else
|
||||
{ // Move hanging ( characters to the new line
|
||||
Str.Truncate(long(Str.Len() - ConsecOpens));
|
||||
Str.Truncate(Str.Len() - ConsecOpens);
|
||||
NestDepth -= ConsecOpens;
|
||||
}
|
||||
Str << '\n';
|
||||
|
|
|
@ -12,6 +12,10 @@ static void SetNodeLine(ZCC_TreeNode *name, ZCCToken &tok)
|
|||
|
||||
static void SetNodeLine(ZCC_TreeNode *name, ZCC_TreeNode *node)
|
||||
{
|
||||
if (name == nullptr || node == nullptr)
|
||||
{
|
||||
I_Error("Fatal parse error");
|
||||
}
|
||||
name->SourceLoc = node->SourceLoc;
|
||||
}
|
||||
|
||||
|
|
|
@ -589,6 +589,7 @@ void ZCCCompiler::CreateClassTypes()
|
|||
{
|
||||
Error(c->cls, "Class name %s already exists", c->NodeName().GetChars());
|
||||
}
|
||||
else DPrintf(DMSG_SPAMMY, "Created class %s with parent %s\n", c->Type()->TypeName.GetChars(), c->Type()->ParentClass->TypeName.GetChars());
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
{
|
||||
|
@ -597,6 +598,10 @@ void ZCCCompiler::CreateClassTypes()
|
|||
c->cls->Type = nullptr;
|
||||
}
|
||||
}
|
||||
if (c->cls->Flags & ZCC_Abstract)
|
||||
{
|
||||
c->Type()->ObjectFlags |= OF_Abstract;
|
||||
}
|
||||
if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName());
|
||||
c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.)
|
||||
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
|
||||
|
@ -2593,7 +2598,7 @@ void ZCCCompiler::CompileStates()
|
|||
statename << FName(part->Id) << '.';
|
||||
part = static_cast<decltype(part)>(part->SiblingNext);
|
||||
} while (part != sg->Label);
|
||||
statename.Truncate((long)statename.Len() - 1); // remove the last '.' in the label name
|
||||
statename.Truncate(statename.Len() - 1); // remove the last '.' in the label name
|
||||
if (sg->Offset != nullptr)
|
||||
{
|
||||
int offset = IntConstFromNode(sg->Offset, c->Type());
|
||||
|
|
|
@ -1189,6 +1189,40 @@ int FTextureManager::CountLumpTextures (int lumpnum)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_TexMan, GetSize)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(texid);
|
||||
auto tex = TexMan[FSetTextureID(texid)];
|
||||
int x, y;
|
||||
if (tex != nullptr)
|
||||
{
|
||||
x = tex->GetWidth();
|
||||
y = tex->GetHeight();
|
||||
}
|
||||
else x = y = -1;
|
||||
if (numret > 0) ret[0].SetInt(x);
|
||||
if (numret > 1) ret[1].SetInt(x);
|
||||
return MIN(numret, 2);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_TexMan, GetScaledSize)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(texid);
|
||||
auto tex = TexMan[FSetTextureID(texid)];
|
||||
if (tex != nullptr)
|
||||
{
|
||||
ACTION_RETURN_VEC2(DVector2(tex->GetScaledWidthDouble(), tex->GetScaledHeightDouble()));
|
||||
}
|
||||
ACTION_RETURN_VEC2(DVector2(-1, -1));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -1752,6 +1752,17 @@ void V_DrawFrame (int left, int top, int width, int height)
|
|||
screen->DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, DrawFrame)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(x);
|
||||
PARAM_INT(y);
|
||||
PARAM_INT(w);
|
||||
PARAM_INT(h);
|
||||
V_DrawFrame(x, y, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// V_DrawBorder
|
||||
|
|
|
@ -2741,3 +2741,8 @@ void V_ClearFonts()
|
|||
SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FFont, GetCursor)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FFont);
|
||||
ACTION_RETURN_STRING(FString(self->GetCursor()));
|
||||
}
|
|
@ -141,6 +141,8 @@ void DCanvas::DrawTextCommon(FFont *font, int normalcolor, double x, double y, c
|
|||
int kerning;
|
||||
FTexture *pic;
|
||||
|
||||
assert(string[0] != '$');
|
||||
|
||||
if (parms.celly == 0) parms.celly = font->GetHeight() + 1;
|
||||
parms.celly *= parms.scaley;
|
||||
|
||||
|
@ -240,7 +242,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawText)
|
|||
PARAM_STRING(chr);
|
||||
|
||||
VMVa_List args = { param + 5, 0, numparam - 5 };
|
||||
const char *txt = chr[0] == '$' ? GStrings(chr) : chr.GetChars();
|
||||
const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars();
|
||||
screen->DrawText(font, cr, x, y, txt, args);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ inline unsigned GetVirtualIndex(PClass *cls, const char *funcname)
|
|||
#define IFVIRTUALPTRNAME(self, cls, funcname) \
|
||||
static unsigned VIndex = ~0u; \
|
||||
if (VIndex == ~0u) { \
|
||||
VIndex = GetVirtualIndex(PClass::FindActor(cls), #funcname); \
|
||||
VIndex = GetVirtualIndex(PClass::FindClass(cls), #funcname); \
|
||||
assert(VIndex != ~0u); \
|
||||
} \
|
||||
auto clss = self->GetClass(); \
|
||||
|
|
|
@ -368,15 +368,15 @@ FString &FString::CopyCStrPart(const char *tail, size_t tailLen)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void FString::Truncate(long newlen)
|
||||
void FString::Truncate(size_t newlen)
|
||||
{
|
||||
if (newlen <= 0)
|
||||
if (newlen == 0)
|
||||
{
|
||||
Data()->Release();
|
||||
NullString.RefCount++;
|
||||
Chars = &NullString.Nothing[0];
|
||||
}
|
||||
else if (newlen < (long)Len())
|
||||
else if (newlen < Len())
|
||||
{
|
||||
ReallocBuffer (newlen);
|
||||
Chars[newlen] = '\0';
|
||||
|
|
|
@ -301,7 +301,7 @@ public:
|
|||
bool IsEmpty() const { return Len() == 0; }
|
||||
bool IsNotEmpty() const { return Len() != 0; }
|
||||
|
||||
void Truncate (long newlen);
|
||||
void Truncate (size_t newlen);
|
||||
void Remove(size_t index, size_t remlen);
|
||||
|
||||
int Compare (const FString &other) const { return strcmp (Chars, other.Chars); }
|
||||
|
|
|
@ -6,9 +6,17 @@
|
|||
#include "zscript/actor.txt"
|
||||
#include "zscript/actor_checks.txt"
|
||||
|
||||
#include "zscript/menu/menuitembase.txt"
|
||||
#include "zscript/menu/menu.txt"
|
||||
//#include "zscript/menu/menuitembase.txt"
|
||||
#include "zscript/menu/listmenuitems.txt"
|
||||
#include "zscript/menu/optionmenu.txt"
|
||||
#include "zscript/menu/optionmenuitems.txt"
|
||||
#include "zscript/menu/colorpickermenu.txt"
|
||||
#include "zscript/menu/joystickmenu.txt"
|
||||
#include "zscript/menu/playerdisplay.txt"
|
||||
#include "zscript/menu/playermenu.txt"
|
||||
#include "zscript/menu/textentermenu.txt"
|
||||
#include "zscript/menu/videomenu.txt"
|
||||
|
||||
#include "zscript/inventory/inventory.txt"
|
||||
#include "zscript/inventory/inv_misc.txt"
|
||||
|
|
|
@ -1,3 +1,55 @@
|
|||
struct InputEvent native
|
||||
{
|
||||
native uint8 type;
|
||||
native uint8 subtype;
|
||||
native int16 data1; // keys / mouse/joystick buttons
|
||||
native int16 data2;
|
||||
native int16 data3;
|
||||
native int x; // mouse/joystick x move
|
||||
native int y; // mouse/joystick y move
|
||||
|
||||
enum EGenericEvent
|
||||
{
|
||||
NoEvent,
|
||||
KeyDown, // data1: scan code, data2: Qwerty ASCII code
|
||||
KeyUp, // same
|
||||
Mouse, // x, y: mouse movement deltas
|
||||
GUI_Event, // subtype specifies actual event
|
||||
DeviceChange,// a device has been connected or removed
|
||||
}
|
||||
|
||||
enum EGUIEvent
|
||||
{
|
||||
GUI_None,
|
||||
GUI_KeyDown, // data1: unshifted ASCII, data2: shifted ASCII, data3: modifiers
|
||||
GUI_KeyRepeat, // same
|
||||
GUI_KeyUp, // same
|
||||
GUI_Char, // data1: translated character (for user text input), data2: alt down?
|
||||
GUI_FirstMouseEvent,
|
||||
GUI_MouseMove,
|
||||
GUI_LButtonDown,
|
||||
GUI_LButtonUp,
|
||||
GUI_LButtonDblClick,
|
||||
GUI_MButtonDown,
|
||||
GUI_MButtonUp,
|
||||
GUI_MButtonDblClick,
|
||||
GUI_RButtonDown,
|
||||
GUI_RButtonUp,
|
||||
GUI_RButtonDblClick,
|
||||
GUI_WheelUp, // data3: shift/ctrl/alt
|
||||
GUI_WheelDown, // "
|
||||
GUI_WheelRight, // "
|
||||
GUI_WheelLeft, // "
|
||||
GUI_BackButtonDown,
|
||||
GUI_BackButtonUp,
|
||||
GUI_FwdButtonDown,
|
||||
GUI_FwdButtonUp,
|
||||
GUI_LastMouseEvent,
|
||||
};
|
||||
|
||||
const KEY_ESCAPE = 0x01;
|
||||
}
|
||||
|
||||
struct TexMan
|
||||
{
|
||||
enum EUseTypes
|
||||
|
@ -42,6 +94,8 @@ struct TexMan
|
|||
|
||||
native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny);
|
||||
native static void ReplaceTextures(String from, String to, int flags);
|
||||
native static int, int GetSize(TextureID tex);
|
||||
native static Vector2 GetScaledSize(TextureID tex);
|
||||
}
|
||||
|
||||
enum DrawTextureTags
|
||||
|
@ -118,7 +172,7 @@ struct Screen native
|
|||
native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...);
|
||||
native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
|
||||
native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
|
||||
|
||||
native static void DrawFrame(int x, int y, int w, int h);
|
||||
}
|
||||
|
||||
class BrokenLines : Object native
|
||||
|
@ -158,10 +212,42 @@ struct Font native
|
|||
CR_CYAN,
|
||||
NUM_TEXT_COLORS
|
||||
};
|
||||
|
||||
const TEXTCOLOR_BRICK = "\034A";
|
||||
const TEXTCOLOR_TAN = "\034B";
|
||||
const TEXTCOLOR_GRAY = "\034C";
|
||||
const TEXTCOLOR_GREY = "\034C";
|
||||
const TEXTCOLOR_GREEN = "\034D";
|
||||
const TEXTCOLOR_BROWN = "\034E";
|
||||
const TEXTCOLOR_GOLD = "\034F";
|
||||
const TEXTCOLOR_RED = "\034G";
|
||||
const TEXTCOLOR_BLUE = "\034H";
|
||||
const TEXTCOLOR_ORANGE = "\034I";
|
||||
const TEXTCOLOR_WHITE = "\034J";
|
||||
const TEXTCOLOR_YELLOW = "\034K";
|
||||
const TEXTCOLOR_UNTRANSLATED = "\034L";
|
||||
const TEXTCOLOR_BLACK = "\034M";
|
||||
const TEXTCOLOR_LIGHTBLUE = "\034N";
|
||||
const TEXTCOLOR_CREAM = "\034O";
|
||||
const TEXTCOLOR_OLIVE = "\034P";
|
||||
const TEXTCOLOR_DARKGREEN = "\034Q";
|
||||
const TEXTCOLOR_DARKRED = "\034R";
|
||||
const TEXTCOLOR_DARKBROWN = "\034S";
|
||||
const TEXTCOLOR_PURPLE = "\034T";
|
||||
const TEXTCOLOR_DARKGRAY = "\034U";
|
||||
const TEXTCOLOR_CYAN = "\034V";
|
||||
|
||||
const TEXTCOLOR_NORMAL = "\034-";
|
||||
const TEXTCOLOR_BOLD = "\034+";
|
||||
|
||||
const TEXTCOLOR_CHAT = "\034*";
|
||||
const TEXTCOLOR_TEAMCHAT = "\034!";
|
||||
|
||||
|
||||
native int GetCharWidth(int code);
|
||||
native int StringWidth(String code);
|
||||
native int GetHeight();
|
||||
native String GetCursor();
|
||||
|
||||
native static int FindFontColor(Name color);
|
||||
native static Font FindFont(Name fontname);
|
||||
|
@ -169,10 +255,24 @@ struct Font native
|
|||
native static BrokenLines BreakLines(String text, int maxlen);
|
||||
}
|
||||
|
||||
struct Translation
|
||||
{
|
||||
Color colors[256];
|
||||
|
||||
native int AddTranslation();
|
||||
native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass);
|
||||
static int MakeID(int group, int num)
|
||||
{
|
||||
return (group << 16) + num;
|
||||
}
|
||||
}
|
||||
|
||||
struct Console native
|
||||
{
|
||||
native static void HideConsole();
|
||||
native static void MidPrint(Font fontname, string textlabel, bool bold = false);
|
||||
native static vararg void Printf(string fmt, ...);
|
||||
native static void DoCommand(String cmd);
|
||||
}
|
||||
|
||||
struct DamageTypeDefinition native
|
||||
|
@ -182,9 +282,24 @@ struct DamageTypeDefinition native
|
|||
|
||||
struct CVar native
|
||||
{
|
||||
enum ECVarType
|
||||
{
|
||||
CVAR_Bool,
|
||||
CVAR_Int,
|
||||
CVAR_Float,
|
||||
CVAR_String,
|
||||
CVAR_Color,
|
||||
};
|
||||
|
||||
native static CVar FindCVar(Name name);
|
||||
native int GetInt();
|
||||
native double GetFloat();
|
||||
native String GetString();
|
||||
native void SetInt(int v);
|
||||
native void SetFloat(double v);
|
||||
native void SetString(String s);
|
||||
native int GetRealType();
|
||||
native int ResetToDefault();
|
||||
}
|
||||
|
||||
struct GameInfoStruct native
|
||||
|
@ -347,7 +462,7 @@ struct LevelLocals native
|
|||
|
||||
struct StringTable native
|
||||
{
|
||||
native static String Localize(String val, bool prefixed = false);
|
||||
native static String Localize(String val, bool prefixed = true);
|
||||
}
|
||||
|
||||
// a few values of this need to be readable by the play code.
|
||||
|
@ -382,6 +497,7 @@ struct State native
|
|||
|
||||
native int DistanceTo(state other);
|
||||
native bool ValidateSpriteFrame();
|
||||
native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0));
|
||||
}
|
||||
|
||||
struct F3DFloor native
|
||||
|
@ -476,7 +592,7 @@ class Floor : Thinker native
|
|||
floorRaiseInstant,
|
||||
floorMoveToValue,
|
||||
floorRaiseToLowestCeiling,
|
||||
floorRaiseByTexture,
|
||||
floorRaiseuint8xture,
|
||||
|
||||
floorLowerAndChange,
|
||||
floorRaiseAndChange,
|
||||
|
@ -484,7 +600,7 @@ class Floor : Thinker native
|
|||
floorRaiseToLowest,
|
||||
floorRaiseToCeiling,
|
||||
floorLowerToLowestCeiling,
|
||||
floorLowerByTexture,
|
||||
floorLoweruint8xture,
|
||||
floorLowerToCeiling,
|
||||
|
||||
donutRaise,
|
||||
|
@ -493,7 +609,7 @@ class Floor : Thinker native
|
|||
waitStair,
|
||||
resetStair,
|
||||
|
||||
// Not to be used as parameters to EV_DoFloor()
|
||||
// Not to be used as parameters to DoFloor()
|
||||
genFloorChg0,
|
||||
genFloorChgT,
|
||||
genFloorChg
|
||||
|
@ -527,8 +643,8 @@ class Ceiling : Thinker native
|
|||
ceilLowerToNearest,
|
||||
ceilRaiseToHighestFloor,
|
||||
ceilRaiseToFloor,
|
||||
ceilRaiseByTexture,
|
||||
ceilLowerByTexture,
|
||||
ceilRaiseuint8xture,
|
||||
ceilLoweruint8xture,
|
||||
|
||||
genCeilingChg0,
|
||||
genCeilingChgT,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// for flag changer functions.
|
||||
const FLAG_NO_CHANGE = -1;
|
||||
const MAXPLAYERS = 8;
|
||||
const MAXPLAYERNAME = 15;
|
||||
|
||||
enum EStateUseFlags
|
||||
{
|
||||
|
|
|
@ -32,18 +32,93 @@
|
|||
**
|
||||
*/
|
||||
|
||||
class ColorpickerMenu : Menu native
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// This is only used by the color picker
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuSliderVar : OptionMenuSliderBase
|
||||
{
|
||||
native float mRed;
|
||||
native float mGreen;
|
||||
native float mBlue;
|
||||
int mIndex;
|
||||
|
||||
native int mGridPosX;
|
||||
native int mGridPosY;
|
||||
OptionMenuSliderVar Init(String label, int index, double min, double max, double step, int showval)
|
||||
{
|
||||
Super.Init(label, min, max, step, showval);
|
||||
mIndex = index;
|
||||
return self;
|
||||
}
|
||||
|
||||
native int mStartItem;
|
||||
override double GetSliderValue()
|
||||
{
|
||||
return ColorpickerMenu(Menu.GetCurrentMenu()).GetColor(mIndex);
|
||||
}
|
||||
|
||||
native CVar mCVar;
|
||||
override void SetSliderValue(double val)
|
||||
{
|
||||
ColorpickerMenu(Menu.GetCurrentMenu()).setColor(mIndex, val);
|
||||
}
|
||||
}
|
||||
|
||||
class ColorpickerMenu : OptionMenu
|
||||
{
|
||||
float mRed;
|
||||
float mGreen;
|
||||
float mBlue;
|
||||
|
||||
int mGridPosX;
|
||||
int mGridPosY;
|
||||
|
||||
int mStartItem;
|
||||
|
||||
CVar mCVar;
|
||||
|
||||
double GetColor(int index)
|
||||
{
|
||||
double v = index == 0? mRed : index == 1? mGreen : mBlue;
|
||||
return v;
|
||||
}
|
||||
|
||||
void SetColor(int index, double val)
|
||||
{
|
||||
if (index == 0) mRed = val;
|
||||
else if (index == 1) mGreen = val;
|
||||
else mBlue = val;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Init(Menu parent, String name, OptionMenuDescriptor desc, CVar cv)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
|
||||
mStartItem = mDesc.mItems.Size();
|
||||
mCVar = cv;
|
||||
|
||||
ResetColor();
|
||||
mGridPosX = 0;
|
||||
mGridPosY = 0;
|
||||
|
||||
// This menu uses some features that are hard to implement in an external control lump
|
||||
// so it creates its own list of menu items.
|
||||
mDesc.mItems.Resize(mStartItem+8);
|
||||
mDesc.mItems[mStartItem+0] = new ("OptionMenuItemStaticText").Init(name, false);
|
||||
mDesc.mItems[mStartItem+1] = new ("OptionMenuItemStaticText").Init(" ", false);
|
||||
mDesc.mItems[mStartItem+2] = new ("OptionMenuSliderVar").Init("Red", 0, 0, 255, 15, 0);
|
||||
mDesc.mItems[mStartItem+3] = new ("OptionMenuSliderVar").Init("Green", 1, 0, 255, 15, 0);
|
||||
mDesc.mItems[mStartItem+4] = new ("OptionMenuSliderVar").Init("Blue", 2, 0, 255, 15, 0);
|
||||
mDesc.mItems[mStartItem+5] = new ("OptionMenuItemStaticText").Init(" ", false);
|
||||
mDesc.mItems[mStartItem+6] = new ("OptionMenuItemCommand").Init("Undo changes", "undocolorpic");
|
||||
mDesc.mItems[mStartItem+7] = new ("OptionMenuItemStaticText").Init(" ", false);
|
||||
mDesc.mSelectedItem = mStartItem + 2;
|
||||
mDesc.mIndent = 0;
|
||||
mDesc.CalcIndent();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -256,5 +331,24 @@ class ColorpickerMenu : Menu native
|
|||
screen.DrawText (SmallFont, Font.CR_WHITE, x+(48+24-SmallFont.StringWidth("New")/2)*CleanXfac_1, y, "New", DTA_CleanNoMove_1, true);
|
||||
}
|
||||
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
if (mStartItem >= 0)
|
||||
{
|
||||
mDesc.mItems.Resize(mStartItem);
|
||||
if (mCVar != null) mCVar.SetInt(Color(int(mRed), int(mGreen), int(mBlue)));
|
||||
mStartItem = -1;
|
||||
}
|
||||
}
|
||||
|
||||
override void ResetColor()
|
||||
{
|
||||
if (mCVar != null)
|
||||
{
|
||||
Color clr = Color(mCVar.GetInt());
|
||||
mRed = clr.r;
|
||||
mGreen = clr.g;
|
||||
mBlue = clr.b;
|
||||
}
|
||||
}
|
||||
}
|
225
wadsrc/static/zscript/menu/joystickmenu.txt
Normal file
225
wadsrc/static/zscript/menu/joystickmenu.txt
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
** joystickmenu.cpp
|
||||
** The joystick configuration menus
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuSliderJoySensitivity : OptionMenuSliderBase
|
||||
{
|
||||
void Init(String label, double min, double max, double step, int showval)
|
||||
{
|
||||
Super.Init(label, min, max, step, showval);
|
||||
}
|
||||
|
||||
override double GetSliderValue()
|
||||
{
|
||||
return Menu.GetCurrentJoystickConfig().GetSensitivity();
|
||||
}
|
||||
|
||||
override void SetSliderValue(double val)
|
||||
{
|
||||
Menu.GetCurrentJoystickConfig().SetSensitivity(val);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuSliderJoyScale : OptionMenuSliderBase
|
||||
{
|
||||
int mAxis;
|
||||
int mNeg;
|
||||
|
||||
void Init(String label, int axis, double min, double max, double step, int showval)
|
||||
{
|
||||
Super.Init(label, min, max, step, showval);
|
||||
mAxis = axis;
|
||||
mNeg = 1;
|
||||
}
|
||||
|
||||
override double GetSliderValue()
|
||||
{
|
||||
double d = Menu.GetCurrentJoystickConfig().GetAxisScale(mAxis);
|
||||
mNeg = d < 0? -1:1;
|
||||
return d;
|
||||
}
|
||||
|
||||
override void SetSliderValue(double val)
|
||||
{
|
||||
Menu.GetCurrentJoystickConfig().SetAxisScale(mAxis, val * mNeg);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuSliderJoyDeadZone : OptionMenuSliderBase
|
||||
{
|
||||
int mAxis;
|
||||
int mNeg;
|
||||
|
||||
|
||||
void Init(String label, int axis, double min, double max, double step, int showval)
|
||||
{
|
||||
Super.Init(label, min, max, step, showval);
|
||||
mAxis = axis;
|
||||
mNeg = 1;
|
||||
}
|
||||
|
||||
override double GetSliderValue()
|
||||
{
|
||||
double d = Menu.GetCurrentJoystickConfig().GetAxisDeadZone(mAxis);
|
||||
mNeg = d < 0? -1:1;
|
||||
return d;
|
||||
}
|
||||
|
||||
override void SetSliderValue(double val)
|
||||
{
|
||||
Menu.GetCurrentJoystickConfig().SetAxisDeadZone(mAxis, val * mNeg);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuItemJoyMap : OptionMenuItemOptionBase
|
||||
{
|
||||
int mAxis;
|
||||
|
||||
void Init(String label, int axis, Name values, int center)
|
||||
{
|
||||
Super.Init(label, 'none', values, null, center);
|
||||
mAxis = axis;
|
||||
}
|
||||
|
||||
override int GetSelection()
|
||||
{
|
||||
double f = Menu.GetCurrentJoystickConfig().GetAxisMap(mAxis);
|
||||
let opt = OptionValues.GetCount(mValues);
|
||||
if (opt > 0)
|
||||
{
|
||||
// Map from joystick axis to menu selection.
|
||||
for(int i = 0; i < opt; i++)
|
||||
{
|
||||
if (f ~== OptionValues.GetValue(mValues, i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
override void SetSelection(int selection)
|
||||
{
|
||||
let opt = OptionValues.GetCount(mValues);
|
||||
// Map from menu selection to joystick axis.
|
||||
if (opt == 0 || selection >= opt)
|
||||
{
|
||||
selection = JoystickConfig.JOYAXIS_None;
|
||||
}
|
||||
else
|
||||
{
|
||||
selection = int(OptionValues.GetValue(mValues, selection));
|
||||
}
|
||||
Menu.GetCurrentJoystickConfig().SetAxisMap(mAxis, selection);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuItemInverter : OptionMenuItemOptionBase
|
||||
{
|
||||
int mAxis;
|
||||
|
||||
|
||||
void Init(String label, int axis, int center)
|
||||
{
|
||||
Super.Init(label, "none", "YesNo", NULL, center);
|
||||
mAxis = axis;
|
||||
}
|
||||
|
||||
override int GetSelection()
|
||||
{
|
||||
float f = Menu.GetCurrentJoystickConfig().GetAxisScale(mAxis);
|
||||
return f > 0? 0:1;
|
||||
}
|
||||
|
||||
override void SetSelection(int Selection)
|
||||
{
|
||||
let f = abs(Menu.GetCurrentJoystickConfig().GetAxisScale(mAxis));
|
||||
if (Selection) f*=-1;
|
||||
Menu.GetCurrentJoystickConfig().SetAxisScale(mAxis, f);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Executes a CCMD, action is a CCMD name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu
|
||||
{
|
||||
JoystickConfig mJoy;
|
||||
|
||||
void Init(String label = "", JoystickConfig joy = null)
|
||||
{
|
||||
Super.Init(label, "JoystickConfigMenu");
|
||||
mJoy = joy;
|
||||
}
|
||||
|
||||
override bool Activate()
|
||||
{
|
||||
//UpdateJoystickConfigMenu(mJoy);
|
||||
return Super.Activate();
|
||||
}
|
||||
}
|
||||
|
309
wadsrc/static/zscript/menu/listmenuitems.txt
Normal file
309
wadsrc/static/zscript/menu/listmenuitems.txt
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
** listmenu.cpp
|
||||
** A simple menu consisting of a list of items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
class ListMenuItem : MenuItemBase
|
||||
{
|
||||
void DrawSelector(int xofs, int yofs, TextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((Menu.MenuTime() % 8) < 6)
|
||||
{
|
||||
screen.DrawText(ConFont, OptionMenuSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// static patch
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemStaticPatch : ListMenuItem
|
||||
{
|
||||
TextureID mTexture;
|
||||
bool mCentered;
|
||||
|
||||
void Init(int x, int y, TextureID patch, bool centered = false)
|
||||
{
|
||||
Super.Init(x, y);
|
||||
mTexture = patch;
|
||||
mCentered = centered;
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
if (!mTexture.Exists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int x = mXpos;
|
||||
Vector2 vec = TexMan.GetScaledSize(mTexture);
|
||||
if (mYpos >= 0)
|
||||
{
|
||||
if (mCentered) x -= int(vec.X) / 2;
|
||||
screen.DrawTexture (mTexture, true, x, mYpos, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth()>>1);
|
||||
if (mCentered) x -= (int(vec.X) * CleanXfac)/2;
|
||||
screen.DrawTexture (mTexture, true, x, -mYpos*CleanYfac, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ListMenuItemStaticPatchCentered : ListMenuItemStaticPatch
|
||||
{
|
||||
void Init(int x, int y, TextureID patch)
|
||||
{
|
||||
Super.Init(x, y, patch, true);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// static text
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemStaticText : ListMenuItem
|
||||
{
|
||||
String mText;
|
||||
Font mFont;
|
||||
int mColor;
|
||||
bool mCentered;
|
||||
|
||||
void Init(ListMenuDescriptor desc, int x, int y, String text, int color = Font.CR_UNTRANSLATED)
|
||||
{
|
||||
Super.Init(x, y);
|
||||
mText = text;
|
||||
mFont = desc.mFont;
|
||||
mColor = color >= 0? color : desc.mFontColor;
|
||||
mCentered = false;
|
||||
}
|
||||
|
||||
void InitDirect(int x, int y, String text, Font font, int color = Font.CR_UNTRANSLATED, bool centered = false)
|
||||
{
|
||||
Super.Init(x, y);
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mColor = color;
|
||||
mCentered = centered;
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
if (mText.Length() != 0)
|
||||
{
|
||||
String text = Stringtable.Localize(mText);
|
||||
if (mYpos >= 0)
|
||||
{
|
||||
int x = mXpos;
|
||||
if (mCentered) x -= mFont.StringWidth(text)/2;
|
||||
screen.DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth() >> 1);
|
||||
if (mCentered) x -= (mFont.StringWidth(text) * CleanXfac)/2;
|
||||
screen.DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ListMenuItemStaticTextCentered : ListMenuItemStaticText
|
||||
{
|
||||
void Init(ListMenuDescriptor desc, int x, int y, String text, int color = -1)
|
||||
{
|
||||
Super.Init(desc, x, y, text, color);
|
||||
mCentered = true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// selectable items
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemSelectable : ListMenuItem
|
||||
{
|
||||
int mHotkey;
|
||||
int mHeight;
|
||||
int mParam;
|
||||
|
||||
protected void Init(int x, int y, int height, Name childmenu, int param = -1)
|
||||
{
|
||||
Super.Init(x, y, childmenu);
|
||||
mHeight = height;
|
||||
mParam = param;
|
||||
mHotkey = 0;
|
||||
}
|
||||
|
||||
override bool CheckCoordinate(int x, int y)
|
||||
{
|
||||
return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here
|
||||
}
|
||||
|
||||
override bool Selectable()
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
override bool CheckHotkey(int c)
|
||||
{
|
||||
return c == mHotkey;
|
||||
}
|
||||
|
||||
override bool Activate()
|
||||
{
|
||||
Menu.SetMenu(mAction, mParam);
|
||||
return true;
|
||||
}
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == Menu.MOUSE_Release)
|
||||
{
|
||||
let m = Menu.GetCurrentMenu();
|
||||
if (m != NULL && m.MenuEvent(Menu.MKEY_Enter, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override Name, int GetAction()
|
||||
{
|
||||
return mAction, mParam;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// text item
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemTextItem : ListMenuItemSelectable
|
||||
{
|
||||
String mText;
|
||||
Font mFont;
|
||||
int mColor;
|
||||
int mColorSelected;
|
||||
|
||||
void Init(ListMenuDescriptor desc, String text, String hotkey, Name child, int param = 0)
|
||||
{
|
||||
Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, child, param);
|
||||
mText = text;
|
||||
mFont = desc.mFont;
|
||||
mColor = desc.mFontColor;
|
||||
mColorSelected = desc.mFontcolor2;
|
||||
mHotkey = hotkey.CharCodeAt(0);
|
||||
}
|
||||
|
||||
void InitDirect(int x, int y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0)
|
||||
{
|
||||
Super.Init(x, y, height, child, param);
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mColor = color;
|
||||
mColorSelected = color2;
|
||||
mHotkey = hotkey.CharCodeAt(0);
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
screen.DrawText(mFont, selected ? mColorSelected : mColor, mXpos, mYpos, mText, DTA_Clean, true);
|
||||
}
|
||||
|
||||
override int GetWidth()
|
||||
{
|
||||
return min(1, mFont.StringWidth(StringTable.Localize(mText)));
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// patch item
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemPatchItem : ListMenuItemSelectable
|
||||
{
|
||||
TextureID mTexture;
|
||||
|
||||
void Init(ListMenuDescriptor desc, TextureID patch, String hotkey, Name child, int param = 0)
|
||||
{
|
||||
Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, child, param);
|
||||
mHotkey = hotkey.CharCodeAt(0);
|
||||
mTexture = patch;
|
||||
}
|
||||
|
||||
void InitDirect(int x, int y, int height, TextureID patch, String hotkey, Name child, int param = 0)
|
||||
{
|
||||
Super.Init(x, y, height, child, param);
|
||||
mHotkey = hotkey.CharCodeAt(0);
|
||||
mTexture = patch;
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
screen.DrawTexture (mTexture, true, mXpos, mYpos, DTA_Clean, true);
|
||||
}
|
||||
|
||||
override int GetWidth()
|
||||
{
|
||||
return TexMan.GetSize(mTexture);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,48 @@
|
|||
|
||||
struct KeyBindings native
|
||||
{
|
||||
native static String NameKeys(int k1, int k2);
|
||||
|
||||
native int, int GetKeysForCommand(String cmd);
|
||||
native void SetBind(int key, String cmd);
|
||||
native void UnbindACommand (String str);
|
||||
}
|
||||
|
||||
struct OptionValues native
|
||||
{
|
||||
native static int GetCount(Name group);
|
||||
native static String GetText(Name group, int index);
|
||||
native static double GetValue(Name group, int index);
|
||||
native static String GetTextValue(Name group, int index);
|
||||
}
|
||||
|
||||
struct JoystickConfig native
|
||||
{
|
||||
enum EJoyAxis
|
||||
{
|
||||
JOYAXIS_None = -1,
|
||||
JOYAXIS_Yaw,
|
||||
JOYAXIS_Pitch,
|
||||
JOYAXIS_Forward,
|
||||
JOYAXIS_Side,
|
||||
JOYAXIS_Up,
|
||||
// JOYAXIS_Roll, // Ha ha. No roll for you.
|
||||
NUM_JOYAXIS,
|
||||
};
|
||||
|
||||
native float GetSensitivity();
|
||||
native void SetSensitivity(float scale);
|
||||
|
||||
native float GetAxisScale(int axis);
|
||||
native void SetAxisScale(int axis, float scale);
|
||||
|
||||
native float GetAxisDeadZone(int axis);
|
||||
native void SetAxisDeadZone(int axis, float zone);
|
||||
|
||||
native int GetAxisMap(int axis);
|
||||
native void SetAxisMap(int axis, int gameaxis);
|
||||
}
|
||||
|
||||
class Menu : Object native
|
||||
{
|
||||
enum EMenuKey
|
||||
|
@ -29,17 +73,53 @@ class Menu : Object native
|
|||
MOUSE_Release
|
||||
};
|
||||
|
||||
//native static int MenuTime();
|
||||
enum EMenuState
|
||||
{
|
||||
Off, // Menu is closed
|
||||
On, // Menu is opened
|
||||
WaitKey, // Menu is opened and waiting for a key in the controls menu
|
||||
OnNoPause, // Menu is opened but does not pause the game
|
||||
};
|
||||
|
||||
native Menu mParentMenu;
|
||||
|
||||
void Init(Menu parent)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
}
|
||||
|
||||
native static int MenuTime();
|
||||
native static void SetVideoMode();
|
||||
native static Menu GetCurrentMenu();
|
||||
native static JoystickConfig GetCurrentJoystickConfig();
|
||||
native static void SetMenu(Name mnu, int param = 0);
|
||||
native static void StartMessage(String msg, int mode = 0, Name command = 'none');
|
||||
|
||||
virtual bool TranslateKeyboardEvents() { return true; }
|
||||
virtual void SetFocus(MenuItemBase fc) {}
|
||||
virtual bool CheckFocus(MenuItemBase fc) { return false; }
|
||||
virtual void ReleaseFocus() {}
|
||||
virtual void ResetColor() {}
|
||||
|
||||
native virtual bool Responder(InputEvent ev);
|
||||
native virtual bool MenuEvent (int mkey, bool fromcontroller);
|
||||
native virtual bool MouseEvent(int type, int mx, int my);
|
||||
native virtual void Ticker();
|
||||
native virtual void Drawer();
|
||||
native void Close();
|
||||
native MenuItemBase GetItem(Name n);
|
||||
native void ActivateMenu();
|
||||
|
||||
void MenuSound(Sound snd)
|
||||
static void MenuSound(Sound snd)
|
||||
{
|
||||
S_Sound (snd, CHAN_VOICE | CHAN_UI, snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
|
||||
static void DrawConText (int color, int x, int y, String str)
|
||||
{
|
||||
screen.DrawText (ConFont, color, x, y, str, DTA_CellX, 8 * CleanXfac_1, DTA_CellY, 8 * CleanYfac_1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MenuDescriptor : Object native
|
||||
|
@ -47,17 +127,42 @@ class MenuDescriptor : Object native
|
|||
native Name mMenuName;
|
||||
native String mNetgameMessage;
|
||||
native Class<Menu> mClass;
|
||||
|
||||
native static MenuDescriptor GetDescriptor(Name n);
|
||||
}
|
||||
|
||||
class MenuItemBase : object native
|
||||
class ListMenuDescriptor : MenuDescriptor native
|
||||
{
|
||||
native Array<ListMenuItem> mItems;
|
||||
native int mSelectedItem;
|
||||
native int mSelectOfsX;
|
||||
native int mSelectOfsY;
|
||||
native TextureID mSelector;
|
||||
native int mDisplayTop;
|
||||
native int mXpos, mYpos;
|
||||
native Name mAction;
|
||||
native bool mEnabled;
|
||||
|
||||
// making this virtual now would require exporting all classes at once.
|
||||
native /*virtual*/ bool MenuEvent (int mkey, bool fromcontroller);
|
||||
|
||||
native int mWLeft, mWRight;
|
||||
native int mLinespacing; // needs to be stored for dynamically created menus
|
||||
native int mAutoselect; // this can only be set by internal menu creation functions
|
||||
native Font mFont;
|
||||
native int mFontColor;
|
||||
native int mFontColor2;
|
||||
native bool mCenter;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
// Reset the default settings (ignore all other values in the struct)
|
||||
mSelectOfsX = 0;
|
||||
mSelectOfsY = 0;
|
||||
mSelector.SetInvalid();
|
||||
mDisplayTop = 0;
|
||||
mXpos = 0;
|
||||
mYpos = 0;
|
||||
mLinespacing = 0;
|
||||
mNetgameMessage = "";
|
||||
mFont = NULL;
|
||||
mFontColor = Font.CR_UNTRANSLATED;
|
||||
mFontColor2 = Font.CR_UNTRANSLATED;
|
||||
}
|
||||
}
|
||||
|
||||
struct FOptionMenuSettings
|
||||
|
@ -84,7 +189,7 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
native int mPosition;
|
||||
native bool mDontDim;
|
||||
|
||||
//native void CalcIndent();
|
||||
native void CalcIndent();
|
||||
//native OptionMenuItem GetItem(Name iname);
|
||||
void Reset()
|
||||
{
|
||||
|
@ -96,20 +201,3 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
}
|
||||
}
|
||||
|
||||
class OptionMenuItem : MenuItemBase native
|
||||
{
|
||||
native String mLabel;
|
||||
native bool mCentered;
|
||||
|
||||
//native void drawLabel(int indent, int y, EColorRange color, bool grayed = false);
|
||||
}
|
||||
|
||||
class OptionMenu : Menu native
|
||||
{
|
||||
native bool CanScrollUp;
|
||||
native bool CanScrollDown;
|
||||
native int VisBottom;
|
||||
native OptionMenuItem mFocusControl;
|
||||
native OptionMenuDescriptor mDesc;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
|
||||
class MenuItemBase : Object native
|
||||
{
|
||||
protected int mXpos, mYpos;
|
||||
protected Name mAction;
|
||||
protected native int mXpos, mYpos;
|
||||
protected native Name mAction;
|
||||
native bool mEnabled;
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
protected void Init(int xpos = 0, int ypos = 0, Name actionname = 'None')
|
||||
void Init(int xpos = 0, int ypos = 0, Name actionname = 'None')
|
||||
{
|
||||
mXpos = xpos;
|
||||
mYpos = ypos;
|
||||
|
@ -34,33 +33,17 @@ class MenuItemBase : Object native
|
|||
virtual bool MouseEvent(int type, int x, int y) { return false; }
|
||||
virtual bool CheckHotkey(int c) { return false; }
|
||||
virtual int GetWidth() { return 0; }
|
||||
virtual void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||
virtual int GetY() { return mYpos; }
|
||||
virtual int GetX() { return mXpos; }
|
||||
virtual void SetX(int x) { mXpos = x; }
|
||||
|
||||
/*
|
||||
virtual void DrawSelector(int xofs, int yofs, TextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((Menu.MenuTime() % 8) < 6)
|
||||
{
|
||||
screen.DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
virtual int GetIndent() { return 0; }
|
||||
virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { return indent; }
|
||||
|
||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||
int GetY() { return mYpos; }
|
||||
int GetX() { return mXpos; }
|
||||
void SetX(int x) { mXpos = x; }
|
||||
}
|
||||
|
||||
// this is only used to parse font color ranges in MENUDEF
|
||||
enum MenudefColorRange
|
||||
{
|
||||
NO_COLOR = -1
|
||||
}
|
469
wadsrc/static/zscript/menu/optionmenu.txt
Normal file
469
wadsrc/static/zscript/menu/optionmenu.txt
Normal file
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
** optionmenu.cpp
|
||||
** Handler class for the option menus and associated items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class OptionMenu : Menu
|
||||
{
|
||||
OptionMenuDescriptor mDesc;
|
||||
bool CanScrollUp;
|
||||
bool CanScrollDown;
|
||||
int VisBottom;
|
||||
OptionMenuItem mFocusControl;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual void Init(Menu parent, OptionMenuDescriptor desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
mDesc = desc;
|
||||
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int FirstSelectable()
|
||||
{
|
||||
if (mDesc != NULL)
|
||||
{
|
||||
// Go down to the first selectable item
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
i++;
|
||||
}
|
||||
while (i < mDesc.mItems.Size() && !mDesc.mItems[i].Selectable());
|
||||
if (i>=0 && i < mDesc.mItems.Size()) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEvent ev)
|
||||
{
|
||||
if (ev.type == InputEvent.GUI_Event)
|
||||
{
|
||||
if (ev.subtype == InputEvent.GUI_WheelUp)
|
||||
{
|
||||
int scrollamt = MIN(2, mDesc.mScrollPos);
|
||||
mDesc.mScrollPos -= scrollamt;
|
||||
return true;
|
||||
}
|
||||
else if (ev.subtype == InputEvent.GUI_WheelDown)
|
||||
{
|
||||
if (CanScrollDown)
|
||||
{
|
||||
if (VisBottom >= 0 && VisBottom < (mDesc.mItems.Size()-2))
|
||||
{
|
||||
mDesc.mScrollPos += 2;
|
||||
VisBottom += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc.mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int startedAt = mDesc.mSelectedItem;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (mDesc.mSelectedItem == -1)
|
||||
{
|
||||
mDesc.mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
--mDesc.mSelectedItem;
|
||||
|
||||
if (mDesc.mScrollPos > 0 &&
|
||||
mDesc.mSelectedItem <= mDesc.mScrollTop + mDesc.mScrollPos)
|
||||
{
|
||||
mDesc.mScrollPos = MAX(mDesc.mSelectedItem - mDesc.mScrollTop - 1, 0);
|
||||
}
|
||||
|
||||
if (mDesc.mSelectedItem < 0)
|
||||
{
|
||||
// Figure out how many lines of text fit on the menu
|
||||
int y = mDesc.mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc.mTitle.Length() > 0)
|
||||
{
|
||||
y = -y + BigFont.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
y *= CleanYfac_1;
|
||||
int rowheight = OptionMenuSettings.mLinespacing * CleanYfac_1;
|
||||
int maxitems = (screen.GetHeight() - rowheight - y) / rowheight + 1;
|
||||
|
||||
mDesc.mScrollPos = MAX (0, mDesc.mItems.Size() - maxitems + mDesc.mScrollTop);
|
||||
mDesc.mSelectedItem = mDesc.mItems.Size()-1;
|
||||
}
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_Down:
|
||||
if (mDesc.mSelectedItem == -1)
|
||||
{
|
||||
mDesc.mSelectedItem = FirstSelectable();
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
++mDesc.mSelectedItem;
|
||||
|
||||
if (CanScrollDown && mDesc.mSelectedItem == VisBottom)
|
||||
{
|
||||
mDesc.mScrollPos++;
|
||||
VisBottom++;
|
||||
}
|
||||
if (mDesc.mSelectedItem >= mDesc.mItems.Size())
|
||||
{
|
||||
if (startedAt == -1)
|
||||
{
|
||||
mDesc.mSelectedItem = -1;
|
||||
mDesc.mScrollPos = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc.mSelectedItem = 0;
|
||||
mDesc.mScrollPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
break;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (mDesc.mScrollPos > 0)
|
||||
{
|
||||
mDesc.mScrollPos -= VisBottom - mDesc.mScrollPos - mDesc.mScrollTop;
|
||||
if (mDesc.mScrollPos < 0)
|
||||
{
|
||||
mDesc.mScrollPos = 0;
|
||||
}
|
||||
if (mDesc.mSelectedItem != -1)
|
||||
{
|
||||
mDesc.mSelectedItem = mDesc.mScrollTop + mDesc.mScrollPos + 1;
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable())
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size())
|
||||
{
|
||||
mDesc.mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc.mScrollPos > mDesc.mSelectedItem)
|
||||
{
|
||||
mDesc.mScrollPos = mDesc.mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (CanScrollDown)
|
||||
{
|
||||
int pagesize = VisBottom - mDesc.mScrollPos - mDesc.mScrollTop;
|
||||
mDesc.mScrollPos += pagesize;
|
||||
if (mDesc.mScrollPos + mDesc.mScrollTop + pagesize > mDesc.mItems.Size())
|
||||
{
|
||||
mDesc.mScrollPos = mDesc.mItems.Size() - mDesc.mScrollTop - pagesize;
|
||||
}
|
||||
if (mDesc.mSelectedItem != -1)
|
||||
{
|
||||
mDesc.mSelectedItem = mDesc.mScrollTop + mDesc.mScrollPos;
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable())
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size())
|
||||
{
|
||||
mDesc.mSelectedItem = 0;
|
||||
}
|
||||
}
|
||||
if (mDesc.mScrollPos > mDesc.mSelectedItem)
|
||||
{
|
||||
mDesc.mScrollPos = mDesc.mSelectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mItems[mDesc.mSelectedItem].Activate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// fall through to default
|
||||
default:
|
||||
if (mDesc.mSelectedItem >= 0 &&
|
||||
mDesc.mItems[mDesc.mSelectedItem].MenuEvent(mkey, fromcontroller)) return true;
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
if (mDesc.mSelectedItem != startedAt)
|
||||
{
|
||||
MenuSound ("menu/cursor");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
y = (y / CleanYfac_1) - mDesc.mDrawTop;
|
||||
|
||||
if (mFocusControl)
|
||||
{
|
||||
mFocusControl.MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int yline = (y / OptionMenuSettings.mLinespacing);
|
||||
if (yline >= mDesc.mScrollTop)
|
||||
{
|
||||
yline += mDesc.mScrollPos;
|
||||
}
|
||||
if (yline >= 0 && yline < mDesc.mItems.Size() && mDesc.mItems[yline].Selectable())
|
||||
{
|
||||
if (yline != mDesc.mSelectedItem)
|
||||
{
|
||||
mDesc.mSelectedItem = yline;
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc.mItems[yline].MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mDesc.mSelectedItem = -1;
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Ticker ()
|
||||
{
|
||||
Super.Ticker();
|
||||
for(int i = 0; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
mDesc.mItems[i].Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
int y = mDesc.mPosition;
|
||||
|
||||
if (y <= 0)
|
||||
{
|
||||
if (BigFont && mDesc.mTitle.Length() > 0)
|
||||
{
|
||||
let tt = Stringtable.Localize(mDesc.mTitle);
|
||||
screen.DrawText (BigFont, OptionMenuSettings.mTitleColor,
|
||||
(screen.GetWidth() - BigFont.StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1,
|
||||
tt, DTA_CleanNoMove_1, true);
|
||||
y = -y + BigFont.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
mDesc.mDrawTop = y;
|
||||
int fontheight = OptionMenuSettings.mLinespacing * CleanYfac_1;
|
||||
y *= CleanYfac_1;
|
||||
|
||||
int indent = mDesc.mIndent;
|
||||
if (indent > 280)
|
||||
{ // kludge for the compatibility options with their extremely long labels
|
||||
if (indent + 40 <= CleanWidth_1)
|
||||
{
|
||||
indent = (screen.GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = screen.GetWidth() - 40 * CleanXfac_1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = (indent - 160) * CleanXfac_1 + screen.GetWidth() / 2;
|
||||
}
|
||||
|
||||
int ytop = y + mDesc.mScrollTop * 8 * CleanYfac_1;
|
||||
int lastrow = screen.GetHeight() - SmallFont.GetHeight() * CleanYfac_1;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < mDesc.mItems.Size() && y <= lastrow; i++)
|
||||
{
|
||||
// Don't scroll the uppermost items
|
||||
if (i == mDesc.mScrollTop)
|
||||
{
|
||||
i += mDesc.mScrollPos;
|
||||
if (i >= mDesc.mItems.Size()) break; // skipped beyond end of menu
|
||||
}
|
||||
bool isSelected = mDesc.mSelectedItem == i;
|
||||
int cur_indent = mDesc.mItems[i].Draw(mDesc, y, indent, isSelected);
|
||||
if (cur_indent >= 0 && isSelected && mDesc.mItems[i].Selectable())
|
||||
{
|
||||
if (((MenuTime() % 8) < 6) || GetCurrentMenu() != self)
|
||||
{
|
||||
DrawConText(OptionMenuSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd");
|
||||
}
|
||||
}
|
||||
y += fontheight;
|
||||
}
|
||||
|
||||
CanScrollUp = (mDesc.mScrollPos > 0);
|
||||
CanScrollDown = (i < mDesc.mItems.Size());
|
||||
VisBottom = i - 1;
|
||||
|
||||
if (CanScrollUp)
|
||||
{
|
||||
DrawConText(Font.CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a");
|
||||
}
|
||||
if (CanScrollDown)
|
||||
{
|
||||
DrawConText(Font.CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b");
|
||||
}
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void SetFocus(MenuItemBase fc)
|
||||
{
|
||||
mFocusControl = OptionMenuItem(fc);
|
||||
}
|
||||
|
||||
override bool CheckFocus(MenuItemBase fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
|
||||
override void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class GameplayMenu : OptionMenu
|
||||
{
|
||||
override void Drawer ()
|
||||
{
|
||||
Super.Drawer();
|
||||
|
||||
String s = String.Format("dmflags = %d dmflags2 = %d", dmflags, dmflags2);
|
||||
screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue,
|
||||
(screen.GetWidth() - SmallFont.StringWidth (s) * CleanXfac_1) / 2, 0, s,
|
||||
DTA_CleanNoMove_1, true);
|
||||
}
|
||||
}
|
||||
|
||||
class CompatibilityMenu : OptionMenu
|
||||
{
|
||||
override void Drawer ()
|
||||
{
|
||||
Super.Drawer();
|
||||
|
||||
String s = String.Format("compatflags = %d compatflags2 = %d", compatflags, compatflags2);
|
||||
screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue,
|
||||
(screen.GetWidth() - SmallFont.StringWidth (s) * CleanXfac_1) / 2, 0, s,
|
||||
DTA_CleanNoMove_1, true);
|
||||
}
|
||||
}
|
||||
|
||||
class JoystickConfigMenu : OptionMenu
|
||||
{
|
||||
// This is not really needed anymore but needs to be kept for old MENUDEFs that keep the entry
|
||||
}
|
||||
|
1200
wadsrc/static/zscript/menu/optionmenuitems.txt
Normal file
1200
wadsrc/static/zscript/menu/optionmenuitems.txt
Normal file
File diff suppressed because it is too large
Load diff
290
wadsrc/static/zscript/menu/playerdisplay.txt
Normal file
290
wadsrc/static/zscript/menu/playerdisplay.txt
Normal file
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
** playerdisplay.cpp
|
||||
** The player display for the player setup and class selection screen
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// the player sprite window
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemPlayerDisplay : ListMenuItem
|
||||
{
|
||||
ListMenuDescriptor mOwner;
|
||||
TextureID mBackdrop;
|
||||
PlayerClass mPlayerClass;
|
||||
State mPlayerState;
|
||||
int mPlayerTics;
|
||||
bool mNoportrait;
|
||||
int8 mRotation;
|
||||
int8 mMode; // 0: automatic (used by class selection), 1: manual (used by player setup)
|
||||
int8 mTranslate;
|
||||
int mSkin;
|
||||
int mRandomClass;
|
||||
int mRandomTimer;
|
||||
int mClassNum;
|
||||
int mTranslation;
|
||||
|
||||
enum EPDFlags
|
||||
{
|
||||
PDF_ROTATION = 0x10001,
|
||||
PDF_SKIN = 0x10002,
|
||||
PDF_CLASS = 0x10003,
|
||||
PDF_MODE = 0x10004,
|
||||
PDF_TRANSLATE = 0x10005,
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
void Init(ListMenuDescriptor menu, int x, int y, Color c1, Color c2, bool np = false, Name command = 'None' )
|
||||
{
|
||||
Super.Init(x, y, command);
|
||||
mOwner = menu;
|
||||
|
||||
Translation trans;
|
||||
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;
|
||||
trans.colors[i] = Color(255, r, g, b);
|
||||
}
|
||||
mTranslation = trans.AddTranslation();
|
||||
|
||||
mBackdrop = TexMan.CheckForTexture("PlayerBackdrop", TexMan.Type_MiscPatch);
|
||||
mPlayerClass = NULL;
|
||||
mPlayerState = NULL;
|
||||
mNoportrait = np;
|
||||
mMode = 0;
|
||||
mRotation = 0;
|
||||
mTranslate = false;
|
||||
mSkin = 0;
|
||||
mRandomClass = 0;
|
||||
mRandomTimer = 0;
|
||||
mClassNum = -1;
|
||||
}
|
||||
|
||||
private void UpdatePlayer(int classnum)
|
||||
{
|
||||
mPlayerClass = PlayerClasses[classnum];
|
||||
mPlayerState = GetDefaultByType (mPlayerClass.Type).SeeState;
|
||||
if (mPlayerState == NULL)
|
||||
{ // No see state, so try spawn state.
|
||||
mPlayerState = GetDefaultByType (mPlayerClass.Type).SpawnState;
|
||||
}
|
||||
mPlayerTics = mPlayerState != NULL ? mPlayerState.Tics : -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
private void UpdateRandomClass()
|
||||
{
|
||||
if (--mRandomTimer < 0)
|
||||
{
|
||||
if (++mRandomClass >= PlayerClasses.Size ()) mRandomClass = 0;
|
||||
UpdatePlayer(mRandomClass);
|
||||
mPlayerTics = mPlayerState != NULL ? mPlayerState.Tics : -1;
|
||||
mRandomTimer = 6;
|
||||
|
||||
// Since the newly displayed class may use a different translation
|
||||
// range than the old one, we need to update the translation, too.
|
||||
Translation.SetPlayerTranslation(TRANSLATION_Players, MAXPLAYERS, consoleplayer, mPlayerClass);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void SetPlayerClass(int classnum, bool force = false)
|
||||
{
|
||||
if (classnum < 0 || classnum >= PlayerClasses.Size ())
|
||||
{
|
||||
if (mClassNum != -1)
|
||||
{
|
||||
mClassNum = -1;
|
||||
mRandomTimer = 0;
|
||||
UpdateRandomClass();
|
||||
}
|
||||
}
|
||||
else if (mPlayerClass != PlayerClasses[classnum] || force)
|
||||
{
|
||||
UpdatePlayer(classnum);
|
||||
mClassNum = classnum;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool UpdatePlayerClass()
|
||||
{
|
||||
if (mOwner.mSelectedItem >= 0)
|
||||
{
|
||||
int classnum;
|
||||
Name seltype;
|
||||
|
||||
[seltype, classnum] = mOwner.mItems[mOwner.mSelectedItem].GetAction();
|
||||
|
||||
if (seltype != 'Episodemenu') return false;
|
||||
if (PlayerClasses.Size() == 0) return false;
|
||||
|
||||
SetPlayerClass(classnum);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool 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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Ticker()
|
||||
{
|
||||
if (mClassNum < 0) UpdateRandomClass();
|
||||
|
||||
if (mPlayerState != NULL && mPlayerState.Tics != -1 && mPlayerState.NextState != NULL)
|
||||
{
|
||||
if (--mPlayerTics <= 0)
|
||||
{
|
||||
mPlayerState = mPlayerState.NextState;
|
||||
mPlayerTics = mPlayerState.Tics;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
if (mMode == 0 && !UpdatePlayerClass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
let playdef = GetDefaultByType((class<PlayerPawn>)(mPlayerClass.Type));
|
||||
|
||||
Name portrait = playdef.Portrait;
|
||||
|
||||
if (portrait != 'None' && !mNoportrait)
|
||||
{
|
||||
TextureID texid = TexMan.CheckForTexture(portrait, TexMan.Type_MiscPatch);
|
||||
screen.DrawTexture (texid, true, mXpos, mYpos, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = (mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1);
|
||||
int y = (mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1);
|
||||
|
||||
screen.DrawTexture(mBackdrop, false, x, y - 1,
|
||||
DTA_DestWidth, 72 * CleanXfac,
|
||||
DTA_DestHeight, 80 * CleanYfac,
|
||||
DTA_TranslationIndex, mTranslation,
|
||||
DTA_Masked, true);
|
||||
|
||||
Screen.DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1);
|
||||
|
||||
if (mPlayerState != NULL)
|
||||
{
|
||||
Vector2 Scale;
|
||||
TextureID sprite;
|
||||
bool flip;
|
||||
|
||||
[sprite, flip, Scale] = mPlayerState.GetSpriteTexture(mRotation, mSkin, playdef.Scale);
|
||||
|
||||
if (sprite.IsValid())
|
||||
{
|
||||
int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0;
|
||||
let tscale = TexMan.GetScaledSize(sprite);
|
||||
Scale.X *= CleanXfac * tscale.X;
|
||||
Scale.Y *= CleanYfac * tscale.Y;
|
||||
|
||||
screen.DrawTexture (sprite, false,
|
||||
x + 36*CleanXfac, y + 71*CleanYfac,
|
||||
DTA_DestWidthF, Scale.X, DTA_DestHeightF, Scale.Y,
|
||||
DTA_TranslationIndex, trans,
|
||||
DTA_FlipX, flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
522
wadsrc/static/zscript/menu/playermenu.txt
Normal file
522
wadsrc/static/zscript/menu/playermenu.txt
Normal file
|
@ -0,0 +1,522 @@
|
|||
/*
|
||||
** playermenu.txt
|
||||
** The player setup menu
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
||||
{
|
||||
String mText;
|
||||
Font mFont;
|
||||
int mFontColor;
|
||||
int mFrameSize;
|
||||
String mPlayerName;
|
||||
TextEnterMenu mEnter;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Player's name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Init(ListMenuDescriptor desc, String text, int frameofs, Name command)
|
||||
{
|
||||
Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command);
|
||||
mText = text;
|
||||
mFont = desc.mFont;
|
||||
mFontColor = desc.mFontColor;
|
||||
mFrameSize = frameofs;
|
||||
mPlayerName = "";
|
||||
mEnter = null;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Player's name
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void InitDirect(int x, int y, int height, int frameofs, String text, Font font, int color, Name command)
|
||||
{
|
||||
Super.Init(x, y, height, command);
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mFontColor = color;
|
||||
mFrameSize = frameofs;
|
||||
mPlayerName = "";
|
||||
mEnter = null;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool SetString(int i, String s)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mPlayerName = s.Mid(0, MAXPLAYERNAME);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override bool, String GetString(int i)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
return true, mPlayerName;
|
||||
}
|
||||
return false, "";
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// [RH] Width of the border is variable
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void DrawBorder (int x, int y, int len)
|
||||
{
|
||||
let left = TexMan.CheckForTexture("M_LSLEFT", TexMan.Type_MiscPatch);
|
||||
let mid = TexMan.CheckForTexture("M_LSCNTR", TexMan.Type_MiscPatch);
|
||||
let right = TexMan.CheckForTexture("M_LSRGHT", TexMan.Type_MiscPatch);
|
||||
if (left.IsValid() && right.IsValid() && mid.IsValid())
|
||||
{
|
||||
int i;
|
||||
|
||||
screen.DrawTexture (left, false, x-8, y+7, DTA_Clean, true);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
screen.DrawTexture (mid, false, x, y+7, DTA_Clean, true);
|
||||
x += 8;
|
||||
}
|
||||
|
||||
screen.DrawTexture (right, false, x, y+7, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
let slot = TexMan.CheckForTexture("M_FSLOT", TexMan.Type_MiscPatch);
|
||||
if (slot.IsValid())
|
||||
{
|
||||
screen.DrawTexture (slot, false, x, y+1, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.Clear(x, y, x + len, y + SmallFont.GetHeight() * 3/2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
String text = StringTable.Localize(mText);
|
||||
if (text.Length() > 0)
|
||||
{
|
||||
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
||||
}
|
||||
|
||||
// Draw player name box
|
||||
int x = mXpos + mFont.StringWidth(text) + 16 + mFrameSize;
|
||||
DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1);
|
||||
if (!mEnter)
|
||||
{
|
||||
screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
let printit = mEnter.GetText() .. SmallFont.GetCursor();
|
||||
screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, printit, DTA_Clean, true);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == Menu.MKEY_Enter)
|
||||
{
|
||||
Menu.MenuSound ("menu/choose");
|
||||
mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), mPlayerName, MAXPLAYERNAME, 2, fromcontroller);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == Menu.MKEY_Input)
|
||||
{
|
||||
mPlayerName = mEnter.GetText();
|
||||
mEnter = null;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == Menu.MKEY_Abort)
|
||||
{
|
||||
mEnter = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemValueText : ListMenuItemSelectable
|
||||
{
|
||||
Array<String> mSelections;
|
||||
String mText;
|
||||
int mSelection;
|
||||
Font mFont;
|
||||
int mFontColor;
|
||||
int mFontColor2;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Init(ListMenuDescriptor desc, String text, Name command, Name values = 'None')
|
||||
{
|
||||
Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command);
|
||||
mText = text;
|
||||
mFont = desc.mFont;
|
||||
mFontColor = desc.mFontColor;
|
||||
mFontColor2 = desc.mFontColor2;
|
||||
mSelection = 0;
|
||||
let cnt = OptionValues.GetCount(values);
|
||||
for(int i = 0; i < cnt; i++)
|
||||
{
|
||||
SetString(i, OptionValues.GetText(values, i));
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void InitDirect(int x, int y, int height, String text, Font font, int color, int valuecolor, Name command, Name values)
|
||||
{
|
||||
Super.Init(x, y, height, command);
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mFontColor = color;
|
||||
mFontColor2 = valuecolor;
|
||||
mSelection = 0;
|
||||
let cnt = OptionValues.GetCount(values);
|
||||
for(int i = 0; i < cnt; i++)
|
||||
{
|
||||
SetString(i, OptionValues.GetText(values, i));
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool SetString(int i, String s)
|
||||
{
|
||||
// should actually use the index...
|
||||
if (i==0) mSelections.Clear();
|
||||
mSelections.Push(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool SetValue(int i, int value)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mSelection = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override bool, int GetValue(int i)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
return true, mSelection;
|
||||
}
|
||||
return false, 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mSelections.Size() > 1)
|
||||
{
|
||||
if (mkey == Menu.MKEY_Left)
|
||||
{
|
||||
Menu.MenuSound("menu/change");
|
||||
if (--mSelection < 0) mSelection = mSelections.Size() - 1;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter)
|
||||
{
|
||||
Menu.MenuSound("menu/change");
|
||||
if (++mSelection >= mSelections.Size()) mSelection = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (mkey == Menu.MKEY_Enter); // needs to eat enter keys so that Activate won't get called
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
String text = Stringtable.Localize(mText);
|
||||
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
||||
|
||||
int x = mXpos + mFont.StringWidth(text) + 8;
|
||||
if (mSelections.Size() > 0)
|
||||
{
|
||||
screen.DrawText(mFont, mFontColor2, x, mYpos, mSelections[mSelection], DTA_Clean, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenuItemSlider : ListMenuItemSelectable
|
||||
{
|
||||
String mText;
|
||||
Font mFont;
|
||||
int mFontColor;
|
||||
int mMinrange, mMaxrange;
|
||||
int mStep;
|
||||
int mSelection;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Init(ListMenuDescriptor desc, String text, Name command, int min, int max, int step)
|
||||
{
|
||||
Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command);
|
||||
mText = text;
|
||||
mFont = desc.mFont;
|
||||
mFontColor = desc.mFontColor;
|
||||
mSelection = 0;
|
||||
mMinrange = min;
|
||||
mMaxrange = max;
|
||||
mStep = step;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// items for the player menu
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void InitDirect(int x, int y, int height, String text, Font font, int color, Name command, int min, int max, int step)
|
||||
{
|
||||
Super.Init(x, y, height, command);
|
||||
mText = text;
|
||||
mFont = font;
|
||||
mFontColor = color;
|
||||
mSelection = 0;
|
||||
mMinrange = min;
|
||||
mMaxrange = max;
|
||||
mStep = step;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool SetValue(int i, int value)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
mSelection = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override bool, int GetValue(int i)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
return true, mSelection;
|
||||
}
|
||||
return false, 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == Menu.MKEY_Left)
|
||||
{
|
||||
Menu.MenuSound("menu/change");
|
||||
if ((mSelection -= mStep) < mMinrange) mSelection = mMinrange;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter)
|
||||
{
|
||||
Menu.MenuSound("menu/change");
|
||||
if ((mSelection += mStep) > mMaxrange) mSelection = mMaxrange;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
let lm = Menu.GetCurrentMenu();
|
||||
if (type != Menu.MOUSE_Click)
|
||||
{
|
||||
if (!lm.CheckFocus(self)) return false;
|
||||
}
|
||||
if (type == Menu.MOUSE_Release)
|
||||
{
|
||||
lm.ReleaseFocus();
|
||||
}
|
||||
|
||||
int slide_left = SmallFont.StringWidth ("Green") + 8 + mXpos;
|
||||
int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each.
|
||||
|
||||
if (type == Menu.MOUSE_Click)
|
||||
{
|
||||
if (x < slide_left || x >= slide_right) return true;
|
||||
}
|
||||
|
||||
x = clamp(x, slide_left, slide_right);
|
||||
int v = mMinrange + (x - slide_left) * (mMaxrange - mMinrange) / (slide_right - slide_left);
|
||||
if (v != mSelection)
|
||||
{
|
||||
mSelection = v;
|
||||
Menu.MenuSound("menu/change");
|
||||
}
|
||||
if (type == Menu.MOUSE_Click)
|
||||
{
|
||||
lm.SetFocus(self);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void DrawSlider (int x, int y)
|
||||
{
|
||||
int range = mMaxrange - mMinrange;
|
||||
int cur = mSelection - mMinrange;
|
||||
|
||||
x = (x - 160) * CleanXfac + screen.GetWidth() / 2;
|
||||
y = (y - 100) * CleanYfac + screen.GetHeight() / 2;
|
||||
|
||||
screen.DrawText (ConFont, Font.CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac);
|
||||
screen.DrawText (ConFont, Font.CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, "\x13", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer(bool selected)
|
||||
{
|
||||
String text = StringTable.Localize(mText);
|
||||
|
||||
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
||||
|
||||
int x = SmallFont.StringWidth ("Green") + 8 + mXpos;
|
||||
int x2 = SmallFont.StringWidth (text) + 8 + mXpos;
|
||||
DrawSlider (MAX(x2, x), mYpos);
|
||||
}
|
||||
}
|
15
wadsrc/static/zscript/menu/textentermenu.txt
Normal file
15
wadsrc/static/zscript/menu/textentermenu.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
// This is only the parts that are needed to make the menu fully work right now. More to come later.
|
||||
class TextEnterMenu : Menu native
|
||||
{
|
||||
native bool mInputGridOkay;
|
||||
|
||||
native static TextEnterMenu Open(Menu parent, String text, int maxlen, int sizemode, bool fromcontroller);
|
||||
native String GetText();
|
||||
|
||||
|
||||
override bool TranslateKeyboardEvents()
|
||||
{
|
||||
return mInputGridOkay;
|
||||
}
|
||||
}
|
73
wadsrc/static/zscript/menu/videomenu.txt
Normal file
73
wadsrc/static/zscript/menu/videomenu.txt
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
** videomenu.txt
|
||||
** The video modes menu
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class VideoModeMenu : OptionMenu
|
||||
{
|
||||
native static bool SetSelectedSize();
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if ((mkey == MKEY_Up || mkey == MKEY_Down) && mDesc.mSelectedItem >= 0 && mDesc.mSelectedItem < mDesc.mItems.Size())
|
||||
{
|
||||
int sel;
|
||||
bool selected;
|
||||
[selected, sel] = mDesc.mItems[mDesc.mSelectedItem].GetValue(OptionMenuItemScreenResolution.SRL_SELECTION);
|
||||
bool res = Super.MenuEvent(mkey, fromcontroller);
|
||||
if (selected) mDesc.mItems[mDesc.mSelectedItem].SetValue(OptionMenuItemScreenResolution.SRL_SELECTION, sel);
|
||||
return res;
|
||||
}
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
override bool Responder(InputEvent ev)
|
||||
{
|
||||
if (ev.type == InputEvent.GUI_Event && ev.subtype == InputEvent.GUI_KeyDown && (ev.data1 == 0x54 || ev.data1 == 0x74))
|
||||
{
|
||||
if (SetSelectedSize())
|
||||
{
|
||||
MenuSound ("menu/choose");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
}
|
||||
|
|
@ -315,3 +315,12 @@ userinfo_t userinfo;
|
|||
native void BringUpWeapon();
|
||||
|
||||
}
|
||||
|
||||
struct PlayerClass native
|
||||
{
|
||||
native class<Actor> Type;
|
||||
native uint Flags;
|
||||
native Array<int> Skins;
|
||||
|
||||
native bool CheckSkin(int skin);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class Coin : Inventory
|
|||
}
|
||||
else
|
||||
{
|
||||
String msg = StringTable.Localize("TXT_XGOLD");
|
||||
String msg = StringTable.Localize("$TXT_XGOLD");
|
||||
msg.Replace("%d", "" .. Amount);
|
||||
return msg;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ extend class Actor
|
|||
}
|
||||
}
|
||||
|
||||
String msgid = "TXT_QUEST_" .. questitem;
|
||||
String msgid = "$TXT_QUEST_" .. questitem;
|
||||
String msg = StringTable.Localize(msgid);
|
||||
|
||||
if (msg != msgid) // if both are identical there was no message of this name in the stringtable.
|
||||
|
|
Loading…
Reference in a new issue