This commit is contained in:
Rachael Alexanderson 2019-03-18 05:26:22 -04:00
commit acad5caa4c
449 changed files with 59313 additions and 1204 deletions

View file

@ -1125,6 +1125,7 @@ set (PCH_SOURCES
gamedata/fonts/singlepicfont.cpp
gamedata/fonts/specialfont.cpp
gamedata/fonts/font.cpp
gamedata/fonts/hexfont.cpp
gamedata/fonts/v_font.cpp
gamedata/fonts/v_text.cpp
gamedata/p_xlat.cpp

View file

@ -46,6 +46,7 @@
#include "vm.h"
#include "i_time.h"
#include "menu/menu.h"
#include "v_text.h"
const char *KeyNames[NUM_KEYS] =
{
@ -297,7 +298,7 @@ void C_NameKeys (char *str, int first, int second)
c++;
strcpy (str, KeyName (first));
if (second)
strcat (str, " or ");
strcat (str, TEXTCOLOR_BLACK ", " TEXTCOLOR_NORMAL);
}
if (second)

View file

@ -1199,7 +1199,7 @@ static void PrintSecretString(const char *string, bool thislevel)
else colstr = TEXTCOLOR_GREEN;
}
}
auto brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string);
auto brok = V_BreakLines(CurrentConsoleFont, screen->GetWidth()*95/100, string);
for (auto &line : brok)
{
@ -1243,10 +1243,12 @@ CCMD(secret)
FString levelname;
level_info_t *info = FindLevelInfo(mapname);
const char *ln = !(info->flags & LEVEL_LOOKUPLEVELNAME)? info->LevelName.GetChars() : GStrings[info->LevelName.GetChars()];
levelname.Format("%s - %s\n", mapname, ln);
size_t llen = levelname.Len() - 1;
levelname.Format("%s - %s", mapname, ln);
Printf(TEXTCOLOR_YELLOW "%s\n", levelname.GetChars());
size_t llen = levelname.Len();
levelname = "";
for(size_t ii=0; ii<llen; ii++) levelname += '-';
Printf(TEXTCOLOR_YELLOW"%s\n", levelname.GetChars());
Printf(TEXTCOLOR_YELLOW "%s\n", levelname.GetChars());
foundsome = true;
}
}

View file

