- almost done with TextEnterMenu.

This commit is contained in:
Christoph Oelckers 2017-02-18 21:18:23 +01:00
parent 0c41a9dee7
commit f5a0f6b3bf
8 changed files with 255 additions and 256 deletions

View file

@ -1195,6 +1195,8 @@ CCMD(undocolorpic)
DEFINE_FIELD(DMenu, mParentMenu) DEFINE_FIELD(DMenu, mParentMenu)
DEFINE_FIELD(DMenu, mMouseCapture);
DEFINE_FIELD(DMenu, mBackbuttonSelected);
DEFINE_FIELD(DMenuDescriptor, mMenuName) DEFINE_FIELD(DMenuDescriptor, mMenuName)
DEFINE_FIELD(DMenuDescriptor, mNetgameMessage) DEFINE_FIELD(DMenuDescriptor, mNetgameMessage)

View file

@ -253,9 +253,7 @@ class DMenu : public DObject
DECLARE_CLASS (DMenu, DObject) DECLARE_CLASS (DMenu, DObject)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
protected:
bool mMouseCapture;
bool mBackbuttonSelected;
public: public:
enum enum
@ -271,6 +269,8 @@ public:
}; };
TObjPtr<DMenu> mParentMenu; TObjPtr<DMenu> mParentMenu;
bool mMouseCapture;
bool mBackbuttonSelected;
DMenu(DMenu *parent = NULL); DMenu(DMenu *parent = NULL);
virtual bool Responder (event_t *ev); virtual bool Responder (event_t *ev);
@ -354,7 +354,7 @@ extern FOptionMap OptionValues;
class DTextEnterMenu : public DMenu class DTextEnterMenu : public DMenu
{ {
DECLARE_ABSTRACT_CLASS(DTextEnterMenu, DMenu) DECLARE_CLASS(DTextEnterMenu, DMenu)
public: public:
FString mEnterString; FString mEnterString;
@ -370,12 +370,7 @@ public:
bool AllowColors; bool AllowColors;
// [TP] Added allowcolors DTextEnterMenu() {}
DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false);
bool MenuEvent (int mkey, bool fromcontroller);
bool Responder(event_t *ev);
bool MouseEvent(int type, int x, int y);
}; };

View file

