- ported Doom's type-on text screens as a screen job overlay.

This commit is contained in:
Christoph Oelckers 2021-05-22 12:08:08 +02:00
parent 5337513044
commit 6ae09f8ec9
6 changed files with 230 additions and 6 deletions

View file

@ -98,8 +98,7 @@ unsigned FCommandBuffer::CalcCellSize(unsigned length)
unsigned cellcount = 0;
for (unsigned i = 0; i < length; i++)
{
int w;
NewConsoleFont->GetChar(Text[i], CR_UNTRANSLATED, &w);
int w = NewConsoleFont->GetCharWidth(Text[i]);
cellcount += w / 9;
}
return cellcount;
@ -112,8 +111,7 @@ unsigned FCommandBuffer::CharsForCells(unsigned cellin, bool *overflow)
int cells = cellin;
while (cells > 0)
{
int w;
NewConsoleFont->GetChar(Text[chars++], CR_UNTRANSLATED, &w);
int w = NewConsoleFont->GetCharWidth(Text[chars++]);
cells -= w / 9;
}
*overflow = (cells < 0);

View file

@ -50,7 +50,6 @@
#include "flatvertices.h"
#include "version.h"
#include "hw_material.h"
#include "v_2ddrawer.h"
#include <chrono>
#include <thread>

View file

@ -564,6 +564,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, Substitute, StringSubst)
return 0;
}
static void StringStripRight(FString* self, const FString& junk)
{
if (junk.IsNotEmpty()) self->StripRight(junk);
else self->StripRight();
}
DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, StripRight, StringStripRight)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_STRING(junk);
StringStripRight(self, junk);
return 0;
}
static void StringSplit(FString* self, TArray<FString>* tokens, const FString& delimiter, int keepEmpty)
{
self->Split(*tokens, delimiter, static_cast<FString::EmptyTokenType>(keepEmpty));

View file

@ -698,6 +698,18 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetGlyphHeight, GetGlyphHeight)
PARAM_INT(code);
ACTION_RETURN_INT(GetGlyphHeight(self, code));
}
static int GetDefaultKerning(FFont* font)
{
return font->GetDefaultKerning();
}
DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetDefaultKerning, GetDefaultKerning)
{
PARAM_SELF_STRUCT_PROLOGUE(FFont);
ACTION_RETURN_INT(self->GetDefaultKerning());
}
//==========================================================================
//
// file system

View file

@ -517,6 +517,7 @@ struct Font native
native static Font GetFont(Name fontname);
native BrokenLines BreakLines(String text, int maxlen);
native int GetGlyphHeight(int code);
native int GetDefaultKerning();
}
struct Console native
@ -687,6 +688,7 @@ struct StringStruct native
native int CodePointCount() const;
native int, int GetNextCodePoint(int position) const;
native void Substitute(String str, String replace);
native void StripRight(String junk = "");
}
struct Translation version("2.4")

View file