@ -32,6 +32,8 @@
**
*/
#include <string>
#include "templates.h"
#include "p_setup.h"
#include "i_system.h"
@ -77,6 +79,9 @@ CUSTOM_CVAR(Int, con_buffersize, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
if (self >= 0 && self < 128) self = 128;
}
CVAR(Bool, con_consolefont, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, con_midconsolefont, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
FConsoleBuffer *conbuffer;
static void C_TabComplete (bool goForward);
@ -126,13 +131,6 @@ static GameAtExit *ExitCmdList;
EXTERN_CVAR (Bool, show_messages)
static unsigned int TickerAt, TickerMax;
static bool TickerPercent;
static const char *TickerLabel;
static bool TickerVisible;
static bool ConsoleDrawing;
// Buffer for AddToConsole()
static char *work = NULL;
static int worklen = 0;
@ -169,13 +167,13 @@ struct History
struct FCommandBuffer
{
private:
FString Text; // The actual command line text
std::u32string Text;
unsigned CursorPos = 0;
unsigned StartPos = 0; // First character to display
unsigned CursorPosChars = 0;
unsigned StartPosChars = 0;
unsigned CursorPosCells = 0;
unsigned StartPosCells = 0;
FString YankBuffer; // Deleted text buffer
std::u32string YankBuffer; // Deleted text buffer
public:
bool AppendToYankBuffer = false; // Append consecutive deletes to buffer
@ -191,37 +189,39 @@ public:
FString GetText() const
{
return Text;
FString build;
for (auto chr : Text) build.AppendCharacter(chr);
return build;
}
size_t TextLength() const
{
return Text.Len();
return Text.length();
}
void Draw(int x, int y, int scale, bool cursor)
{
if (scale == 1)
{
screen->DrawChar(ConFont, CR_ORANGE, x, y, '\x1c', TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, x + ConFont->GetCharWidth(0x1c), y,
screen->DrawChar(CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', TAG_DONE);
screen->DrawText(CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y,
&Text[StartPos], TAG_DONE);
if (cursor)
{
screen->DrawChar(ConFont, CR_YELLOW,
x + ConFont->GetCharWidth(0x1c) + (CursorPosChars - StartPosChars) * ConFont->GetCharWidth(0xb),
screen->DrawChar(CurrentConsoleFont, CR_YELLOW,
x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb),
y, '\xb', TAG_DONE);
}
}
else
{
screen->DrawChar(ConFont, CR_ORANGE, x, y, '\x1c',
screen->DrawChar(CurrentConsoleFont, CR_ORANGE, x, y, '\x1c',
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
DTA_KeepRatio, true, TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, x + ConFont->GetCharWidth(0x1c), y,
screen->DrawText(CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y,
&Text[StartPos],
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
@ -229,8 +229,8 @@ public:
if (cursor)
{
screen->DrawChar(ConFont, CR_YELLOW,
x + ConFont->GetCharWidth(0x1c) + (CursorPosChars - StartPosChars) * ConFont->GetCharWidth(0xb),
screen->DrawChar(CurrentConsoleFont, CR_YELLOW,
x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb),
y, '\xb',
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
@ -239,72 +239,99 @@ public:
}
}
unsigned BytesForChars(unsigned chars)
unsigned CalcCellSize(unsigned length)
{
unsigned bytes = 0;
while (chars > 0)
unsigned cellcount = 0;
for (unsigned i = 0; i < length; i++)
{
if ((Text[bytes++] & 0xc0) != 0x80) chars--;
int w;
NewConsoleFont->GetChar(Text[i], CR_UNTRANSLATED, &w);
cellcount += w / 9;
}
return bytes;
return cellcount;
}
unsigned CharsForCells(unsigned cellin, bool *overflow)
{
unsigned chars = 0;
int cells = cellin;
while (cells > 0)
{
int w;
NewConsoleFont->GetChar(Text[chars++], CR_UNTRANSLATED, &w);
cells -= w / 9;
}
*overflow = (cells < 0);
return chars;
}
void MakeStartPosGood()
{
int n = StartPosChars;
// Make sure both values point to something valid.
if (CursorPos > Text.length()) CursorPos = (unsigned)Text.length();
if (StartPos > Text.length()) StartPos = (unsigned)Text.length();
CursorPosCells = CalcCellSize(CursorPos);
StartPosCells = CalcCellSize(StartPos);
unsigned LengthCells = CalcCellSize((unsigned)Text.length());
int n = StartPosCells;
unsigned cols = ConCols / active_con_scale();
if (StartPosChars >= Text.CharacterCount())
if (StartPosCells >= LengthCells)
{ // Start of visible line is beyond end of line
n = CursorPosChars - cols + 2;
n = CursorPosCells - cols + 2;
}
if ((CursorPosChars - StartPosChars) >= cols - 2)
if ((CursorPosCells - StartPosCells) >= cols - 2)
{ // The cursor is beyond the visible part of the line
n = CursorPosChars - cols + 2;
n = CursorPosCells - cols + 2;
}
if (StartPosChars > CursorPosChars)
if (StartPosCells > CursorPosCells)
{ // The cursor is in front of the visible part of the line
n = CursorPosChars;
n = CursorPosCells;
}
StartPosCells = MAX(0, n);
bool overflow;
StartPos = CharsForCells(StartPosCells, &overflow);
if (overflow)
{
// We ended up in the middle of a double cell character, so set the start to the following character.
StartPosCells++;
StartPos = CharsForCells(StartPosCells, &overflow);
}
StartPosChars = MAX(0, n);
StartPos = BytesForChars(StartPosChars);
}
void CursorStart()
{
CursorPos = 0;
StartPos = 0;
CursorPosChars = 0;
StartPosChars = 0;
CursorPosCells = 0;
StartPosCells = 0;
}
void CursorEnd()
{
CursorPos = (unsigned)Text.Len();
CursorPosChars = (unsigned)Text.CharacterCount();
StartPosChars = 0;
CursorPos = (unsigned)Text.length();
MakeStartPosGood();
}
private:
void MoveCursorLeft()
{
CursorPosChars--;
do CursorPos--;
while ((Text[CursorPos] & 0xc0) == 0x80); // Step back to the last non-continuation byte.
CursorPos--;
}
void MoveCursorRight()
{
CursorPosChars++;
do CursorPos++;
while ((Text[CursorPos] & 0xc0) == 0x80); // Step back to the last non-continuation byte.
CursorPos++;
}
public:
void CursorLeft()
{
if (CursorPosChars > 0)
if (CursorPos > 0)
{
MoveCursorLeft();
MakeStartPosGood();
@ -313,7 +340,7 @@ public:
void CursorRight()
{
if (CursorPosChars < Text.CharacterCount())
if (CursorPos < Text.length())
{
MoveCursorRight();
MakeStartPosGood();
@ -322,20 +349,20 @@ public:
void CursorWordLeft()
{
if (CursorPosChars > 0)
if (CursorPos > 0)
{
do MoveCursorLeft();
while (CursorPosChars > 0 && Text[CursorPos - 1] != ' ');
while (CursorPos > 0 && Text[CursorPos - 1] != ' ');
MakeStartPosGood();
}
}
void CursorWordRight()
{
if (CursorPosChars < Text.CharacterCount())
if (CursorPos < Text.length())
{
do MoveCursorRight();
while (CursorPosChars < Text.CharacterCount() && Text[CursorPos] != ' ');
while (CursorPos < Text.length() && Text[CursorPos] != ' ');
MakeStartPosGood();
}
}
@ -344,22 +371,17 @@ public:
{
if (CursorPos > 0)
{
auto now = CursorPos;
MoveCursorLeft();
Text.Remove(CursorPos, now - CursorPos);
Text.erase(CursorPos, 1);
MakeStartPosGood();
}
}
void DeleteRight()
{
if (CursorPosChars < Text.CharacterCount())
if (CursorPos < Text.length())
{
auto now = CursorPos;
MoveCursorRight();
Text.Remove(now, CursorPos - now);
CursorPos = now;
CursorPosChars--;
Text.erase(CursorPos, 1);
MakeStartPosGood();
}
}
@ -373,11 +395,11 @@ public:
CursorWordLeft();
if (AppendToYankBuffer) {
YankBuffer = FString(&Text[CursorPos], now - CursorPos) + YankBuffer;
YankBuffer = Text.substr(CursorPos, now - CursorPos) + YankBuffer;
} else {
YankBuffer = FString(&Text[CursorPos], now - CursorPos);
YankBuffer = Text.substr(CursorPos, now - CursorPos);
}
Text.Remove(CursorPos, now - CursorPos);
Text.erase(CursorPos, now - CursorPos);
MakeStartPosGood();
}
}
@ -387,48 +409,42 @@ public:
if (CursorPos > 0)
{
if (AppendToYankBuffer) {
YankBuffer = FString(&Text[0], CursorPos) + YankBuffer;
YankBuffer = Text.substr(0, CursorPos) + YankBuffer;
} else {
YankBuffer = FString(&Text[0], CursorPos);
YankBuffer = Text.substr(0, CursorPos);
}
Text.Remove(0, CursorPos);
Text.erase(0, CursorPos);
CursorStart();
}
}
void DeleteLineRight()
{
if (CursorPos < Text.Len())
if (CursorPos < Text.length())
{
if (AppendToYankBuffer) {
YankBuffer += FString(&Text[CursorPos], Text.Len() - CursorPos);
YankBuffer += Text.substr(CursorPos, Text.length() - CursorPos);
} else {
YankBuffer = FString(&Text[CursorPos], Text.Len() - CursorPos);
YankBuffer = Text.substr(CursorPos, Text.length() - CursorPos);
}
Text.Truncate(CursorPos);
Text.resize(CursorPos);
CursorEnd();
}
}
void AddChar(int character)
{
int size;
auto encoded = MakeUTF8(character, &size);
if (*encoded != 0)
if (Text.length() == 0)
{
if (Text.IsEmpty())
{
Text = encoded;
Text += character;
}
else
{
Text.Insert(CursorPos, (char*)encoded);
Text.insert(CursorPos, 1, character);
}
CursorPos += size;
CursorPosChars++;
CursorPos++;
MakeStartPosGood();
}
}
void AddString(FString clip)
{
@ -436,35 +452,52 @@ public:
{
// Only paste the first line.
long brk = clip.IndexOfAny("\r\n\b");
std::u32string build;
if (brk >= 0)
{
clip.Truncate(brk);
clip = MakeUTF8(clip.GetChars()); // Make sure that we actually have UTF-8 text.
}
if (Text.IsEmpty())
auto strp = (const uint8_t*)clip.GetChars();
while (auto chr = GetCharFromString(strp)) build += chr;
if (Text.length() == 0)
{
Text = clip;
Text = build;
}
else
{
Text.Insert(CursorPos, clip);
Text.insert(CursorPos, build);
}
CursorPos += (unsigned)clip.Len();
CursorPosChars += (unsigned)clip.CharacterCount();
CursorPos += (unsigned)build.length();
MakeStartPosGood();
}
}
void SetString(const FString &str)
{
Text = MakeUTF8(str);
Text.clear();
auto strp = (const uint8_t*)str.GetChars();
while (auto chr = GetCharFromString(strp)) Text += chr;
CursorEnd();
MakeStartPosGood();
}
void AddYankBuffer()
{
AddString(YankBuffer);
if (YankBuffer.length() > 0)
{
if (Text.length() == 0)
{
Text = YankBuffer;
}
else
{
Text.insert(CursorPos, YankBuffer);
}
CursorPos += (unsigned)YankBuffer.length();
MakeStartPosGood();
}
}
};
static FCommandBuffer CmdLine;
@ -551,47 +584,10 @@ CUSTOM_CVAR (Int, msgmidcolor2, 4, CVAR_ARCHIVE)
setmsgcolor (PRINTLEVELS+1, self);
}
struct TextQueue
EColorRange C_GetDefaultFontColor()
{
TextQueue (bool notify, int printlevel, const char *text)
: Next(NULL), bNotify(notify), PrintLevel(printlevel), Text(text)
{
}
TextQueue *Next;
bool bNotify;
int PrintLevel;
FString Text;
};
TextQueue *EnqueuedText, **EnqueuedTextTail = &EnqueuedText;
void EnqueueConsoleText (bool notify, int printlevel, const char *text)
{
TextQueue *queued = new TextQueue (notify, printlevel, text);
*EnqueuedTextTail = queued;
EnqueuedTextTail = &queued->Next;
}
void DequeueConsoleText ()
{
TextQueue *queued = EnqueuedText;
while (queued != NULL)
{
TextQueue *next = queued->Next;
if (queued->bNotify)
{
NotifyStrings.AddString(queued->PrintLevel, queued->Text);
}
else
{
AddToConsole (queued->PrintLevel, queued->Text);
}
delete queued;
queued = next;
}
EnqueuedText = NULL;
EnqueuedTextTail = &EnqueuedText;
// Ideally this should analyze the SmallFont and pick a matching color.
return gameinfo.gametype == GAME_Doom ? CR_RED : gameinfo.gametype == GAME_Chex ? CR_GREEN : gameinfo.gametype == GAME_Strife ? CR_GOLD : CR_GRAY;
}
void C_InitConback()
@ -616,10 +612,10 @@ void C_InitConsole (int width, int height, bool ingame)
int cwidth, cheight;
vidactive = ingame;
if (ConFont != NULL)
if (CurrentConsoleFont != NULL)
{
cwidth = ConFont->GetCharWidth ('M');
cheight = ConFont->GetHeight();
cwidth = CurrentConsoleFont->GetCharWidth ('M');
cheight = CurrentConsoleFont->GetHeight();
}
else
{
@ -786,22 +782,18 @@ void FNotifyBuffer::AddString(int printlevel, FString source)
con_notifylines == 0)
return;
if (ConsoleDrawing)
{
EnqueueConsoleText (true, printlevel, source);
return;
}
width = DisplayWidth / active_con_scaletext(con_consolefont);
width = DisplayWidth / active_con_scaletext();
FFont *font = *con_consolefont ? NewSmallFont : SmallFont;
if (AddType == APPENDLINE && Text.Size() > 0 && Text[Text.Size() - 1].PrintLevel == printlevel)
{
FString str = Text[Text.Size() - 1].Text + source;
lines = V_BreakLines (SmallFont, width, str);
lines = V_BreakLines (font, width, str);
}
else
{
lines = V_BreakLines (SmallFont, width, source);
lines = V_BreakLines (font, width, source);
if (AddType == APPENDLINE)
{
AddType = NEWLINE;
@ -845,11 +837,51 @@ void FNotifyBuffer::AddString(int printlevel, FString source)
void AddToConsole (int printlevel, const char *text)
{
conbuffer->AddText(printlevel, MakeUTF8(text), Logfile);
conbuffer->AddText(printlevel, MakeUTF8(text));
}
int PrintString (int printlevel, const char *outline)
//==========================================================================
//
//
//
//==========================================================================
void WriteLineToLog(FILE *LogFile, const char *outline)
{
// Strip out any color escape sequences before writing to the log file
TArray<char> copy(strlen(outline) + 1);
const char * srcp = outline;
char * dstp = copy.Data();
while (*srcp != 0)
{
if (*srcp != TEXTCOLOR_ESCAPE)
{
*dstp++ = *srcp++;
}
else if (srcp[1] == '[')
{
srcp += 2;
while (*srcp != ']' && *srcp != 0) srcp++;
if (*srcp == ']') srcp++;
}
else
{
if (srcp[1] != 0) srcp += 2;
else break;
}
}
*dstp = 0;
fputs(copy.Data(), LogFile);
fflush(LogFile);
}
int PrintString (int iprintlevel, const char *outline)
{
int printlevel = iprintlevel & PRINT_TYPES;
if (printlevel < msglevel || *outline == '\0')
{
return 0;
@ -864,16 +896,15 @@ int PrintString (int printlevel, const char *outline)
{
I_PrintStr(outline);
conbuffer->AddText(printlevel, outline, Logfile);
if (vidactive && screen && SmallFont)
conbuffer->AddText(printlevel, outline);
if (vidactive && screen && SmallFont && !(iprintlevel & PRINT_NONOTIFY))
{
NotifyStrings.AddString(printlevel, outline);
}
}
else if (Logfile != nullptr)
if (Logfile != nullptr && !(iprintlevel & PRINT_NOLOG))
{
fputs(outline, Logfile);
fflush(Logfile);
WriteLineToLog(Logfile, outline);
}
return count;
}
@ -1036,7 +1067,8 @@ void FNotifyBuffer::Draw()
line = Top;
canskip = true;
lineadv = SmallFont->GetHeight ();
FFont *font = *con_consolefont ? NewSmallFont : SmallFont;
lineadv = font->GetHeight ();
for (unsigned i = 0; i < Text.Size(); ++ i)
{
@ -1058,15 +1090,19 @@ void FNotifyBuffer::Draw()
else
color = PrintColors[notify.PrintLevel];
int scale = active_con_scaletext();
if (color == CR_UNTRANSLATED && *con_consolefont)
{
color = C_GetDefaultFontColor();
}
int scale = active_con_scaletext(con_consolefont);
if (!center)
screen->DrawText (SmallFont, color, 0, line, notify.Text,
screen->DrawText (font, color, 0, line, notify.Text,
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
DTA_KeepRatio, true,
DTA_Alpha, alpha, TAG_DONE);
else
screen->DrawText (SmallFont, color, (screen->GetWidth() -
screen->DrawText (font, color, (screen->GetWidth() -
SmallFont->StringWidth (notify.Text) * scale) / 2 / scale,
line, notify.Text,
DTA_VirtualWidth, screen->GetWidth() / scale,
@ -1092,19 +1128,6 @@ void FNotifyBuffer::Draw()
}
}
void C_InitTicker (const char *label, unsigned int max, bool showpercent)
{
TickerPercent = showpercent;
TickerMax = max;
TickerLabel = label;
TickerAt = 0;
}
void C_SetTicker (unsigned int at, bool forceUpdate)
{
TickerAt = at > TickerMax ? TickerMax : at;
}
void C_DrawConsole ()
{
static int oldbottom = 0;
@ -1113,15 +1136,15 @@ void C_DrawConsole ()
int textScale = active_con_scale();
left = LEFTMARGIN;
lines = (ConBottom/textScale-ConFont->GetHeight()*2)/ConFont->GetHeight();
if (-ConFont->GetHeight() + lines*ConFont->GetHeight() > ConBottom/textScale - ConFont->GetHeight()*7/2)
lines = (ConBottom/textScale-CurrentConsoleFont->GetHeight()*2)/CurrentConsoleFont->GetHeight();
if (-CurrentConsoleFont->GetHeight() + lines*CurrentConsoleFont->GetHeight() > ConBottom/textScale - CurrentConsoleFont->GetHeight()*7/2)
{
offset = -ConFont->GetHeight()/2;
offset = -CurrentConsoleFont->GetHeight()/2;
lines--;
}
else
{
offset = -ConFont->GetHeight();
offset = -CurrentConsoleFont->GetHeight();
}
oldbottom = ConBottom;
@ -1153,71 +1176,19 @@ void C_DrawConsole ()
if (ConBottom >= 12)
{
if (textScale == 1)
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
ConFont->StringWidth (GetVersionString()),
ConBottom / textScale - ConFont->GetHeight() - 4,
screen->DrawText (CurrentConsoleFont, CR_ORANGE, SCREENWIDTH - 8 -
CurrentConsoleFont->StringWidth (GetVersionString()),
ConBottom / textScale - CurrentConsoleFont->GetHeight() - 4,
GetVersionString(), TAG_DONE);
else
screen->DrawText(ConFont, CR_ORANGE, SCREENWIDTH / textScale - 8 -
ConFont->StringWidth(GetVersionString()),
ConBottom / textScale - ConFont->GetHeight() - 4,
screen->DrawText(CurrentConsoleFont, CR_ORANGE, SCREENWIDTH / textScale - 8 -
CurrentConsoleFont->StringWidth(GetVersionString()),
ConBottom / textScale - CurrentConsoleFont->GetHeight() - 4,
GetVersionString(),
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
if (TickerMax)
{
char tickstr[256];
const int tickerY = ConBottom / textScale - ConFont->GetHeight() - 4;
size_t i;
int tickend = ConCols / textScale - SCREENWIDTH / textScale / 90 - 6;
int tickbegin = 0;
if (TickerLabel)
{
tickbegin = (int)strlen (TickerLabel) + 2;
mysnprintf (tickstr, countof(tickstr), "%s: ", TickerLabel);
}
if (tickend > 256 - ConFont->GetCharWidth(0x12))
tickend = 256 - ConFont->GetCharWidth(0x12);
tickstr[tickbegin] = 0x10;
memset (tickstr + tickbegin + 1, 0x11, tickend - tickbegin);
tickstr[tickend + 1] = 0x12;
tickstr[tickend + 2] = ' ';
if (TickerPercent)
{
mysnprintf (tickstr + tickend + 3, countof(tickstr) - tickend - 3,
"%d%%", Scale (TickerAt, 100, TickerMax));
}
else
{
tickstr[tickend+3] = 0;
}
if (textScale == 1)
screen->DrawText (ConFont, CR_BROWN, LEFTMARGIN, tickerY, tickstr, TAG_DONE);
else
screen->DrawText (ConFont, CR_BROWN, LEFTMARGIN, tickerY, tickstr,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
// Draw the marker
i = LEFTMARGIN+5+tickbegin*8 + Scale (TickerAt, (int32_t)(tickend - tickbegin)*8, TickerMax);
if (textScale == 1)
screen->DrawChar (ConFont, CR_ORANGE, (int)i, tickerY, 0x13, TAG_DONE);
else
screen->DrawChar(ConFont, CR_ORANGE, (int)i, tickerY, 0x13,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
TickerVisible = true;
}
else
{
TickerVisible = false;
}
}
}
@ -1230,46 +1201,42 @@ void C_DrawConsole ()
if (lines > 0)
{
// No more enqueuing because adding new text to the console won't touch the actual print data.
conbuffer->FormatText(ConFont, ConWidth / textScale);
conbuffer->FormatText(CurrentConsoleFont, ConWidth / textScale);
unsigned int consolelines = conbuffer->GetFormattedLineCount();
FBrokenLines *blines = conbuffer->GetLines();
FBrokenLines *printline = blines + consolelines - 1 - RowAdjust;
int bottomline = ConBottom / textScale - ConFont->GetHeight()*2 - 4;
ConsoleDrawing = true;
int bottomline = ConBottom / textScale - CurrentConsoleFont->GetHeight()*2 - 4;
for(FBrokenLines *p = printline; p >= blines && lines > 0; p--, lines--)
{
if (textScale == 1)
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), p->Text, TAG_DONE);
screen->DrawText(CurrentConsoleFont, CR_TAN, LEFTMARGIN, offset + lines * CurrentConsoleFont->GetHeight(), p->Text, TAG_DONE);
}
else
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), p->Text,
screen->DrawText(CurrentConsoleFont, CR_TAN, LEFTMARGIN, offset + lines * CurrentConsoleFont->GetHeight(), p->Text,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
}
}
ConsoleDrawing = false;
if (ConBottom >= 20)
{
if (gamestate != GS_STARTUP)
{
CmdLine.Draw(left, bottomline, textScale, cursoron);
}
if (RowAdjust && ConBottom >= ConFont->GetHeight()*7/2)
if (RowAdjust && ConBottom >= CurrentConsoleFont->GetHeight()*7/2)
{
// Indicate that the view has been scrolled up (10)
// and if we can scroll no further (12)
if (textScale == 1)
screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE);
screen->DrawChar (CurrentConsoleFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE);
else
screen->DrawChar(ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10,
screen->DrawChar(CurrentConsoleFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
@ -1294,7 +1261,6 @@ void C_FullConsole ()
primaryLevel->Music = "";
S_Start ();
P_FreeLevelData ();
V_SetBlend (0,0,0,0);
}
else
{
@ -1405,7 +1371,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer up one page
RowAdjust += (SCREENHEIGHT-4)/active_con_scale() /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? ConFont->GetHeight() : ConFont->GetHeight()*2) - 3;
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? CurrentConsoleFont->GetHeight() : CurrentConsoleFont->GetHeight()*2) - 3;
}
else if (RowAdjust < conbuffer->GetFormattedLineCount())
{ // Scroll console buffer up
@ -1428,7 +1394,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer down one page
const int scrollamt = (SCREENHEIGHT-4)/active_con_scale() /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? ConFont->GetHeight() : ConFont->GetHeight()*2) - 3;
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? CurrentConsoleFont->GetHeight() : CurrentConsoleFont->GetHeight()*2) - 3;
if (RowAdjust < scrollamt)
{
RowAdjust = 0;
@ -1776,45 +1742,30 @@ CCMD (echo)
/* Printing in the middle of the screen */
CVAR (Float, con_midtime, 3.f, CVAR_ARCHIVE)
CVAR(Float, con_midtime, 3.f, CVAR_ARCHIVE)
static const char bar1[] = TEXTCOLOR_RED "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_TAN "\n";
static const char bar2[] = TEXTCOLOR_RED "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_GREEN "\n";
static const char bar3[] = TEXTCOLOR_RED "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_NORMAL "\n";
const char *console_bar = "----------------------------------------";
void C_MidPrint (FFont *font, const char *msg)
void C_MidPrint (FFont *font, const char *msg, bool bold)
{
if (StatusBar == NULL || screen == NULL)
if (StatusBar == nullptr || screen == nullptr)
return;
if (msg != NULL)
if (msg != nullptr)
{
AddToConsole (-1, bar1);
AddToConsole (-1, msg);
AddToConsole (-1, bar3);
auto color = (EColorRange)PrintColors[bold? PRINTLEVELS+1 : PRINTLEVELS];
Printf(PRINT_NONOTIFY, TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", color, console_bar, msg, console_bar);
bool altscale = false;
if (font == nullptr)
{
altscale = con_midconsolefont;
font = altscale ? NewSmallFont : SmallFont;
if (altscale && color == CR_UNTRANSLATED) color = C_GetDefaultFontColor();
}
StatusBar->AttachMessage (Create<DHUDMessage>(font, msg, 1.5f, 0.375f, 0, 0,
(EColorRange)PrintColors[PRINTLEVELS], con_midtime), MAKE_ID('C','N','T','R'));
}
else
{
StatusBar->DetachMessage (MAKE_ID('C','N','T','R'));
}
}
void C_MidPrintBold (FFont *font, const char *msg)
{
if (msg)
{
AddToConsole (-1, bar2);
AddToConsole (-1, msg);
AddToConsole (-1, bar3);
StatusBar->AttachMessage (Create<DHUDMessage> (font, msg, 1.5f, 0.375f, 0, 0,
(EColorRange)PrintColors[PRINTLEVELS+1], con_midtime), MAKE_ID('C','N','T','R'));
color, con_midtime, altscale), MAKE_ID('C','N','T','R'));
}
else
{
@ -1825,13 +1776,12 @@ void C_MidPrintBold (FFont *font, const char *msg)
DEFINE_ACTION_FUNCTION(_Console, MidPrint)
{
PARAM_PROLOGUE;
PARAM_POINTER_NOT_NULL(fnt, FFont);
PARAM_POINTER(fnt, FFont);
PARAM_STRING(text);
PARAM_BOOL(bold);
const char *txt = text[0] == '$'? GStrings(&text[1]) : text.GetChars();
if (!bold) C_MidPrint(fnt, txt);
else C_MidPrintBold(fnt, txt);
C_MidPrint(fnt, txt, bold);
return 0;
}

View file

@ -47,7 +47,10 @@ typedef enum cstate_t
}
constate_e;
#define PRINTLEVELS 5
enum
{
PRINTLEVELS = 5
};
extern int PrintColors[PRINTLEVELS + 2];
extern constate_e ConsoleState;
@ -74,12 +77,8 @@ void C_HideConsole (void);
void C_AdjustBottom (void);
void C_FlushDisplay (void);
void C_InitTicker (const char *label, unsigned int max, bool showpercent=true);
void C_SetTicker (unsigned int at, bool forceUpdate=false);
class FFont;
void C_MidPrint (FFont *font, const char *message);
void C_MidPrintBold (FFont *font, const char *message);
void C_MidPrint (FFont *font, const char *message, bool bold = false);
bool C_Responder (event_t *ev);
@ -87,4 +86,6 @@ void C_AddTabCommand (const char *name);
void C_RemoveTabCommand (const char *name);
void C_ClearTabCommands(); // Removes all tab commands
extern const char *console_bar;
#endif

View file

@ -55,33 +55,6 @@ FConsoleBuffer::FConsoleBuffer()
mBrokenStart.Push(0);
}
//==========================================================================
//
//
//
//==========================================================================
FConsoleBuffer::~FConsoleBuffer()
{
FreeBrokenText();
}
//==========================================================================
//
//
//
//==========================================================================
void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end)
{
if (end > m_BrokenConsoleText.Size()) end = m_BrokenConsoleText.Size();
for (unsigned i = start; i < end; i++)
{
m_BrokenConsoleText[i].Clear();
m_BrokenConsoleText[i].ShrinkToFit();
}
}
//==========================================================================
//
// Adds a new line of text to the console
@ -95,7 +68,7 @@ void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end)
//
//==========================================================================
void FConsoleBuffer::AddText(int printlevel, const char *text, FILE *logfile)
void FConsoleBuffer::AddText(int printlevel, const char *text)
{
FString build = TEXTCOLOR_TAN;
@ -135,117 +108,9 @@ void FConsoleBuffer::AddText(int printlevel, const char *text, FILE *logfile)
mAddType = APPENDLINE;
}
// don't bother about linefeeds etc. inside the text, we'll let the formatter sort this out later.
// don't bother with linefeeds etc. inside the text, we'll let the formatter sort this out later.
build.AppendCStrPart(text, textsize);
mConsoleText.Push(build);
if (logfile != NULL) WriteLineToLog(logfile, text);
}
//==========================================================================
//
//
//
//==========================================================================
void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline)
{
// Strip out any color escape sequences before writing to the log file
TArray<char> copy(strlen(outline)+1);
const char * srcp = outline;
char * dstp = copy.Data();
while (*srcp != 0)
{
if (*srcp != TEXTCOLOR_ESCAPE)
{
switch (*srcp)
{
case '\35':
*dstp++ = '<';
break;
case '\36':
*dstp++ = '-';
break;
case '\37':
*dstp++ = '>';
break;
default:
*dstp++=*srcp;
break;
}
srcp++;
}
else if (srcp[1] == '[')
{
srcp+=2;
while (*srcp != ']' && *srcp != 0) srcp++;
if (*srcp == ']') srcp++;
}
else
{
if (srcp[1]!=0) srcp+=2;
else break;
}
}
*dstp=0;
fputs (copy.Data(), LogFile);
fflush (LogFile);
}
//==========================================================================
//
//
//
//==========================================================================
void FConsoleBuffer::WriteContentToLog(FILE *LogFile)
{
if (LogFile != NULL)
{
for (unsigned i = 0; i < mConsoleText.Size(); i++)
{
WriteLineToLog(LogFile, mConsoleText[i]);
}
}
}
//==========================================================================
//
// ensures that the following text is not appended to the current line.
//
//==========================================================================
void FConsoleBuffer::Linefeed(FILE *Logfile)
{
if (mAddType != NEWLINE && Logfile != NULL) fputc('\n', Logfile);
mAddType = NEWLINE;
}
//==========================================================================
//
//
//
//==========================================================================
static const char bar1[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_TAN "\n";
static const char bar2[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_GREEN "\n";
static const char bar3[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_NORMAL "\n";
void FConsoleBuffer::AddMidText(const char *string, bool bold, FILE *Logfile)
{
Linefeed(Logfile);
AddText (-1, bold? bar2 : bar1, Logfile);
AddText (-1, string, Logfile);
Linefeed(Logfile);
AddText(-1, bar3, Logfile);
}
//==========================================================================
@ -258,7 +123,6 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
{
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
{
FreeBrokenText();
m_BrokenConsoleText.Clear();
mBrokenStart.Clear();
mBrokenStart.Push(0);

View file

@ -61,19 +61,12 @@ class FConsoleBuffer
int mLastDisplayWidth;
bool mLastLineNeedsUpdate;
void WriteLineToLog(FILE *LogFile, const char *outline);
void FreeBrokenText(unsigned int start = 0, unsigned int end = INT_MAX);
void Linefeed(FILE *Logfile);
public:
FConsoleBuffer();
~FConsoleBuffer();
void AddText(int printlevel, const char *string, FILE *logfile = NULL);
void AddMidText(const char *string, bool bold, FILE *logfile);
void AddText(int printlevel, const char *string);
void FormatText(FFont *formatfont, int displaywidth);
void ResizeBuffer(unsigned newsize);
void WriteContentToLog(FILE *logfile);
void Clear()
{
mBufferWasCleared = true;

View file

@ -563,7 +563,7 @@ void C_DoCommand (const char *cmd, int keynum)
const char *beg;
// Skip any beginning whitespace
while (*cmd && *cmd <= ' ')
while (*cmd > 0 && *cmd <= ' ')
cmd++;
// Find end of the command name
@ -575,7 +575,7 @@ void C_DoCommand (const char *cmd, int keynum)
else
{
beg = cmd;
for (end = cmd+1; *end > ' '; ++end)
for (end = cmd+1; *end > ' ' || *end < 0; ++end)
;
}
@ -728,7 +728,7 @@ void AddCommandString (const char *text, int keynum)
more = 0;
}
// Intercept wait commands here. Note: wait must be lowercase
while (*cmd && *cmd <= ' ')
while (*cmd > 0 && *cmd <= ' ')
cmd++;
if (*cmd)
{

View file

@ -40,6 +40,7 @@
#include "sbar.h"
#include "v_video.h"
#include "utf8.h"
#include "gstrings.h"
enum
{
@ -233,16 +234,16 @@ void CT_PasteChat(const char *clip)
void CT_Drawer (void)
{
FFont *displayfont = ConFont;
FFont *displayfont = NewConsoleFont;
if (chatmodeon)
{
static const char *prompt = "Say: ";
FStringf prompt("%s ", GStrings("TXT_SAY"));
int x, scalex, y, promptwidth;
y = (viewactive || gamestate != GS_LEVEL) ? -10 : -30;
y = (viewactive || gamestate != GS_LEVEL) ? -displayfont->GetHeight()-2 : -displayfont->GetHeight() - 22;
scalex = 1;
int scale = active_con_scaletext();
int scale = active_con_scaletext(true);
int screen_width = SCREENWIDTH / scale;
int screen_height= SCREENHEIGHT / scale;
int st_y = StatusBar->GetTopOfStatusbar() / scale;
@ -264,7 +265,7 @@ void CT_Drawer (void)
}
printstr += displayfont->GetCursor();
screen->DrawText (displayfont, CR_GREEN, 0, y, prompt,
screen->DrawText (displayfont, CR_GREEN, 0, y, prompt.GetChars(),
DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE);
screen->DrawText (displayfont, CR_GREY, promptwidth, y, printstr,
DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE);

View file

@ -790,7 +790,7 @@ void D_Display ()
screen->DrawBlend(viewsec);
if (automapactive)
{
primaryLevel->automap->Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
primaryLevel->automap->Drawer ((hud_althud && viewheight == SCREENHEIGHT) ? viewheight : StatusBar->GetTopOfStatusbar());
}
// for timing the statusbar code.
@ -1247,7 +1247,6 @@ void D_DoAdvanceDemo (void)
return;
}
V_SetBlend (0,0,0,0);
players[consoleplayer].playerstate = PST_LIVE; // not reborn
usergame = false; // no save / end game here
paused = 0;
@ -1293,6 +1292,7 @@ void D_DoAdvanceDemo (void)
}
else
{
singledemo = false;
G_DeferedPlayDemo (demoname);
demosequence = 2;
break;
@ -2635,6 +2635,7 @@ void D_DoomMain (void)
V_Init2();
UpdateJoystickMenu(NULL);
UpdateVRModes();
v = Args->CheckValue ("-loadgame");
if (v)
@ -2697,8 +2698,6 @@ void D_DoomMain (void)
}
else
{
// let the renderer reinitialize some stuff if needed
screen->InitPalette();
// These calls from inside V_Init2 are still necessary
C_NewModeAdjust();
D_StartTitle (); // start up intro loop

View file

@ -2169,7 +2169,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
case DEM_CENTERPRINT:
s = ReadString (stream);
C_MidPrint (SmallFont, s);
C_MidPrint (nullptr, s);
break;
case DEM_UINFCHANGED:

View file

@ -250,7 +250,8 @@ struct userinfo_t : TMap<FName,FBaseCVar *>
}
int GetGender() const
{
return *static_cast<FIntCVar *>(*CheckKey(NAME_Gender));
auto cvar = CheckKey(NAME_Gender);
return cvar ? *static_cast<FIntCVar *>(*cvar) : 0;
}
bool GetNoAutostartMap() const
{
@ -280,7 +281,8 @@ class player_t
public:
player_t() = default;
~player_t();
player_t &operator= (const player_t &p);
player_t &operator= (const player_t &p) = delete;
void CopyFrom(player_t &src, bool copyPSP);
void Serialize(FSerializer &arc);
size_t PropagateMark();

View file

@ -89,7 +89,10 @@ enum
PRINT_CHAT, // chat messages
PRINT_TEAMCHAT, // chat messages from a teammate
PRINT_LOG, // only to logfile
PRINT_BOLD = 200 // What Printf_Bold used
PRINT_BOLD = 200, // What Printf_Bold used
PRINT_TYPES = 1023, // Bitmask.
PRINT_NONOTIFY = 1024, // Flag - do not add to notify buffer
PRINT_NOLOG = 2048, // Flag - do not print to log file
};
enum

View file

@ -573,7 +573,7 @@ void FParser::SF_Include(void)
void FParser::SF_Input(void)
{
Printf(PRINT_BOLD,"input() function not available in doom\n");
Printf(PRINT_BOLD,"input() function not available in Doom\n");
}
//==========================================================================
@ -623,7 +623,7 @@ void FParser::SF_Tip(void)
if (t_argc>0 && Script->trigger &&
Script->trigger->CheckLocalView())
{
C_MidPrint(SmallFont, GetFormatString(0).GetChars());
C_MidPrint(nullptr, GetFormatString(0).GetChars());
}
}
@ -643,7 +643,7 @@ void FParser::SF_TimedTip(void)
{
float saved = con_midtime;
con_midtime = intvalue(t_argv[0])/100.0f;
C_MidPrint(SmallFont, GetFormatString(1).GetChars());
C_MidPrint(nullptr, GetFormatString(1).GetChars());
con_midtime=saved;
}
}
@ -662,7 +662,7 @@ void FParser::SF_PlayerTip(void)
int plnum = T_GetPlayerNum(t_argv[0]);
if (plnum!=-1 && Level->Players[plnum]->mo->CheckLocalView())
{
C_MidPrint(SmallFont, GetFormatString(1).GetChars());
C_MidPrint(nullptr, GetFormatString(1).GetChars());
}
}
}

View file

@ -51,6 +51,9 @@ CVAR(Int, developer, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// [RH] Feature control cvars
CVAR(Bool, var_friction, true, CVAR_SERVERINFO);
// Option Search
CVAR(Bool, os_isanyof, true, CVAR_ARCHIVE);
@ -129,9 +132,8 @@ CUSTOM_CVAR(Float, teamdamage, 0.f, CVAR_SERVERINFO | CVAR_NOINITCALL)
}
}
CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL)
CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
{
SetLanguageIDs();
GStrings.UpdateLanguage();
for (auto Level : AllLevels())
{
@ -139,4 +141,3 @@ CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL)
if (Level->info != nullptr) Level->LevelName = Level->info->LookupLevelName();
}
}

View file

@ -42,6 +42,7 @@
#include "w_wad.h"
#include "v_text.h"
#include "c_functions.h"
#include "gstrings.h"
//==========================================================================
//
@ -404,3 +405,22 @@ CCMD(listsnapshots)
}
}
CCMD(printlocalized)
{
if (argv.argc() > 1)
{
if (argv.argc() > 2)
{
FString lang = argv[2];
lang.ToLower();
if (lang.Len() >= 2)
{
Printf("%s\n", GStrings.GetLanguageString(argv[1], MAKE_ID(lang[0], lang[1], lang[2], 0)));
return;
}
}
Printf("%s\n", GStrings(argv[1]));
}
}

View file

@ -108,6 +108,7 @@ CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, longsavemessages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, save_dir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
CVAR (Bool, cl_waitforsave, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, enablescriptscreenshot, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
EXTERN_CVAR (Float, con_midtime);
//==========================================================================
@ -755,10 +756,15 @@ static int LookAdjust(int look)
if (players[consoleplayer].playerstate != PST_DEAD && // No adjustment while dead.
players[consoleplayer].ReadyWeapon != NULL) // No adjustment if no weapon.
{
auto scale = players[consoleplayer].ReadyWeapon->FloatVar(NAME_FOVScale);
if (scale > 0) // No adjustment if it is non-positive.
auto FOVScale = players[consoleplayer].ReadyWeapon->FloatVar(NAME_FOVScale);
auto LookScale = players[consoleplayer].ReadyWeapon->FloatVar(NAME_LookScale);
if (FOVScale > 0) // No adjustment if it is non-positive.
{
look = int(look * scale);
look = int(look * FOVScale);
}
if (LookScale > 0) // No adjustment if it is non-positive.
{
look = int(look * LookScale);
}
}
return look;
@ -1715,7 +1721,7 @@ void G_DoPlayerPop(int playernum)
players[playernum].DestroyPSprites();
}
void G_ScreenShot (char *filename)
void G_ScreenShot (const char *filename)
{
shotfile = filename;
gameaction = ga_screenshot;
@ -2048,7 +2054,7 @@ void G_DoAutoSave ()
}
readableTime = myasctime ();
description.Format("Autosave %.12s", readableTime + 4);
description.Format("Autosave %s", readableTime);
G_DoSaveGame (false, file, description);
}
@ -2071,14 +2077,9 @@ static void PutSaveWads (FSerializer &arc)
static void PutSaveComment (FSerializer &arc)
{
const char *readableTime;
int levelTime;
// Get the current date and time
readableTime = myasctime ();
FString comment;
comment.Format("%.10s%.5s%.9s", readableTime, &readableTime[19], &readableTime[10]);
FString comment = myasctime();
arc.AddString("Creation Time", comment);
@ -2094,6 +2095,56 @@ static void PutSaveComment (FSerializer &arc)
arc.AddString("Comment", comment);
}
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown)
{
PalEntry palette[256];
PalEntry modulateColor;
auto blend = screen->CalcBlend(viewsector, &modulateColor);
int pixelsize = 1;
// Apply the screen blend, because the renderer does not provide this.
if (ssformat == SS_RGB)
{
int numbytes = width * height * 3;
pixelsize = 3;
if (modulateColor != 0xffffffff)
{
float r = modulateColor.r / 255.f;
float g = modulateColor.g / 255.f;
float b = modulateColor.b / 255.f;
for (int i = 0; i < numbytes; i += 3)
{
scr[i] = uint8_t(scr[i] * r);
scr[i + 1] = uint8_t(scr[i + 1] * g);
scr[i + 2] = uint8_t(scr[i + 2] * b);
}
}
float iblendfac = 1.f - blend.W;
blend.X *= blend.W;
blend.Y *= blend.W;
blend.Z *= blend.W;
for (int i = 0; i < numbytes; i += 3)
{
scr[i] = uint8_t(scr[i] * iblendfac + blend.X);
scr[i + 1] = uint8_t(scr[i + 1] * iblendfac + blend.Y);
scr[i + 2] = uint8_t(scr[i + 2] * iblendfac + blend.Z);
}
}
else
{
// Apply the screen blend to the palette. The colormap related parts get skipped here because these are already part of the image.
DoBlending(GPalette.BaseColors, palette, 256, uint8_t(blend.X), uint8_t(blend.Y), uint8_t(blend.Z), uint8_t(blend.W*255));
}
int pitch = width * pixelsize;
if (upsidedown)
{
scr += ((height - 1) * width * pixelsize);
pitch *= -1;
}
M_CreatePNG(file, scr, ssformat == SS_PAL? palette : nullptr, ssformat, width, height, pitch, Gamma);
}
static void PutSavePic (FileWriter *file, int width, int height)
{
if (width <= 0 || height <= 0 || !storesavepic)
@ -2676,7 +2727,7 @@ void G_DoPlayDemo (void)
}
demo_p = demobuffer;
Printf ("Playing demo %s\n", defdemoname.GetChars());
if (singledemo) Printf ("Playing demo %s\n", defdemoname.GetChars());
C_BackupCVars (); // [RH] Save cvars that might be affected by demo
@ -2693,7 +2744,7 @@ void G_DoPlayDemo (void)
}
else
{
Printf (PRINT_BOLD, "%s", eek);
//Printf (PRINT_BOLD, "%s", eek);
gameaction = ga_nothing;
}
}
@ -2876,6 +2927,26 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, StartSlideshow)
return 0;
}
DEFINE_ACTION_FUNCTION(FLevelLocals, MakeScreenShot)
{
if (enablescriptscreenshot)
{
G_ScreenShot("");
}
return 0;
}
void G_MakeAutoSave()
{
gameaction = ga_autosave;
}
DEFINE_ACTION_FUNCTION(FLevelLocals, MakeAutoSave)
{
G_MakeAutoSave();
return 0;
}
DEFINE_GLOBAL(players)
DEFINE_GLOBAL(playeringame)
DEFINE_GLOBAL(PlayerClasses)

View file

@ -95,7 +95,7 @@ bool G_CheckDemoStatus (void);
void G_Ticker (void);
bool G_Responder (event_t* ev);
void G_ScreenShot (char *filename);
void G_ScreenShot (const char* filename);
void G_StartSlideshow(FLevelLocals *Level, FName whichone);
FString G_BuildSaveName (const char *prefix, int slot);

View file

@ -1062,12 +1062,8 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au
if (isPrimaryLevel())
{
FString mapname = nextmapname;
mapname.ToLower();
Printf(
"\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"
TEXTCOLOR_BOLD "%s - %s\n\n",
mapname.GetChars(), LevelName.GetChars());
mapname.ToUpper();
Printf("\n%s\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", console_bar, mapname.GetChars(), LevelName.GetChars());
}
// Set the sky map.
@ -2142,9 +2138,9 @@ int IsPointInMap(FLevelLocals *Level, double x, double y, double z)
for (uint32_t i = 0; i < subsector->numlines; i++)
{
// Skip single sided lines.
// Skip double sided lines.
seg_t *seg = subsector->firstline + i;
if (seg->backsector != nullptr) continue;
if (seg->backsector != nullptr || seg->linedef == nullptr) continue;
divline_t dline;
P_MakeDivline(seg->linedef, &dline);

View file

@ -128,7 +128,7 @@ void DHUDMessageBase::CallDraw(int bottom, int visibility)
//============================================================================
DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime)
EColorRange textColor, float holdTime, bool altscale)
{
if (hudwidth == 0 || hudheight == 0)
{
@ -139,6 +139,7 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
// for x range [0.0, 1.0]: Positions center of box
// for x range [1.0, 2.0]: Positions center of box, and centers text inside it
HUDWidth = HUDHeight = 0;
AltScale = altscale;
if (fabs (x) > 2.f)
{
CenterX = true;
@ -319,7 +320,7 @@ void DHUDMessage::ResetText (const char *text)
}
else
{
width = SCREENWIDTH / active_con_scaletext();
width = SCREENWIDTH / active_con_scaletext(AltScale);
}
Lines = V_BreakLines (Font, NoWrap ? INT_MAX : width, (uint8_t *)text);
@ -379,7 +380,7 @@ void DHUDMessage::Draw (int bottom, int visibility)
xscale = yscale = 1;
if (HUDWidth == 0)
{
int scale = active_con_scaletext();
int scale = active_con_scaletext(AltScale);
screen_width /= scale;
screen_height /= scale;
bottom /= scale;
@ -483,7 +484,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
{
if (hudheight == 0)
{
int scale = active_con_scaletext();
int scale = active_con_scaletext(AltScale);
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH / scale,
DTA_VirtualHeight, SCREENHEIGHT / scale,
@ -576,7 +577,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
float trans = float(Alpha * -(Tics - FadeOutTics) / FadeOutTics);
if (hudheight == 0)
{
int scale = active_con_scaletext();
int scale = active_con_scaletext(AltScale);
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH / scale,
DTA_VirtualHeight, SCREENHEIGHT / scale,
@ -665,7 +666,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
float trans = float(Alpha * Tics / FadeInTics);
if (hudheight == 0)
{
int scale = active_con_scaletext();
int scale = active_con_scaletext(AltScale);
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH / scale,
DTA_VirtualHeight, SCREENHEIGHT / scale,
@ -741,7 +742,7 @@ void DHUDMessageTypeOnFadeOut::Serialize(FSerializer &arc)
bool DHUDMessageTypeOnFadeOut::Tick ()
{
if (LineLen > 0 && !Super::Tick ())
if (!Super::Tick ())
{
if (State == 3)
{
@ -836,7 +837,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
{
if (hudheight == 0)
{
int scale = active_con_scaletext();
int scale = active_con_scaletext(AltScale);
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH / scale,
DTA_VirtualHeight, SCREENHEIGHT / scale,

View file

@ -84,7 +84,7 @@ class DHUDMessage : public DHUDMessageBase
DECLARE_CLASS (DHUDMessage, DHUDMessageBase)
public:
DHUDMessage (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime);
EColorRange textColor, float holdTime, bool altscale = false);
virtual void OnDestroy () override;
virtual void Serialize(FSerializer &arc);
@ -140,6 +140,7 @@ protected:
int ClipX, ClipY, ClipWidth, ClipHeight, WrapWidth; // in HUD coords
int ClipLeft, ClipTop, ClipRight, ClipBot; // in screen coords
bool HandleAspect;
bool AltScale;
EColorRange TextColor;
FFont *Font;
FRenderStyle Style;

View file

@ -48,6 +48,7 @@
#include "g_levellocals.h"
#include "vm.h"
#include "i_system.h"
#include "utf8.h"
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
enum

View file

@ -55,6 +55,7 @@
CVAR(Int,hud_althudscale, 0, CVAR_ARCHIVE) // Scale the hud to 640x400?
CVAR(Bool,hud_althud, false, CVAR_ARCHIVE) // Enable/Disable the alternate HUD
CVAR(Bool, hud_althudfont, false, CVAR_ARCHIVE) // Enable/Disable the alternate HUD
// These are intentionally not the same as in the automap!
CVAR (Bool, hud_showsecrets, true,CVAR_ARCHIVE); // Show secrets on HUD
CVAR (Bool, hud_showmonsters, true,CVAR_ARCHIVE); // Show monster stats on HUD

View file

@ -58,6 +58,7 @@
#include "gstrings.h"
#include "events.h"
#include "g_game.h"
#include "utf8.h"
#include "../version.h"

View file

@ -220,7 +220,7 @@ static void PrintMessage (const char *str)
{
str = GStrings(str+1);
}
C_MidPrint (SmallFont, str);
C_MidPrint (nullptr, str);
}
}

View file

@ -751,12 +751,24 @@ int FFont::GetCharCode(int code, bool needpic) const
}
}
code = originalcode;
if (myislower(code))
{
int upper = upperforlower[code];
// Stripping accents did not help - now try uppercase for lowercase
if (upper != code) return GetCharCode(upper, needpic);
}
// Same for the uppercase character. Since we restart at the accented version this must go through the entire thing again.
while ((newcode = stripaccent(code)) != code)
{
code = newcode;
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr))
{
return code;
}
}
}
return -1;

View file

@ -0,0 +1,397 @@
/*
** bdffont.cpp
** Management for the VGA consolefont
**
**---------------------------------------------------------------------------
** Copyright 2019 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 "doomerrors.h"
#include "textures.h"
#include "image.h"
#include "v_font.h"
#include "w_wad.h"
#include "utf8.h"
#include "sc_man.h"
#include "fontinternals.h"
struct HexDataSource
{
int FirstChar = INT_MAX, LastChar = INT_MIN;
TArray<uint8_t> glyphdata;
unsigned glyphmap[65536] = {};
//==========================================================================
//
// parse a HEX font
//
//==========================================================================
void ParseDefinition(int lumpnum)
{
FScanner sc;
sc.OpenLumpNum(lumpnum);
sc.SetCMode(true);
glyphdata.Push(0); // ensure that index 0 can be used as 'not present'.
while (sc.GetString())
{
int codepoint = (int)strtoull(sc.String, nullptr, 16);
sc.MustGetStringName(":");
sc.MustGetString();
if (codepoint >= 0 && codepoint < 65536 && !sc.Compare("00000000000000000000000000000000")) // don't set up empty glyphs.
{
unsigned size = (unsigned)strlen(sc.String);
unsigned offset = glyphdata.Reserve(size / 2 + 1);
glyphmap[codepoint] = offset;
glyphdata[offset++] = size / 2;
for (unsigned i = 0; i < size; i += 2)
{
char hex[] = { sc.String[i], sc.String[i + 1], 0 };
glyphdata[offset++] = (uint8_t)strtoull(hex, nullptr, 16);
}
if (codepoint < FirstChar) FirstChar = codepoint;
if (codepoint > LastChar) LastChar = codepoint;
}
}
}
};
static HexDataSource hexdata;
// This is a font character that reads RLE compressed data.
class FHexFontChar : public FImageSource
{
public:
FHexFontChar(uint8_t *sourcedata, int swidth, int width, int height);
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
protected:
int SourceWidth;
const uint8_t *SourceData;
};
//==========================================================================
//
// FHexFontChar :: FHexFontChar
//
// Used by HEX fonts.
//
//==========================================================================
FHexFontChar::FHexFontChar (uint8_t *sourcedata, int swidth, int width, int height)
: SourceData (sourcedata)
{
SourceWidth = swidth;
Width = width;
Height = height;
LeftOffset = 0;
TopOffset = 0;
}
//==========================================================================
//
// FHexFontChar :: Get8BitPixels
//
// The render style has no relevance here.
//
//==========================================================================
TArray<uint8_t> FHexFontChar::CreatePalettedPixels(int)
{
int destSize = Width * Height;
TArray<uint8_t> Pixels(destSize, true);
uint8_t *dest_p = Pixels.Data();
const uint8_t *src_p = SourceData;
memset(dest_p, 0, destSize);
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < SourceWidth; x++)
{
int byte = *src_p++;
uint8_t *pixelstart = dest_p + 8 * x * Height + y;
for (int bit = 0; bit < 8; bit++)
{
if (byte & (128 >> bit))
{
pixelstart[bit*Height] = y+2;
// Add a shadow at the bottom right, similar to the old console font.
if (y != Height - 1)
{
pixelstart[bit*Height + Height + 1] = 1;
}
}
}
}
}
return Pixels;
}
class FHexFontChar2 : public FHexFontChar
{
public:
FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int height);
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
};
//==========================================================================
//
// FHexFontChar :: FHexFontChar
//
// Used by HEX fonts.
//
//==========================================================================
FHexFontChar2::FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int height)
: FHexFontChar(sourcedata, swidth, width, height)
{
}
//==========================================================================
//
// FHexFontChar :: Get8BitPixels
//
// The render style has no relevance here.
//
//==========================================================================
TArray<uint8_t> FHexFontChar2::CreatePalettedPixels(int)
{
int destSize = Width * Height;
TArray<uint8_t> Pixels(destSize, true);
uint8_t *dest_p = Pixels.Data();
auto drawLayer = [&](int ix, int iy, int color)
{
const uint8_t *src_p = SourceData;
for (int y = 0; y < Height-2; y++)
{
for (int x = 0; x < SourceWidth; x++)
{
int byte = *src_p++;
uint8_t *pixelstart = dest_p + (ix + 8 * x) * Height + (iy+y);
for (int bit = 0; bit < 8; bit++)
{
if (byte & (128 >> bit))
{
pixelstart[bit*Height] = color;
}
}
}
}
};
memset(dest_p, 0, destSize);
const int darkcolor = 3;
const int brightcolor = 14;
for (int xx=0;xx<3;xx++) for (int yy=0;yy<3;yy++) if (xx !=1 || yy != 1)
drawLayer(xx, yy, darkcolor);
drawLayer(1, 1, brightcolor);
return Pixels;
}
class FHexFont : public FFont
{
public:
//==========================================================================
//
// FHexFont :: FHexFont
//
// Loads a HEX font
//
//==========================================================================
FHexFont (const char *fontname, int lump)
: FFont(lump)
{
assert(lump >= 0);
FontName = fontname;
FirstChar = hexdata.FirstChar;
LastChar = hexdata.LastChar;
Next = FirstFont;
FirstFont = this;
FontHeight = 16;
SpaceWidth = 9;
GlobalKerning = 0;
translateUntranslated = true;
LoadTranslations();
}
//==========================================================================
//
// FHexFont :: LoadTranslations
//
//==========================================================================
void LoadTranslations()
{
const int spacing = 9;
double luminosity[256];
memset (PatchRemap, 0, 256);
for (int i = 0; i < 18; i++)
{
// Create a gradient similar to the old console font.
PatchRemap[i] = i;
luminosity[i] = i == 1? 0.01 : 0.5 + (i-2) * (0.5 / 17.);
}
ActiveColors = 18;
Chars.Resize(LastChar - FirstChar + 1);
for (int i = FirstChar; i <= LastChar; i++)
{
if (hexdata.glyphmap[i] > 0)
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = new FImageTexture(new FHexFontChar (&hexdata.glyphdata[offset+1], size, size * 9, 16));
Chars[i - FirstChar].TranslatedPic->SetUseType(ETextureType::FontChar);
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
}
BuildTranslations (luminosity, nullptr, &TranslationParms[1][0], ActiveColors, nullptr);
}
};
class FHexFont2 : public FFont
{
public:
//==========================================================================
//
// FHexFont :: FHexFont
//
// Loads a HEX font
//
//==========================================================================
FHexFont2(const char *fontname, int lump)
: FFont(lump)
{
assert(lump >= 0);
FontName = fontname;
FirstChar = hexdata.FirstChar;
LastChar = hexdata.LastChar;
Next = FirstFont;
FirstFont = this;
FontHeight = 18;
SpaceWidth = 10;
GlobalKerning = -1;
translateUntranslated = true;
LoadTranslations();
}
//==========================================================================
//
// FHexFont :: LoadTranslations
//
//==========================================================================
void LoadTranslations()
{
const int spacing = 9;
double luminosity[256];
memset(PatchRemap, 0, 256);
for (int i = 0; i < 18; i++)
{
// Create a gradient similar to the old console font.
PatchRemap[i] = i;
luminosity[i] = i / 17.;
}
ActiveColors = 18;
Chars.Resize(LastChar - FirstChar + 1);
for (int i = FirstChar; i <= LastChar; i++)
{
if (hexdata.glyphmap[i] > 0)
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = new FImageTexture(new FHexFontChar2(&hexdata.glyphdata[offset + 1], size, 2 + size * 8, 18));
Chars[i - FirstChar].TranslatedPic->SetUseType(ETextureType::FontChar);
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
}
BuildTranslations(luminosity, nullptr, &TranslationParms[0][0], ActiveColors, nullptr);
}
};
//==========================================================================
//
//
//
//==========================================================================
FFont *CreateHexLumpFont (const char *fontname, int lump)
{
if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump);
return new FHexFont(fontname, lump);
}
//==========================================================================
//
//
//
//==========================================================================
FFont *CreateHexLumpFont2(const char *fontname, int lump)
{
if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump);
return new FHexFont2(fontname, lump);
}

View file

@ -122,6 +122,7 @@ static const uint16_t loweruppercase[] = {
0x0078,0x0058,
0x0079,0x0059,
0x007A,0x005A,
0x00DF,0x1E9E,
0x00E0,0x00C0,
0x00E1,0x00C1,
0x00E2,0x00C2,
@ -837,9 +838,18 @@ int stripaccent(int code)
return 'P' + (code & 0x20); // well, it sort of looks like a 'P'
}
else if (code >= 0x100 && code < 0x180)
{
// For the double-accented Hungarian letters it makes more sense to first map them to the very similar looking Umlauts.
// (And screw the crappy specs here that do not allow UTF-8 multibyte characters here.)
if (code == 0x150) code = 0xd6;
else if (code == 0x151) code = 0xf6;
else if (code == 0x170) code = 0xdc;
else if (code == 0x171) code = 0xfc;
else
{
static const char accentless[] = "AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnnNnOoOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZz ";
return accentless[code -0x100];
return accentless[code - 0x100];
}
}
else if (code >= 0x200 && code < 0x21c)
{
@ -847,6 +857,11 @@ int stripaccent(int code)
static const uint16_t u200map[] = {0xc4, 0xe4, 0xc2, 0xe2, 0xcb, 0xeb, 0xca, 0xea, 0xcf, 0xef, 0xce, 0xee, 0xd6, 0xf6, 0xd4, 0xe4, 'R', 'r', 'R', 'r', 0xdc, 0xfc, 0xdb, 0xfb, 0x15e, 0x15f, 0x162, 0x163};
return u200map[code - 0x200];
}
else if (code == 0x201d)
{
// Map the typographic upper quotation mark to the generic form
code = '"';
}
// skip the rest of Latin characters because none of them are relevant for modern languages.
@ -855,7 +870,8 @@ int stripaccent(int code)
FFont *V_GetFont(const char *name, const char *fontlumpname)
{
if (!stricmp(name, "CONFONT")) name = "ConsoleFont"; // several mods have used the name CONFONT directly and effectively duplicated the font.
if (!stricmp(name, "DBIGFONT")) name = "BigFont"; // several mods have used the name CONFONT directly and effectively duplicated the font.
else if (!stricmp(name, "CONFONT")) name = "ConsoleFont"; // several mods have used the name CONFONT directly and effectively duplicated the font.
FFont *font = FFont::FindFont (name);
if (font == nullptr)
{
@ -1432,6 +1448,15 @@ void V_InitFonts()
InitLowerUpper();
V_InitCustomFonts();
FFont *CreateHexLumpFont(const char *fontname, int lump);
FFont *CreateHexLumpFont2(const char *fontname, int lump);
auto lump = Wads.CheckNumForFullName("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements.
if (lump == -1) I_FatalError("newconsolefont.hex not found"); // This font is needed - do not start up without it.
NewConsoleFont = CreateHexLumpFont("NewConsoleFont", lump);
NewSmallFont = CreateHexLumpFont2("NewSmallFont", lump);
CurrentConsoleFont = NewConsoleFont;
// load the heads-up font
if (!(SmallFont = V_GetFont("SmallFont", "SMALLFNT")))
{
@ -1517,6 +1542,6 @@ void V_ClearFonts()
delete FFont::FirstFont;
}
FFont::FirstFont = nullptr;
SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = nullptr;
CurrentConsoleFont = NewSmallFont = NewConsoleFont = SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = nullptr;
}

View file

@ -164,7 +164,7 @@ protected:
};
extern FFont *SmallFont, *SmallFont2, *BigFont, *BigUpper, *ConFont, *IntermissionFont;
extern FFont *SmallFont, *SmallFont2, *BigFont, *BigUpper, *ConFont, *IntermissionFont, *NewConsoleFont, *NewSmallFont, *CurrentConsoleFont;
void V_InitFonts();
void V_ClearFonts();

View file

@ -38,6 +38,7 @@
#include <wctype.h>
#include "v_text.h"
#include "utf8.h"
#include "v_video.h"
@ -74,6 +75,9 @@ TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *str
bool lastWasSpace = false;
int kerning = font->GetDefaultKerning ();
// The real isspace is a bit too badly defined, so use our own one
auto myisspace = [](int ch) { return ch == '\t' || ch == '\r' || ch == '\n' || ch == ' '; };
w = 0;
while ( (c = GetCharFromString(string)) )
@ -103,7 +107,7 @@ TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *str
continue;
}
if (iswspace(c))
if (myisspace(c))
{
if (!lastWasSpace)
{
@ -136,12 +140,12 @@ TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *str
start = space;
space = NULL;
while (*start && iswspace (*start) && *start != '\n')
while (*start && myisspace (*start) && *start != '\n')
start++;
if (*start == '\n')
start++;
else
while (*start && iswspace (*start))
while (*start && myisspace (*start))
start++;
string = start;
}
@ -159,7 +163,7 @@ TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *str
while (s < string)
{
// If there is any non-white space in the remainder of the string, add it.
if (!iswspace (*s++))
if (!myisspace (*s++))
{
auto i = Lines.Reserve(1);
breakit (&Lines[i], font, start, string, linecolor);

View file

@ -44,6 +44,7 @@ struct FBrokenLines
};
#define TEXTCOLOR_ESCAPE '\034'
#define TEXTCOLOR_ESCAPESTR "\034"
#define TEXTCOLOR_BRICK "\034A"
#define TEXTCOLOR_TAN "\034B"
@ -85,6 +86,4 @@ inline TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const char
inline TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false)
{ return V_BreakLines (font, maxwidth, (const uint8_t *)str.GetChars(), preservecolor); }
int GetCharFromString(const uint8_t *&string);
#endif //__V_TEXT_H__

View file

@ -2019,7 +2019,7 @@ void FMapInfoParser::ParseEpisodeInfo ()
{
ParseAssign();
sc.MustGetString ();
name = sc.String;
name = strbin1(sc.String);
}
else if (sc.Compare ("picname"))
{

View file

@ -214,7 +214,7 @@ void FMapInfoParser::ParseSkill ()
{
ParseAssign();
sc.MustGetString ();
skill.MenuName = sc.String;
skill.MenuName = strbin1(sc.String);
}
else if (sc.Compare("PlayerClassName"))
{

View file

@ -397,6 +397,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_BOOL(dontcrunchcorpses, "dontcrunchcorpses")
GAMEINFOKEY_BOOL(correctprintbold, "correctprintbold")
GAMEINFOKEY_BOOL(forcetextinmenus, "forcetextinmenus")
GAMEINFOKEY_BOOL(forcenogfxsubstitution, "forcenogfxsubstitution")
GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter")
GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast")
GAMEINFOKEY_COLOR(dimcolor, "dimcolor")

View file

@ -121,6 +121,7 @@ struct gameinfo_t
bool dontcrunchcorpses;
bool correctprintbold;
bool forcetextinmenus;
bool forcenogfxsubstitution;
TArray<FName> creditPages;
TArray<FName> finalePages;
TArray<FName> infoPages;

View file

@ -33,6 +33,7 @@
**
*/
#include <ctype.h>
#include "resourcefile.h"
#include "v_text.h"
#include "w_wad.h"

View file

@ -464,7 +464,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level)
section.ToUpper();
const char *ep_name = StartEpisode->mEpisodeName;
if (*ep_name == '$') ep_name = GStrings[ep_name+1];
if (*ep_name == '$') ep_name = GStrings(ep_name+1);
FStatistics *sl = GetStatisticsList(EpisodeStatistics, section, ep_name);
int statvals[6] = {0,0,0,0,0,0};

View file

@ -45,6 +45,7 @@
#include "d_player.h"
#include "xlsxread/xlsxio_read.h"
EXTERN_CVAR(String, language)
//==========================================================================
//
@ -63,7 +64,6 @@ void FStringTable::LoadStrings ()
if (!LoadLanguageFromSpreadsheet(lump))
LoadLanguage (lump);
}
SetLanguageIDs();
UpdateLanguage();
allMacros.Clear();
}
@ -150,13 +150,15 @@ bool FStringTable::readSheetIntoTable(xlsxioreader reader, const char *sheetname
int column = 0;
char *value;
table.Reserve(1);
auto myisspace = [](int ch) { return ch == '\t' || ch == '\r' || ch == '\n' || ch == ' '; };
while ((value = xlsxioread_sheet_next_cell(sheet)) != nullptr)
{
auto vcopy = value;
if (table.Size() <= (unsigned)row) table.Reserve(1);
while (*vcopy && iswspace((unsigned char)*vcopy)) vcopy++; // skip over leaading whitespace;
while (*vcopy && myisspace((unsigned char)*vcopy)) vcopy++; // skip over leaading whitespace;
auto vend = vcopy + strlen(vcopy);
while (vend > vcopy && iswspace((unsigned char)vend[-1])) *--vend = 0; // skip over trailing whitespace
while (vend > vcopy && myisspace((unsigned char)vend[-1])) *--vend = 0; // skip over trailing whitespace
ProcessEscapes(vcopy);
table[row].Push(vcopy);
column++;
@ -354,7 +356,7 @@ void FStringTable::InsertString(int langid, FName label, const FString &string)
Printf("Bad macro in %s : %s\n", strlangid, label.GetChars());
break;
}
FString macroname(string.GetChars() + index + 2, endindex - index - 2);
FString macroname(te.strings[0].GetChars() + index + 2, endindex - index - 2);
FStringf lookupstr("%s/%s", strlangid, macroname.GetChars());
FStringf replacee("@[%s]", macroname.GetChars());
FName lookupname(lookupstr, true);
@ -376,6 +378,12 @@ void FStringTable::InsertString(int langid, FName label, const FString &string)
void FStringTable::UpdateLanguage()
{
size_t langlen = strlen(language);
int LanguageID = (langlen < 2 || langlen > 3) ?
MAKE_ID('e', 'n', 'u', '\0') :
MAKE_ID(language[0], language[1], language[2], '\0');
currentLanguageSet.Clear();
auto checkone = [&](uint32_t lang_id)
@ -387,11 +395,8 @@ void FStringTable::UpdateLanguage()
checkone(dehacked_table);
checkone(global_table);
for (int i = 0; i < 4; ++i)
{
checkone(LanguageIDs[i]);
checkone(LanguageIDs[i] & MAKE_ID(0xff, 0xff, 0, 0));
}
checkone(LanguageID);
checkone(LanguageID & MAKE_ID(0xff, 0xff, 0, 0));
checkone(default_table);
}

View file

@ -173,7 +173,7 @@ TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion)
int FImageSource::CopyPixels(FBitmap *bmp, int conversion)
{
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
PalEntry *palette = screen->GetPalette();
PalEntry *palette = GPalette.BaseColors;
for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values
auto ppix = CreatePalettedPixels(conversion);
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr);

View file

@ -403,9 +403,11 @@ FTexture *FTextureManager::FindTexture(const char *texname, ETextureType usetype
// 3: Only replace if the string is not the default and the graphic comes from the IWAD. Never replace a localized graphic.
// 4: Like 1, but lets localized graphics pass.
//
// The default is 3, which only replaces known content with non-default texts.
//
//==========================================================================
CUSTOM_CVAR(Int, cl_localizationmode,0, CVAR_ARCHIVE)
CUSTOM_CVAR(Int, cl_gfxlocalization, 3, CVAR_ARCHIVE)
{
if (self < 0 || self > 4) self = 0;
}
@ -421,8 +423,8 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut
if (!texnum.isValid()) return false;
// First the unconditional settings, 0='never' and 1='always'.
if (cl_localizationmode == 1 || gameinfo.forcetextinmenus) return false;
if (cl_localizationmode == 0) return true;
if (cl_gfxlocalization == 1 || gameinfo.forcetextinmenus) return false;
if (cl_gfxlocalization == 0 || gameinfo.forcenogfxsubstitution) return true;
uint32_t langtable = 0;
if (*substitute == '$') substitute = GStrings.GetString(substitute+1, &langtable);
@ -433,11 +435,11 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut
if (localizedTex != texnum.GetIndex()) return true; // Do not substitute a localized variant of the graphics patch.
// For mode 4 we are done now.
if (cl_localizationmode == 4) return false;
if (cl_gfxlocalization == 4) return false;
// Mode 2 and 3 must reject any text replacement from the default language tables.
if ((langtable & MAKE_ID(255,0,0,0)) == MAKE_ID('*', 0, 0, 0)) return true; // Do not substitute if the string comes from the default table.
if (cl_localizationmode == 2) return false;
if (cl_gfxlocalization == 2) return false;
// Mode 3 must also reject substitutions for non-IWAD content.
int file = Wads.GetLumpFile(Textures[texnum.GetIndex()].Texture->SourceLump);
@ -1300,17 +1302,20 @@ int FTextureManager::PalCheck(int tex)
// FTextureManager :: PalCheck
//
//==========================================================================
EXTERN_CVAR(String, language)
int FTextureManager::ResolveLocalizedTexture(int tex)
{
for(int i = 0; i < 4; i++)
{
uint32_t lang = LanguageIDs[i];
size_t langlen = strlen(language);
int lang = (langlen < 2 || langlen > 3) ?
MAKE_ID('e', 'n', 'u', '\0') :
MAKE_ID(language[0], language[1], language[2], '\0');
uint64_t index = (uint64_t(lang) << 32) + tex;
if (auto pTex = LocalizedTextures.CheckKey(index)) return *pTex;
index = (uint64_t(lang & MAKE_ID(255, 255, 0, 0)) << 32) + tex;
if (auto pTex = LocalizedTextures.CheckKey(index)) return *pTex;
}
return tex;
}

View file

@ -24,6 +24,7 @@
#include "r_defs.h"
#include "p_setup.h"
#include "gi.h"
#include "cmdlib.h"
FName MakeEndPic(const char *string);
@ -231,7 +232,7 @@ static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape)
// add the given episode
FEpisode epi;
epi.mEpisodeName = split[1];
epi.mEpisodeName = strbin1(split[1]);
epi.mEpisodeMap = mape->MapName;
epi.mPicName = split[0];
epi.mShortcut = split[2][0];

View file

@ -211,7 +211,6 @@ int DIntermissionScreenFader::Responder (event_t *ev)
{
if (ev->type == EV_KeyDown)
{
V_SetBlend(0,0,0,0);
return -1;
}
return Super::Responder(ev);
@ -848,11 +847,11 @@ void DIntermissionController::OnDestroy ()
void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t state)
{
ScaleOverrider s;
if (DIntermissionController::CurrentIntermission != NULL)
{
DIntermissionController::CurrentIntermission->Destroy();
}
V_SetBlend (0,0,0,0);
S_StopAllChannels ();
gameaction = ga_nothing;
gamestate = GS_FINALE;
@ -894,6 +893,7 @@ void F_StartIntermission(FName seq, uint8_t state)
bool F_Responder (event_t* ev)
{
ScaleOverrider s;
if (DIntermissionController::CurrentIntermission != NULL)
{
return DIntermissionController::CurrentIntermission->Responder(ev);
@ -909,6 +909,7 @@ bool F_Responder (event_t* ev)
void F_Ticker ()
{
ScaleOverrider s;
if (DIntermissionController::CurrentIntermission != NULL)
{
DIntermissionController::CurrentIntermission->Ticker();
@ -923,6 +924,7 @@ void F_Ticker ()
void F_Drawer ()
{
ScaleOverrider s;
if (DIntermissionController::CurrentIntermission != NULL)
{
DIntermissionController::CurrentIntermission->Drawer();
@ -938,6 +940,7 @@ void F_Drawer ()
void F_EndFinale ()
{
ScaleOverrider s;
if (DIntermissionController::CurrentIntermission != NULL)
{
DIntermissionController::CurrentIntermission->Destroy();
@ -953,6 +956,7 @@ void F_EndFinale ()
void F_AdvanceIntermission()
{
ScaleOverrider s;
if (DIntermissionController::CurrentIntermission != NULL)
{
DIntermissionController::CurrentIntermission->mAdvance = true;

View file

@ -34,6 +34,7 @@
*/
#include <ctype.h>
#include "intermission/intermission.h"
#include "g_level.h"
#include "w_wad.h"

View file

@ -612,12 +612,6 @@ void M_ScreenShot (const char *filename)
auto buffer = screen->GetScreenshotBuffer(pitch, color_type, gamma);
if (buffer.Size() > 0)
{
PalEntry palette[256];
if (color_type == SS_PAL)
{
screen->GetFlashedPalette(palette);
}
file = FileWriter::Open(autoname);
if (file == NULL)
{
@ -626,12 +620,12 @@ void M_ScreenShot (const char *filename)
}
if (writepcx)
{
WritePCXfile(file, buffer.Data(), palette, color_type,
WritePCXfile(file, buffer.Data(), nullptr, color_type,
screen->GetWidth(), screen->GetHeight(), pitch);
}
else
{
WritePNGfile(file, buffer.Data(), palette, color_type,
WritePNGfile(file, buffer.Data(), nullptr, color_type,
screen->GetWidth(), screen->GetHeight(), pitch, gamma);
}
delete file;

View file

@ -478,8 +478,7 @@ unsigned FSavegameManager::ExtractSaveData(int index)
comment = time;
if (time.Len() > 0) comment += "\n";
comment += pcomment;
SaveComment = V_BreakLines(SmallFont, WindowSize, comment.GetChars());
SaveCommentString = comment;
// Extract pic
FResourceLump *pic = resf->FindLump("savepic.png");
@ -533,9 +532,8 @@ void FSavegameManager::UnloadSaveData()
{
delete SavePic;
}
SaveComment.Clear();
SaveComment.ShrinkToFit();
SaveCommentString = "";
SavePic = nullptr;
SavePicData.Clear();
}
@ -592,46 +590,6 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, DrawSavePic)
ACTION_RETURN_BOOL(self->DrawSavePic(x, y, w, h));
}
//=============================================================================
//
//
//
//=============================================================================
void FSavegameManager::DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor)
{
int sx = CleanXfac;
int sy = CleanYfac;
CleanXfac = CleanYfac = scalefactor;
int maxlines = screen->GetHeight()>400?10:screen->GetHeight()>240?7:screen->GetHeight()>200?8:5;
if (SmallFont->GetHeight() > 9) maxlines--; // not Doom
// I'm not sure why SaveComment would go nullptr in this loop, but I got
// a crash report where it was nullptr when i reached 1, so now I check
// for that.
for (int i = 0; i < maxlines && (unsigned)i < SaveComment.Size(); ++i)
{
screen->DrawText(font, cr, x, y + font->GetHeight() * i * scalefactor, SaveComment[i].Text, DTA_CleanNoMove, true, TAG_DONE);
}
CleanXfac = sx;
CleanYfac = sy;
}
DEFINE_ACTION_FUNCTION(FSavegameManager, DrawSaveComment)
{
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
PARAM_POINTER(fnt, FFont);
PARAM_INT(cr);
PARAM_INT(x);
PARAM_INT(y);
PARAM_INT(fac);
self->DrawSaveComment(fnt, cr, x, y, fac);
return 0;
}
//=============================================================================
//
//
@ -642,9 +600,7 @@ void FSavegameManager::SetFileInfo(int Selected)
{
if (!SaveGames[Selected]->Filename.IsEmpty())
{
FString work;
work.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
SaveComment = V_BreakLines(SmallFont, WindowSize, work);
SaveCommentString.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
}
}
@ -753,4 +709,5 @@ DEFINE_FIELD(FSaveGameNode, bNoDelete);
DEFINE_FIELD(FSavegameManager, WindowSize);
DEFINE_FIELD(FSavegameManager, quickSaveSlot);
DEFINE_FIELD(FSavegameManager, SaveCommentString);

View file

@ -405,7 +405,7 @@ DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu)
//
//=============================================================================
EXTERN_CVAR(Int, cl_localizationmode)
EXTERN_CVAR(Int, cl_gfxlocalization)
void M_SetMenu(FName menu, int param)
@ -420,7 +420,7 @@ void M_SetMenu(FName menu, int param)
{
menu = NAME_MainmenuTextOnly;
}
else
else if (cl_gfxlocalization != 0 && !gameinfo.forcenogfxsubstitution)
{
// For these games we must check up-front if they get localized because in that case another template must be used.
DMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Mainmenu);
@ -429,7 +429,7 @@ void M_SetMenu(FName menu, int param)
if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor)))
{
DListMenuDescriptor *ld = static_cast<DListMenuDescriptor*>(*desc);
if (ld->mFromEngine && cl_localizationmode != 0)
if (ld->mFromEngine)
{
// This assumes that replacing one graphic will replace all of them.
// So this only checks the "New game" entry for localization capability.

View file

@ -74,10 +74,10 @@ private:
int LastAccessed = -1;
TArray<char> SavePicData;
FTexture *SavePic = nullptr;
TArray<FBrokenLines> SaveComment;
public:
int WindowSize = 0;
FString SaveCommentString;
FSaveGameNode *quickSaveSlot = nullptr;
~FSavegameManager();
@ -363,4 +363,6 @@ DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotk
DMenuItemBase * CreateListMenuItemText(double x, double y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param);
DMenuItemBase * CreateOptionMenuItemCommand(const char *label, FName cmd, bool centered = false);
void UpdateVRModes(bool considerQuadBuffered=true);
#endif

View file

@ -1724,3 +1724,31 @@ fail:
}
}
}
#ifdef _WIN32
EXTERN_CVAR(Bool, vr_enable_quadbuffered)
#endif
void UpdateVRModes(bool considerQuadBuffered)
{
FOptionValues ** pVRModes = OptionValues.CheckKey("VRMode");
if (pVRModes == nullptr) return;
TArray<FOptionValues::Pair> & vals = (*pVRModes)->mValues;
TArray<FOptionValues::Pair> filteredValues;
int cnt = vals.Size();
for (int i = 0; i < cnt; ++i) {
auto const & mode = vals[i];
if (mode.Value == 7) { // Quad-buffered stereo
#ifdef _WIN32
if (!vr_enable_quadbuffered) continue;
#else
continue; // Remove quad-buffered option on Mac and Linux
#endif
if (!considerQuadBuffered) continue; // Probably no compatible screen mode was found
}
filteredValues.Push(mode);
}
vals = filteredValues;
}

View file

@ -536,8 +536,6 @@
extern FILE *Logfile;
FRandom pr_acs ("ACS");
// I imagine this much stack space is probably overkill, but it could
@ -705,7 +703,7 @@ protected:
TObjPtr<AActor*> activator;
line_t *activationline;
bool backSide;
FFont *activefont;
FFont *activefont = nullptr;
int hudwidth, hudheight;
int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight;
int WrapWidth;
@ -774,7 +772,7 @@ protected:
private:
DLevelScript();
DLevelScript() = default;
friend class DACSThinker;
};
@ -3506,11 +3504,6 @@ void DLevelScript::Serialize(FSerializer &arc)
}
}
DLevelScript::DLevelScript ()
{
activefont = SmallFont;
}
void DLevelScript::Unlink ()
{
DACSThinker *controller = Level->ACSThinker;
@ -3924,10 +3917,6 @@ void DLevelScript::DoSetFont (int fontnum)
{
const char *fontname = Level->Behaviors.LookupString (fontnum);
activefont = V_GetFont (fontname);
if (activefont == NULL)
{
activefont = SmallFont;
}
}
int DLevelScript::DoSetMaster (AActor *self, AActor *master)
@ -8623,10 +8612,7 @@ scriptwait:
if (pcd == PCD_ENDPRINTBOLD || screen == NULL ||
screen->CheckLocalView())
{
if (pcd == PCD_ENDPRINTBOLD && (gameinfo.correctprintbold || (Level->flags2 & LEVEL2_HEXENHACK)))
C_MidPrintBold(activefont, work);
else
C_MidPrint (activefont, work);
C_MidPrint (activefont, work, pcd == PCD_ENDPRINTBOLD && (gameinfo.correctprintbold || (Level->flags2 & LEVEL2_HEXENHACK)));
}
STRINGBUILDER_FINISH(work);
}
@ -8676,17 +8662,18 @@ scriptwait:
color = CLAMPCOLOR(Stack[optstart-4]);
}
FFont *font = activefont ? activefont : SmallFont;
switch (type & 0xFF)
{
default: // normal
alpha = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 1.f;
msg = Create<DHUDMessage> (activefont, work, x, y, hudwidth, hudheight, color, holdTime);
msg = Create<DHUDMessage> (font, work, x, y, hudwidth, hudheight, color, holdTime);
break;
case 1: // fade out
{
float fadeTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.5f;
alpha = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 1.f;
msg = Create<DHUDMessageFadeOut> (activefont, work, x, y, hudwidth, hudheight, color, holdTime, fadeTime);
msg = Create<DHUDMessageFadeOut> (font, work, x, y, hudwidth, hudheight, color, holdTime, fadeTime);
}
break;
case 2: // type on, then fade out
@ -8694,7 +8681,7 @@ scriptwait:
float typeTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.05f;
float fadeTime = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 0.5f;
alpha = (optstart < sp-2) ? ACSToFloat(Stack[optstart+2]) : 1.f;
msg = Create<DHUDMessageTypeOnFadeOut> (activefont, work, x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime);
msg = Create<DHUDMessageTypeOnFadeOut> (font, work, x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime);
}
break;
case 3: // fade in, then fade out
@ -8702,7 +8689,7 @@ scriptwait:
float inTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.5f;
float outTime = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 0.5f;
alpha = (optstart < sp-2) ? ACSToFloat(Stack[optstart + 2]) : 1.f;
msg = Create<DHUDMessageFadeInOut> (activefont, work, x, y, hudwidth, hudheight, color, holdTime, inTime, outTime);
msg = Create<DHUDMessageFadeInOut> (font, work, x, y, hudwidth, hudheight, color, holdTime, inTime, outTime);
}
break;
}
@ -8728,17 +8715,8 @@ scriptwait:
(type & HUDMSG_LAYER_MASK) >> HUDMSG_LAYER_SHIFT);
if (type & HUDMSG_LOG)
{
static const char bar[] = TEXTCOLOR_ORANGE "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_NORMAL "\n";
char consolecolor[3];
consolecolor[0] = '\x1c';
consolecolor[1] = color >= CR_BRICK && color <= CR_YELLOW ? color + 'A' : '-';
consolecolor[2] = '\0';
AddToConsole (-1, bar);
AddToConsole (-1, consolecolor);
AddToConsole (-1, work);
AddToConsole (-1, bar);
int consolecolor = color >= CR_BRICK && color <= CR_YELLOW ? color + 'A' : '-';
Printf(PRINT_NONOTIFY, "\n" TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", consolecolor, console_bar, work.GetChars(), console_bar);
}
}
}
@ -10286,7 +10264,6 @@ DLevelScript::DLevelScript (FLevelLocals *l, AActor *who, line_t *where, int num
activator = who;
activationline = where;
backSide = flags & ACS_BACKSIDE;
activefont = SmallFont;
hudwidth = hudheight = 0;
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
HandleAspect = true;

View file

@ -1309,7 +1309,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Print)
con_midtime = float(time);
}
FString formatted = strbin1(text);
C_MidPrint(font != NULL ? font : SmallFont, formatted.GetChars());
C_MidPrint(font, formatted.GetChars());
con_midtime = saved;
}
return 0;
@ -1341,7 +1341,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PrintBold)
con_midtime = float(time);
}
FString formatted = strbin1(text);
C_MidPrintBold(font != NULL ? font : SmallFont, formatted.GetChars());
C_MidPrint(font, formatted.GetChars(), true);
con_midtime = saved;
return 0;
}