@ -44,249 +44,10 @@
// [TP] New #includes // [TP] New #includes
#include "v_text.h" #include "v_text.h"
IMPLEMENT_CLASS(DTextEnterMenu, true, false) IMPLEMENT_CLASS(DTextEnterMenu, false, false)
#define INPUTGRID_WIDTH 13
#define INPUTGRID_HEIGHT 5
// Heretic and Hexen do not, by default, come with glyphs for all of these
// characters. Oh well. Doom and Strife do.
static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] =
"ABCDEFGHIJKLM"
"NOPQRSTUVWXYZ"
"0123456789+-="
".,!?@'\":;[]()"
"<>^#$%&*/_ \b";
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
//=============================================================================
//
//
//
//=============================================================================
// [TP] Added allowcolors
DTextEnterMenu::DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
: DMenu(parent)
{
mEnterString = textbuffer;
mEnterSize = maxlen < 0 ? UINT_MAX : unsigned(maxlen);
mSizeMode = sizemode;
mInputGridOkay = showgrid || m_showinputgrid;
if (mEnterString.IsNotEmpty())
{
InputGridX = INPUTGRID_WIDTH - 1;
InputGridY = INPUTGRID_HEIGHT - 1;
}
else
{
// If we are naming a new save, don't start the cursor on "end".
InputGridX = 0;
InputGridY = 0;
}
AllowColors = allowcolors; // [TP]
}
//=============================================================================
//
//
//
//=============================================================================
bool DTextEnterMenu::Responder(event_t *ev)
{
if (ev->type == EV_GUI_Event)
{
// Save game and player name string input
if (ev->subtype == EV_GUI_Char)
{
mInputGridOkay = false;
if (mEnterString.Len() < mEnterSize &&
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
{
mEnterString.AppendFormat("%c", (char)ev->data1);
}
return true;
}
char ch = (char)ev->data1;
if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b')
{
if (mEnterString.IsNotEmpty())
{
mEnterString.Truncate(mEnterString.Len() - 1);
}
}
else if (ev->subtype == EV_GUI_KeyDown)
{
if (ch == GK_ESCAPE)
{
DMenu *parent = mParentMenu;
Close();
parent->CallMenuEvent(MKEY_Abort, false);
return true;
}
else if (ch == '\r')
{
if (mEnterString.IsNotEmpty())
{
// [TP] If we allow color codes, colorize the string now.
if (AllowColors)
mEnterString = strbin1(mEnterString);
DMenu *parent = mParentMenu;
parent->CallMenuEvent(MKEY_Input, false);
Close();
return true;
}
}
}
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
{
return true;
}
}
return Super::Responder(ev);
}
//=============================================================================
//
//
//
//=============================================================================
bool DTextEnterMenu::MouseEvent(int type, int x, int y)
{
const int cell_width = 18 * CleanXfac;
const int cell_height = 12 * CleanYfac;
const int screen_y = screen->GetHeight() - INPUTGRID_HEIGHT * cell_height;
const int screen_x = (screen->GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y)
{
InputGridX = (x - screen_x) / cell_width;
InputGridY = (y - screen_y) / cell_height;
if (type == DMenu::MOUSE_Release)
{
if (CallMenuEvent(MKEY_Enter, true))
{
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
return true;
}
}
}
else
{
InputGridX = InputGridY = -1;
}
return Super::MouseEvent(type, x, y);
}
//=============================================================================
//
//
//
//=============================================================================
bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
{
if (key == MKEY_Back)
{
mParentMenu->CallMenuEvent(MKEY_Abort, false);
return Super::MenuEvent(key, fromcontroller);
}
if (fromcontroller)
{
mInputGridOkay = true;
}
if (mInputGridOkay)
{
int ch;
if (InputGridX == -1 || InputGridY == -1)
{
InputGridX = InputGridY = 0;
}
switch (key)
{
case MKEY_Down:
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
return true;
case MKEY_Up:
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
return true;
case MKEY_Right:
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
return true;
case MKEY_Left:
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
return true;
case MKEY_Clear:
if (mEnterString.IsNotEmpty())
{
mEnterString.Truncate(mEnterString.Len() - 1);
}
return true;
case MKEY_Enter:
assert(unsigned(InputGridX) < INPUTGRID_WIDTH && unsigned(InputGridY) < INPUTGRID_HEIGHT);
if (mInputGridOkay)
{
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
if (ch == 0) // end
{
if (mEnterString.IsNotEmpty())
{
DMenu *parent = mParentMenu;
Close();
parent->CallMenuEvent(MKEY_Input, false);
return true;
}
}
else if (ch == '\b') // bs
{
if (mEnterString.IsNotEmpty())
{
mEnterString.Truncate(mEnterString.Len() - 1);
}
}
else if (mEnterString.Len() < mEnterSize &&
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
{
mEnterString += char(ch);
}
}
return true;
default:
break; // Keep GCC quiet
}
}
return false;
}
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_FIELD(DTextEnterMenu, mEnterString); DEFINE_FIELD(DTextEnterMenu, mEnterString);
DEFINE_FIELD(DTextEnterMenu, mEnterSize); DEFINE_FIELD(DTextEnterMenu, mEnterSize);
DEFINE_FIELD(DTextEnterMenu, mEnterPos); DEFINE_FIELD(DTextEnterMenu, mEnterPos);

View file

@ -1213,10 +1213,12 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Mid)
ACTION_RETURN_STRING(s); ACTION_RETURN_STRING(s);
} }
DEFINE_ACTION_FUNCTION(FStringStruct, Len) DEFINE_ACTION_FUNCTION(FStringStruct, Truncate)
{ {
PARAM_SELF_STRUCT_PROLOGUE(FString); PARAM_SELF_STRUCT_PROLOGUE(FString);
ACTION_RETURN_INT((int)self->Len()); PARAM_UINT(len);
self->Truncate(len);
return 0;
} }
// CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int. // CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int.
@ -1239,3 +1241,10 @@ DEFINE_ACTION_FUNCTION(FStringStruct, CharCodeAt)
ACTION_RETURN_INT(0); ACTION_RETURN_INT(0);
ACTION_RETURN_INT((*self)[pos]); ACTION_RETURN_INT((*self)[pos]);
} }
DEFINE_ACTION_FUNCTION(FStringStruct, Filter)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
ACTION_RETURN_STRING(strbin1(*self));
}

View file

@ -8,6 +8,8 @@
#include "doomerrors.h" #include "doomerrors.h"
#include "memarena.h" #include "memarena.h"
class DObject;
extern FMemArena ClassDataAllocator; extern FMemArena ClassDataAllocator;
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return #define MAX_RETURNS 8 // Maximum number of results a function called by script code can return

View file

@ -578,9 +578,10 @@ struct StringStruct native
native void Replace(String pattern, String replacement); native void Replace(String pattern, String replacement);
native String Mid(int pos = 0, int len = 2147483647); native String Mid(int pos = 0, int len = 2147483647);
native int Len(); native void Truncate(int newlen);
native String CharAt(int pos); native String CharAt(int pos);
native int CharCodeAt(int pos); native int CharCodeAt(int pos);
native String Filter();
} }
class Floor : Thinker native class Floor : Thinker native

View file

