Use textinput_t for replay save prompt too
This commit is contained in:
parent
99f7a522a7
commit
5de315225c
5 changed files with 137 additions and 39 deletions
39
src/g_demo.c
39
src/g_demo.c
|
|
@ -28,6 +28,7 @@
|
|||
#include "m_misc.h"
|
||||
#include "m_menu.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_textinput.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "z_zone.h"
|
||||
#include "i_video.h"
|
||||
|
|
@ -2776,7 +2777,19 @@ void G_BeginRecording(void)
|
|||
|
||||
// Full replay title
|
||||
demobuf.p += 64;
|
||||
snprintf(demo.titlename, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Record Attack" : connectedservername);
|
||||
{
|
||||
char demotitlename[65];
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
// Print to a separate temp buffer instead of demo.titlename, so we can use it in M_TextInputSetString
|
||||
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
|
||||
|
||||
// Init just in case it isn't initialized already
|
||||
M_TextInputInit(&demo.titlenameinput, demo.titlename, sizeof(demo.titlename));
|
||||
|
||||
// This will indirectly assign to demo.titlename too
|
||||
M_TextInputSetString(&demo.titlenameinput, demotitlename);
|
||||
Z_Free(title);
|
||||
}
|
||||
|
||||
// demo checksum
|
||||
demobuf.p += sizeof(UINT64);
|
||||
|
|
@ -4410,7 +4423,6 @@ void G_SaveDemo(void)
|
|||
|
||||
boolean G_DemoTitleResponder(event_t *ev)
|
||||
{
|
||||
size_t len;
|
||||
INT32 ch;
|
||||
|
||||
if (ev->type != ev_keydown)
|
||||
|
|
@ -4431,28 +4443,7 @@ boolean G_DemoTitleResponder(event_t *ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && fontv[HU_FONT].font[ch-HU_FONTSTART])
|
||||
|| ch == ' ') // Allow spaces, of course
|
||||
{
|
||||
len = strlen(demo.titlename);
|
||||
if (len < 64)
|
||||
{
|
||||
demo.titlename[len+1] = 0;
|
||||
demo.titlename[len] = CON_ShiftChar(ch);
|
||||
}
|
||||
}
|
||||
else if (ch == KEY_BACKSPACE)
|
||||
{
|
||||
if (shiftdown)
|
||||
memset(demo.titlename, 0, sizeof(demo.titlename));
|
||||
else
|
||||
{
|
||||
len = strlen(demo.titlename);
|
||||
|
||||
if (len > 0)
|
||||
demo.titlename[len-1] = 0;
|
||||
}
|
||||
}
|
||||
M_TextInputHandle(&demo.titlenameinput, ch);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_event.h"
|
||||
#include "m_textinput.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -46,6 +47,7 @@ typedef enum
|
|||
// Publicly-accessible demo vars
|
||||
struct demovars_s {
|
||||
char titlename[65];
|
||||
textinput_t titlenameinput;
|
||||
boolean recording, playback, timing;
|
||||
UINT16 version; // Current file format of the demo being played
|
||||
boolean title; // Title Screen demo can be cancelled by any key
|
||||
|
|
|
|||
|
|
@ -815,27 +815,83 @@ static void ST_overlayDrawer(void)
|
|||
}
|
||||
}
|
||||
|
||||
void ST_DrawDemoTitleEntry(void)
|
||||
static void ST_DrawTextInput(INT32 x, INT32 y, textinput_t *input, INT32 flags)
|
||||
{
|
||||
static UINT8 skullAnimCounter = 0;
|
||||
char *nametodraw;
|
||||
static const INT32 MAXINPUTWIDTH = (MAXSTRINGLENGTH-1)*8;
|
||||
|
||||
if (renderisnewtic)
|
||||
skullAnimCounter++;
|
||||
|
||||
skullAnimCounter %= 8;
|
||||
|
||||
nametodraw = demo.titlename;
|
||||
while (V_StringWidth(nametodraw, 0) > MAXSTRINGLENGTH*8 - 8)
|
||||
nametodraw++;
|
||||
char nametodraw[MAXSTRINGLENGTH*2+1] = {0};
|
||||
|
||||
#define x (BASEVIDWIDTH/2 - 139)
|
||||
#define y (BASEVIDHEIGHT/2)
|
||||
size_t drawstart = 0;
|
||||
size_t drawend = 0; // Only used for selection
|
||||
|
||||
INT32 skullx = x;
|
||||
|
||||
while (V_SubStringWidth(input->buffer+drawstart, input->cursor-drawstart, V_ALLOWLOWERCASE) > MAXINPUTWIDTH)
|
||||
++drawstart;
|
||||
|
||||
size_t drawlength = V_SubStringLengthToFit(input->buffer+drawstart, MAXINPUTWIDTH+8, V_ALLOWLOWERCASE)+1;
|
||||
drawend = drawstart + drawlength;
|
||||
|
||||
memcpy(nametodraw, input->buffer+drawstart, drawlength);
|
||||
|
||||
|
||||
if (input->length)
|
||||
skullx += V_SubStringWidth(nametodraw, input->cursor-drawstart, V_ALLOWLOWERCASE);
|
||||
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE|flags, nametodraw);
|
||||
|
||||
// draw text cursor for name
|
||||
if (skullAnimCounter < 4) // blink cursor
|
||||
V_DrawCharacter(skullx, y+3, '_'|flags, false);
|
||||
|
||||
// draw selection
|
||||
if (input->select != input->cursor)
|
||||
{
|
||||
size_t start = min(input->select, input->cursor);
|
||||
size_t end = max(input->select, input->cursor);
|
||||
|
||||
INT32 startx = 0;
|
||||
INT32 width = 0;
|
||||
|
||||
// I couldn't figure out one formula so here's bunch of separate cases
|
||||
if (start < drawstart && end > drawend) // Selection covers whole visible portion of demo name
|
||||
{
|
||||
startx = -2;
|
||||
width = V_StringWidth(nametodraw, V_ALLOWLOWERCASE);
|
||||
}
|
||||
else if (start < drawstart) // Only left side of selection is off visible part
|
||||
{
|
||||
startx = -2;
|
||||
size_t len = (end - start) - (drawstart - start);
|
||||
width = V_SubStringWidth(nametodraw, len, V_ALLOWLOWERCASE)+2;
|
||||
}
|
||||
else if (end > drawend) // Only right side of selection is off visible part
|
||||
{
|
||||
startx = V_SubStringWidth(nametodraw, start-drawstart, V_ALLOWLOWERCASE);
|
||||
width = V_StringWidth(nametodraw+(start-drawstart), V_ALLOWLOWERCASE)+2;
|
||||
}
|
||||
else // All selection is on visible part
|
||||
{
|
||||
startx = V_SubStringWidth(nametodraw, start-drawstart, V_ALLOWLOWERCASE);
|
||||
width = V_SubStringWidth(nametodraw+(start-drawstart), end-start, V_ALLOWLOWERCASE);
|
||||
}
|
||||
|
||||
V_DrawFill(x+startx, y, width, 8, 103|V_TRANSLUCENT|flags);
|
||||
}
|
||||
}
|
||||
|
||||
void ST_DrawDemoTitleEntry(void)
|
||||
{
|
||||
#define x (BASEVIDWIDTH/2 - 139)
|
||||
#define y (BASEVIDHEIGHT/2)
|
||||
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
|
||||
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, nametodraw);
|
||||
if (skullAnimCounter < 4)
|
||||
V_DrawCharacter(x + 8 + V_StringWidth(nametodraw, 0), y + 12,
|
||||
'_' | 0x80, false);
|
||||
|
||||
ST_DrawTextInput(x + 8, y + 12, &demo.titlenameinput, 0);
|
||||
|
||||
M_DrawTextBox(x + 30, y - 24, 26, 1);
|
||||
V_DrawString(x + 38, y - 16, V_ALLOWLOWERCASE, "Enter the name of the replay.");
|
||||
|
|
@ -843,8 +899,8 @@ void ST_DrawDemoTitleEntry(void)
|
|||
M_DrawTextBox(x + 50, y + 20, 20, 1);
|
||||
V_DrawThinString(x + 58, y + 28, V_ALLOWLOWERCASE, "Escape - Cancel");
|
||||
V_DrawRightAlignedThinString(x + 220, y + 28, V_ALLOWLOWERCASE, "Enter - Confirm");
|
||||
#undef x
|
||||
#undef y
|
||||
#undef x
|
||||
#undef y
|
||||
}
|
||||
|
||||
// MayonakaStatic: draw Midnight Channel's TV-like borders
|
||||
|
|
|
|||
|
|
@ -3079,7 +3079,7 @@ INT32 V_ThinSubStringWidth(const char *string, INT32 length, INT32 option)
|
|||
else
|
||||
{
|
||||
w += (charwidth ? charwidth
|
||||
: ((option & V_6WIDTHSPACE && i < strlen(string)-1) ? max(1, fontv[TINY_FONT].font[c]->width-1) // Reuse this flag for the alternate bunched-up spacing
|
||||
: ((option & V_6WIDTHSPACE && i < (ssize_t)strlen(string)-1) ? max(1, fontv[TINY_FONT].font[c]->width-1) // Reuse this flag for the alternate bunched-up spacing
|
||||
: fontv[TINY_FONT].font[c]->width));
|
||||
}
|
||||
}
|
||||
|
|
@ -3097,6 +3097,53 @@ INT32 V_SmallThinStringWidth(const char *string, INT32 option)
|
|||
return w/2 + FRACUNIT; // +FRACUNIT because otherwise it's offset wrong.
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// Find maximum length for substring taken from current string to fit into given width
|
||||
|
||||
//
|
||||
|
||||
INT32 V_SubStringLengthToFit(const char *string, INT32 width, INT32 option)
|
||||
{
|
||||
INT32 c, w = 0;
|
||||
INT32 spacewidth = 4, charwidth = 0;
|
||||
INT32 i;
|
||||
|
||||
switch (option & V_SPACINGMASK)
|
||||
{
|
||||
case V_MONOSPACE:
|
||||
spacewidth = 8;
|
||||
/* FALLTHRU */
|
||||
case V_OLDSPACING:
|
||||
charwidth = 8;
|
||||
break;
|
||||
|
||||
case V_6WIDTHSPACE:
|
||||
spacewidth = 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; string[i] && w < width; i++)
|
||||
{
|
||||
c = string[i];
|
||||
|
||||
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
|
||||
continue;
|
||||
|
||||
c = toupper(c) - HU_FONTSTART;
|
||||
|
||||
if (c < 0 || c >= HU_FONTSIZE || !fontv[HU_FONT].font[c])
|
||||
w += spacewidth;
|
||||
else
|
||||
w += (charwidth ? charwidth : fontv[HU_FONT].font[c]->width);
|
||||
}
|
||||
|
||||
return max(i-1, 0);
|
||||
}
|
||||
|
||||
boolean *heatshifter = NULL;
|
||||
INT32 lastheight = 0;
|
||||
INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
|
||||
|
|
|
|||
|
|
@ -338,6 +338,8 @@ INT32 V_SmallSubStringWidth(const char *string, INT32 length, INT32 option);
|
|||
INT32 V_ThinSubStringWidth(const char *string, INT32 length, INT32 option);
|
||||
#define V_ThinStringWidth(string, option) V_ThinSubStringWidth(string, -1, option)
|
||||
|
||||
INT32 V_SubStringLengthToFit(const char *string, INT32 width, INT32 option);
|
||||
|
||||
void V_DoPostProcessor(INT32 view, INT32 param);
|
||||
|
||||
void V_DrawPatchFill(patch_t *pat);
|
||||
|
|
|
|||
Loading…
Reference in a new issue