View file

@ -695,8 +695,7 @@ static void TerminalResponse (const char *str)
if (StatusBar != NULL)
{
AddToConsole(-1, str);
AddToConsole(-1, "\n");
Printf(PRINT_NONOTIFY, "%s\n", str);
// The message is positioned a bit above the menu choices, because
// merchants can tell you something like this but continue to show
// their dialogue screen. I think most other conversations use this

View file

@ -98,7 +98,7 @@ CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO)
CVAR(Bool, cl_doautoaim, false, CVAR_ARCHIVE)
static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, DVector2 * posforwindowcheck = NULL);
static void SpawnShootDecal(AActor *t1, const FTraceResults &trace);
static void SpawnShootDecal(AActor *t1, AActor *defaults, const FTraceResults &trace);
static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff);
static FRandom pr_tracebleed("TraceBleed");
@ -4566,20 +4566,20 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
{
// [ZK] If puff has FORCEDECAL set, do not use the weapon's decal
if (puffDefaults->flags7 & MF7_FORCEDECAL && puff != NULL && puff->DecalGenerator)
SpawnShootDecal(puff, trace);
SpawnShootDecal(puff, puff, trace);
else
SpawnShootDecal(t1, trace);
SpawnShootDecal(t1, t1, trace);
}
// Else, look if the bulletpuff has a decal defined.
else if (puff != NULL && puff->DecalGenerator)
{
SpawnShootDecal(puff, trace);
SpawnShootDecal(puff, puff, trace);
}
else
{
SpawnShootDecal(t1, trace);
SpawnShootDecal(t1, t1, trace);
}
}
else if (puff != NULL &&
@ -5266,9 +5266,9 @@ void P_RailAttack(FRailParams *p)
puff->Destroy();
}
if (puffDefaults != nullptr && puffDefaults->flags7 & MF7_FORCEDECAL && puffDefaults->DecalGenerator)
SpawnShootDecal(puffDefaults, trace);
SpawnShootDecal(source, puffDefaults, trace);
else
SpawnShootDecal(source, trace);
SpawnShootDecal(source, source, trace);
}
if (trace.HitType == TRACE_HitFloor || trace.HitType == TRACE_HitCeiling)
@ -6744,19 +6744,19 @@ bool P_ChangeSector(sector_t *sector, int crunch, double amt, int floorOrCeil, b
//
//==========================================================================
void SpawnShootDecal(AActor *t1, const FTraceResults &trace)
void SpawnShootDecal(AActor *t1, AActor *defaults, const FTraceResults &trace)
{
FDecalBase *decalbase = NULL;
FDecalBase *decalbase = nullptr;
if (t1->player != NULL && t1->player->ReadyWeapon != NULL)
if (defaults->player != nullptr && defaults->player->ReadyWeapon != nullptr)
{
decalbase = t1->player->ReadyWeapon->DecalGenerator;
decalbase = defaults->player->ReadyWeapon->DecalGenerator;
}
else
{
decalbase = t1->DecalGenerator;
decalbase = defaults->DecalGenerator;
}
if (decalbase != NULL)
if (decalbase != nullptr)
{
DImpactDecal::StaticCreate(t1->Level, decalbase->GetDecal(),
trace.HitPos, trace.Line->sidedef[trace.Side], trace.ffloor);

View file

@ -813,8 +813,7 @@ void FLevelLocals::CopyPlayer(player_t *dst, player_t *src, const char *name)
bool attackdown = dst->attackdown;
bool usedown = dst->usedown;
*dst = *src; // To avoid memory leaks at this point the userinfo in src must be empty which is taken care of by the TransferFrom call above.
dst->CopyFrom(*src, true); // To avoid memory leaks at this point the userinfo in src must be empty which is taken care of by the TransferFrom call above.
dst->cheats |= chasecam;
@ -857,9 +856,6 @@ void FLevelLocals::CopyPlayer(player_t *dst, player_t *src, const char *name)
pspr = pspr->Next;
}
// Don't let the psprites be destroyed when src is destroyed.
src->psprites = nullptr;
// These 2 variables may not be overwritten.
dst->attackdown = attackdown;
dst->usedown = usedown;

View file

@ -592,12 +592,12 @@ void P_GiveSecret(FLevelLocals *Level, AActor *actor, bool printmessage, bool pl
{
if (printmessage)
{
if (!showsecretsector || sectornum < 0) C_MidPrint(SmallFont, GStrings["SECRETMESSAGE"]);
if (!showsecretsector || sectornum < 0) C_MidPrint(nullptr, GStrings["SECRETMESSAGE"]);
else
{
FString s = GStrings["SECRETMESSAGE"];
s.AppendFormat(" (Sector %d)", sectornum);
C_MidPrint(SmallFont, s);
C_MidPrint(nullptr, s);
}
}
if (playsound) S_Sound (CHAN_AUTO | CHAN_UI, "misc/secret", 1, ATTN_NORM);

View file

@ -259,7 +259,7 @@ player_t::~player_t()
DestroyPSprites();
}
player_t &player_t::operator=(const player_t &p)
void player_t::CopyFrom(player_t &p, bool copyPSP)
{
mo = p.mo;
playerstate = p.playerstate;
@ -312,7 +312,6 @@ player_t &player_t::operator=(const player_t &p)
extralight = p.extralight;
fixedcolormap = p.fixedcolormap;
fixedlightlevel = p.fixedlightlevel;
psprites = p.psprites;
morphTics = p.morphTics;
MorphedPlayerClass = p.MorphedPlayerClass;
MorphStyle = p.MorphStyle;
@ -346,7 +345,12 @@ player_t &player_t::operator=(const player_t &p)
ConversationFaceTalker = p.ConversationFaceTalker;
MUSINFOactor = p.MUSINFOactor;
MUSINFOtics = p.MUSINFOtics;
return *this;
if (copyPSP)
{
// This needs to transfer ownership completely.
psprites = p.psprites;
p.psprites = nullptr;
}
}
size_t player_t::PropagateMark()
@ -422,9 +426,7 @@ void player_t::SetLogText (const char *text)
if (mo && mo->CheckLocalView())
{
// Print log text to console
AddToConsole(-1, TEXTCOLOR_GOLD);
AddToConsole(-1, LogText[0] == '$'? GStrings(text+1) : text );
AddToConsole(-1, "\n");
Printf(PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings(text + 1) : text);
}
}
@ -1369,7 +1371,7 @@ void P_PredictPlayer (player_t *player)
}
// Save original values for restoration later
PredictionPlayerBackup = *player;
PredictionPlayerBackup.CopyFrom(*player, false);
auto act = player->mo;
PredictionActor = player->mo;
@ -1494,7 +1496,7 @@ void P_UnPredictPlayer ()
int inventorytics = player->inventorytics;
const bool settings_controller = player->settings_controller;
*player = PredictionPlayerBackup;
player->CopyFrom(PredictionPlayerBackup, false);
player->settings_controller = settings_controller;
// Restore the camera instead of using the backup's copy, because spynext/prev

View file

@ -68,21 +68,6 @@ ticcmd_t* I_BaseTiccmd()
//
// SetLanguageIDs
//
void SetLanguageIDs()
{
size_t langlen = strlen(language);
uint32_t lang = (langlen < 2 || langlen > 3)
? MAKE_ID('e', 'n', 'u', '\0')
: MAKE_ID(language[0], language[1], language[2], '\0');
LanguageIDs[3] = LanguageIDs[2] = LanguageIDs[1] = LanguageIDs[0] = lang;
}
double PerfToSec, PerfToMillisec;
static void CalculateCPUSpeed()
@ -180,7 +165,7 @@ void I_Error (const char *error, ...)
va_start(argptr, error);
vsprintf (errortext, error, argptr);
myvsnprintf (errortext, MAX_ERRORTEXT, error, argptr);
va_end (argptr);
throw CRecoverableError(errortext);
}