@ -600,7 +600,7 @@ class TextOverlay
bool drawclean;
BrokenLines screentext;
void Init(String text, int cr = Font.CR_UNTRANSLATED, int pal = 0, bool clean = false)
void Init(String text, int cr = Font.CR_UNDEFINED, int pal = 0, bool clean = false)
{
screentext = SmallFont.BreakLines(StringTable.Localize(text), 320);
nCrawlY = 199;
@ -639,3 +639,202 @@ class TextOverlay
}
}
//==========================================================================
//
// type-on text, like Doom
//
//==========================================================================
class TextTypeOnOverlay
{
String mText;
Font mFont;
int mTextSpeed;
int mTextX, mTextY;
int mTextCounter;
int mTextLen;
int mTextColor;
int mPalette;
int mLineCount;
int mRowPadding;
bool usesDefault;
int mTicker;
int mTextDelay;
//==========================================================================
//
//
//
//==========================================================================
void Init(Font fnt, String text, int x = 10, int y = 10, int rowpadding = 2, int speed = 2, int cr = Font.CR_UNDEFINED, int pal = 0)
{
let tt = StringTable.Localize(text);
Array<String> lines;
tt.Split(lines, "\n");
mLineCount = lines.Size();
mText = "";
for (int i = 0; i < lines.Size(); i++)
{
tt = lines[i];
tt.StripRight();
mText.AppendFormat("\n%s", tt);
}
mTextSpeed = speed;
if (x < 0)
{
mTextX = mTextY = 10;
usesDefault = true;
}
else
{
mTextX = x;
mTextY = y;
}
if (!generic_ui)
{
// Todo: Split too long texts
// If the text is too wide, center it so that it works better on widescreen displays.
// On 4:3 it'd still be cut off, though.
int width = fnt.StringWidth(mText);
if (usesDefault && mTextX + width > 320 - mTextX)
{
mTextX = (320 - width) / 2;
}
}
else
{
// Todo: Split too long texts
mTextX *= 2;
mTextY *= 2;
int width = NewSmallFont.StringWidth(mText);
if (usesDefault && mTextX + width > 640 - mTextX)
{
mTextX = (640 - width) / 2;
}
}
mTextLen = mText.CodePointCount();
mTextColor = cr;
mPalette = pal;
}
//==========================================================================
//
//
//
//==========================================================================
bool Tick()
{
if (mTicker < mTextDelay + (mTextLen * mTextSpeed))
{
mTicker++;
return false;
}
return true;
}
bool Reveal()
{
if (mTicker < mTextDelay + (mTextLen * mTextSpeed))
{
mTicker = mTextDelay + (mTextLen * mTextSpeed);
return true;
}
return false;
}
//==========================================================================
//
//
//
//==========================================================================
void Drawer ()
{
if (mTicker >= mTextDelay)
{
int w;
int count;
int c;
let width = Screen.GetWidth();
let height = Screen.GetHeight();
// Count number of rows in this text. Since it does not word-wrap, we just count
// line feed characters.
let font = generic_ui ? NewSmallFont : SmallFont;
let fontscale = MAX(generic_ui ? MIN(width / 640, height / 400) : MIN(width / 400, height / 250), 1);
int cleanwidth = width / fontscale;
int cleanheight = height / fontscale;
int refwidth = generic_ui ? 640 : 320;
int refheight = generic_ui ? 400 : 200;
int kerning = font.GetDefaultKerning();
int rowheight = font.GetHeight() * fontscale;
int rowpadding = mRowPadding;
int cx = (mTextX - refwidth/2) * fontscale + width / 2;
int cy = (mTextY - refheight/2) * fontscale + height / 2;
cx = MAX(0, cx);
int startx = cx;
if (usesDefault)
{
int allheight;
while ((allheight = mLineCount * (rowheight + rowpadding)) > height && rowpadding > 0)
{
rowpadding--;
}
allheight = mLineCount * (rowheight + rowpadding);
if (height - cy - allheight < cy)
{
cy = (height - allheight) / 2;
if (cy < 0) cy = 0;
}
}
else
{
// Does this text fall off the end of the screen? If so, try to eliminate some margins first.
while (rowpadding > 0 && cy + mLineCount * (rowheight + rowpadding) - rowpadding > height)
{
rowpadding--;
}
// If it's still off the bottom, you are screwed if the origin is fixed.
}
rowheight += rowpadding;
// draw some of the text onto the screen
int curpos = 0;
for (count = (mTicker - mTextDelay) / mTextSpeed; count > 0 ; count-- )
{
[c, curpos] = mText.GetNextCodePoint(curpos);
if (!c)
break;
if (c == "\n")
{
cx = startx;
cy += rowheight;
continue;
}
w = font.GetCharWidth(c);
w += kerning;
w *= fontscale;
if (cx + w > width)
continue;
Screen.DrawChar(font, mTextColor, cx/fontscale, cy/fontscale, c, DTA_KeepRatio, true, DTA_VirtualWidth, cleanwidth, DTA_VirtualHeight, cleanheight);
cx += w;
}
}
}
}