@ -87,6 +87,8 @@ class Menu : Object native
}; };
native Menu mParentMenu; native Menu mParentMenu;
native bool mMouseCapture;
native bool mBackbuttonSelected;
void Init(Menu parent) void Init(Menu parent)
{ {

View file

@ -16,8 +16,46 @@ class TextEnterMenu : Menu native
native int InputGridY; native int InputGridY;
native bool AllowColors; native bool AllowColors;
native static TextEnterMenu Open(Menu parent, String text, int maxlen, int sizemode, bool fromcontroller); //=============================================================================
//
//
//
//=============================================================================
// [TP] Added allowcolors
private void Init(Menu parent, String textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
{
Super.init(parent);
mEnterString = textbuffer;
mEnterSize = maxlen < 0 ? 0x7fffffff : maxlen;
mSizeMode = sizemode;
mInputGridOkay = showgrid || m_showinputgrid;
if (mEnterString.Length() > 0)
{
InputGridX = INPUTGRID_WIDTH - 1;
InputGridY = INPUTGRID_HEIGHT - 1;
}
else
{
// If we are naming a new save, don't start the cursor on "end".
InputGridX = 0;
InputGridY = 0;
}
AllowColors = allowcolors; // [TP]
}
static TextEnterMenu Open(Menu parent, String textbuffer, int maxlen, int sizemode, bool showgrid = false, bool allowcolors = false)
{
let me = new("TextEnterMenu");
me.Init(parent, textbuffer, maxlen, sizemode, showgrid, allowcolors);
return me;
}
//=============================================================================
//
//
//
//=============================================================================
String GetText() String GetText()
{ {
@ -29,6 +67,195 @@ class TextEnterMenu : Menu native
return mInputGridOkay; return mInputGridOkay;
} }
//=============================================================================
//
//
//
//=============================================================================
override bool Responder(InputEventData ev)
{
if (ev.type == InputEventData.GUI_Event)
{
// Save game and player name string input
if (ev.subtype == InputEventData.GUI_Char)
{
mInputGridOkay = false;
if (mEnterString.Length() < mEnterSize &&
(mSizeMode == 2/*entering player name*/ || SmallFont.StringWidth(mEnterString) < (mEnterSize-1)*8))
{
mEnterString.AppendFormat("%c", ev.data1);
}
return true;
}
int ch = ev.data1;
if ((ev.subtype == InputEventData.GUI_KeyDown || ev.subtype == InputEventData.GUI_KeyRepeat) && ch == 8)
{
if (mEnterString.Length() > 0)
{
mEnterString.Truncate(mEnterString.Length() - 1);
}
}
else if (ev.subtype == InputEventData.GUI_KeyDown)
{
if (ch == UIEvent.Key_ESCAPE)
{
Menu parent = mParentMenu;
Close();
parent.MenuEvent(MKEY_Abort, false);
return true;
}
else if (ch == 13)
{
if (mEnterString.Length() > 0)
{
// [TP] If we allow color codes, colorize the string now.
if (AllowColors)
mEnterString = mEnterString.Filter();
Menu parent = mParentMenu;
parent.MenuEvent(MKEY_Input, false);
Close();
return true;
}
}
}
if (ev.subtype == InputEventData.GUI_KeyDown || ev.subtype == InputEventData.GUI_KeyRepeat)
{
return true;
}
}
return Super.Responder(ev);
}
//=============================================================================
//
//
//
//=============================================================================
override bool MouseEvent(int type, int x, int y)
{
if (mMouseCapture || m_use_mouse == 1)
{
int cell_width = 18 * CleanXfac;
int cell_height = 12 * CleanYfac;
int screen_y = screen.GetHeight() - INPUTGRID_HEIGHT * cell_height;
int screen_x = (screen.GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y)
{
InputGridX = (x - screen_x) / cell_width;
InputGridY = (y - screen_y) / cell_height;
if (type == MOUSE_Release)
{
if (MenuEvent(MKEY_Enter, true))
{
MenuSound("menu/choose");
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
return true;
}
}
}
else
{
InputGridX = InputGridY = -1;
}
}
return Super.MouseEvent(type, x, y);
}
//=============================================================================
//
//
//
//=============================================================================
override bool MenuEvent (int key, bool fromcontroller)
{
String InputGridChars = Chars;
if (key == MKEY_Back)
{
mParentMenu.MenuEvent(MKEY_Abort, false);
return Super.MenuEvent(key, fromcontroller);
}
if (fromcontroller)
{
mInputGridOkay = true;
}
if (mInputGridOkay)
{
int ch;
if (InputGridX == -1 || InputGridY == -1)
{
InputGridX = InputGridY = 0;
}
switch (key)
{
case MKEY_Down:
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
return true;
case MKEY_Up:
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
return true;
case MKEY_Right:
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
return true;
case MKEY_Left:
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
return true;
case MKEY_Clear:
if (mEnterString.Length() > 0)
{
mEnterString.Truncate(mEnterString.Length() - 1);
}
return true;
case MKEY_Enter:
if (mInputGridOkay)
{
String c = InputGridChars.CharAt(InputGridX + InputGridY * INPUTGRID_WIDTH);
int ch = c.CharCodeAt(0);
if (ch == 0) // end
{
if (mEnterString.Length() > 0)
{
Menu parent = mParentMenu;
Close();
parent.MenuEvent(MKEY_Input, false);
return true;
}
}
else if (ch == 8) // bs
{
if (mEnterString.Length() > 0)
{
mEnterString.Truncate(mEnterString.Length() - 1);
}
}
else if (mEnterString.Length() < mEnterSize &&
(mSizeMode == 2/*entering player name*/ || SmallFont.StringWidth(mEnterString) < (mEnterSize-1)*8))
{
mEnterString = mEnterString .. c;
}
}
return true;
default:
break; // Keep GCC quiet
}
}
return false;
}
//============================================================================= //=============================================================================
// //
// //