View file

@ -294,8 +294,6 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void*, const bool fullscreen)
, m_hiDPI(false)
, m_window(CreateWindow(STYLE_MASK_WINDOWED))
{
SetFlash(0, 0);
NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat();
if (nil == pixelFormat)

View file

@ -45,16 +45,6 @@ struct WadStuff;
#define SHARE_DIR "/usr/local/share/"
#endif
// Index values into the LanguageIDs array
enum
{
LANGIDX_UserPreferred,
LANGIDX_UserDefault,
LANGIDX_SysPreferred,
LANGIDX_SysDefault
};
extern uint32_t LanguageIDs[4];
extern void SetLanguageIDs ();
// Called by DoomMain.
void I_Init (void);

View file

@ -149,11 +149,11 @@ void I_SetFPSLimit(int limit)
{
FPSLimitTimerEnabled = true;
if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1)
Printf(DMSG_WARNING, "Failed to create FPS limitter event\n");
Printf(DMSG_WARNING, "Failed to create FPS limiter event\n");
itimerspec period = { {0, 0}, {0, 0} };
period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit;
if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1)
Printf(DMSG_WARNING, "Failed to set FPS limitter timer\n");
Printf(DMSG_WARNING, "Failed to set FPS limiter timer\n");
DPrintf(DMSG_NOTIFY, "FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000);
}
}

