mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-03-01 22:40:51 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
# Conflicts: # src/r_main.cpp
This commit is contained in:
commit
9472f09b7a
46 changed files with 910 additions and 547 deletions
|
@ -284,7 +284,7 @@ enum ActorFlag4
|
|||
enum ActorFlag5
|
||||
{
|
||||
MF5_DONTDRAIN = 0x00000001, // cannot be drained health from.
|
||||
/* FREE SLOT 0x00000002*/
|
||||
MF5_GETOWNER = 0x00000002,
|
||||
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
|
||||
MF5_NOFORWARDFALL = 0x00000008, // Does not make any actor fall forward by being damaged by this
|
||||
MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret
|
||||
|
|
|
@ -159,12 +159,37 @@ static int HistSize;
|
|||
|
||||
CVAR (Float, con_notifytime, 3.f, CVAR_ARCHIVE)
|
||||
CVAR (Bool, con_centernotify, false, CVAR_ARCHIVE)
|
||||
CUSTOM_CVAR (Int, con_scaletext, 0, CVAR_ARCHIVE) // Scale notify text at high resolutions?
|
||||
CUSTOM_CVAR (Int, con_scaletext, 1, CVAR_ARCHIVE) // Scale notify text at high resolutions?
|
||||
{
|
||||
if (self < 0) self = 0;
|
||||
if (self > 3) self = 3;
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, con_scale, 0, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0) self = 0;
|
||||
}
|
||||
|
||||
int active_con_scale()
|
||||
{
|
||||
if (con_scale == 0)
|
||||
return uiscale;
|
||||
else
|
||||
return con_scale;
|
||||
}
|
||||
|
||||
int active_con_scaletext()
|
||||
{
|
||||
switch (con_scaletext)
|
||||
{
|
||||
default:
|
||||
case 0: return 1;
|
||||
case 1: return uiscale;
|
||||
case 2: return 2;
|
||||
case 3: return 4;
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Float, con_alpha, 0.75f, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0.f) self = 0.f;
|
||||
|
@ -493,13 +518,13 @@ void C_AddNotifyString (int printlevel, const char *source)
|
|||
return;
|
||||
}
|
||||
|
||||
switch (con_scaletext)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
default:
|
||||
case 0: width = DisplayWidth; break;
|
||||
case 1: width = DisplayWidth / CleanXfac; break;
|
||||
case 2: width = DisplayWidth / 2; break;
|
||||
case 3: width = DisplayWidth / 4; break;
|
||||
width = DisplayWidth / CleanXfac;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = DisplayWidth / active_con_scaletext();
|
||||
}
|
||||
|
||||
if (addtype == APPENDLINE && NotifyStrings[NUMNOTIFIES-1].PrintLevel == printlevel)
|
||||
|
@ -721,7 +746,7 @@ static void C_DrawNotifyText ()
|
|||
canskip = true;
|
||||
|
||||
lineadv = SmallFont->GetHeight ();
|
||||
if (con_scaletext == 1)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
lineadv *= CleanYfac;
|
||||
}
|
||||
|
@ -755,7 +780,7 @@ static void C_DrawNotifyText ()
|
|||
else
|
||||
color = PrintColors[NotifyStrings[i].PrintLevel];
|
||||
|
||||
if (con_scaletext == 1)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
if (!center)
|
||||
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
|
||||
|
@ -766,7 +791,7 @@ static void C_DrawNotifyText ()
|
|||
line, NotifyStrings[i].Text, DTA_CleanNoMove, true,
|
||||
DTA_AlphaF, alpha, TAG_DONE);
|
||||
}
|
||||
else if (con_scaletext == 0)
|
||||
else if (active_con_scaletext() == 1)
|
||||
{
|
||||
if (!center)
|
||||
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
|
||||
|
@ -777,37 +802,20 @@ static void C_DrawNotifyText ()
|
|||
line, NotifyStrings[i].Text,
|
||||
DTA_AlphaF, alpha, TAG_DONE);
|
||||
}
|
||||
else if (con_scaletext == 3)
|
||||
{
|
||||
if (!center)
|
||||
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
|
||||
DTA_VirtualWidth, screen->GetWidth() / 4,
|
||||
DTA_VirtualHeight, screen->GetHeight() / 4,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_AlphaF, alpha, TAG_DONE);
|
||||
else
|
||||
screen->DrawText (SmallFont, color, (screen->GetWidth() / 4 -
|
||||
SmallFont->StringWidth (NotifyStrings[i].Text))/4,
|
||||
line, NotifyStrings[i].Text,
|
||||
DTA_VirtualWidth, screen->GetWidth() / 4,
|
||||
DTA_VirtualHeight, screen->GetHeight() / 4,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_AlphaF, alpha, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!center)
|
||||
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
|
||||
DTA_VirtualWidth, screen->GetWidth() / 2,
|
||||
DTA_VirtualHeight, screen->GetHeight() / 2,
|
||||
DTA_VirtualWidth, screen->GetWidth() / active_con_scaletext(),
|
||||
DTA_VirtualHeight, screen->GetHeight() / active_con_scaletext(),
|
||||
DTA_KeepRatio, true,
|
||||
DTA_AlphaF, alpha, TAG_DONE);
|
||||
else
|
||||
screen->DrawText (SmallFont, color, (screen->GetWidth() / 2 -
|
||||
SmallFont->StringWidth (NotifyStrings[i].Text))/2,
|
||||
screen->DrawText (SmallFont, color, (screen->GetWidth() -
|
||||
SmallFont->StringWidth (NotifyStrings[i].Text) * active_con_scaletext()) / 2 / active_con_scaletext(),
|
||||
line, NotifyStrings[i].Text,
|
||||
DTA_VirtualWidth, screen->GetWidth() / 2,
|
||||
DTA_VirtualHeight, screen->GetHeight() / 2,
|
||||
DTA_VirtualWidth, screen->GetWidth() / active_con_scaletext(),
|
||||
DTA_VirtualHeight, screen->GetHeight() / active_con_scaletext(),
|
||||
DTA_KeepRatio, true,
|
||||
DTA_AlphaF, alpha, TAG_DONE);
|
||||
}
|
||||
|
@ -851,9 +859,13 @@ void C_DrawConsole (bool hw2d)
|
|||
static int oldbottom = 0;
|
||||
int lines, left, offset;
|
||||
|
||||
int textScale = active_con_scale();
|
||||
if (textScale == 0)
|
||||
textScale = CleanXfac;
|
||||
|
||||
left = LEFTMARGIN;
|
||||
lines = (ConBottom-ConFont->GetHeight()*2)/ConFont->GetHeight();
|
||||
if (-ConFont->GetHeight() + lines*ConFont->GetHeight() > ConBottom - ConFont->GetHeight()*7/2)
|
||||
lines = (ConBottom/textScale-ConFont->GetHeight()*2)/ConFont->GetHeight();
|
||||
if (-ConFont->GetHeight() + lines*ConFont->GetHeight() > ConBottom/textScale - ConFont->GetHeight()*7/2)
|
||||
{
|
||||
offset = -ConFont->GetHeight()/2;
|
||||
lines--;
|
||||
|
@ -899,16 +911,26 @@ void C_DrawConsole (bool hw2d)
|
|||
|
||||
if (ConBottom >= 12)
|
||||
{
|
||||
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
|
||||
ConFont->StringWidth (GetVersionString()),
|
||||
ConBottom - ConFont->GetHeight() - 4,
|
||||
GetVersionString(), TAG_DONE);
|
||||
if (textScale == 1)
|
||||
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
|
||||
ConFont->StringWidth (GetVersionString()),
|
||||
ConBottom / textScale - ConFont->GetHeight() - 4,
|
||||
GetVersionString(), TAG_DONE);
|
||||
else
|
||||
screen->DrawText(ConFont, CR_ORANGE, SCREENWIDTH / textScale - 8 -
|
||||
ConFont->StringWidth(GetVersionString()),
|
||||
ConBottom / textScale - ConFont->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 - ConFont->GetHeight() - 4;
|
||||
const int tickerY = ConBottom / textScale - ConFont->GetHeight() - 4;
|
||||
size_t i;
|
||||
int tickend = ConCols - SCREENWIDTH / 90 - 6;
|
||||
int tickend = ConCols / textScale - SCREENWIDTH / textScale / 90 - 6;
|
||||
int tickbegin = 0;
|
||||
|
||||
if (TickerLabel)
|
||||
|
@ -931,11 +953,23 @@ void C_DrawConsole (bool hw2d)
|
|||
{
|
||||
tickstr[tickend+3] = 0;
|
||||
}
|
||||
screen->DrawText (ConFont, CR_BROWN, LEFTMARGIN, tickerY, tickstr, TAG_DONE);
|
||||
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, (SDWORD)(tickend - tickbegin)*8, TickerMax);
|
||||
screen->DrawChar (ConFont, CR_ORANGE, (int)i, tickerY, 0x13, TAG_DONE);
|
||||
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;
|
||||
}
|
||||
|
@ -971,18 +1005,28 @@ void C_DrawConsole (bool hw2d)
|
|||
if (lines > 0)
|
||||
{
|
||||
// No more enqueuing because adding new text to the console won't touch the actual print data.
|
||||
conbuffer->FormatText(ConFont, ConWidth);
|
||||
conbuffer->FormatText(ConFont, ConWidth / textScale);
|
||||
unsigned int consolelines = conbuffer->GetFormattedLineCount();
|
||||
FBrokenLines **blines = conbuffer->GetLines();
|
||||
FBrokenLines **printline = blines + consolelines - 1 - RowAdjust;
|
||||
|
||||
int bottomline = ConBottom - ConFont->GetHeight()*2 - 4;
|
||||
int bottomline = ConBottom / textScale - ConFont->GetHeight()*2 - 4;
|
||||
|
||||
ConsoleDrawing = true;
|
||||
|
||||
for(FBrokenLines **p = printline; p >= blines && lines > 0; p--, lines--)
|
||||
{
|
||||
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE);
|
||||
if (textScale == 1)
|
||||
{
|
||||
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text,
|
||||
DTA_VirtualWidth, screen->GetWidth() / textScale,
|
||||
DTA_VirtualHeight, screen->GetHeight() / textScale,
|
||||
DTA_KeepRatio, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
ConsoleDrawing = false;
|
||||
|
@ -997,21 +1041,52 @@ void C_DrawConsole (bool hw2d)
|
|||
FString command((char *)&CmdLine[2+CmdLine[259]]);
|
||||
int cursorpos = CmdLine[1] - CmdLine[259];
|
||||
|
||||
screen->DrawChar (ConFont, CR_ORANGE, left, bottomline, '\x1c', TAG_DONE);
|
||||
screen->DrawText (ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
|
||||
command, TAG_DONE);
|
||||
|
||||
if (cursoron)
|
||||
if (textScale == 1)
|
||||
{
|
||||
screen->DrawChar (ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
|
||||
bottomline, '\xb', TAG_DONE);
|
||||
screen->DrawChar(ConFont, CR_ORANGE, left, bottomline, '\x1c', TAG_DONE);
|
||||
screen->DrawText(ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
|
||||
command, TAG_DONE);
|
||||
|
||||
if (cursoron)
|
||||
{
|
||||
screen->DrawChar(ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
|
||||
bottomline, '\xb', TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawChar(ConFont, CR_ORANGE, left, bottomline, '\x1c',
|
||||
DTA_VirtualWidth, screen->GetWidth() / textScale,
|
||||
DTA_VirtualHeight, screen->GetHeight() / textScale,
|
||||
DTA_KeepRatio, true, TAG_DONE);
|
||||
|
||||
screen->DrawText(ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
|
||||
command,
|
||||
DTA_VirtualWidth, screen->GetWidth() / textScale,
|
||||
DTA_VirtualHeight, screen->GetHeight() / textScale,
|
||||
DTA_KeepRatio, true, TAG_DONE);
|
||||
|
||||
if (cursoron)
|
||||
{
|
||||
screen->DrawChar(ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
|
||||
bottomline, '\xb',
|
||||
DTA_VirtualWidth, screen->GetWidth() / textScale,
|
||||
DTA_VirtualHeight, screen->GetHeight() / textScale,
|
||||
DTA_KeepRatio, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (RowAdjust && ConBottom >= ConFont->GetHeight()*7/2)
|
||||
{
|
||||
// Indicate that the view has been scrolled up (10)
|
||||
// and if we can scroll no further (12)
|
||||
screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE);
|
||||
if (textScale == 1)
|
||||
screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE);
|
||||
else
|
||||
screen->DrawChar(ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10,
|
||||
DTA_VirtualWidth, screen->GetWidth() / textScale,
|
||||
DTA_VirtualHeight, screen->GetHeight() / textScale,
|
||||
DTA_KeepRatio, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ EXTERN_CVAR (Bool, sb_cooperative_enable)
|
|||
EXTERN_CVAR (Bool, sb_deathmatch_enable)
|
||||
EXTERN_CVAR (Bool, sb_teamdeathmatch_enable)
|
||||
|
||||
int active_con_scaletext();
|
||||
|
||||
// Public data
|
||||
|
||||
void CT_Init ();
|
||||
|
@ -224,7 +226,7 @@ void CT_Drawer (void)
|
|||
int i, x, scalex, y, promptwidth;
|
||||
|
||||
y = (viewactive || gamestate != GS_LEVEL) ? -10 : -30;
|
||||
if (con_scaletext == 1)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
scalex = CleanXfac;
|
||||
y *= CleanYfac;
|
||||
|
@ -235,25 +237,17 @@ void CT_Drawer (void)
|
|||
}
|
||||
|
||||
int screen_width, screen_height, st_y;
|
||||
switch (con_scaletext)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
case 1:
|
||||
screen_width = SCREENWIDTH;
|
||||
screen_height = SCREENHEIGHT;
|
||||
st_y = ST_Y;
|
||||
break;
|
||||
case 2:
|
||||
screen_width = SCREENWIDTH / 2;
|
||||
screen_height = SCREENHEIGHT / 2;
|
||||
st_y = ST_Y / 2;
|
||||
break;
|
||||
case 3:
|
||||
screen_width = SCREENWIDTH / 4;
|
||||
screen_height = SCREENHEIGHT / 4;
|
||||
st_y = ST_Y / 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
screen_width = SCREENWIDTH / active_con_scaletext();
|
||||
screen_height = SCREENHEIGHT / active_con_scaletext();
|
||||
st_y = ST_Y / active_con_scaletext();
|
||||
}
|
||||
|
||||
y += ((SCREENHEIGHT == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y;
|
||||
|
@ -280,10 +274,10 @@ void CT_Drawer (void)
|
|||
// draw the prompt, text, and cursor
|
||||
ChatQueue[len] = SmallFont->GetCursor();
|
||||
ChatQueue[len+1] = '\0';
|
||||
if (con_scaletext < 2)
|
||||
if (active_con_scaletext() < 2)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_GREEN, 0, y, prompt, DTA_CleanNoMove, *con_scaletext, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GREY, promptwidth, y, (char *)(ChatQueue + i), DTA_CleanNoMove, *con_scaletext, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GREEN, 0, y, prompt, DTA_CleanNoMove, active_con_scaletext() == 0, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GREY, promptwidth, y, (char *)(ChatQueue + i), DTA_CleanNoMove, active_con_scaletext() == 0, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -166,8 +166,14 @@ void AFastProjectile::Effect()
|
|||
if (trail != NULL)
|
||||
{
|
||||
AActor *act = Spawn (trail, PosAtZ(hitz), ALLOW_REPLACE);
|
||||
if (act != NULL)
|
||||
if (act != nullptr)
|
||||
{
|
||||
if ((flags5 & MF5_GETOWNER) && (target != nullptr))
|
||||
act->target = target;
|
||||
else
|
||||
act->target = this;
|
||||
|
||||
act->Angles.Pitch = Angles.Pitch;
|
||||
act->Angles.Yaw = Angles.Yaw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ double DEarthquake::GetModWave(double waveMultiplier) const
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
double DEarthquake::GetModIntensity(double intensity) const
|
||||
double DEarthquake::GetModIntensity(double intensity, bool fake) const
|
||||
{
|
||||
assert(m_CountdownStart >= m_Countdown);
|
||||
|
||||
|
@ -195,7 +195,7 @@ double DEarthquake::GetModIntensity(double intensity) const
|
|||
}
|
||||
scalar = (scalar > divider) ? divider : scalar;
|
||||
|
||||
if (m_Flags & QF_FULLINTENSITY)
|
||||
if (!fake && (m_Flags & QF_FULLINTENSITY))
|
||||
{
|
||||
scalar *= 2;
|
||||
}
|
||||
|
@ -273,64 +273,69 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
|
|||
DEarthquake *quake;
|
||||
int count = 0;
|
||||
|
||||
while ( (quake = iterator.Next()) != NULL)
|
||||
while ( (quake = iterator.Next()) != nullptr)
|
||||
{
|
||||
if (quake->m_Spot != NULL)
|
||||
if (quake->m_Spot != nullptr)
|
||||
{
|
||||
double dist = quake->m_Spot->Distance2D (victim, true);
|
||||
const double dist = quake->m_Spot->Distance2D(victim, true);
|
||||
if (dist < quake->m_TremorRadius)
|
||||
{
|
||||
const double falloff = quake->GetFalloff(dist);
|
||||
const double rfalloff = (quake->m_RollIntensity != 0) ? falloff : 0.;
|
||||
++count;
|
||||
double x = quake->GetModIntensity(quake->m_Intensity.X);
|
||||
double y = quake->GetModIntensity(quake->m_Intensity.Y);
|
||||
double z = quake->GetModIntensity(quake->m_Intensity.Z);
|
||||
double r = quake->GetModIntensity(quake->m_RollIntensity);
|
||||
const double falloff = quake->GetFalloff(dist);
|
||||
const double r = quake->GetModIntensity(quake->m_RollIntensity);
|
||||
const double strength = quake->GetModIntensity(1.0, true);
|
||||
DVector3 intensity;
|
||||
intensity.X = quake->GetModIntensity(quake->m_Intensity.X);
|
||||
intensity.Y = quake->GetModIntensity(quake->m_Intensity.Y);
|
||||
intensity.Z = quake->GetModIntensity(quake->m_Intensity.Z);
|
||||
|
||||
if (!(quake->m_Flags & QF_WAVE))
|
||||
{
|
||||
jiggers.Falloff = MAX(falloff, jiggers.Falloff);
|
||||
jiggers.RFalloff = MAX(rfalloff, jiggers.RFalloff);
|
||||
jiggers.RollIntensity = MAX(r, jiggers.RollIntensity);
|
||||
jiggers.RollIntensity = MAX(r, jiggers.RollIntensity) * jiggers.Falloff;
|
||||
|
||||
intensity *= jiggers.Falloff;
|
||||
if (quake->m_Flags & QF_RELATIVE)
|
||||
{
|
||||
jiggers.RelIntensity.X = MAX(x, jiggers.RelIntensity.X);
|
||||
jiggers.RelIntensity.Y = MAX(y, jiggers.RelIntensity.Y);
|
||||
jiggers.RelIntensity.Z = MAX(z, jiggers.RelIntensity.Z);
|
||||
jiggers.RelIntensity.X = MAX(intensity.X, jiggers.RelIntensity.X);
|
||||
jiggers.RelIntensity.Y = MAX(intensity.Y, jiggers.RelIntensity.Y);
|
||||
jiggers.RelIntensity.Z = MAX(intensity.Z, jiggers.RelIntensity.Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
jiggers.Intensity.X = MAX(x, jiggers.Intensity.X);
|
||||
jiggers.Intensity.Y = MAX(y, jiggers.Intensity.Y);
|
||||
jiggers.Intensity.Z = MAX(z, jiggers.Intensity.Z);
|
||||
jiggers.Intensity.X = MAX(intensity.X, jiggers.Intensity.X);
|
||||
jiggers.Intensity.Y = MAX(intensity.Y, jiggers.Intensity.Y);
|
||||
jiggers.Intensity.Z = MAX(intensity.Z, jiggers.Intensity.Z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jiggers.WFalloff = MAX(falloff, jiggers.WFalloff);
|
||||
jiggers.RWFalloff = MAX(rfalloff, jiggers.RWFalloff);
|
||||
jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave);
|
||||
double mx = x * quake->GetModWave(quake->m_WaveSpeed.X);
|
||||
double my = y * quake->GetModWave(quake->m_WaveSpeed.Y);
|
||||
double mz = z * quake->GetModWave(quake->m_WaveSpeed.Z);
|
||||
jiggers.Falloff = MAX(falloff, jiggers.Falloff);
|
||||
jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave) * jiggers.Falloff * strength;
|
||||
|
||||
|
||||
intensity.X *= quake->GetModWave(quake->m_WaveSpeed.X);
|
||||
intensity.Y *= quake->GetModWave(quake->m_WaveSpeed.Y);
|
||||
intensity.Z *= quake->GetModWave(quake->m_WaveSpeed.Z);
|
||||
intensity *= strength * jiggers.Falloff;
|
||||
|
||||
// [RH] This only gives effect to the last sine quake. I would
|
||||
// prefer if some way was found to make multiples coexist
|
||||
// peacefully, but just summing them together is undesirable
|
||||
// because they could cancel each other out depending on their
|
||||
// relative phases.
|
||||
|
||||
// [MC] Now does so. And they stack rather well. I'm a little
|
||||
// surprised at how easy it was.
|
||||
|
||||
|
||||
if (quake->m_Flags & QF_RELATIVE)
|
||||
{
|
||||
jiggers.RelOffset.X = mx;
|
||||
jiggers.RelOffset.Y = my;
|
||||
jiggers.RelOffset.Z = mz;
|
||||
jiggers.RelOffset += intensity;
|
||||
}
|
||||
else
|
||||
{
|
||||
jiggers.Offset.X = mx;
|
||||
jiggers.Offset.Y = my;
|
||||
jiggers.Offset.Z = mz;
|
||||
jiggers.Offset += intensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ struct FQuakeJiggers
|
|||
DVector3 RelIntensity;
|
||||
DVector3 Offset;
|
||||
DVector3 RelOffset;
|
||||
double Falloff, WFalloff, RFalloff, RWFalloff;
|
||||
double Falloff;
|
||||
double RollIntensity, RollWave;
|
||||
};
|
||||
|
||||
|
@ -180,8 +180,7 @@ public:
|
|||
int m_Highpoint, m_MiniCount;
|
||||
double m_RollIntensity, m_RollWave;
|
||||
|
||||
|
||||
double GetModIntensity(double intensity) const;
|
||||
double GetModIntensity(double intensity, bool fake = false) const;
|
||||
double GetModWave(double waveMultiplier) const;
|
||||
double GetFalloff(double dist) const;
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
#include "doomstat.h"
|
||||
#include "farchive.h"
|
||||
|
||||
EXTERN_CVAR (Int, con_scaletext)
|
||||
EXTERN_CVAR(Int, con_scaletext)
|
||||
int active_con_scaletext();
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (DHUDMessage)
|
||||
DECLARE_POINTER(Next)
|
||||
|
@ -260,13 +261,10 @@ void DHUDMessage::ResetText (const char *text)
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (con_scaletext)
|
||||
switch (active_con_scaletext())
|
||||
{
|
||||
default:
|
||||
case 0: width = SCREENWIDTH; break;
|
||||
case 1: width = SCREENWIDTH / CleanXfac; break;
|
||||
case 2: width = SCREENWIDTH / 2; break;
|
||||
case 3: width = SCREENWIDTH / 4; break;
|
||||
case 0: width = SCREENWIDTH / CleanXfac; break;
|
||||
default: width = SCREENWIDTH / active_con_scaletext(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +330,7 @@ void DHUDMessage::Draw (int bottom, int visibility)
|
|||
|
||||
int screen_width = SCREENWIDTH;
|
||||
int screen_height = SCREENHEIGHT;
|
||||
if (HUDWidth == 0 && con_scaletext==1)
|
||||
if (HUDWidth == 0 && active_con_scaletext() == 0)
|
||||
{
|
||||
clean = true;
|
||||
xscale = CleanXfac;
|
||||
|
@ -341,17 +339,11 @@ void DHUDMessage::Draw (int bottom, int visibility)
|
|||
else
|
||||
{
|
||||
xscale = yscale = 1;
|
||||
if (HUDWidth==0 && con_scaletext==2)
|
||||
if (HUDWidth == 0)
|
||||
{
|
||||
screen_width/=2;
|
||||
screen_height/=2;
|
||||
bottom/=2;
|
||||
}
|
||||
else if (HUDWidth==0 && con_scaletext==3)
|
||||
{
|
||||
screen_width/=4;
|
||||
screen_height/=4;
|
||||
bottom/=4;
|
||||
screen_width /= active_con_scaletext();
|
||||
screen_height /= active_con_scaletext();
|
||||
bottom /= active_con_scaletext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,7 +445,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
|
|||
{
|
||||
if (hudheight == 0)
|
||||
{
|
||||
if (con_scaletext <= 1)
|
||||
if (active_con_scaletext() <= 1)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_CleanNoMove, clean,
|
||||
|
@ -461,21 +453,11 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
|
|||
DTA_RenderStyle, Style,
|
||||
TAG_DONE);
|
||||
}
|
||||
else if (con_scaletext == 3)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/4,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/4,
|
||||
DTA_AlphaF, Alpha,
|
||||
DTA_RenderStyle, Style,
|
||||
DTA_KeepRatio, true,
|
||||
TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/2,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/2,
|
||||
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
|
||||
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
|
||||
DTA_AlphaF, Alpha,
|
||||
DTA_RenderStyle, Style,
|
||||
DTA_KeepRatio, true,
|
||||
|
@ -566,7 +548,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
|
|||
float trans = float(Alpha * -(Tics - FadeOutTics) / FadeOutTics);
|
||||
if (hudheight == 0)
|
||||
{
|
||||
if (con_scaletext <= 1)
|
||||
if (active_con_scaletext() <= 1)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_CleanNoMove, clean,
|
||||
|
@ -574,21 +556,11 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
|
|||
DTA_RenderStyle, Style,
|
||||
TAG_DONE);
|
||||
}
|
||||
else if (con_scaletext == 3)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/4,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/4,
|
||||
DTA_AlphaF, trans,
|
||||
DTA_RenderStyle, Style,
|
||||
DTA_KeepRatio, true,
|
||||
TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/2,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/2,
|
||||
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
|
||||
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
|
||||
DTA_AlphaF, trans,
|
||||
DTA_RenderStyle, Style,
|
||||
DTA_KeepRatio, true,
|
||||
|
@ -676,7 +648,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
|
|||
float trans = float(Alpha * Tics / FadeInTics);
|
||||
if (hudheight == 0)
|
||||
{
|
||||
if (con_scaletext <= 1)
|
||||
if (active_con_scaletext() <= 1)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_CleanNoMove, clean,
|
||||
|
@ -684,21 +656,11 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
|
|||
DTA_RenderStyle, Style,
|
||||
TAG_DONE);
|
||||
}
|
||||
else if (con_scaletext == 3)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/4,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/4,
|
||||
DTA_AlphaF, trans,
|
||||
DTA_RenderStyle, Style,
|
||||
DTA_KeepRatio, true,
|
||||
TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/2,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/2,
|
||||
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
|
||||
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
|
||||
DTA_AlphaF, trans,
|
||||
DTA_RenderStyle, Style,
|
||||
DTA_KeepRatio, true,
|
||||
|
@ -864,7 +826,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
|
|||
{
|
||||
if (hudheight == 0)
|
||||
{
|
||||
if (con_scaletext <= 1)
|
||||
if (active_con_scaletext() <= 1)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_CleanNoMove, clean,
|
||||
|
@ -873,22 +835,11 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
|
|||
DTA_RenderStyle, Style,
|
||||
TAG_DONE);
|
||||
}
|
||||
else if (con_scaletext == 3)
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/4,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/4,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_TextLen, LineVisible,
|
||||
DTA_AlphaF, Alpha,
|
||||
DTA_RenderStyle, Style,
|
||||
TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
|
||||
DTA_VirtualWidth, SCREENWIDTH/2,
|
||||
DTA_VirtualHeight, SCREENHEIGHT/2,
|
||||
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
|
||||
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
|
||||
DTA_KeepRatio, true,
|
||||
DTA_TextLen, LineVisible,
|
||||
DTA_AlphaF, Alpha,
|
||||
|
|
|
@ -1013,7 +1013,15 @@ public:
|
|||
void ScreenSizeChanged()
|
||||
{
|
||||
Super::ScreenSizeChanged();
|
||||
V_CalcCleanFacs(script->resW, script->resH, SCREENWIDTH, SCREENHEIGHT, &script->cleanX, &script->cleanY);
|
||||
if (uiscale > 0)
|
||||
{
|
||||
script->cleanX = uiscale;
|
||||
script->cleanY = uiscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
V_CalcCleanFacs(script->resW, script->resH, SCREENWIDTH, SCREENHEIGHT, &script->cleanX, &script->cleanY);
|
||||
}
|
||||
}
|
||||
|
||||
void Draw (EHudState state)
|
||||
|
|
|
@ -66,7 +66,7 @@ EXTERN_CVAR (Int, screenblocks)
|
|||
EXTERN_CVAR (Bool, am_showtime)
|
||||
EXTERN_CVAR (Bool, am_showtotaltime)
|
||||
|
||||
CVAR(Int,hud_althudscale, 2, CVAR_ARCHIVE) // Scale the hud to 640x400?
|
||||
CVAR(Int,hud_althudscale, 4, CVAR_ARCHIVE) // Scale the hud to 640x400?
|
||||
CVAR(Bool,hud_althud, false, CVAR_ARCHIVE) // Enable/Disable the alternate HUD
|
||||
|
||||
// These are intentionally not the same as in the automap!
|
||||
|
@ -118,7 +118,7 @@ static int hudwidth, hudheight; // current width/height for HUD display
|
|||
static int statspace;
|
||||
|
||||
DVector2 AM_GetPosition();
|
||||
|
||||
int active_con_scaletext();
|
||||
|
||||
FTextureID GetHUDIcon(PClassInventory *cls)
|
||||
{
|
||||
|
@ -886,22 +886,15 @@ static void DrawCoordinates(player_t * CPlayer)
|
|||
}
|
||||
|
||||
int vwidth, vheight;
|
||||
switch (con_scaletext)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
vwidth = SCREENWIDTH;
|
||||
vheight = SCREENHEIGHT;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
vwidth = SCREENWIDTH/2;
|
||||
vheight = SCREENHEIGHT/2;
|
||||
break;
|
||||
case 3:
|
||||
vwidth = SCREENWIDTH/4;
|
||||
vheight = SCREENHEIGHT/4;
|
||||
break;
|
||||
vwidth = SCREENWIDTH / 2;
|
||||
vheight = SCREENHEIGHT / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
vwidth = SCREENWIDTH / active_con_scaletext();
|
||||
vheight = SCREENHEIGHT / active_con_scaletext();
|
||||
}
|
||||
|
||||
int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6;
|
||||
|
@ -1090,7 +1083,20 @@ void DrawHUD()
|
|||
if (hud_althudscale && SCREENWIDTH>640)
|
||||
{
|
||||
hudwidth=SCREENWIDTH/2;
|
||||
if (hud_althudscale == 3)
|
||||
if (hud_althudscale == 4)
|
||||
{
|
||||
if (uiscale == 0)
|
||||
{
|
||||
hudwidth = CleanWidth;
|
||||
hudheight = CleanHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
hudwidth = SCREENWIDTH / uiscale;
|
||||
hudheight = SCREENHEIGHT / uiscale;
|
||||
}
|
||||
}
|
||||
else if (hud_althudscale == 3)
|
||||
{
|
||||
hudwidth = SCREENWIDTH / 4;
|
||||
hudheight = SCREENHEIGHT / 4;
|
||||
|
|
|
@ -74,6 +74,8 @@ EXTERN_CVAR (Bool, am_showtotaltime)
|
|||
EXTERN_CVAR (Bool, noisedebug)
|
||||
EXTERN_CVAR (Int, con_scaletext)
|
||||
|
||||
int active_con_scaletext();
|
||||
|
||||
DBaseStatusBar *StatusBar;
|
||||
|
||||
extern int setblocks;
|
||||
|
@ -1240,17 +1242,17 @@ void DBaseStatusBar::Draw (EHudState state)
|
|||
int xpos;
|
||||
int y;
|
||||
|
||||
if (con_scaletext == 0)
|
||||
if (active_con_scaletext() == 1)
|
||||
{
|
||||
vwidth = SCREENWIDTH;
|
||||
vheight = SCREENHEIGHT;
|
||||
xpos = vwidth - 80;
|
||||
y = ::ST_Y - height;
|
||||
}
|
||||
else if (con_scaletext == 3)
|
||||
else if (active_con_scaletext() > 1)
|
||||
{
|
||||
vwidth = SCREENWIDTH/4;
|
||||
vheight = SCREENHEIGHT/4;
|
||||
vwidth = SCREENWIDTH / active_con_scaletext();
|
||||
vheight = SCREENHEIGHT / active_con_scaletext();
|
||||
xpos = vwidth - SmallFont->StringWidth("X: -00000")-6;
|
||||
y = ::ST_Y/4 - height;
|
||||
}
|
||||
|
@ -1264,9 +1266,9 @@ void DBaseStatusBar::Draw (EHudState state)
|
|||
|
||||
if (gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
if (con_scaletext == 0)
|
||||
if (active_con_scaletext() == 1)
|
||||
y -= height * 4;
|
||||
else if (con_scaletext == 3)
|
||||
else if (active_con_scaletext() > 3)
|
||||
y -= height;
|
||||
else
|
||||
y -= height * 2;
|
||||
|
@ -1400,27 +1402,15 @@ void DBaseStatusBar::DrawLog ()
|
|||
if (CPlayer->LogText.IsNotEmpty())
|
||||
{
|
||||
// This uses the same scaling as regular HUD messages
|
||||
switch (con_scaletext)
|
||||
if (active_con_scaletext() == 0)
|
||||
{
|
||||
default:
|
||||
hudwidth = SCREENWIDTH;
|
||||
hudheight = SCREENHEIGHT;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hudwidth = SCREENWIDTH / CleanXfac;
|
||||
hudheight = SCREENHEIGHT / CleanYfac;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
hudwidth = SCREENWIDTH / 2;
|
||||
hudheight = SCREENHEIGHT / 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
hudwidth = SCREENWIDTH / 4;
|
||||
hudheight = SCREENHEIGHT / 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
hudwidth = SCREENWIDTH / active_con_scaletext();
|
||||
hudheight = SCREENHEIGHT / active_con_scaletext();
|
||||
}
|
||||
|
||||
int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560;
|
||||
|
|
|
@ -552,7 +552,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave)
|
|||
|
||||
// If the torpedo hit the ceiling, it should still spawn the wave
|
||||
savedz = self->Z();
|
||||
if (wavedef && self->ceilingz < wavedef->Top())
|
||||
if (wavedef && self->ceilingz < self->Z() + wavedef->Height)
|
||||
{
|
||||
self->SetZ(self->ceilingz - wavedef->Height);
|
||||
}
|
||||
|
|
|
@ -378,7 +378,7 @@ void F2DDrawer::AddPixel(int x1, int y1, int palcolor, uint32 color)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void F2DDrawer::Flush()
|
||||
void F2DDrawer::Draw()
|
||||
{
|
||||
F2DDrawer::EDrawType lasttype = DrawTypeTexture;
|
||||
|
||||
|
@ -490,10 +490,12 @@ void F2DDrawer::Flush()
|
|||
}
|
||||
i += dg->mLen;
|
||||
}
|
||||
mVertices.Clear();
|
||||
mData.Clear();
|
||||
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
|
||||
glset.lightmode = savedlightmode;
|
||||
}
|
||||
|
||||
|
||||
void F2DDrawer::Clear()
|
||||
{
|
||||
mVertices.Clear();
|
||||
mData.Clear();
|
||||
}
|
||||
|
|
|
@ -66,7 +66,8 @@ public:
|
|||
void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color);
|
||||
void AddPixel(int x1, int y1, int palcolor, uint32 color);
|
||||
|
||||
void Flush();
|
||||
void Draw();
|
||||
void Clear();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "gl/shaders/gl_lensshader.h"
|
||||
#include "gl/shaders/gl_presentshader.h"
|
||||
#include "gl/renderer/gl_2ddrawer.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -257,7 +258,7 @@ void FGLRenderer::BindTonemapPalette(int texunit)
|
|||
{
|
||||
for (int b = 0; b < 64; b++)
|
||||
{
|
||||
PalEntry color = GPalette.BaseColors[ColorMatcher.Pick((r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4))];
|
||||
PalEntry color = GPalette.BaseColors[(BYTE)PTM_BestColor((uint32 *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), 0, 256)];
|
||||
int index = ((r * 64 + g) * 64 + b) * 4;
|
||||
lut[index] = color.r;
|
||||
lut[index + 1] = color.g;
|
||||
|
@ -375,6 +376,41 @@ void FGLRenderer::LensDistortScene()
|
|||
FGLDebug::PopGroup();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copies the rendered screen to its final destination
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FGLRenderer::Flush()
|
||||
{
|
||||
const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
|
||||
|
||||
if (stereo3dMode.IsMono() || !FGLRenderBuffers::IsEnabled())
|
||||
{
|
||||
CopyToBackbuffer(nullptr, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Render 2D to eye textures
|
||||
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
|
||||
{
|
||||
FGLDebug::PushGroup("Eye2D");
|
||||
mBuffers->BindEyeFB(eye_ix);
|
||||
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
||||
glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
||||
m2DDrawer->Draw();
|
||||
FGLDebug::PopGroup();
|
||||
}
|
||||
m2DDrawer->Clear();
|
||||
|
||||
FGLPostProcessState savedState;
|
||||
FGLDebug::PushGroup("PresentEyes");
|
||||
stereo3dMode.Present();
|
||||
FGLDebug::PopGroup();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Gamma correct while copying to frame buffer
|
||||
|
@ -383,7 +419,9 @@ void FGLRenderer::LensDistortScene()
|
|||
|
||||
void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
|
||||
{
|
||||
m2DDrawer->Flush(); // draw all pending 2D stuff before copying the buffer
|
||||
m2DDrawer->Draw(); // draw all pending 2D stuff before copying the buffer
|
||||
m2DDrawer->Clear();
|
||||
|
||||
FGLDebug::PushGroup("CopyToBackbuffer");
|
||||
if (FGLRenderBuffers::IsEnabled())
|
||||
{
|
||||
|
@ -401,28 +439,8 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
|
|||
box = mOutputLetterbox;
|
||||
}
|
||||
|
||||
// Present what was rendered:
|
||||
glViewport(box.left, box.top, box.width, box.height);
|
||||
|
||||
mPresentShader->Bind();
|
||||
mPresentShader->InputTexture.Set(0);
|
||||
if (!applyGamma || framebuffer->IsHWGammaActive())
|
||||
{
|
||||
mPresentShader->InvGamma.Set(1.0f);
|
||||
mPresentShader->Contrast.Set(1.0f);
|
||||
mPresentShader->Brightness.Set(0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
|
||||
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
|
||||
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
|
||||
}
|
||||
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
|
||||
mBuffers->BindCurrentTexture(0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
RenderScreenQuad();
|
||||
DrawPresentTexture(box, applyGamma);
|
||||
}
|
||||
else if (!bounds)
|
||||
{
|
||||
|
@ -432,6 +450,32 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
|
|||
FGLDebug::PopGroup();
|
||||
}
|
||||
|
||||
void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma)
|
||||
{
|
||||
glViewport(box.left, box.top, box.width, box.height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
mPresentShader->Bind();
|
||||
mPresentShader->InputTexture.Set(0);
|
||||
if (!applyGamma || framebuffer->IsHWGammaActive())
|
||||
{
|
||||
mPresentShader->InvGamma.Set(1.0f);
|
||||
mPresentShader->Contrast.Set(1.0f);
|
||||
mPresentShader->Brightness.Set(0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
|
||||
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
|
||||
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
|
||||
}
|
||||
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
|
||||
RenderScreenQuad();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Fills the black bars around the screen letterbox
|
||||
|
@ -472,3 +516,40 @@ void FGLRenderer::ClearBorders()
|
|||
}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
|
||||
// [SP] Re-implemented BestColor for more precision rather than speed. This function is only ever called once until the game palette is changed.
|
||||
|
||||
int FGLRenderer::PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num)
|
||||
{
|
||||
const PalEntry *pal = (const PalEntry *)pal_in;
|
||||
static double powtable[256];
|
||||
static bool firstTime = true;
|
||||
|
||||
double fbestdist, fdist;
|
||||
int bestcolor;
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
firstTime = false;
|
||||
for (int x = 0; x < 256; x++) powtable[x] = pow((double)x/255,1.2);
|
||||
}
|
||||
|
||||
for (int color = first; color < num; color++)
|
||||
{
|
||||
double x = powtable[abs(r-pal[color].r)];
|
||||
double y = powtable[abs(g-pal[color].g)];
|
||||
double z = powtable[abs(b-pal[color].b)];
|
||||
fdist = x + y + z;
|
||||
if (color == first || fdist < fbestdist)
|
||||
{
|
||||
if (fdist == 0)
|
||||
return color;
|
||||
|
||||
fbestdist = fdist;
|
||||
bestcolor = color;
|
||||
}
|
||||
}
|
||||
return bestcolor;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ FGLRenderBuffers::~FGLRenderBuffers()
|
|||
{
|
||||
ClearScene();
|
||||
ClearPipeline();
|
||||
ClearEyeBuffers();
|
||||
ClearBloom();
|
||||
}
|
||||
|
||||
|
@ -119,6 +120,18 @@ void FGLRenderBuffers::ClearBloom()
|
|||
}
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::ClearEyeBuffers()
|
||||
{
|
||||
for (auto handle : mEyeFBs)
|
||||
DeleteFrameBuffer(handle);
|
||||
|
||||
for (auto handle : mEyeTextures)
|
||||
DeleteTexture(handle);
|
||||
|
||||
mEyeTextures.Clear();
|
||||
mEyeFBs.Clear();
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
|
||||
{
|
||||
if (handle != 0)
|
||||
|
@ -202,6 +215,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
|||
{
|
||||
ClearScene();
|
||||
ClearPipeline();
|
||||
ClearEyeBuffers();
|
||||
ClearBloom();
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
|
@ -239,6 +253,7 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples)
|
|||
void FGLRenderBuffers::CreatePipeline(int width, int height)
|
||||
{
|
||||
ClearPipeline();
|
||||
ClearEyeBuffers();
|
||||
|
||||
for (int i = 0; i < NumPipelineTextures; i++)
|
||||
{
|
||||
|
@ -279,6 +294,35 @@ void FGLRenderBuffers::CreateBloom(int width, int height)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates eye buffers if needed
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::CreateEyeBuffers(int eye)
|
||||
{
|
||||
if (mEyeFBs.Size() > eye)
|
||||
return;
|
||||
|
||||
GLint activeTex, textureBinding, frameBufferBinding;
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding);
|
||||
|
||||
while (mEyeFBs.Size() <= eye)
|
||||
{
|
||||
GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight);
|
||||
mEyeTextures.Push(texture);
|
||||
mEyeFBs.Push(CreateFrameBuffer("EyeFB", texture));
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureBinding);
|
||||
glActiveTexture(activeTex);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferBinding);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates a 2D texture defaulting to linear filtering and clamp to edge
|
||||
|
@ -471,6 +515,43 @@ void FGLRenderBuffers::BlitSceneToTexture()
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Eye textures and their frame buffers
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::BlitToEyeTexture(int eye)
|
||||
{
|
||||
CreateEyeBuffers(eye);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mPipelineFB[mCurrentPipelineTexture]);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mEyeFBs[eye]);
|
||||
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
if ((gl.flags & RFL_INVALIDATE_BUFFER) != 0)
|
||||
{
|
||||
GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_STENCIL_ATTACHMENT };
|
||||
glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, attachments);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::BindEyeTexture(int eye, int texunit)
|
||||
{
|
||||
CreateEyeBuffers(eye);
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, mEyeTextures[eye]);
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer)
|
||||
{
|
||||
CreateEyeBuffers(eye);
|
||||
glBindFramebuffer(readBuffer ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER, mEyeFBs[eye]);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Makes the scene frame buffer active (multisample, depth, stecil, etc.)
|
||||
|
|
|
@ -32,6 +32,10 @@ public:
|
|||
|
||||
void BindOutputFB();
|
||||
|
||||
void BlitToEyeTexture(int eye);
|
||||
void BindEyeTexture(int eye, int texunit);
|
||||
void BindEyeFB(int eye, bool readBuffer = false);
|
||||
|
||||
enum { NumBloomLevels = 4 };
|
||||
FGLBloomTextureLevel BloomLevels[NumBloomLevels];
|
||||
|
||||
|
@ -43,10 +47,12 @@ public:
|
|||
private:
|
||||
void ClearScene();
|
||||
void ClearPipeline();
|
||||
void ClearEyeBuffers();
|
||||
void ClearBloom();
|
||||
void CreateScene(int width, int height, int samples);
|
||||
void CreatePipeline(int width, int height);
|
||||
void CreateBloom(int width, int height);
|
||||
void CreateEyeBuffers(int eye);
|
||||
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height);
|
||||
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
|
||||
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
|
||||
|
@ -83,6 +89,10 @@ private:
|
|||
// Back buffer frame buffer
|
||||
GLuint mOutputFB = 0;
|
||||
|
||||
// Eye buffers
|
||||
TArray<GLuint> mEyeTextures;
|
||||
TArray<GLuint> mEyeFBs;
|
||||
|
||||
static bool FailedCreate;
|
||||
static bool BuffersActive;
|
||||
};
|
||||
|
|
|
@ -173,7 +173,8 @@ public:
|
|||
void ClearTonemapPalette();
|
||||
void LensDistortScene();
|
||||
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
|
||||
void Flush() { CopyToBackbuffer(nullptr, true); }
|
||||
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
|
||||
void Flush();
|
||||
|
||||
void SetProjection(float fov, float ratio, float fovratio);
|
||||
void SetProjection(VSMatrix matrix); // raw matrix input from stereo 3d modes
|
||||
|
@ -189,6 +190,8 @@ public:
|
|||
void FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
|
||||
|
||||
int PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num);
|
||||
};
|
||||
|
||||
// Global functions. Make them members of GLRenderer later?
|
||||
|
|
|
@ -419,15 +419,17 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG
|
|||
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
gl_SetColor(lightlevel, rel, Colormap, alpha);
|
||||
gl_SetFog(lightlevel, rel, &Colormap, false);
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
||||
if (!gltexture)
|
||||
{
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
||||
gl_RenderState.EnableTexture(false);
|
||||
DrawSubsectors(pass, false, true);
|
||||
gl_RenderState.EnableTexture(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
||||
else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
||||
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
|
||||
gl_SetPlaneTextureRotation(&plane, gltexture);
|
||||
DrawSubsectors(pass, !gl.legacyMode, true);
|
||||
|
@ -477,6 +479,21 @@ inline void GLFlat::PutFlat(bool fog)
|
|||
// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.
|
||||
list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
||||
}
|
||||
else if (gltexture->GetTransparent())
|
||||
{
|
||||
if (stack)
|
||||
{
|
||||
list = GLDL_TRANSLUCENTBORDER;
|
||||
}
|
||||
else if ((renderflags&SSRF_RENDER3DPLANES) && !plane.plane.isSlope())
|
||||
{
|
||||
list = GLDL_TRANSLUCENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = GLDL_PLAINFLATS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
|
||||
|
|
|
@ -137,12 +137,7 @@ void GLPortal::ClearScreen()
|
|||
glDisable(GL_MULTISAMPLE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
FQuadDrawer qd;
|
||||
qd.Set(0, 0, 0, 0, 0, 0);
|
||||
qd.Set(1, 0, SCREENHEIGHT, 0, 0, 0);
|
||||
qd.Set(2, SCREENWIDTH, SCREENHEIGHT, 0, 0, 0);
|
||||
qd.Set(3, SCREENWIDTH, 0, 0, 0, 0);
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
gl_MatrixStack.Pop(gl_RenderState.mProjectionMatrix);
|
||||
|
|
|
@ -863,6 +863,8 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
|
|||
DrawBlend(lviewsector);
|
||||
}
|
||||
mDrawingScene2D = false;
|
||||
if (!stereo3dMode.IsMono() && FGLRenderBuffers::IsEnabled())
|
||||
mBuffers->BlitToEyeTexture(eye_ix);
|
||||
eye->TearDown();
|
||||
}
|
||||
stereo3dMode.TearDown();
|
||||
|
|
|
@ -110,17 +110,125 @@ CVAR(Bool, gl_nolayer, false, 0)
|
|||
|
||||
static const float LARGE_VALUE = 1e19f;
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLSprite::CalculateVertices(FVector3 *v)
|
||||
{
|
||||
// [BB] Billboard stuff
|
||||
const bool drawWithXYBillboard = ((particle && gl_billboard_particles) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD)
|
||||
//&& GLRenderer->mViewActor != NULL
|
||||
&& (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD))));
|
||||
|
||||
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
|
||||
// [Nash] has +ROLLSPRITE
|
||||
const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE);
|
||||
|
||||
|
||||
// [fgsfds] check sprite type mask
|
||||
DWORD spritetype = (DWORD)-1;
|
||||
if (actor != nullptr) spritetype = actor->renderflags & RF_SPRITETYPEMASK;
|
||||
|
||||
// [Nash] is a flat sprite
|
||||
const bool isFlatSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE || spritetype == RF_FLATSPRITE);
|
||||
const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER);
|
||||
|
||||
// [Nash] check for special sprite drawing modes
|
||||
if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || isFlatSprite)
|
||||
{
|
||||
// Compute center of sprite
|
||||
float xcenter = (x1 + x2)*0.5;
|
||||
float ycenter = (y1 + y2)*0.5;
|
||||
float zcenter = (z1 + z2)*0.5;
|
||||
float xx = -xcenter + x;
|
||||
float zz = -zcenter + z;
|
||||
float yy = -ycenter + y;
|
||||
Matrix3x4 mat;
|
||||
mat.MakeIdentity();
|
||||
mat.Translate(xcenter, zcenter, ycenter); // move to sprite center
|
||||
|
||||
// Order of rotations matters. Perform yaw rotation (Y, face camera) before pitch (X, tilt up/down).
|
||||
if (drawBillboardFacingCamera && !isFlatSprite)
|
||||
{
|
||||
// [CMB] Rotate relative to camera XY position, not just camera direction,
|
||||
// which is nicer in VR
|
||||
float xrel = xcenter - ViewPos.X;
|
||||
float yrel = ycenter - ViewPos.Y;
|
||||
float absAngleDeg = RAD2DEG(atan2(-yrel, xrel));
|
||||
float counterRotationDeg = 270. - GLRenderer->mAngles.Yaw.Degrees; // counteracts existing sprite rotation
|
||||
float relAngleDeg = counterRotationDeg + absAngleDeg;
|
||||
|
||||
mat.Rotate(0, 1, 0, relAngleDeg);
|
||||
}
|
||||
|
||||
// [fgsfds] calculate yaw vectors
|
||||
float yawvecX = 0, yawvecY = 0, rollDegrees = 0;
|
||||
float angleRad = (270. - GLRenderer->mAngles.Yaw).Radians();
|
||||
if (actor) rollDegrees = actor->Angles.Roll.Degrees;
|
||||
if (isFlatSprite)
|
||||
{
|
||||
yawvecX = actor->Angles.Yaw.Cos();
|
||||
yawvecY = actor->Angles.Yaw.Sin();
|
||||
}
|
||||
|
||||
// [fgsfds] Rotate the sprite about the sight vector (roll)
|
||||
if (spritetype == RF_WALLSPRITE)
|
||||
{
|
||||
mat.Rotate(0, 1, 0, 0);
|
||||
if (drawRollSpriteActor)
|
||||
{
|
||||
if (useOffsets) mat.Translate(xx, zz, yy);
|
||||
mat.Rotate(yawvecX, 0, yawvecY, rollDegrees);
|
||||
if (useOffsets) mat.Translate(-xx, -zz, -yy);
|
||||
}
|
||||
}
|
||||
else if (drawRollSpriteActor)
|
||||
{
|
||||
if (useOffsets) mat.Translate(xx, zz, yy);
|
||||
if (drawWithXYBillboard)
|
||||
{
|
||||
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
|
||||
}
|
||||
mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees);
|
||||
if (useOffsets) mat.Translate(-xx, -zz, -yy);
|
||||
}
|
||||
else if (drawWithXYBillboard)
|
||||
{
|
||||
// Rotate the sprite about the vector starting at the center of the sprite
|
||||
// triangle strip and with direction orthogonal to where the player is looking
|
||||
// in the x/y plane.
|
||||
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
|
||||
}
|
||||
|
||||
mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center
|
||||
v[0] = mat * FVector3(x1, z1, y1);
|
||||
v[1] = mat * FVector3(x2, z1, y2);
|
||||
v[2] = mat * FVector3(x1, z2, y1);
|
||||
v[3] = mat * FVector3(x2, z2, y2);
|
||||
}
|
||||
else // traditional "Y" billboard mode
|
||||
{
|
||||
v[0] = FVector3(x1, z1, y1);
|
||||
v[1] = FVector3(x2, z1, y2);
|
||||
v[2] = FVector3(x1, z2, y1);
|
||||
v[3] = FVector3(x2, z2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLSprite::Draw(int pass)
|
||||
{
|
||||
if (pass == GLPASS_DECALS || pass == GLPASS_LIGHTSONLY) return;
|
||||
|
||||
|
||||
|
||||
bool additivefog = false;
|
||||
bool foglayer = false;
|
||||
int rel = fullbright? 0 : getExtraLight();
|
||||
|
@ -264,147 +372,23 @@ void GLSprite::Draw(int pass)
|
|||
|
||||
if (!modelframe)
|
||||
{
|
||||
// [BB] Billboard stuff
|
||||
const bool drawWithXYBillboard = ((particle && gl_billboard_particles) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD)
|
||||
//&& GLRenderer->mViewActor != NULL
|
||||
&& (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD))));
|
||||
|
||||
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
|
||||
// [Nash] has +ROLLSPRITE
|
||||
const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE);
|
||||
gl_RenderState.Apply();
|
||||
|
||||
FVector3 v1;
|
||||
FVector3 v2;
|
||||
FVector3 v3;
|
||||
FVector3 v4;
|
||||
|
||||
// [fgsfds] check sprite type mask
|
||||
DWORD spritetype = (DWORD)-1;
|
||||
if (actor != nullptr) spritetype = actor->renderflags & RF_SPRITETYPEMASK;
|
||||
|
||||
// [Nash] is a flat sprite
|
||||
const bool isFlatSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE || spritetype == RF_FLATSPRITE);
|
||||
const bool dontFlip = (actor != nullptr) && (actor->renderflags & RF_DONTFLIP);
|
||||
const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER);
|
||||
|
||||
// [Nash] check for special sprite drawing modes
|
||||
if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || isFlatSprite)
|
||||
FVector3 v[4];
|
||||
if ((actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE)
|
||||
{
|
||||
// Compute center of sprite
|
||||
float xcenter = (x1 + x2)*0.5;
|
||||
float ycenter = (y1 + y2)*0.5;
|
||||
float zcenter = (z1 + z2)*0.5;
|
||||
float xx = -xcenter + x;
|
||||
float zz = -zcenter + z;
|
||||
float yy = -ycenter + y;
|
||||
Matrix3x4 mat;
|
||||
mat.MakeIdentity();
|
||||
mat.Translate(xcenter, zcenter, ycenter); // move to sprite center
|
||||
|
||||
// Order of rotations matters. Perform yaw rotation (Y, face camera) before pitch (X, tilt up/down).
|
||||
if (drawBillboardFacingCamera && !isFlatSprite)
|
||||
{
|
||||
// [CMB] Rotate relative to camera XY position, not just camera direction,
|
||||
// which is nicer in VR
|
||||
float xrel = xcenter - ViewPos.X;
|
||||
float yrel = ycenter - ViewPos.Y;
|
||||
float absAngleDeg = RAD2DEG(atan2(-yrel, xrel));
|
||||
float counterRotationDeg = 270. - GLRenderer->mAngles.Yaw.Degrees; // counteracts existing sprite rotation
|
||||
float relAngleDeg = counterRotationDeg + absAngleDeg;
|
||||
|
||||
mat.Rotate(0, 1, 0, relAngleDeg);
|
||||
}
|
||||
|
||||
// [fgsfds] calculate yaw vectors
|
||||
float yawvecX = 0, yawvecY = 0, rollDegrees = 0;
|
||||
float angleRad = (270. - GLRenderer->mAngles.Yaw).Radians();
|
||||
if (actor) rollDegrees = actor->Angles.Roll.Degrees;
|
||||
if (isFlatSprite)
|
||||
{
|
||||
yawvecX = actor->Angles.Yaw.Cos();
|
||||
yawvecY = actor->Angles.Yaw.Sin();
|
||||
}
|
||||
|
||||
// [MC] This is the only thing that I changed in Nash's submission which
|
||||
// was constantly applying roll to everything. That was wrong. Flat sprites
|
||||
// with roll literally look like paper thing space ships trying to swerve.
|
||||
// However, it does well with wall sprites.
|
||||
// Also, renamed FLOORSPRITE to FLATSPRITE because that's technically incorrect.
|
||||
// I plan on adding proper FLOORSPRITEs which can actually curve along sloped
|
||||
// 3D floors later... if possible.
|
||||
|
||||
// Here we need some form of priority in order to work.
|
||||
if (spritetype == RF_FLATSPRITE)
|
||||
{
|
||||
float pitchDegrees = -actor->Angles.Pitch.Degrees;
|
||||
DVector3 apos = { x, y, z };
|
||||
DVector3 diff = ViewPos - apos;
|
||||
DAngle angto = diff.Angle();
|
||||
|
||||
angto = deltaangle(actor->Angles.Yaw, angto);
|
||||
|
||||
bool noFlipSprite = (!dontFlip || (fabs(angto) < 90.));
|
||||
mat.Rotate(0, 1, 0, (noFlipSprite) ? 0 : 180);
|
||||
|
||||
mat.Rotate(-yawvecY, 0, yawvecX, (noFlipSprite) ? -pitchDegrees : pitchDegrees);
|
||||
if (drawRollSpriteActor)
|
||||
{
|
||||
if (useOffsets) mat.Translate(xx, zz, yy);
|
||||
mat.Rotate(yawvecX, 0, yawvecY, (noFlipSprite) ? -rollDegrees : rollDegrees);
|
||||
if (useOffsets) mat.Translate(-xx, -zz, -yy);
|
||||
}
|
||||
}
|
||||
// [fgsfds] Rotate the sprite about the sight vector (roll)
|
||||
else if (spritetype == RF_WALLSPRITE)
|
||||
{
|
||||
mat.Rotate(0, 1, 0, 0);
|
||||
if (drawRollSpriteActor)
|
||||
{
|
||||
if (useOffsets) mat.Translate(xx, zz, yy);
|
||||
mat.Rotate(yawvecX, 0, yawvecY, rollDegrees);
|
||||
if (useOffsets) mat.Translate(-xx, -zz, -yy);
|
||||
}
|
||||
}
|
||||
else if (drawRollSpriteActor)
|
||||
{
|
||||
if (useOffsets) mat.Translate(xx, zz, yy);
|
||||
if (drawWithXYBillboard)
|
||||
{
|
||||
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
|
||||
}
|
||||
mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees);
|
||||
if (useOffsets) mat.Translate(-xx, -zz, -yy);
|
||||
}
|
||||
|
||||
// apply the transform
|
||||
else if (drawWithXYBillboard)
|
||||
{
|
||||
// Rotate the sprite about the vector starting at the center of the sprite
|
||||
// triangle strip and with direction orthogonal to where the player is looking
|
||||
// in the x/y plane.
|
||||
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
|
||||
}
|
||||
|
||||
mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center
|
||||
v1 = mat * FVector3(x1, z1, y1);
|
||||
v2 = mat * FVector3(x2, z1, y2);
|
||||
v3 = mat * FVector3(x1, z2, y1);
|
||||
v4 = mat * FVector3(x2, z2, y2);
|
||||
}
|
||||
else // traditional "Y" billboard mode
|
||||
else
|
||||
{
|
||||
v1 = FVector3(x1, z1, y1);
|
||||
v2 = FVector3(x2, z1, y2);
|
||||
v3 = FVector3(x1, z2, y1);
|
||||
v4 = FVector3(x2, z2, y2);
|
||||
CalculateVertices(v);
|
||||
}
|
||||
|
||||
|
||||
FQuadDrawer qd;
|
||||
qd.Set(0, v1[0], v1[1], v1[2], ul, vt);
|
||||
qd.Set(1, v2[0], v2[1], v2[2], ur, vt);
|
||||
qd.Set(2, v3[0], v3[1], v3[2], ul, vb);
|
||||
qd.Set(3, v4[0], v4[1], v4[2], ur, vb);
|
||||
qd.Set(0, v[0][0], v[0][1], v[0][2], ul, vt);
|
||||
qd.Set(1, v[1][0], v[1][1], v[1][2], ur, vt);
|
||||
qd.Set(2, v[2][0], v[2][1], v[2][2], ul, vb);
|
||||
qd.Set(3, v[3][0], v[3][1], v[3][2], ur, vb);
|
||||
qd.Render(GL_TRIANGLE_STRIP);
|
||||
|
||||
if (foglayer)
|
||||
|
@ -453,7 +437,7 @@ inline void GLSprite::PutSprite(bool translucent)
|
|||
{
|
||||
int list;
|
||||
// [BB] Allow models to be drawn in the GLDL_TRANSLUCENT pass.
|
||||
if (translucent || !modelframe)
|
||||
if (translucent || (!modelframe && (actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE))
|
||||
{
|
||||
list = GLDL_TRANSLUCENT;
|
||||
}
|
||||
|
@ -703,7 +687,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
|
|||
x = thingpos.X;
|
||||
z = thingpos.Z;
|
||||
y = thingpos.Y;
|
||||
if (spritetype == RF_FLATSPRITE) z -= thing->Floorclip;
|
||||
if (spritetype == RF_FACESPRITE) z -= thing->Floorclip; // wall and flat sprites are to be considered level geometry so this may not apply.
|
||||
|
||||
// [RH] Make floatbobbing a renderer-only effect.
|
||||
if (thing->flags2 & MF2_FLOATBOB)
|
||||
|
@ -719,9 +703,19 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
|
|||
DAngle ang = (thingpos - ViewPos).Angle();
|
||||
FTextureID patch;
|
||||
if (thing->flags7 & MF7_SPRITEANGLE)
|
||||
{
|
||||
patch = gl_GetSpriteFrame(spritenum, thing->frame, -1, (thing->SpriteAngle).BAMs(), &mirror);
|
||||
else
|
||||
}
|
||||
else if (!(thing->renderflags & RF_FLATSPRITE))
|
||||
{
|
||||
patch = gl_GetSpriteFrame(spritenum, thing->frame, -1, (ang - (thing->Angles.Yaw + thing->SpriteRotation)).BAMs(), &mirror);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flat sprites cannot rotate in a predictable manner.
|
||||
patch = gl_GetSpriteFrame(spritenum, thing->frame, 0, 0, &mirror);
|
||||
}
|
||||
|
||||
if (!patch.isValid()) return;
|
||||
int type = thing->renderflags & RF_SPRITETYPEMASK;
|
||||
gltexture = FMaterial::ValidateTexture(patch, (type == RF_FACESPRITE), false);
|
||||
|
@ -773,6 +767,9 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
|
|||
break;
|
||||
|
||||
case RF_FLATSPRITE:
|
||||
// needs careful rethinking
|
||||
return;
|
||||
|
||||
case RF_WALLSPRITE:
|
||||
viewvecX = thing->Angles.Yaw.Cos();
|
||||
viewvecY = thing->Angles.Yaw.Sin();
|
||||
|
@ -902,8 +899,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
|
|||
// This is a non-translucent sprite (i.e. STYLE_Normal or equivalent)
|
||||
trans=1.f;
|
||||
|
||||
|
||||
if (!gl_sprite_blend || modelframe)
|
||||
if (!gl_sprite_blend || modelframe || (thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
|
||||
{
|
||||
RenderStyle.SrcAlpha = STYLEALPHA_One;
|
||||
RenderStyle.DestAlpha = STYLEALPHA_Zero;
|
||||
|
|
|
@ -371,6 +371,7 @@ public:
|
|||
void SplitSprite(sector_t * frontsector, bool translucent);
|
||||
void SetLowerParam();
|
||||
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
|
||||
void CalculateVertices(FVector3 *v);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
*/
|
||||
|
||||
#include "gl_anaglyph.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
@ -44,6 +46,25 @@ MaskAnaglyph::MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters)
|
|||
eye_ptrs.Push(&rightEye);
|
||||
}
|
||||
|
||||
void MaskAnaglyph::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
|
||||
gl_RenderState.SetColorMask(leftEye.GetColorMask().r, leftEye.GetColorMask().g, leftEye.GetColorMask().b, true);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
|
||||
gl_RenderState.SetColorMask(rightEye.GetColorMask().r, rightEye.GetColorMask().g, rightEye.GetColorMask().b, true);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
|
||||
gl_RenderState.ResetColorMask();
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
const GreenMagenta& GreenMagenta::getInstance(float ipd)
|
||||
|
|
|
@ -61,14 +61,8 @@ class AnaglyphLeftPose : public LeftEyePose
|
|||
{
|
||||
public:
|
||||
AnaglyphLeftPose(const ColorMask& colorMask, float ipd) : LeftEyePose(ipd), colorMask(colorMask) {}
|
||||
virtual void SetUp() const {
|
||||
gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
virtual void TearDown() const {
|
||||
gl_RenderState.ResetColorMask();
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
ColorMask GetColorMask() const { return colorMask; }
|
||||
|
||||
private:
|
||||
ColorMask colorMask;
|
||||
};
|
||||
|
@ -77,14 +71,8 @@ class AnaglyphRightPose : public RightEyePose
|
|||
{
|
||||
public:
|
||||
AnaglyphRightPose(const ColorMask& colorMask, float ipd) : RightEyePose(ipd), colorMask(colorMask) {}
|
||||
virtual void SetUp() const {
|
||||
gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true);
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
virtual void TearDown() const {
|
||||
gl_RenderState.ResetColorMask();
|
||||
gl_RenderState.ApplyColorMask();
|
||||
}
|
||||
ColorMask GetColorMask() const { return colorMask; }
|
||||
|
||||
private:
|
||||
ColorMask colorMask;
|
||||
};
|
||||
|
@ -93,6 +81,7 @@ class MaskAnaglyph : public Stereo3DMode
|
|||
{
|
||||
public:
|
||||
MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters);
|
||||
void Present() const override;
|
||||
private:
|
||||
AnaglyphLeftPose leftEye;
|
||||
AnaglyphRightPose rightEye;
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
*/
|
||||
|
||||
#include "gl_quadstereo.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
|
||||
namespace s3d {
|
||||
|
||||
|
@ -43,20 +45,75 @@ QuadStereo::QuadStereo(double ipdMeters)
|
|||
// Check whether quad-buffered stereo is supported in the current context
|
||||
// We are assuming the OpenGL context is already current at this point,
|
||||
// i.e. this constructor is called "just in time".
|
||||
GLboolean supportsStereo, supportsBuffered;
|
||||
glGetBooleanv(GL_STEREO, &supportsStereo);
|
||||
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
|
||||
bool bQuadStereoSupported = supportsStereo && supportsBuffered;
|
||||
leftEye.bQuadStereoSupported = bQuadStereoSupported;
|
||||
rightEye.bQuadStereoSupported = bQuadStereoSupported;
|
||||
|
||||
eye_ptrs.Push(&leftEye);
|
||||
// If stereo is not supported, just draw scene once (left eye view only)
|
||||
if (bQuadStereoSupported) {
|
||||
eye_ptrs.Push(&rightEye);
|
||||
// First initialize to mono-ish initial state
|
||||
bQuadStereoSupported = leftEye.bQuadStereoSupported = rightEye.bQuadStereoSupported = false;
|
||||
eye_ptrs.Push(&leftEye); // We ALWAYS want to show at least this one view...
|
||||
// We will possibly advance to true stereo mode in the Setup() method...
|
||||
}
|
||||
|
||||
// Sometimes the stereo render context is not ready immediately at start up
|
||||
/* private */
|
||||
void QuadStereo::checkInitialRenderContextState()
|
||||
{
|
||||
// Keep trying until we see at least one good OpenGL context to render to
|
||||
static bool bDecentContextWasFound = false;
|
||||
if (!bDecentContextWasFound) {
|
||||
// I'm using a "random" OpenGL call (glGetFramebufferAttachmentParameteriv)
|
||||
// that appears to correlate with whether the context is ready
|
||||
GLint attachmentType = GL_NONE;
|
||||
glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
|
||||
if (attachmentType != GL_NONE) // Finally, a useful OpenGL context
|
||||
{
|
||||
// This block will be executed exactly ONCE during a game run
|
||||
bDecentContextWasFound = true; // now we can stop checking every frame...
|
||||
// Now check whether this context supports hardware stereo
|
||||
GLboolean supportsStereo, supportsBuffered;
|
||||
glGetBooleanv(GL_STEREO, &supportsStereo);
|
||||
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
|
||||
bQuadStereoSupported = supportsStereo && supportsBuffered;
|
||||
leftEye.bQuadStereoSupported = bQuadStereoSupported;
|
||||
rightEye.bQuadStereoSupported = bQuadStereoSupported;
|
||||
if (bQuadStereoSupported)
|
||||
eye_ptrs.Push(&rightEye); // Use the other eye too, if we can do stereo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuadStereo::Present() const
|
||||
{
|
||||
if (bQuadStereoSupported)
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
|
||||
glDrawBuffer(GL_BACK_LEFT);
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
|
||||
glDrawBuffer(GL_BACK_RIGHT);
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(1, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
}
|
||||
}
|
||||
|
||||
void QuadStereo::SetUp() const
|
||||
{
|
||||
Stereo3DMode::SetUp();
|
||||
// Maybe advance to true stereo mode (ONCE), after the stereo context is finally ready
|
||||
const_cast<QuadStereo*>(this)->checkInitialRenderContextState();
|
||||
}
|
||||
|
||||
/* static */
|
||||
const QuadStereo& QuadStereo::getInstance(float ipd)
|
||||
{
|
||||
|
|
|
@ -47,14 +47,6 @@ class QuadStereoLeftPose : public LeftEyePose
|
|||
{
|
||||
public:
|
||||
QuadStereoLeftPose(float ipd) : LeftEyePose(ipd), bQuadStereoSupported(false) {}
|
||||
virtual void SetUp() const {
|
||||
if (bQuadStereoSupported)
|
||||
glDrawBuffer(GL_BACK_LEFT);
|
||||
}
|
||||
virtual void TearDown() const {
|
||||
if (bQuadStereoSupported)
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
bool bQuadStereoSupported;
|
||||
};
|
||||
|
||||
|
@ -62,14 +54,6 @@ class QuadStereoRightPose : public RightEyePose
|
|||
{
|
||||
public:
|
||||
QuadStereoRightPose(float ipd) : RightEyePose(ipd), bQuadStereoSupported(false){}
|
||||
virtual void SetUp() const {
|
||||
if (bQuadStereoSupported)
|
||||
glDrawBuffer(GL_BACK_RIGHT);
|
||||
}
|
||||
virtual void TearDown() const {
|
||||
if (bQuadStereoSupported)
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
bool bQuadStereoSupported;
|
||||
};
|
||||
|
||||
|
@ -84,10 +68,14 @@ class QuadStereo : public Stereo3DMode
|
|||
{
|
||||
public:
|
||||
QuadStereo(double ipdMeters);
|
||||
void Present() const override;
|
||||
void SetUp() const override;
|
||||
static const QuadStereo& getInstance(float ipd);
|
||||
private:
|
||||
QuadStereoLeftPose leftEye;
|
||||
QuadStereoRightPose rightEye;
|
||||
bool bQuadStereoSupported;
|
||||
void checkInitialRenderContextState();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@ public:
|
|||
virtual void SetUp() const {};
|
||||
virtual void TearDown() const {};
|
||||
|
||||
virtual bool IsMono() const { return false; }
|
||||
virtual void Present() const = 0;
|
||||
|
||||
protected:
|
||||
TArray<const EyePose *> eye_ptrs;
|
||||
|
||||
|
@ -102,6 +105,9 @@ class MonoView : public Stereo3DMode
|
|||
public:
|
||||
static const MonoView& getInstance();
|
||||
|
||||
bool IsMono() const override { return true; }
|
||||
void Present() const override { }
|
||||
|
||||
protected:
|
||||
MonoView() { eye_ptrs.Push(¢ralEye); }
|
||||
EyePose centralEye;
|
||||
|
|
|
@ -37,7 +37,10 @@
|
|||
#include "vectors.h" // RAD2DEG
|
||||
#include "doomtype.h" // M_PI
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include <cmath>
|
||||
|
||||
EXTERN_CVAR(Float, vr_screendist)
|
||||
|
@ -89,6 +92,13 @@ const LeftEyeView& LeftEyeView::getInstance(float ipd)
|
|||
return instance;
|
||||
}
|
||||
|
||||
void LeftEyeView::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
}
|
||||
|
||||
/* static */
|
||||
const RightEyeView& RightEyeView::getInstance(float ipd)
|
||||
|
@ -98,5 +108,13 @@ const RightEyeView& RightEyeView::getInstance(float ipd)
|
|||
return instance;
|
||||
}
|
||||
|
||||
void RightEyeView::Present() const
|
||||
{
|
||||
GLRenderer->mBuffers->BindOutputFB();
|
||||
GLRenderer->ClearBorders();
|
||||
GLRenderer->mBuffers->BindEyeTexture(0, 0);
|
||||
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace s3d */
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
LeftEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); }
|
||||
float getIpd() const { return eye.getIpd(); }
|
||||
void setIpd(float ipd) { eye.setIpd(ipd); }
|
||||
void Present() const override;
|
||||
protected:
|
||||
LeftEyePose eye;
|
||||
};
|
||||
|
@ -96,6 +97,7 @@ public:
|
|||
RightEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); }
|
||||
float getIpd() const { return eye.getIpd(); }
|
||||
void setIpd(float ipd) { eye.setIpd(ipd); }
|
||||
void Present() const override;
|
||||
protected:
|
||||
RightEyePose eye;
|
||||
};
|
||||
|
|
|
@ -189,7 +189,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
|
|||
|
||||
void OpenGLFrameBuffer::WipeEndScreen()
|
||||
{
|
||||
GLRenderer->m2DDrawer->Flush();
|
||||
GLRenderer->m2DDrawer->Draw();
|
||||
GLRenderer->m2DDrawer->Clear();
|
||||
|
||||
const auto &viewport = GLRenderer->mScreenViewport;
|
||||
wipeendscreen = new FHardwareTexture(viewport.width, viewport.height, true);
|
||||
|
|
|
@ -267,3 +267,5 @@ public:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -4451,6 +4451,7 @@ enum EACSFunctions
|
|||
|
||||
ACSF_CheckClass = 200,
|
||||
ACSF_DamageActor, // [arookas]
|
||||
ACSF_SetActorFlag,
|
||||
|
||||
// ZDaemon
|
||||
ACSF_GetTeamScore = 19620, // (int team)
|
||||
|
@ -6046,6 +6047,34 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
return P_DamageMobj(target, inflictor, inflictor, args[4], damagetype);
|
||||
}
|
||||
|
||||
case ACSF_SetActorFlag:
|
||||
{
|
||||
int tid = args[0];
|
||||
FString flagname = FBehavior::StaticLookupString(args[1]);
|
||||
bool flagvalue = !!args[2];
|
||||
int count = 0; // Return value; number of actors affected
|
||||
if (tid == 0)
|
||||
{
|
||||
if (ModActorFlag(activator, flagname, flagvalue))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FActorIterator it(tid);
|
||||
while ((actor = it.Next()) != nullptr)
|
||||
{
|
||||
// Don't log errors when affecting many actors because things might share a TID but not share the flag
|
||||
if (ModActorFlag(actor, flagname, flagvalue, false))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -482,7 +482,7 @@ NSOpenGLPixelFormat* CreatePixelFormat(const OpenGLProfile profile)
|
|||
attributes[i++] = NSOpenGLPFAAllowOfflineRenderers;
|
||||
}
|
||||
|
||||
if (NSAppKitVersionNumber >= AppKit10_7 && OpenGLProfile::Core == profile)
|
||||
if (NSAppKitVersionNumber >= AppKit10_7 && OpenGLProfile::Core == profile && 1 == vid_renderer)
|
||||
{
|
||||
NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersion3_2Core;
|
||||
const char* const glversion = Args->CheckValue("-glversion");
|
||||
|
|
|
@ -657,7 +657,7 @@ void R_AddInterpolationPoint(const DVector3a &vec)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static double QuakePower(double factor, double intensity, double offset, double falloff, double wfalloff)
|
||||
static double QuakePower(double factor, double intensity, double offset)
|
||||
{
|
||||
double randumb;
|
||||
if (intensity == 0)
|
||||
|
@ -668,7 +668,7 @@ static double QuakePower(double factor, double intensity, double offset, double
|
|||
{
|
||||
randumb = pr_torchflicker.GenRand_Real2() * (intensity * 2) - intensity;
|
||||
}
|
||||
return factor * (wfalloff * offset + falloff * randumb);
|
||||
return factor * (offset + randumb);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -798,36 +798,36 @@ void R_SetupFrame (AActor *actor)
|
|||
|
||||
if (jiggers.RollIntensity != 0 || jiggers.RollWave != 0)
|
||||
{
|
||||
ViewRoll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave, jiggers.RFalloff, jiggers.RWFalloff);
|
||||
ViewRoll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave);
|
||||
}
|
||||
if (jiggers.RelIntensity.X != 0 || jiggers.RelOffset.X != 0)
|
||||
{
|
||||
an = camera->Angles.Yaw;
|
||||
double power = QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X, jiggers.Falloff, jiggers.WFalloff);
|
||||
double power = QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X);
|
||||
ViewPos += an.ToVector(power);
|
||||
}
|
||||
if (jiggers.RelIntensity.Y != 0 || jiggers.RelOffset.Y != 0)
|
||||
{
|
||||
an = camera->Angles.Yaw + 90;
|
||||
double power = QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y, jiggers.Falloff, jiggers.WFalloff);
|
||||
double power = QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y);
|
||||
ViewPos += an.ToVector(power);
|
||||
}
|
||||
// FIXME: Relative Z is not relative
|
||||
if (jiggers.RelIntensity.Z != 0 || jiggers.RelOffset.Z != 0)
|
||||
{
|
||||
ViewPos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z, jiggers.Falloff, jiggers.WFalloff);
|
||||
ViewPos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z);
|
||||
}
|
||||
if (jiggers.Intensity.X != 0 || jiggers.Offset.X != 0)
|
||||
{
|
||||
ViewPos.X += QuakePower(quakefactor, jiggers.Intensity.X, jiggers.Offset.X, jiggers.Falloff, jiggers.WFalloff);
|
||||
ViewPos.X += QuakePower(quakefactor, jiggers.Intensity.X, jiggers.Offset.X);
|
||||
}
|
||||
if (jiggers.Intensity.Y != 0 || jiggers.Offset.Y != 0)
|
||||
{
|
||||
ViewPos.Y += QuakePower(quakefactor, jiggers.Intensity.Y, jiggers.Offset.Y, jiggers.Falloff, jiggers.WFalloff);
|
||||
ViewPos.Y += QuakePower(quakefactor, jiggers.Intensity.Y, jiggers.Offset.Y);
|
||||
}
|
||||
if (jiggers.Intensity.Z != 0 || jiggers.Offset.Z != 0)
|
||||
{
|
||||
ViewPos.Z += QuakePower(quakefactor, jiggers.Intensity.Z, jiggers.Offset.Z, jiggers.Falloff, jiggers.WFalloff);
|
||||
ViewPos.Z += QuakePower(quakefactor, jiggers.Intensity.Z, jiggers.Offset.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,7 +380,7 @@ struct bCopyAlpha
|
|||
};
|
||||
|
||||
struct bOverlay
|
||||
{
|
||||
{
|
||||
static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (s*a + d*(255-a))/255; }
|
||||
static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = MAX(s,d); }
|
||||
static __forceinline bool ProcessAlpha0() { return false; }
|
||||
|
|
|
@ -628,8 +628,9 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota
|
|||
{
|
||||
ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info);
|
||||
}
|
||||
|
||||
if (ret > retv) retv = ret;
|
||||
// treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done.
|
||||
if (ret == -1) retv = ret;
|
||||
else if (retv != -1 && ret > retv) retv = ret;
|
||||
}
|
||||
// Restore previous clipping rectangle.
|
||||
bmp->SetClipRect(saved_cr);
|
||||
|
|
|
@ -30,6 +30,7 @@ void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int in
|
|||
bool CheckDeprecatedFlags(const AActor *actor, PClassActor *info, int index);
|
||||
const char *GetFlagName(unsigned int flagnum, int flagoffset);
|
||||
void ModActorFlag(AActor *actor, FFlagDef *fd, bool set);
|
||||
bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror = true);
|
||||
INTBOOL CheckActorFlag(const AActor *actor, FFlagDef *fd);
|
||||
INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror = true);
|
||||
|
||||
|
|
|
@ -1422,7 +1422,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
|
|||
damagetype = self->DamageType;
|
||||
}
|
||||
|
||||
int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, flags, fulldmgdistance);
|
||||
int pflags = 0;
|
||||
if (flags & XF_HURTSOURCE) pflags |= RADF_HURTSOURCE;
|
||||
if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT;
|
||||
|
||||
int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, pflags, fulldmgdistance);
|
||||
P_CheckSplash(self, distance);
|
||||
if (alert && self->target != NULL && self->target->player != NULL)
|
||||
{
|
||||
|
@ -4681,90 +4685,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
|
|||
PARAM_STRING (flagname);
|
||||
PARAM_BOOL (value);
|
||||
|
||||
const char *dot = strchr(flagname, '.');
|
||||
FFlagDef *fd;
|
||||
PClassActor *cls = self->GetClass();
|
||||
|
||||
if (dot != NULL)
|
||||
{
|
||||
FString part1(flagname.GetChars(), dot - flagname);
|
||||
fd = FindFlag(cls, part1, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = FindFlag(cls, flagname, NULL);
|
||||
}
|
||||
|
||||
if (fd != NULL)
|
||||
{
|
||||
bool kill_before, kill_after;
|
||||
INTBOOL item_before, item_after;
|
||||
INTBOOL secret_before, secret_after;
|
||||
|
||||
kill_before = self->CountsAsKill();
|
||||
item_before = self->flags & MF_COUNTITEM;
|
||||
secret_before = self->flags5 & MF5_COUNTSECRET;
|
||||
|
||||
if (fd->structoffset == -1)
|
||||
{
|
||||
HandleDeprecatedFlags(self, cls, value, fd->flagbit);
|
||||
}
|
||||
else
|
||||
{
|
||||
ActorFlags *flagp = (ActorFlags*) (((char*)self) + fd->structoffset);
|
||||
|
||||
// If these 2 flags get changed we need to update the blockmap and sector links.
|
||||
bool linkchange = flagp == &self->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
|
||||
|
||||
if (linkchange) self->UnlinkFromWorld();
|
||||
ModActorFlag(self, fd, value);
|
||||
if (linkchange) self->LinkToWorld();
|
||||
}
|
||||
kill_after = self->CountsAsKill();
|
||||
item_after = self->flags & MF_COUNTITEM;
|
||||
secret_after = self->flags5 & MF5_COUNTSECRET;
|
||||
// Was this monster previously worth a kill but no longer is?
|
||||
// Or vice versa?
|
||||
if (kill_before != kill_after)
|
||||
{
|
||||
if (kill_after)
|
||||
{ // It counts as a kill now.
|
||||
level.total_monsters++;
|
||||
}
|
||||
else
|
||||
{ // It no longer counts as a kill.
|
||||
level.total_monsters--;
|
||||
}
|
||||
}
|
||||
// same for items
|
||||
if (item_before != item_after)
|
||||
{
|
||||
if (item_after)
|
||||
{ // It counts as an item now.
|
||||
level.total_items++;
|
||||
}
|
||||
else
|
||||
{ // It no longer counts as an item
|
||||
level.total_items--;
|
||||
}
|
||||
}
|
||||
// and secretd
|
||||
if (secret_before != secret_after)
|
||||
{
|
||||
if (secret_after)
|
||||
{ // It counts as an secret now.
|
||||
level.total_secrets++;
|
||||
}
|
||||
else
|
||||
{ // It no longer counts as an secret
|
||||
level.total_secrets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("Unknown flag '%s' in '%s'\n", flagname.GetChars(), cls->TypeName.GetChars());
|
||||
}
|
||||
ModActorFlag(self, flagname, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4),
|
||||
|
||||
DEFINE_FLAG(MF5, DONTDRAIN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, GETOWNER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOFORWARDFALL, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5),
|
||||
|
|
|
@ -309,7 +309,8 @@ static FxExpression *ParseExpressionC (FScanner &sc, PClassActor *cls)
|
|||
static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls)
|
||||
{
|
||||
sc.GetToken();
|
||||
switch(sc.TokenType)
|
||||
int token = sc.TokenType;
|
||||
switch(token)
|
||||
{
|
||||
case '~':
|
||||
return new FxUnaryNotBitwise(ParseExpressionA (sc, cls));
|
||||
|
@ -325,7 +326,7 @@ static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls)
|
|||
|
||||
case TK_Incr:
|
||||
case TK_Decr:
|
||||
return new FxPreIncrDecr(ParseExpressionA(sc, cls), sc.TokenType);
|
||||
return new FxPreIncrDecr(ParseExpressionA(sc, cls), token);
|
||||
|
||||
default:
|
||||
sc.UnGet();
|
||||
|
|
|
@ -162,6 +162,71 @@ void ModActorFlag(AActor *actor, FFlagDef *fd, bool set)
|
|||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Finds a flag by name and sets or clears it
|
||||
//
|
||||
// Returns true if the flag was found for the actor; else returns false
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (actor != NULL)
|
||||
{
|
||||
const char *dot = strchr(flagname, '.');
|
||||
FFlagDef *fd;
|
||||
PClassActor *cls = actor->GetClass();
|
||||
|
||||
if (dot != NULL)
|
||||
{
|
||||
FString part1(flagname.GetChars(), dot - flagname);
|
||||
fd = FindFlag(cls, part1, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = FindFlag(cls, flagname, NULL);
|
||||
}
|
||||
|
||||
if (fd != NULL)
|
||||
{
|
||||
found = true;
|
||||
|
||||
if (actor->CountsAsKill() && actor->health > 0) --level.total_monsters;
|
||||
if (actor->flags & MF_COUNTITEM) --level.total_items;
|
||||
if (actor->flags5 & MF5_COUNTSECRET) --level.total_secrets;
|
||||
|
||||
if (fd->structoffset == -1)
|
||||
{
|
||||
HandleDeprecatedFlags(actor, cls, set, fd->flagbit);
|
||||
}
|
||||
else
|
||||
{
|
||||
ActorFlags *flagp = (ActorFlags*)(((char*)actor) + fd->structoffset);
|
||||
|
||||
// If these 2 flags get changed we need to update the blockmap and sector links.
|
||||
bool linkchange = flagp == &actor->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
|
||||
|
||||
if (linkchange) actor->UnlinkFromWorld();
|
||||
ModActorFlag(actor, fd, set);
|
||||
if (linkchange) actor->LinkToWorld();
|
||||
}
|
||||
|
||||
if (actor->CountsAsKill() && actor->health > 0) ++level.total_monsters;
|
||||
if (actor->flags & MF_COUNTITEM) ++level.total_items;
|
||||
if (actor->flags5 & MF5_COUNTSECRET) ++level.total_secrets;
|
||||
}
|
||||
else if (printerror)
|
||||
{
|
||||
DPrintf(DMSG_ERROR, "ACS/DECORATE: '%s' is not a flag in '%s'\n", flagname.GetChars(), cls->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Returns whether an actor flag is true or not.
|
||||
|
|
|
@ -57,6 +57,14 @@
|
|||
#include "colormatcher.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
||||
CUSTOM_CVAR(Int, uiscale, 2, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||
{
|
||||
if (StatusBar != NULL)
|
||||
{
|
||||
StatusBar->ScreenSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// [RH] Stretch values to make a 320x200 image best fit the screen
|
||||
// without using fractional steppings
|
||||
int CleanXfac, CleanYfac;
|
||||
|
@ -70,7 +78,7 @@ int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
|
|||
// FillSimplePoly uses this
|
||||
extern "C" short spanend[MAXHEIGHT];
|
||||
|
||||
CVAR (Bool, hud_scale, false, CVAR_ARCHIVE);
|
||||
CVAR (Bool, hud_scale, true, CVAR_ARCHIVE);
|
||||
|
||||
// For routines that take RGB colors, cache the previous lookup in case there
|
||||
// are several repetitions with the same color.
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "menu/menu.h"
|
||||
#include "r_data/voxels.h"
|
||||
|
||||
int active_con_scale();
|
||||
|
||||
FRenderer *Renderer;
|
||||
|
||||
|
@ -858,10 +859,20 @@ void DFrameBuffer::DrawRateStuff ()
|
|||
int chars;
|
||||
int rate_x;
|
||||
|
||||
int textScale = active_con_scale();
|
||||
if (textScale == 0)
|
||||
textScale = CleanXfac;
|
||||
|
||||
chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount);
|
||||
rate_x = Width - ConFont->StringWidth(&fpsbuff[0]);
|
||||
Clear (rate_x, 0, Width, ConFont->GetHeight(), GPalette.BlackIndex, 0);
|
||||
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
|
||||
rate_x = Width / textScale - ConFont->StringWidth(&fpsbuff[0]);
|
||||
Clear (rate_x * textScale, 0, Width, ConFont->GetHeight() * textScale, GPalette.BlackIndex, 0);
|
||||
if (textScale == 1)
|
||||
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
|
||||
else
|
||||
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0],
|
||||
DTA_VirtualWidth, screen->GetWidth() / textScale,
|
||||
DTA_VirtualHeight, screen->GetHeight() / textScale,
|
||||
DTA_KeepRatio, true, TAG_DONE);
|
||||
|
||||
DWORD thisSec = ms/1000;
|
||||
if (LastSec < thisSec)
|
||||
|
|
|
@ -522,4 +522,6 @@ inline bool Is54Aspect(int ratio) {
|
|||
return ratio == 4;
|
||||
}
|
||||
|
||||
EXTERN_CVAR(Int, uiscale);
|
||||
|
||||
#endif // __V_VIDEO_H__
|
||||
|
|
|
@ -1807,6 +1807,7 @@ DSPLYMNU_STILLBOB = "View bob amount while not moving";
|
|||
HUDMNU_TITLE = "HUD Options";
|
||||
HUDMNU_ALTHUD = "Alternative HUD";
|
||||
HUDMNU_MESSAGE = "Message Options";
|
||||
HUDMNU_UISCALE = "User interface scale";
|
||||
HUDMNU_CROSSHAIR = "Default Crosshair";
|
||||
HUDMNU_FORCECROSSHAIR = "Force default crosshair";
|
||||
HUDMNU_GROWCROSSHAIR = "Grow crosshair when picking up items";
|
||||
|
@ -1946,6 +1947,7 @@ MSGMNU_SHOWMESSAGES = "Show messages";
|
|||
MSGMNU_SHOWOBITUARIES = "Show obituaries";
|
||||
MSGMNU_SHOWSECRETS = "Show secret notifications";
|
||||
MSGMNU_SCALETEXT = "Scale text in high res";
|
||||
MSGMNU_SCALECONSOLE = "Scale console";
|
||||
MSGMNU_MESSAGELEVEL = "Minimum message level";
|
||||
MSGMNU_CENTERMESSAGES = "Center messages";
|
||||
MSGMNU_MESSAGECOLORS = "Message Colors";
|
||||
|
@ -2237,6 +2239,7 @@ OPTVAL_ANIMATED = "Animated";
|
|||
OPTVAL_ROTATED = "Rotated";
|
||||
OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only";
|
||||
OPTVAL_DOUBLE = "Double";
|
||||
OPTVAL_TRIPLE = "Triple";
|
||||
OPTVAL_QUADRUPLE = "Quadruple";
|
||||
OPTVAL_ITEMPICKUP = "Item Pickup";
|
||||
OPTVAL_OBITUARIES = "Obituaries";
|
||||
|
|
|
@ -768,6 +768,8 @@ OptionMenu "HUDOptions"
|
|||
Submenu "$HUDMNU_ALTHUD", "AltHudOptions"
|
||||
Submenu "$HUDMNU_MESSAGE", "MessageOptions"
|
||||
StaticText " "
|
||||
Slider "$HUDMNU_UISCALE", "uiscale", 0.0, 8.0, 1.0, 0
|
||||
StaticText " "
|
||||
Option "$HUDMNU_CROSSHAIR", "crosshair", "Crosshairs"
|
||||
Option "$HUDMNU_FORCECROSSHAIR", "crosshairforce", "OnOff"
|
||||
Option "$HUDMNU_GROWCROSSHAIR", "crosshairgrow", "OnOff"
|
||||
|
@ -802,6 +804,7 @@ OptionValue "AMCoordinates"
|
|||
OptionValue "AltHUDScale"
|
||||
{
|
||||
0, "$OPTVAL_OFF"
|
||||
4, "$OPTVAL_ON"
|
||||
1, "$OPTVAL_SCALETO640X400"
|
||||
2, "$OPTVAL_PIXELDOUBLE"
|
||||
3, "$OPTVAL_PIXELQUADRUPLE"
|
||||
|
@ -1124,6 +1127,15 @@ OptionValue ScaleValues
|
|||
3, "$OPTVAL_QUADRUPLE"
|
||||
}
|
||||
|
||||
OptionValue ConsoleScaleValues
|
||||
{
|
||||
1, "$OPTVAL_OFF"
|
||||
0, "$OPTVAL_ON"
|
||||
2, "$OPTVAL_DOUBLE"
|
||||
3, "$OPTVAL_TRIPLE"
|
||||
4, "$OPTVAL_QUADRUPLE"
|
||||
}
|
||||
|
||||
OptionValue MessageLevels
|
||||
{
|
||||
0.0, "$OPTVAL_ITEMPICKUP"
|
||||
|
@ -1147,6 +1159,7 @@ OptionMenu MessageOptions
|
|||
Option "$MSGMNU_SHOWOBITUARIES", "show_obituaries", "OnOff"
|
||||
Option "$MSGMNU_SHOWSECRETS", "cl_showsecretmessage", "OnOff"
|
||||
Option "$MSGMNU_SCALETEXT", "con_scaletext", "ScaleValues"
|
||||
Option "$MSGMNU_SCALECONSOLE", "con_scale", "ConsoleScaleValues"
|
||||
Option "$MSGMNU_MESSAGELEVEL", "msg", "MessageLevels"
|
||||
Option "$MSGMNU_DEVELOPER", "developer", "DevMessageLevels"
|
||||
Option "$MSGMNU_CENTERMESSAGES", "con_centernotify", "OnOff"
|
||||
|
|
Loading…
Reference in a new issue