View file

@ -92,20 +92,6 @@ void I_EndRead(void)
}
//
// SetLanguageIDs
//
void SetLanguageIDs ()
{
size_t langlen = strlen(language);
uint32_t lang = (langlen < 2 || langlen > 3) ?
MAKE_ID('e','n','u','\0') :
MAKE_ID(language[0],language[1],language[2],'\0');
LanguageIDs[3] = LanguageIDs[2] = LanguageIDs[1] = LanguageIDs[0] = lang;
}
//
// I_Init
//
@ -229,7 +215,7 @@ void I_Error (const char *error, ...)
va_start(argptr, error);
vsprintf (errortext, error, argptr);
myvsnprintf (errortext, MAX_ERRORTEXT, error, argptr);
va_end (argptr);
throw CRecoverableError(errortext);
}

View file

@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <ctype.h>
#include "m_swap.h"
#include "m_argv.h"

View file

@ -223,9 +223,9 @@ void R_SetWindow (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, int wind
else
{
viewwindow.WidescreenRatio = ActiveRatio(fullWidth, fullHeight);
DrawFSHUD = (windowSize == 11);
}
DrawFSHUD = (windowSize == 11);
// [RH] Sky height fix for screens not 200 (or 240) pixels tall
R_InitSkyMap ();

View file

@ -87,6 +87,28 @@ int GetUIScale(int altval)
return MAX(1,MIN(scaleval, max));
}
// The new console font is twice as high, so the scaling calculation must factor that in.
int GetConScale(int altval)
{
int scaleval;
if (altval > 0) scaleval = altval;
else if (uiscale == 0)
{
// Default should try to scale to 640x400
int vscale = screen->GetHeight() / 800;
int hscale = screen->GetWidth() / 1280;
scaleval = clamp(vscale, 1, hscale);
}
else scaleval = uiscale / 2;
// block scales that result in something larger than the current screen.
int vmax = screen->GetHeight() / 400;
int hmax = screen->GetWidth() / 640;
int max = MAX(vmax, hmax);
return MAX(1, MIN(scaleval, max));
}
// [RH] Stretch values to make a 320x200 image best fit the screen
// without using fractional steppings
int CleanXfac, CleanYfac;
@ -1351,12 +1373,13 @@ void DFrameBuffer::DrawBorder (FTextureID picnum, int x1, int y1, int x2, int y2
}
}
///==========================================================================
//==========================================================================
//
// Draws a blend over the entire view
//
//==========================================================================
void DFrameBuffer::DrawBlend(sector_t * viewsector)
FVector4 DFrameBuffer::CalcBlend(sector_t * viewsector, PalEntry *modulateColor)
{
float blend[4] = { 0,0,0,0 };
PalEntry blendv = 0;
@ -1366,6 +1389,8 @@ void DFrameBuffer::DrawBlend(sector_t * viewsector)
player_t *player = nullptr;
bool fullbright = false;
if (modulateColor) *modulateColor = 0xffffffff;
if (players[consoleplayer].camera != nullptr)
{
player = players[consoleplayer].camera->player;
@ -1427,7 +1452,7 @@ void DFrameBuffer::DrawBlend(sector_t * viewsector)
// black multiplicative blends are ignored
if (extra_red || extra_green || extra_blue)
{
screen->Dim(blendv, 1, 0, 0, screen->GetWidth(), screen->GetHeight(), &LegacyRenderStyles[STYLE_Multiply]);
if (modulateColor) *modulateColor = blendv;
}
blendv = 0;
}
@ -1452,7 +1477,7 @@ void DFrameBuffer::DrawBlend(sector_t * viewsector)
if (in->IsKindOf(torchtype))
{
// The software renderer already bakes the torch flickering into its output, so this must be omitted here.
float r = vid_rendermode < 4? 1.f : (0.8f + (7 - player->fixedlightlevel) / 70.0f);
float r = vid_rendermode < 4 ? 1.f : (0.8f + (7 - player->fixedlightlevel) / 70.0f);
if (r > 1.0f) r = 1.0f;
int rr = (int)(r * 255);
int b = rr;
@ -1467,9 +1492,9 @@ void DFrameBuffer::DrawBlend(sector_t * viewsector)
}
}
}
if (color != 0xffffffff)
if (modulateColor)
{
screen->Dim(color, 1, 0, 0, screen->GetWidth(), screen->GetHeight(), &LegacyRenderStyles[STYLE_Multiply]);
*modulateColor = color;
}
}
@ -1488,8 +1513,26 @@ void DFrameBuffer::DrawBlend(sector_t * viewsector)
const float br = clamp(blend[0] * 255.f, 0.f, 255.f);
const float bg = clamp(blend[1] * 255.f, 0.f, 255.f);
const float bb = clamp(blend[2] * 255.f, 0.f, 255.f);
const PalEntry bcolor(255, uint8_t(br), uint8_t(bg), uint8_t(bb));
screen->Dim(bcolor, blend[3], 0, 0, screen->GetWidth(), screen->GetHeight());
return { br, bg, bb, blend[3] };
}
//==========================================================================
//
// Draws a blend over the entire view
//
//==========================================================================
void DFrameBuffer::DrawBlend(sector_t * viewsector)
{
PalEntry modulateColor;
auto blend = CalcBlend(viewsector, &modulateColor);
if (modulateColor != 0xffffffff)
{
Dim(modulateColor, 1, 0, 0, GetWidth(), GetHeight(), &LegacyRenderStyles[STYLE_Multiply]);
}
const PalEntry bcolor(255, uint8_t(blend.X), uint8_t(blend.Y), uint8_t(blend.Z));
Dim(bcolor, blend.W, 0, 0, GetWidth(), GetHeight());
}

View file

@ -38,6 +38,7 @@
#include <wctype.h>
#include "v_text.h"
#include "utf8.h"
#include "v_video.h"
@ -248,10 +249,14 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawChar)
//
//==========================================================================
void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms)
// This is only needed as a dummy. The code using wide strings does not need color control.
EColorRange V_ParseFontColor(const char32_t *&color_value, int normalcolor, int boldcolor) { return CR_UNTRANSLATED; }
template<class chartype>
void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double y, const chartype *string, DrawParms &parms)
{
int w;
const uint8_t *ch;
const chartype *ch;
int c;
double cx;
double cy;
@ -274,13 +279,13 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
kerning = font->GetDefaultKerning();
ch = (const uint8_t *)string;
ch = string;
cx = x;
cy = y;
auto currentcolor = normalcolor;
while ((const char *)ch - string < parms.maxstrlen)
while (ch - string < parms.maxstrlen)
{
c = GetCharFromString(ch);
if (!c)
@ -327,6 +332,24 @@ void DFrameBuffer::DrawText(FFont *font, int normalcolor, double x, double y, co
Va_List tags;
DrawParms parms;
if (font == NULL || string == NULL)
return;
va_start(tags.list, tag_first);
bool res = ParseDrawTextureTags(nullptr, 0, 0, tag_first, tags, &parms, true);
va_end(tags.list);
if (!res)
{
return;
}
DrawTextCommon(font, normalcolor, x, y, (const uint8_t*)string, parms);
}
void DFrameBuffer::DrawText(FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...)
{
Va_List tags;
DrawParms parms;
if (font == NULL || string == NULL)
return;
@ -353,13 +376,13 @@ void DFrameBuffer::DrawText(FFont *font, int normalcolor, double x, double y, co
{
return;
}
DrawTextCommon(font, normalcolor, x, y, string, parms);
DrawTextCommon(font, normalcolor, x, y, (const uint8_t*)string, parms);
}
DEFINE_ACTION_FUNCTION(_Screen, DrawText)
{
PARAM_PROLOGUE;
PARAM_POINTER(font, FFont);
PARAM_POINTER_NOT_NULL(font, FFont);
PARAM_INT(cr);
PARAM_FLOAT(x);
PARAM_FLOAT(y);

View file

@ -121,20 +121,11 @@ void FGLRenderer::BlurScene(float gameinfobluramount)
mBuffers->UpdateEffectTextures();
auto vrmode = VRMode::GetVRMode(true);
if (vrmode->mEyeCount == 1)
int eyeCount = vrmode->mEyeCount;
for (int i = 0; i < eyeCount; ++i)
{
mBuffers->RenderEffect("BlurScene");
}
else
{
for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix)
{
FGLDebug::PushGroup("EyeBlur");
mBuffers->BlitFromEyeTexture(eye_ix);
mBuffers->RenderEffect("BlurScene");
mBuffers->BlitToEyeTexture(eye_ix);
FGLDebug::PopGroup();
}
if (eyeCount - i > 1) mBuffers->NextEye(eyeCount);
}
}
@ -159,13 +150,12 @@ void FGLRenderer::Flush()
else
{
// Render 2D to eye textures
for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix)
int eyeCount = vrmode->mEyeCount;
for (int eye_ix = 0; eye_ix < eyeCount; ++eye_ix)
{
FGLDebug::PushGroup("Eye2D");
mBuffers->BlitFromEyeTexture(eye_ix);
screen->Draw2D();
mBuffers->BlitToEyeTexture(eye_ix);
FGLDebug::PopGroup();
if (eyeCount - eye_ix > 1)
mBuffers->NextEye(eyeCount);
}
screen->Clear2D();

View file

@ -532,7 +532,7 @@ void FGLRenderBuffers::BlitSceneToTexture()
//
//==========================================================================
void FGLRenderBuffers::BlitToEyeTexture(int eye)
void FGLRenderBuffers::BlitToEyeTexture(int eye, bool allowInvalidate)
{
CreateEyeBuffers(eye);
@ -540,7 +540,7 @@ void FGLRenderBuffers::BlitToEyeTexture(int eye)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mEyeFBs[eye].handle);
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
if ((gl.flags & RFL_INVALIDATE_BUFFER) != 0)
if ((gl.flags & RFL_INVALIDATE_BUFFER) != 0 && allowInvalidate)
{
GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, attachments);
@ -552,7 +552,7 @@ void FGLRenderBuffers::BlitToEyeTexture(int eye)
void FGLRenderBuffers::BlitFromEyeTexture(int eye)
{
CreateEyeBuffers(eye);
if (mEyeFBs.Size() <= unsigned(eye)) return;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mPipelineFB[mCurrentPipelineTexture].handle);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mEyeFBs[eye].handle);
@ -1002,4 +1002,17 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
FGLDebug::PopGroup();
}
// Store the current stereo 3D eye buffer, and Load the next one
int FGLRenderBuffers::NextEye(int eyeCount)
{
int nextEye = (mCurrentEye + 1) % eyeCount;
if (nextEye == mCurrentEye) return mCurrentEye;
BlitToEyeTexture(mCurrentEye);
mCurrentEye = nextEye;
BlitFromEyeTexture(mCurrentEye);
return mCurrentEye;
}
} // namespace OpenGLRenderer

View file

@ -87,9 +87,11 @@ public:
void BindOutputFB();
void BlitToEyeTexture(int eye);
void BlitToEyeTexture(int eye, bool allowInvalidate=true);
void BlitFromEyeTexture(int eye);
void BindEyeTexture(int eye, int texunit);
int NextEye(int eyeCount);
int & CurrentEye() { return mCurrentEye; }
void BindDitherTexture(int texunit);
@ -156,6 +158,7 @@ private:
// Eye buffers
TArray<PPGLTexture> mEyeTextures;
TArray<PPGLFrameBuffer> mEyeFBs;
int mCurrentEye = 0;
// Shadow map texture
PPGLTexture mShadowMapTexture;

View file

@ -67,6 +67,8 @@ EXTERN_CVAR(Bool, cl_capfps)
extern bool NoInterpolateView;
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown);
namespace OpenGLRenderer
{
@ -370,9 +372,11 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers
glFinish();
uint8_t * scr = (uint8_t *)M_Malloc(width * height * 3);
int numpixels = width * height;
uint8_t * scr = (uint8_t *)M_Malloc(numpixels * 3);
glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr);
M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width * 3, Gamma);
DoWriteSavePic(file, SS_RGB, scr, width, height, viewsector, true);
M_Free(scr);
// Switch back the screen render buffers

View file

@ -138,7 +138,7 @@ bool FGLRenderState::ApplyShader()
activeShader->muLightIndex.Set(-1);
activeShader->muClipSplit.Set(mClipSplit);
activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel);
activeShader->muAddColor.Set(mAddColor); // Can this be done without a shader?
activeShader->muAddColor.Set(mAddColor);
if (mGlowEnabled)
{

View file

@ -111,12 +111,12 @@ void FGLRenderer::DrawScene(HWDrawInfo *di, int drawmode)
if (vp.camera != nullptr)
{
ActorRenderFlags savedflags = vp.camera->renderflags;
di->CreateScene();
di->CreateScene(drawmode == DM_MAINVIEW);
vp.camera->renderflags = savedflags;
}
else
{
di->CreateScene();
di->CreateScene(false);
}
glDepthMask(true);
@ -163,9 +163,11 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
// Render (potentially) multiple views for stereo 3d
// Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode.
auto vrmode = VRMode::GetVRMode(mainview && toscreen);
for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix)
const int eyeCount = vrmode->mEyeCount;
mBuffers->CurrentEye() = 0; // always begin at zero, in case eye count changed
for (int eye_ix = 0; eye_ix < eyeCount; ++eye_ix)
{
const auto &eye = vrmode->mEyes[eye_ix];
const auto &eye = vrmode->mEyes[mBuffers->CurrentEye()];
screen->SetViewportRects(bounds);
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
@ -218,8 +220,8 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
PostProcess.Unclock();
}
di->EndDrawInfo();
if (vrmode->mEyeCount > 1)
mBuffers->BlitToEyeTexture(eye_ix);
if (eyeCount - eye_ix > 1)
mBuffers->NextEye(eyeCount);
}
return mainvp.sector;

View file

@ -34,6 +34,7 @@
#include "gl/system/gl_framebuffer.h"
#include "hwrenderer/postprocessing/hw_presentshader.h"
#include "hwrenderer/postprocessing/hw_present3dRowshader.h"
#include "menu/menu.h"
EXTERN_CVAR(Int, vr_mode)
EXTERN_CVAR(Float, vid_saturation)
@ -283,6 +284,8 @@ bool FGLRenderer::QuadStereoCheckInitialRenderContextState()
// Now check whether this context supports hardware stereo
glGetBooleanv(GL_STEREO, &supportsStereo);
bQuadStereoSupported = supportsStereo && supportsBuffered;
if (! bQuadStereoSupported)
UpdateVRModes(false);
}
}
return bQuadStereoSupported;
@ -324,6 +327,12 @@ void FGLRenderer::PresentQuadStereo()
void FGLRenderer::PresentStereo()
{
auto vrmode = VRMode::GetVRMode(true);
const int eyeCount = vrmode->mEyeCount;
// Don't invalidate the bound framebuffer (..., false)
if (eyeCount > 1)
mBuffers->BlitToEyeTexture(mBuffers->CurrentEye(), false);
switch (vr_mode)
{
default:

View file

@ -58,6 +58,7 @@ void GLViewpointBuffer::CheckSize()
mBufferSize *= 2;
mByteSize *= 2;
mBuffer->Resize(mByteSize);
m2DHeight = m2DWidth = -1;
}
}

View file

@ -59,6 +59,7 @@ public:
void BindBase()
{
mBuffer->BindBase();
mLastMappedIndex = UINT_MAX;
}
};

View file

@ -796,7 +796,7 @@ void HWDrawInfo::RenderBSPNode (void *node)
DoSubsector ((subsector_t *)((uint8_t *)node - 1));
}
void HWDrawInfo::RenderBSP(void *node)
void HWDrawInfo::RenderBSP(void *node, bool drawpsprites)
{
Bsp.Clock();
@ -829,6 +829,6 @@ void HWDrawInfo::RenderBSP(void *node)
// Process all the sprites on the current portal's back side which touch the portal.
if (mCurrentPortal != nullptr) mCurrentPortal->RenderAttached(this);
if (drawpsprites)
PreparePlayerSprites(Viewpoint.sector, in_area);
}

View file

@ -421,7 +421,7 @@ GLDecal *HWDrawInfo::AddDecal(bool onmirror)
//
//-----------------------------------------------------------------------------
void HWDrawInfo::CreateScene()
void HWDrawInfo::CreateScene(bool drawpsprites)
{
const auto &vp = Viewpoint;
angle_t a1 = FrustumAngle();
@ -436,7 +436,7 @@ void HWDrawInfo::CreateScene()
screen->mVertexData->Map();
screen->mLights->Map();
RenderBSP(Level->HeadNode());
RenderBSP(Level->HeadNode(), drawpsprites);
// And now the crappy hacks that have to be done to avoid rendering anomalies.
// These cannot be multithreaded when the time comes because all these depend

View file

@ -237,7 +237,7 @@ public:
HWPortal * FindPortal(const void * src);
void RenderBSPNode(void *node);
void RenderBSP(void *node);
void RenderBSP(void *node, bool drawpsprites);
static HWDrawInfo *StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
void StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
@ -246,7 +246,7 @@ public:
void SetViewArea();
int SetFullbrightFlags(player_t *player);
void CreateScene();
void CreateScene(bool drawpsprites);
void RenderScene(FRenderState &state);
void RenderTranslucent(FRenderState &state);
void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil);

View file

@ -155,7 +155,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
{
state.SetTextureMode(TM_FIXEDCOLORMAP);
state.SetObjectColor(cmd.mSpecialColormap[0]);
state.SetObjectColor2(cmd.mSpecialColormap[1]);
state.SetAddColor(cmd.mSpecialColormap[1]);
}
state.SetFog(cmd.mColor1, 0);
state.SetColor(1, 1, 1, 1, cmd.mDesaturate);

View file

@ -68,7 +68,7 @@ void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuff
RenderTarget = target;
RenderToCanvas = false;
RenderActorView(player->mo, false);
RenderActorView(player->mo, true, false);
Threads.MainThread()->FlushDrawQueue();
@ -102,7 +102,7 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int
viewactive = true;
// Render:
RenderActorView(actor, dontmaplines);
RenderActorView(actor, false, dontmaplines);
Threads.MainThread()->FlushDrawQueue();
DrawerThreads::WaitForWorkers();
@ -119,7 +119,7 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int
RenderTarget = savedRenderTarget;
}
void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
void PolyRenderer::RenderActorView(AActor *actor, bool drawpsprites, bool dontmaplines)
{
PolyTotalBatches = 0;
PolyTotalTriangles = 0;
@ -181,7 +181,9 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
mainViewpoint.StencilValue = GetNextStencilValue();
Scene.CurrentViewpoint = &mainViewpoint;
Scene.Render(&mainViewpoint);
if (drawpsprites)
PlayerSprites.Render(Threads.MainThread());
Scene.CurrentViewpoint = nullptr;
if (Viewpoint.camera)

View file

@ -71,7 +71,7 @@ public:
FLevelLocals *Level;
private:
void RenderActorView(AActor *actor, bool dontmaplines);
void RenderActorView(AActor *actor, bool drawpsprites, bool dontmaplines);
void SetSceneViewport();
RenderPolyPlayerSprites PlayerSprites;

View file

@ -208,10 +208,11 @@ void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *vide
});
}
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown);
void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
{
DCanvas pic(width, height, false);
PalEntry palette[256];
// Take a snapshot of the player's view
if (V_IsPolyRenderer())
@ -230,8 +231,7 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi
r_viewpoint = mScene.MainThread()->Viewport->viewpoint;
r_viewwindow = mScene.MainThread()->Viewport->viewwindow;
}
screen->GetFlashedPalette (palette);
M_CreatePNG (file, pic.GetPixels(), palette, SS_PAL, width, height, pic.GetPitch(), Gamma);
DoWriteSavePic(file, SS_PAL, pic.GetPixels(), width, height, r_viewpoint.sector, false);
}
void FSoftwareRenderer::DrawRemainingPlayerSprites()

View file

@ -129,7 +129,7 @@ namespace swrenderer
DrawerThreads::ResetDebugDrawPos();
}
RenderActorView(player->mo);
RenderActorView(player->mo, true, false);
auto copyqueue = std::make_shared<DrawerCommandQueue>(MainThread()->FrameMemory.get());
copyqueue->Push<MemcpyCommand>(videobuffer, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1);
@ -140,7 +140,7 @@ namespace swrenderer
DrawerWaitCycles.Unclock();
}
void RenderScene::RenderActorView(AActor *actor, bool dontmaplines)
void RenderScene::RenderActorView(AActor *actor, bool renderPlayerSprites, bool dontmaplines)
{
WallCycles.Reset();
PlaneCycles.Reset();
@ -180,6 +180,7 @@ namespace swrenderer
if (r_modelscene)
MainThread()->Viewport->SetupPolyViewport(MainThread());
if (renderPlayerSprites)
RenderPSprites();
MainThread()->Viewport->viewpoint.camera->renderflags = savedflags;
@ -384,7 +385,7 @@ namespace swrenderer
PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget);
// Render:
RenderActorView(actor, dontmaplines);
RenderActorView(actor, false, dontmaplines);
DrawerWaitCycles.Clock();
DrawerThreads::WaitForWorkers();
DrawerWaitCycles.Unclock();

View file

@ -56,7 +56,7 @@ namespace swrenderer
RenderThread *MainThread() { return Threads.front().get(); }
private:
void RenderActorView(AActor *actor, bool dontmaplines = false);
void RenderActorView(AActor *actor,bool renderplayersprite, bool dontmaplines);
void RenderThreadSlices();
void RenderThreadSlice(RenderThread *thread);
void RenderPSprites();

View file

@ -183,21 +183,21 @@ void S_NoiseDebug (void)
int y, color;
y = 32 * CleanYfac;
screen->DrawText (SmallFont, CR_YELLOW, 0, y, "*** SOUND DEBUG INFO ***", TAG_DONE);
y += 8;
screen->DrawText (NewConsoleFont, CR_YELLOW, 0, y, "*** SOUND DEBUG INFO ***", TAG_DONE);
y += NewConsoleFont->GetHeight();
screen->DrawText (SmallFont, CR_GOLD, 0, y, "name", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 70, y, "x", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 120, y, "y", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 170, y, "z", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 220, y, "vol", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 260, y, "dist", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 300, y, "chan", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 340, y, "pri", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 380, y, "flags", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 460, y, "aud", TAG_DONE);
screen->DrawText (SmallFont, CR_GOLD, 520, y, "pos", TAG_DONE);
y += 8;
screen->DrawText (NewConsoleFont, CR_GOLD, 0, y, "name", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 70, y, "x", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 120, y, "y", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 170, y, "z", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 220, y, "vol", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 260, y, "dist", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 300, y, "chan", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 340, y, "pri", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 380, y, "flags", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 460, y, "aud", TAG_DONE);
screen->DrawText (NewConsoleFont, CR_GOLD, 520, y, "pos", TAG_DONE);
y += NewConsoleFont->GetHeight();
if (Channels == NULL)
{
@ -220,52 +220,52 @@ void S_NoiseDebug (void)
// Name
Wads.GetLumpName (temp, S_sfx[chan->SoundID].lumpnum);
temp[8] = 0;
screen->DrawText (SmallFont, color, 0, y, temp, TAG_DONE);
screen->DrawText (NewConsoleFont, color, 0, y, temp, TAG_DONE);
if (!(chan->ChanFlags & CHAN_IS3D))
{
screen->DrawText(SmallFont, color, 70, y, "---", TAG_DONE); // X
screen->DrawText(SmallFont, color, 120, y, "---", TAG_DONE); // Y
screen->DrawText(SmallFont, color, 170, y, "---", TAG_DONE); // Z
screen->DrawText(SmallFont, color, 260, y, "---", TAG_DONE); // Distance
screen->DrawText(NewConsoleFont, color, 70, y, "---", TAG_DONE); // X
screen->DrawText(NewConsoleFont, color, 120, y, "---", TAG_DONE); // Y
screen->DrawText(NewConsoleFont, color, 170, y, "---", TAG_DONE); // Z
screen->DrawText(NewConsoleFont, color, 260, y, "---", TAG_DONE); // Distance
}
else
{
// X coordinate
mysnprintf(temp, countof(temp), "%.0f", origin.X);
screen->DrawText(SmallFont, color, 70, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 70, y, temp, TAG_DONE);
// Y coordinate
mysnprintf(temp, countof(temp), "%.0f", origin.Z);
screen->DrawText(SmallFont, color, 120, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 120, y, temp, TAG_DONE);
// Z coordinate
mysnprintf(temp, countof(temp), "%.0f", origin.Y);
screen->DrawText(SmallFont, color, 170, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 170, y, temp, TAG_DONE);
// Distance
if (chan->DistanceScale > 0)
{
mysnprintf(temp, countof(temp), "%.0f", (origin - listener).Length());
screen->DrawText(SmallFont, color, 260, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 260, y, temp, TAG_DONE);
}
else
{
screen->DrawText(SmallFont, color, 260, y, "---", TAG_DONE);
screen->DrawText(NewConsoleFont, color, 260, y, "---", TAG_DONE);
}
}
// Volume
mysnprintf(temp, countof(temp), "%.2g", chan->Volume);
screen->DrawText(SmallFont, color, 220, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 220, y, temp, TAG_DONE);
// Channel
mysnprintf(temp, countof(temp), "%d", chan->EntChannel);
screen->DrawText(SmallFont, color, 300, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 300, y, temp, TAG_DONE);
// Priority
mysnprintf(temp, countof(temp), "%d", chan->Priority);
screen->DrawText(SmallFont, color, 340, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 340, y, temp, TAG_DONE);
// Flags
mysnprintf(temp, countof(temp), "%s3%sZ%sU%sM%sN%sA%sL%sE%sV",
@ -278,18 +278,18 @@ void S_NoiseDebug (void)
(chan->ChanFlags & CHAN_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK);
screen->DrawText(SmallFont, color, 380, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 380, y, temp, TAG_DONE);
// Audibility
mysnprintf(temp, countof(temp), "%.4f", GSnd->GetAudibility(chan));
screen->DrawText(SmallFont, color, 460, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 460, y, temp, TAG_DONE);
// Position
mysnprintf(temp, countof(temp), "%u", GSnd->GetPosition(chan));
screen->DrawText(SmallFont, color, 520, y, temp, TAG_DONE);
screen->DrawText(NewConsoleFont, color, 520, y, temp, TAG_DONE);
y += 8;
y += NewConsoleFont->GetHeight();
if (chan->PrevChan == &Channels)
{
break;

View file

@ -7343,6 +7343,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
auto parentfield = static_cast<FxMemberBase *>(Array)->membervar;
SizeAddr = parentfield->Offset + sizeof(void*);
}
else if (Array->ExprType == EFX_ArrayElement)
{
SizeAddr = ~0u;
}
else
{
ScriptPosition.Message(MSG_ERROR, "Invalid resizable array");
@ -7415,6 +7419,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
ExpEmit arrayvar = Array->Emit(build);
ExpEmit start;
ExpEmit bound;
bool nestedarray = false;
if (SizeAddr != ~0u)
{
@ -7425,20 +7430,44 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
auto f = Create<PField>(NAME_None, TypeUInt32, ismeta? VARF_Meta : 0, SizeAddr);
static_cast<FxMemberBase *>(Array)->membervar = f;
static_cast<FxMemberBase *>(Array)->AddressRequested = false;
auto arraymemberbase = static_cast<FxMemberBase *>(Array);
auto origmembervar = arraymemberbase->membervar;
auto origaddrreq = arraymemberbase->AddressRequested;
auto origvaluetype = Array->ValueType;
arraymemberbase->membervar = f;
arraymemberbase->AddressRequested = false;
Array->ValueType = TypeUInt32;
bound = Array->Emit(build);
arraymemberbase->membervar = origmembervar;
arraymemberbase->AddressRequested = origaddrreq;
Array->ValueType = origvaluetype;
}
else if (Array->ExprType == EFX_ArrayElement && Array->isStaticArray())
{
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
arrayvar.Free(build);
start = ExpEmit(build, REGT_POINTER);
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
bound = ExpEmit(build, REGT_INT);
build->Emit(OP_LW, bound.RegNum, arrayvar.RegNum, build->GetConstantInt(sizeof(void*)));
nestedarray = true;
}
else start = arrayvar;
if (index->isConstant())
{
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
assert(SizeAddr != ~0u || (indexval < arraytype->ElementCount && "Array index out of bounds"));
assert(SizeAddr != ~0u || nestedarray || (indexval < arraytype->ElementCount && "Array index out of bounds"));
// For resizable arrays we even need to check the bounds if if the index is constant because they are not known at compile time.
if (SizeAddr != ~0u)
if (SizeAddr != ~0u || nestedarray)
{
ExpEmit indexreg(build, REGT_INT);
build->EmitLoadInt(indexreg.RegNum, indexval);

View file

@ -2147,19 +2147,14 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FFont *&fon
{
if (arc.isWriting())
{
FName n = font->GetName();
FName n = font? font->GetName() : NAME_None;
return arc(key, n);
}
else
{
FName n = NAME_None;
arc(key, n);
font = V_GetFont(n);
if (font == nullptr)
{
Printf(TEXTCOLOR_ORANGE "Could not load font %s\n", n.GetChars());
font = SmallFont;
}
font = n == NAME_None? nullptr : V_GetFont(n);
return arc;
}

View file

@ -828,7 +828,7 @@ void cmsg(int type, int verbosity_level, const char *fmt, ...)
char buf[1024];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
myvsnprintf(buf, sizeof buf, fmt, args);
va_end(args);
I_DebugPrint(buf);
#endif

View file

@ -426,6 +426,7 @@ void FormatGUID (char *buffer, size_t buffsize, const GUID &guid)
const char *myasctime ()
{
static char readabletime[50];
time_t clock;
struct tm *lt;
@ -433,11 +434,12 @@ const char *myasctime ()
lt = localtime (&clock);
if (lt != NULL)
{
return asctime (lt);
strftime(readabletime, 50, "%F %T", lt);
return readabletime;
}
else
{
return "Pre Jan 01 00:00:00 1970\n";
return "Unknown\n";
}
}

View file

@ -1029,6 +1029,7 @@ xx(Kickback)
xx(MinSelAmmo1)
xx(bDehAmmo)
xx(FOVScale)
xx(LookScale)
xx(YAdjust)
xx(Crosshair)
xx(WeaponFlags)

View file

@ -87,7 +87,7 @@ void FStat::PrintStat ()
{
int textScale = active_con_scale();
int fontheight = ConFont->GetHeight() + 1;
int fontheight = NewConsoleFont->GetHeight() + 1;
int y = SCREENHEIGHT / textScale;
int count = 0;
@ -105,7 +105,7 @@ void FStat::PrintStat ()
// Count number of linefeeds but ignore terminating ones.
if (stattext[i] == '\n') y -= fontheight;
}
screen->DrawText(ConFont, CR_GREEN, 5 / textScale, y, stattext,
screen->DrawText(NewConsoleFont, CR_GREEN, 5 / textScale, y, stattext,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);

View file

@ -3,6 +3,10 @@
int utf8_encode(int32_t codepoint, uint8_t *buffer, int *size);
int utf8_decode(const uint8_t *src, int *size);
int GetCharFromString(const uint8_t *&string);
inline int GetCharFromString(const char32_t *&string)
{
return *string++;
}
const char *MakeUTF8(const char *outline, int *numchars = nullptr); // returns a pointer to a static buffer, assuming that its caller will immediately process the result.
const char *MakeUTF8(int codepoint, int *psize = nullptr);

View file

@ -66,7 +66,7 @@ zip_file_t *zip_fopen(zip_t *zipfile, const char *filename)
if (!zipfile || !filename) return NULL;
auto lump = zipfile->FindLump(filename);
if (!lump) return NULL;
return new FileReader(std::move(lump->NewReader()));
return new FileReader(lump->NewReader());
}
void zip_fclose(zip_file_t *zippedfile)

View file

@ -393,8 +393,8 @@ size_t FString::CharacterCount() const
int FString::GetNextCharacter(int &position) const
{
const uint8_t *cp = (const uint8_t*)Chars;
const uint8_t *cpread = cp + position;
const uint8_t *cp = (const uint8_t*)Chars + position;
const uint8_t *cpread = cp;
int chr = GetCharFromString(cpread);
position += int(cpread - cp);
return chr;
@ -828,12 +828,12 @@ void FString::StripLeftRight ()
if (max == 0) return;
for (i = 0; i < max; ++i)
{
if (!isspace((unsigned char)Chars[i]))
if (Chars[i] < 0 || !isspace((unsigned char)Chars[i]))
break;
}
for (j = max - 1; j >= i; --j)
{
if (!isspace((unsigned char)Chars[j]))
if (Chars[i] < 0 || !isspace((unsigned char)Chars[j]))
break;
}
if (i == 0 && j == max - 1)

View file

@ -202,11 +202,6 @@ void DFrameBuffer::DrawRateStuff ()
//
//==========================================================================
void DFrameBuffer::GetFlashedPalette(PalEntry pal[256])
{
DoBlending(SourcePalette, pal, 256, Flash.r, Flash.g, Flash.b, Flash.a);
}
void DFrameBuffer::Update()
{
CheckBench();
@ -225,24 +220,6 @@ void DFrameBuffer::Update()
}
}
PalEntry *DFrameBuffer::GetPalette()
{
return SourcePalette;
}
bool DFrameBuffer::SetFlash(PalEntry rgb, int amount)
{
Flash = PalEntry(amount, rgb.r, rgb.g, rgb.b);
return true;
}
void DFrameBuffer::GetFlash(PalEntry &rgb, int &amount)
{
rgb = Flash;
rgb.a = 0;
amount = Flash.a;
}
void DFrameBuffer::SetClearColor(int color)
{
PalEntry pe = GPalette.BaseColors[color];
@ -293,18 +270,6 @@ FTexture *DFrameBuffer::WipeEndScreen()
return nullptr;
}
//==========================================================================
//
// DFrameBuffer :: InitPalette
//
//==========================================================================
void DFrameBuffer::InitPalette()
{
memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256);
UpdatePalette();
}
//==========================================================================
//
// DFrameBuffer :: GetCaps

View file

@ -443,29 +443,6 @@ void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, in
}
}
void V_SetBlend (int blendr, int blendg, int blendb, int blenda)
{
// Don't do anything if the new blend is the same as the old
if (((blenda|BlendA) == 0) ||
(blendr == BlendR &&
blendg == BlendG &&
blendb == BlendB &&
blenda == BlendA))
return;
V_ForceBlend (blendr, blendg, blendb, blenda);
}
void V_ForceBlend (int blendr, int blendg, int blendb, int blenda)
{
BlendR = blendr;
BlendG = blendg;
BlendB = blendb;
BlendA = blenda;
screen->SetFlash (PalEntry (BlendR, BlendG, BlendB), BlendA);
}
CCMD (testblend)
{
FString colorstring;

View file

@ -77,23 +77,6 @@ void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, in
void ReadPalette(int lumpnum, uint8_t *buffer);
void InitPalette ();
// V_SetBlend()
// input: blendr: red component of blend
// blendg: green component of blend
// blendb: blue component of blend
// blenda: alpha component of blend
//
// Applies the blend to all palettes with PALETTEF_BLEND flag
void V_SetBlend (int blendr, int blendg, int blendb, int blenda);
// V_ForceBlend()
//
// Normally, V_SetBlend() does nothing if the new blend is the
// same as the old. This function will perform the blending
// even if the blend hasn't changed.
void V_ForceBlend (int blendr, int blendg, int blendb, int blenda);
EXTERN_CVAR (Int, paletteflash)
enum PaletteFlashFlags
{

View file

@ -145,7 +145,7 @@ public:
int DisplayWidth, DisplayHeight;
FFont *SmallFont, *SmallFont2, *BigFont, *BigUpper, *ConFont, *IntermissionFont;
FFont *SmallFont, *SmallFont2, *BigFont, *BigUpper, *ConFont, *IntermissionFont, *NewConsoleFont, *NewSmallFont, *CurrentConsoleFont;
uint32_t Col2RGB8[65][256];
uint32_t *Col2RGB8_LessPrecision[65];
@ -540,12 +540,9 @@ CCMD(clean)
void V_UpdateModeSize (int width, int height)
{
int cx1, cx2;
V_CalcCleanFacs(320, 200, width, height, &CleanXfac, &CleanYfac, &cx1, &cx2);
CleanWidth = width / CleanXfac;
CleanHeight = height / CleanYfac;
assert(CleanWidth >= 320 && CleanHeight >= 200);
// This calculates the menu scale.
// The optimal scale will always be to fit a virtual 640 pixel wide display onto the screen.
// Exceptions are made for a few ranges where the available virtual width is > 480.
int w = screen->GetWidth();
int factor;
@ -554,7 +551,11 @@ void V_UpdateModeSize (int width, int height)
else if (w >= 1600 && w < 1920) factor = 3;
else factor = w / 640;
CleanXfac_1 = CleanYfac_1 = factor;
CleanXfac = CleanYfac = factor;
CleanWidth = width / CleanXfac;
CleanHeight = height / CleanYfac;
CleanYfac_1 = CleanXfac_1 = MAX(1, int (CleanXfac * 0.7));
CleanWidth_1 = width / CleanXfac_1;
CleanHeight_1 = height / CleanYfac_1;
@ -581,52 +582,8 @@ void V_OutputResized (int width, int height)
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2)
{
float ratio;
int cwidth;
int cheight;
int cx1, cy1, cx2, cy2;
// For larger screems always use at least a 16:9 ratio for clean factor calculation, even if the actual ratio is narrower.
if (realwidth > 1280 && (double)realwidth / realheight < 16./9)
{
realheight = realwidth * 9 / 16;
}
ratio = ActiveRatio(realwidth, realheight);
if (AspectTallerThanWide(ratio))
{
cwidth = realwidth;
cheight = realheight * AspectMultiplier(ratio) / 48;
}
else
{
cwidth = realwidth * AspectMultiplier(ratio) / 48;
cheight = realheight;
}
// Use whichever pair of cwidth/cheight or width/height that produces less difference
// between CleanXfac and CleanYfac.
cx1 = MAX(cwidth / designwidth, 1);
cy1 = MAX(cheight / designheight, 1);
cx2 = MAX(realwidth / designwidth, 1);
cy2 = MAX(realheight / designheight, 1);
if (abs(cx1 - cy1) <= abs(cx2 - cy2) || MAX(cx1, cx2) >= 4)
{ // e.g. 640x360 looks better with this.
*cleanx = cx1;
*cleany = cy1;
}
else
{ // e.g. 720x480 looks better with this.
*cleanx = cx2;
*cleany = cy2;
}
if (*cleanx < *cleany)
*cleany = *cleanx;
else
*cleanx = *cleany;
if (_cx1 != NULL) *_cx1 = cx1;
if (_cx2 != NULL) *_cx2 = cx2;
if (designheight < 240 && realheight >= 480) designheight = 240;
*cleanx = *cleany = std::min(realwidth / designwidth, realheight / designheight);
}
bool IVideo::SetResolution ()
@ -696,9 +653,6 @@ void V_Init (bool restart)
// Update screen palette when restarting
else
{
PalEntry *palette = screen->GetPalette ();
for (int i = 0; i < 256; ++i)
*palette++ = GPalette.BaseColors[i];
screen->UpdatePalette();
}
@ -953,6 +907,8 @@ DEFINE_GLOBAL(SmallFont)
DEFINE_GLOBAL(SmallFont2)
DEFINE_GLOBAL(BigFont)
DEFINE_GLOBAL(ConFont)
DEFINE_GLOBAL(NewConsoleFont)
DEFINE_GLOBAL(NewSmallFont)
DEFINE_GLOBAL(IntermissionFont)
DEFINE_GLOBAL(CleanXfac)
DEFINE_GLOBAL(CleanYfac)

View file

@ -343,7 +343,8 @@ protected:
template<class T>
bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const;
void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms);
template<class T>
void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const T *string, DrawParms &parms);
F2DDrawer m2DDrawer;
private:
@ -352,16 +353,12 @@ private:
protected:
int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1;
PalEntry Flash; // Only needed to support some cruft in the interface that only makes sense for the software renderer
PalEntry SourcePalette[256]; // This is where unpaletted textures get their palette from
public:
// Hardware render state that needs to be exposed to the API independent part of the renderer. For ease of access this is stored in the base class.
int hwcaps = 0; // Capability flags
float glslversion = 0; // This is here so that the differences between old OpenGL and new OpenGL/Vulkan can be handled by platform independent code.
int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance.
int stencilValue = 0; // Global stencil test value
bool enable_quadbuffered = false; // Quad-buffered stereo available?
unsigned int uniformblockalignment = 256; // Hardware dependent uniform buffer alignment.
unsigned int maxuniformblock = 65536;
const char *gl_vendorstring; // On OpenGL (not Vulkan) we have to account for some issues with Intel.
@ -405,26 +402,12 @@ public:
// Make the surface visible.
virtual void Update ();
// Return a pointer to 256 palette entries that can be written to.
PalEntry *GetPalette ();
// Stores the palette with flash blended in into 256 dwords
void GetFlashedPalette (PalEntry palette[256]);
// Mark the palette as changed. It will be updated on the next Update().
virtual void UpdatePalette() {}
virtual void SetGamma() {}
// Sets a color flash. RGB is the color, and amount is 0-256, with 256
// being all flash and 0 being no flash. Returns false if the hardware
// does not support this. (Always true for now, since palettes can always
// be flashed.)
bool SetFlash (PalEntry rgb, int amount);
// Converse of SetFlash
void GetFlash (PalEntry &rgb, int &amount);
// Returns true if running fullscreen.
virtual bool IsFullscreen () = 0;
virtual void ToggleFullscreen(bool yes) {}
@ -476,7 +459,6 @@ public:
}
// Report a game restart
void InitPalette();
void SetClearColor(int color);
virtual uint32_t GetCaps();
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
@ -503,6 +485,7 @@ public:
// Dim part of the canvas
void Dim(PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle *style = nullptr);
void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle *style = nullptr);
FVector4 CalcBlend(sector_t * viewsector, PalEntry *modulateColor);
void DrawBlend(sector_t * viewsector);
// Fill an area with a texture
@ -547,6 +530,7 @@ public:
void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args);
void DrawChar(FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...);
void DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args);
void DrawText(FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...);
void DrawFrame(int left, int top, int width, int height);
void DrawBorder(FTextureID, int x1, int y1, int x2, int y2);
@ -627,20 +611,52 @@ bool AspectTallerThanWide(float aspect);
void ScaleWithAspect(int &w, int &h, int Width, int Height);
int GetUIScale(int altval);
int GetConScale(int altval);
EXTERN_CVAR(Int, uiscale);
EXTERN_CVAR(Int, con_scaletext);
EXTERN_CVAR(Int, con_scale);
inline int active_con_scaletext()
inline int active_con_scaletext(bool newconfont = false)
{
return GetUIScale(con_scaletext);
return newconfont? GetConScale(con_scaletext) : GetUIScale(con_scaletext);
}
inline int active_con_scale()
{
return GetUIScale(con_scale);
return GetConScale(con_scale);
}
class ScaleOverrider
{
int savedxfac, savedyfac, savedwidth, savedheight;
public:
// This is to allow certain elements to use an optimal fullscreen scale which for the menu would be too large.
// The old code contained far too much mess to compensate for the menus which negatively affected everything else.
// However, for compatibility reasons the currently used variables cannot be changed so they have to be overridden temporarily.
// This class provides a safe interface for this because it ensures that the values get restored afterward.
// Currently, the intermission and the level summary screen use this.
ScaleOverrider()
{
savedxfac = CleanXfac;
savedyfac = CleanYfac;
savedwidth = CleanWidth;
savedheight = CleanHeight;
V_CalcCleanFacs(320, 200, screen->GetWidth(), screen->GetHeight(), &CleanXfac, &CleanYfac);
CleanWidth = screen->GetWidth() / CleanXfac;
CleanHeight = screen->GetHeight() / CleanYfac;
}
~ScaleOverrider()
{
CleanXfac = savedxfac;
CleanYfac = savedyfac;
CleanWidth = savedwidth;
CleanHeight = savedheight;
}
};
#endif // __V_VIDEO_H__

View file

@ -701,6 +701,7 @@ void WI_Ticker()
{
if (WI_Screen)
{
ScaleOverrider s;
IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Ticker)
{
VMValue self = WI_Screen;
@ -720,6 +721,7 @@ void WI_Drawer()
{
if (WI_Screen)
{
ScaleOverrider s;
IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Drawer)
{
VMValue self = WI_Screen;
@ -761,13 +763,13 @@ void WI_Start(wbstartstruct_t *wbstartstruct)
}
}
V_SetBlend(0, 0, 0, 0);
S_StopAllChannels();
for (auto Level : AllLevels())
{
SN_StopAllSequences(Level);
}
WI_Screen = cls->CreateNew();
ScaleOverrider s;
IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Start)
{
VMValue val[2] = { WI_Screen, wbstartstruct };

View file

@ -56,14 +56,6 @@ extern HWND Window;
PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
// For broadest GL compatibility, require user to explicitly enable quad-buffered stereo mode.
// Setting vr_enable_quadbuffered_stereo does not automatically invoke quad-buffered stereo,
// but makes it possible for subsequent "vr_mode 7" to invoke quad-buffered stereo
CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("You must restart " GAMENAME " to switch quad stereo mode\n");
}
//==========================================================================
//
// Windows framebuffer
@ -111,7 +103,6 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst
}
}
ReleaseDC(Window, hDC);
enable_quadbuffered = vr_enable_quadbuffered;
}
//==========================================================================

View file

@ -433,7 +433,7 @@ void Writef (HANDLE file, const char *format, ...)
DWORD len;
va_start (args, format);
len = vsprintf (buffer, format, args);
len = myvsnprintf (buffer, sizeof buffer, format, args);
va_end (args);
WriteFile (file, buffer, len, &len, NULL);
}

Some files were not shown because too many files have changed in this diff Show more