mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 14:51:46 +00:00
- moved the drawing utilities to the abstact base statusbar function.
This commit is contained in:
parent
3f61ab7fbf
commit
196d3c32bb
6 changed files with 612 additions and 586 deletions
|
@ -44,6 +44,7 @@
|
|||
#include "vm.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
int ListGetInt(VMVa_List &tags);
|
||||
|
||||
|
||||
|
|
|
@ -42,19 +42,24 @@
|
|||
#include "cmdlib.h"
|
||||
#include "texturemanager.h"
|
||||
#include "c_cvars.h"
|
||||
#include "v_font.h"
|
||||
#include "utf8.h"
|
||||
#include "v_text.h"
|
||||
#include "vm.h"
|
||||
|
||||
FGameTexture* CrosshairImage;
|
||||
static int CrosshairNum;
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(DStatusBarCore, false, false)
|
||||
IMPLEMENT_CLASS(DStatusBarCore, true, false)
|
||||
IMPLEMENT_CLASS(DHUDFont, true, false);
|
||||
|
||||
|
||||
CVAR(Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE);
|
||||
CVAR(Int, crosshairhealth, 1, CVAR_ARCHIVE);
|
||||
CVAR(Float, crosshairscale, 1.0, CVAR_ARCHIVE);
|
||||
CVAR(Bool, crosshairgrow, false, CVAR_ARCHIVE);
|
||||
EXTERN_CVAR(Bool, vid_fps)
|
||||
|
||||
|
||||
|
||||
|
@ -228,16 +233,437 @@ void FormatNumber(int number, int minsize, int maxsize, int flags, const FString
|
|||
else fmt.Format("%s%*d", prefix.GetChars(), minsize, number);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, FormatNumber, FormatNumber)
|
||||
void DStatusBarCore::ValidateResolution(int& hres, int& vres) const
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(number);
|
||||
PARAM_INT(minsize);
|
||||
PARAM_INT(maxsize);
|
||||
PARAM_INT(flags);
|
||||
PARAM_STRING(prefix);
|
||||
FString fmt;
|
||||
FormatNumber(number, minsize, maxsize, flags, prefix, &fmt);
|
||||
ACTION_RETURN_STRING(fmt);
|
||||
if (hres == 0)
|
||||
{
|
||||
static const int HORIZONTAL_RESOLUTION_DEFAULT = 320;
|
||||
hres = HORIZONTAL_RESOLUTION_DEFAULT;
|
||||
}
|
||||
|
||||
if (vres == 0)
|
||||
{
|
||||
static const int VERTICAL_RESOLUTION_DEFAULT = 200;
|
||||
vres = VERTICAL_RESOLUTION_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::StatusbarToRealCoords(double& x, double& y, double& w, double& h) const
|
||||
{
|
||||
if (SBarScale.X == -1 || ForcedScale)
|
||||
{
|
||||
int hres = HorizontalResolution;
|
||||
int vres = VerticalResolution;
|
||||
ValidateResolution(hres, vres);
|
||||
|
||||
VirtualToRealCoords(twod, x, y, w, h, hres, vres, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = ST_X + x * SBarScale.X;
|
||||
y = ST_Y + y * SBarScale.Y;
|
||||
w *= SBarScale.X;
|
||||
h *= SBarScale.Y;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY)
|
||||
{
|
||||
if (!texture.isValid())
|
||||
return;
|
||||
|
||||
FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE));
|
||||
|
||||
double texwidth = tex->GetDisplayWidth() * scaleX;
|
||||
double texheight = tex->GetDisplayHeight() * scaleY;
|
||||
|
||||
if (boxwidth > 0 || boxheight > 0)
|
||||
{
|
||||
if (!(flags & DI_FORCEFILL))
|
||||
{
|
||||
double scale1 = 1., scale2 = 1.;
|
||||
|
||||
if (boxwidth > 0 && (boxwidth < texwidth || (flags & DI_FORCESCALE)))
|
||||
{
|
||||
scale1 = boxwidth / texwidth;
|
||||
}
|
||||
if (boxheight != -1 && (boxheight < texheight || (flags & DI_FORCESCALE)))
|
||||
{
|
||||
scale2 = boxheight / texheight;
|
||||
}
|
||||
|
||||
if (flags & DI_FORCESCALE)
|
||||
{
|
||||
if (boxwidth <= 0 || (boxheight > 0 && scale2 < scale1))
|
||||
scale1 = scale2;
|
||||
}
|
||||
else scale1 = MIN(scale1, scale2);
|
||||
|
||||
boxwidth = texwidth * scale1;
|
||||
boxheight = texheight * scale1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boxwidth = texwidth;
|
||||
boxheight = texheight;
|
||||
}
|
||||
|
||||
// resolve auto-alignment before making any adjustments to the position values.
|
||||
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
|
||||
{
|
||||
if (x < 0) flags |= DI_SCREEN_RIGHT;
|
||||
else flags |= DI_SCREEN_LEFT;
|
||||
if (y < 0) flags |= DI_SCREEN_BOTTOM;
|
||||
else flags |= DI_SCREEN_TOP;
|
||||
}
|
||||
|
||||
Alpha *= this->Alpha;
|
||||
if (Alpha <= 0) return;
|
||||
x += drawOffset.X;
|
||||
y += drawOffset.Y;
|
||||
|
||||
switch (flags & DI_ITEM_HMASK)
|
||||
{
|
||||
case DI_ITEM_HCENTER: x -= boxwidth / 2; break;
|
||||
case DI_ITEM_RIGHT: x -= boxwidth; break;
|
||||
case DI_ITEM_HOFFSET: x -= tex->GetDisplayLeftOffset() * boxwidth / texwidth; break;
|
||||
}
|
||||
|
||||
switch (flags & DI_ITEM_VMASK)
|
||||
{
|
||||
case DI_ITEM_VCENTER: y -= boxheight / 2; break;
|
||||
case DI_ITEM_BOTTOM: y -= boxheight; break;
|
||||
case DI_ITEM_VOFFSET: y -= tex->GetDisplayTopOffset() * boxheight / texheight; break;
|
||||
}
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
StatusbarToRealCoords(x, y, boxwidth, boxheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
double orgx, orgy;
|
||||
|
||||
switch (flags & DI_SCREEN_HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break;
|
||||
case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (flags & DI_SCREEN_VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||
}
|
||||
|
||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
||||
|
||||
DVector2 Scale = GetHUDScale();
|
||||
|
||||
x *= Scale.X;
|
||||
y *= Scale.Y;
|
||||
boxwidth *= Scale.X;
|
||||
boxheight *= Scale.Y;
|
||||
x += orgx;
|
||||
y += orgy;
|
||||
}
|
||||
DrawTexture(twod, tex, x, y,
|
||||
DTA_TopOffset, 0,
|
||||
DTA_LeftOffset, 0,
|
||||
DTA_DestWidthF, boxwidth,
|
||||
DTA_DestHeightF, boxheight,
|
||||
DTA_TranslationIndex, (flags & DI_TRANSLATABLE) ? GetTranslation() : 0,
|
||||
DTA_ColorOverlay, (flags & DI_DIM) ? MAKEARGB(170, 0, 0, 0) : 0,
|
||||
DTA_Alpha, Alpha,
|
||||
DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED),
|
||||
DTA_FillColor, (flags & DI_ALPHAMAPPED) ? 0 : -1,
|
||||
DTA_FlipX, !!(flags & DI_MIRROR),
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw a string
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY)
|
||||
{
|
||||
bool monospaced = monospacing != EMonospacing::Off;
|
||||
double dx = 0;
|
||||
int spacingparm = monospaced ? -spacing : spacing;
|
||||
|
||||
switch (flags & DI_TEXT_ALIGN)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case DI_TEXT_ALIGN_RIGHT:
|
||||
dx = font->StringWidth(cstring, spacingparm);
|
||||
break;
|
||||
case DI_TEXT_ALIGN_CENTER:
|
||||
dx = font->StringWidth(cstring, spacingparm) / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Take text scale into account
|
||||
x -= dx * scaleX;
|
||||
|
||||
const uint8_t* str = (const uint8_t*)cstring.GetChars();
|
||||
const EColorRange boldTranslation = EColorRange(translation ? translation - 1 : NumTextColors - 1);
|
||||
int fontcolor = translation;
|
||||
double orgx = 0, orgy = 0;
|
||||
DVector2 Scale;
|
||||
|
||||
if (fullscreenOffsets)
|
||||
{
|
||||
Scale = GetHUDScale();
|
||||
shadowX *= (int)Scale.X;
|
||||
shadowY *= (int)Scale.Y;
|
||||
|
||||
switch (flags & DI_SCREEN_HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break;
|
||||
case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (flags & DI_SCREEN_VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||
}
|
||||
|
||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
Scale = { 1.,1. };
|
||||
}
|
||||
int ch;
|
||||
while (ch = GetCharFromString(str), ch != '\0')
|
||||
{
|
||||
if (ch == ' ')
|
||||
{
|
||||
x += monospaced ? spacing : font->GetSpaceWidth() + spacing;
|
||||
continue;
|
||||
}
|
||||
else if (ch == TEXTCOLOR_ESCAPE)
|
||||
{
|
||||
EColorRange newColor = V_ParseFontColor(str, translation, boldTranslation);
|
||||
if (newColor != CR_UNDEFINED)
|
||||
fontcolor = newColor;
|
||||
continue;
|
||||
}
|
||||
|
||||
int width;
|
||||
auto c = font->GetChar(ch, fontcolor, &width);
|
||||
if (c == NULL) //missing character.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!monospaced) //If we are monospaced lets use the offset
|
||||
x += (c->GetDisplayLeftOffset() + 1); //ignore x offsets since we adapt to character size
|
||||
|
||||
double rx, ry, rw, rh;
|
||||
rx = x + drawOffset.X;
|
||||
ry = y + drawOffset.Y;
|
||||
rw = c->GetDisplayWidth();
|
||||
rh = c->GetDisplayHeight();
|
||||
|
||||
if (monospacing == EMonospacing::CellCenter)
|
||||
rx += (spacing - rw) / 2;
|
||||
else if (monospacing == EMonospacing::CellRight)
|
||||
rx += (spacing - rw);
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
StatusbarToRealCoords(rx, ry, rw, rh);
|
||||
}
|
||||
else
|
||||
{
|
||||
rx *= Scale.X;
|
||||
ry *= Scale.Y;
|
||||
rw *= Scale.X;
|
||||
rh *= Scale.Y;
|
||||
|
||||
rx += orgx;
|
||||
ry += orgy;
|
||||
}
|
||||
|
||||
// Apply text scale
|
||||
rw *= scaleX;
|
||||
rh *= scaleY;
|
||||
|
||||
// This is not really such a great way to draw shadows because they can overlap with previously drawn characters.
|
||||
// This may have to be changed to draw the shadow text up front separately.
|
||||
if ((shadowX != 0 || shadowY != 0) && !(flags & DI_NOSHADOW))
|
||||
{
|
||||
DrawChar(twod, font, CR_UNTRANSLATED, rx + shadowX, ry + shadowY, ch,
|
||||
DTA_DestWidthF, rw,
|
||||
DTA_DestHeightF, rh,
|
||||
DTA_Alpha, (Alpha * 0.4),
|
||||
DTA_FillColor, 0,
|
||||
TAG_DONE);
|
||||
}
|
||||
DrawChar(twod, font, fontcolor, rx, ry, ch,
|
||||
DTA_DestWidthF, rw,
|
||||
DTA_DestHeightF, rh,
|
||||
DTA_Alpha, Alpha,
|
||||
TAG_DONE);
|
||||
|
||||
dx = monospaced
|
||||
? spacing
|
||||
: width + spacing - (c->GetDisplayLeftOffset() + 1);
|
||||
|
||||
// Take text scale into account
|
||||
x += dx * scaleX;
|
||||
}
|
||||
}
|
||||
|
||||
void SBar_DrawString(DStatusBarCore* self, DHUDFont* font, const FString& string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY)
|
||||
{
|
||||
if (font == nullptr) ThrowAbortException(X_READ_NIL, nullptr);
|
||||
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||
|
||||
// resolve auto-alignment before making any adjustments to the position values.
|
||||
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
|
||||
{
|
||||
if (x < 0) flags |= DI_SCREEN_RIGHT;
|
||||
else flags |= DI_SCREEN_LEFT;
|
||||
if (y < 0) flags |= DI_SCREEN_BOTTOM;
|
||||
else flags |= DI_SCREEN_TOP;
|
||||
}
|
||||
|
||||
if (wrapwidth > 0)
|
||||
{
|
||||
auto brk = V_BreakLines(font->mFont, int(wrapwidth * scaleX), string, true);
|
||||
for (auto& line : brk)
|
||||
{
|
||||
self->DrawString(font->mFont, line.Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY, scaleX, scaleY);
|
||||
y += (font->mFont->GetHeight() + linespacing) * scaleY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->DrawString(font->mFont, string, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY, scaleX, scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::TransformRect(double& x, double& y, double& w, double& h, int flags)
|
||||
{
|
||||
// resolve auto-alignment before making any adjustments to the position values.
|
||||
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
|
||||
{
|
||||
if (x < 0) flags |= DI_SCREEN_RIGHT;
|
||||
else flags |= DI_SCREEN_LEFT;
|
||||
if (y < 0) flags |= DI_SCREEN_BOTTOM;
|
||||
else flags |= DI_SCREEN_TOP;
|
||||
}
|
||||
|
||||
x += drawOffset.X;
|
||||
y += drawOffset.Y;
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
StatusbarToRealCoords(x, y, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
double orgx, orgy;
|
||||
|
||||
switch (flags & DI_SCREEN_HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break;
|
||||
case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (flags & DI_SCREEN_VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||
}
|
||||
|
||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
||||
|
||||
DVector2 Scale = GetHUDScale();
|
||||
|
||||
x *= Scale.X;
|
||||
y *= Scale.Y;
|
||||
w *= Scale.X;
|
||||
h *= Scale.Y;
|
||||
x += orgx;
|
||||
y += orgy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::Fill(PalEntry color, double x, double y, double w, double h, int flags)
|
||||
{
|
||||
double Alpha = color.a * this->Alpha / 255;
|
||||
if (Alpha <= 0) return;
|
||||
|
||||
TransformRect(x, y, w, h, flags);
|
||||
|
||||
int x1 = int(x);
|
||||
int y1 = int(y);
|
||||
int ww = int(x + w - x1); // account for scaling to non-integers. Truncating the values separately would fail for cases like
|
||||
int hh = int(y + h - y1); // y=3.5, height = 5.5 where adding both values gives a larger integer than adding the two integers.
|
||||
|
||||
Dim(twod, color, float(Alpha), x1, y1, ww, hh);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::SetClipRect(double x, double y, double w, double h, int flags)
|
||||
{
|
||||
TransformRect(x, y, w, h, flags);
|
||||
int x1 = int(x);
|
||||
int y1 = int(y);
|
||||
int ww = int(x + w - x1); // account for scaling to non-integers. Truncating the values separately would fail for cases like
|
||||
int hh = int(y + h - y1); // y=3.5, height = 5.5 where adding both values gives a larger integer than adding the two integers.
|
||||
twod->SetClipRect(x1, y1, ww, hh);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,171 @@
|
|||
#pragma once
|
||||
|
||||
#include "dobject.h"
|
||||
#include "textureid.h"
|
||||
#include "zstring.h"
|
||||
#include "v_draw.h"
|
||||
|
||||
class FGameTexture;
|
||||
class FFont;
|
||||
extern FGameTexture* CrosshairImage;
|
||||
void ST_LoadCrosshair(int num, bool alwaysload);
|
||||
void ST_UnloadCrosshair();
|
||||
void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale);
|
||||
|
||||
|
||||
enum DI_Flags
|
||||
{
|
||||
DI_SKIPICON = 0x1,
|
||||
DI_SKIPALTICON = 0x2,
|
||||
DI_SKIPSPAWN = 0x4,
|
||||
DI_SKIPREADY = 0x8,
|
||||
DI_ALTICONFIRST = 0x10,
|
||||
DI_TRANSLATABLE = 0x20,
|
||||
DI_FORCESCALE = 0x40,
|
||||
DI_DIM = 0x80,
|
||||
DI_DRAWCURSORFIRST = 0x100, // only for DrawInventoryBar.
|
||||
DI_ALWAYSSHOWCOUNT = 0x200, // only for DrawInventoryBar.
|
||||
DI_DIMDEPLETED = 0x400,
|
||||
DI_DONTANIMATE = 0x800, // do not animate the texture
|
||||
DI_MIRROR = 0x1000, // flip the texture horizontally, like a mirror
|
||||
|
||||
DI_SCREEN_AUTO = 0, // decide based on given offsets.
|
||||
DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect
|
||||
|
||||
DI_SCREEN_TOP = DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_VCENTER = 0x8000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_BOTTOM = 0x10000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_VOFFSET = 0x18000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_VMASK = 0x18000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
|
||||
DI_SCREEN_LEFT = DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_HCENTER = 0x20000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_RIGHT = 0x40000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_HOFFSET = 0x60000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_HMASK = 0x60000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
|
||||
DI_SCREEN_LEFT_TOP = DI_SCREEN_TOP | DI_SCREEN_LEFT,
|
||||
DI_SCREEN_RIGHT_TOP = DI_SCREEN_TOP | DI_SCREEN_RIGHT,
|
||||
DI_SCREEN_LEFT_BOTTOM = DI_SCREEN_BOTTOM | DI_SCREEN_LEFT,
|
||||
DI_SCREEN_RIGHT_BOTTOM = DI_SCREEN_BOTTOM | DI_SCREEN_RIGHT,
|
||||
DI_SCREEN_CENTER = DI_SCREEN_VCENTER | DI_SCREEN_HCENTER,
|
||||
DI_SCREEN_CENTER_BOTTOM = DI_SCREEN_BOTTOM | DI_SCREEN_HCENTER,
|
||||
DI_SCREEN_OFFSETS = DI_SCREEN_HOFFSET | DI_SCREEN_VOFFSET,
|
||||
|
||||
DI_ITEM_AUTO = 0, // equivalent with bottom center, which is the default alignment.
|
||||
|
||||
DI_ITEM_TOP = 0x80000,
|
||||
DI_ITEM_VCENTER = 0x100000,
|
||||
DI_ITEM_BOTTOM = 0, // this is the default vertical alignment
|
||||
DI_ITEM_VOFFSET = 0x180000,
|
||||
DI_ITEM_VMASK = 0x180000,
|
||||
|
||||
DI_ITEM_LEFT = 0x200000,
|
||||
DI_ITEM_HCENTER = 0, // this is the deafault horizontal alignment
|
||||
DI_ITEM_RIGHT = 0x400000,
|
||||
DI_ITEM_HOFFSET = 0x600000,
|
||||
DI_ITEM_HMASK = 0x600000,
|
||||
|
||||
DI_ITEM_LEFT_TOP = DI_ITEM_TOP | DI_ITEM_LEFT,
|
||||
DI_ITEM_RIGHT_TOP = DI_ITEM_TOP | DI_ITEM_RIGHT,
|
||||
DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM | DI_ITEM_LEFT,
|
||||
DI_ITEM_RIGHT_BOTTOM = DI_ITEM_BOTTOM | DI_ITEM_RIGHT,
|
||||
DI_ITEM_CENTER = DI_ITEM_VCENTER | DI_ITEM_HCENTER,
|
||||
DI_ITEM_CENTER_BOTTOM = DI_ITEM_BOTTOM | DI_ITEM_HCENTER,
|
||||
DI_ITEM_OFFSETS = DI_ITEM_HOFFSET | DI_ITEM_VOFFSET,
|
||||
|
||||
DI_TEXT_ALIGN_LEFT = 0,
|
||||
DI_TEXT_ALIGN_RIGHT = 0x800000,
|
||||
DI_TEXT_ALIGN_CENTER = 0x1000000,
|
||||
DI_TEXT_ALIGN = 0x1800000,
|
||||
|
||||
DI_ALPHAMAPPED = 0x2000000,
|
||||
DI_NOSHADOW = 0x4000000,
|
||||
DI_ALWAYSSHOWCOUNTERS = 0x8000000,
|
||||
DI_ARTIFLASH = 0x10000000,
|
||||
DI_FORCEFILL = 0x20000000,
|
||||
|
||||
// These 2 flags are only used by SBARINFO so these duplicate other flags not used by SBARINFO
|
||||
DI_DRAWINBOX = DI_TEXT_ALIGN_RIGHT,
|
||||
DI_ALTERNATEONFAIL = DI_TEXT_ALIGN_CENTER,
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// encapsulates all settings a HUD font may need
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
class DHUDFont : public DObject
|
||||
{
|
||||
// this blocks CreateNew on this class which is the intent here.
|
||||
DECLARE_ABSTRACT_CLASS(DHUDFont, DObject);
|
||||
|
||||
public:
|
||||
FFont* mFont;
|
||||
int mSpacing;
|
||||
EMonospacing mMonospacing;
|
||||
int mShadowX;
|
||||
int mShadowY;
|
||||
|
||||
DHUDFont(FFont* f, int sp, EMonospacing ms, int sx, int sy)
|
||||
: mFont(f), mSpacing(sp), mMonospacing(ms), mShadowX(sx), mShadowY(sy)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class DStatusBarCore : public DObject
|
||||
{
|
||||
DECLARE_CLASS(DStatusBarCore, DObject)
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum EAlign
|
||||
{
|
||||
TOP = 0,
|
||||
VCENTER = 1,
|
||||
BOTTOM = 2,
|
||||
VOFFSET = 3,
|
||||
VMASK = 3,
|
||||
|
||||
LEFT = 0,
|
||||
HCENTER = 4,
|
||||
RIGHT = 8,
|
||||
HOFFSET = 12,
|
||||
HMASK = 12,
|
||||
|
||||
CENTER = VCENTER | HCENTER,
|
||||
CENTER_BOTTOM = BOTTOM | HCENTER
|
||||
};
|
||||
|
||||
int ST_X;
|
||||
int ST_Y;
|
||||
int SBarTop;
|
||||
DVector2 SBarScale;
|
||||
int RelTop;
|
||||
int HorizontalResolution, VerticalResolution;
|
||||
double Alpha = 1.;
|
||||
DVector2 drawOffset = { 0,0 }; // can be set by subclasses to offset drawing operations
|
||||
double drawClip[4] = { 0,0,0,0 }; // defines a clipping rectangle (not used yet)
|
||||
bool fullscreenOffsets = false; // current screen is displayed with fullscreen behavior.
|
||||
bool ForcedScale = false;
|
||||
|
||||
|
||||
virtual DVector2 GetHUDScale() const = 0;
|
||||
virtual uint32_t GetTranslation() const { return 0; }
|
||||
void ValidateResolution(int& hres, int& vres) const;
|
||||
void StatusbarToRealCoords(double& x, double& y, double& w, double& h) const;
|
||||
void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY);
|
||||
void DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY);
|
||||
void TransformRect(double& x, double& y, double& w, double& h, int flags = 0);
|
||||
void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0);
|
||||
void SetClipRect(double x, double y, double w, double h, int flags = 0);
|
||||
|
||||
};
|
|
@ -332,30 +332,6 @@ enum
|
|||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// encapsulates all settings a HUD font may need
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
class DHUDFont : public DObject
|
||||
{
|
||||
// this blocks CreateNew on this class which is the intent here.
|
||||
DECLARE_ABSTRACT_CLASS(DHUDFont, DObject);
|
||||
|
||||
public:
|
||||
FFont *mFont;
|
||||
int mSpacing;
|
||||
EMonospacing mMonospacing;
|
||||
int mShadowX;
|
||||
int mShadowY;
|
||||
|
||||
DHUDFont(FFont *f, int sp, EMonospacing ms, int sx, int sy)
|
||||
: mFont(f), mSpacing(sp), mMonospacing(ms), mShadowX(sx), mShadowY(sy)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
class DBaseStatusBar : public DStatusBarCore
|
||||
{
|
||||
friend class DSBarInfo;
|
||||
|
@ -392,24 +368,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
enum EAlign
|
||||
{
|
||||
TOP = 0,
|
||||
VCENTER = 1,
|
||||
BOTTOM = 2,
|
||||
VOFFSET = 3,
|
||||
VMASK = 3,
|
||||
|
||||
LEFT = 0,
|
||||
HCENTER = 4,
|
||||
RIGHT = 8,
|
||||
HOFFSET = 12,
|
||||
HMASK = 12,
|
||||
|
||||
CENTER = VCENTER | HCENTER,
|
||||
CENTER_BOTTOM = BOTTOM | HCENTER
|
||||
};
|
||||
|
||||
DBaseStatusBar ();
|
||||
void SetSize(int reltop = 32, int hres = 320, int vres = 200, int hhres = -1, int hvres = -1);
|
||||
void OnDestroy() override;
|
||||
|
@ -435,7 +393,7 @@ public:
|
|||
void DrawBottomStuff (EHudState state);
|
||||
void DrawTopStuff (EHudState state);
|
||||
void AttachToPlayer(player_t *player);
|
||||
DVector2 GetHUDScale() const;
|
||||
DVector2 GetHUDScale() const override;
|
||||
virtual void FlashCrosshair ();
|
||||
void NewGame ();
|
||||
virtual void ScreenSizeChanged ();
|
||||
|
@ -444,21 +402,14 @@ public:
|
|||
virtual bool MustDrawLog(EHudState state);
|
||||
virtual void SetMugShotState (const char *state_name, bool wait_till_done=false, bool reset=false);
|
||||
void DrawLog();
|
||||
uint32_t GetTranslation() const;
|
||||
uint32_t GetTranslation() const override;
|
||||
|
||||
void CreateAltHUD();
|
||||
void DrawAltHUD();
|
||||
|
||||
void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY);
|
||||
void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY);
|
||||
void TransformRect(double &x, double &y, double &w, double &h, int flags = 0);
|
||||
void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0);
|
||||
void SetClipRect(double x, double y, double w, double h, int flags = 0);
|
||||
|
||||
void BeginStatusBar(int resW, int resH, int relTop, bool forceScaled);
|
||||
void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false);
|
||||
bool ForceHUDScale(bool on) { std::swap(ForcedScale, on); return on; } // This is for SBARINFO which should not use BeginStatusBar or BeginHUD.
|
||||
void StatusbarToRealCoords(double &x, double &y, double &w, double &h) const;
|
||||
int GetTopOfStatusbar() const
|
||||
{
|
||||
return SBarTop;
|
||||
|
@ -481,15 +432,8 @@ public:
|
|||
void DrawCrosshair ();
|
||||
|
||||
// Sizing info for ths status bar.
|
||||
int ST_X;
|
||||
int ST_Y;
|
||||
int SBarTop;
|
||||
DVector2 SBarScale;
|
||||
int RelTop;
|
||||
int HorizontalResolution, VerticalResolution;
|
||||
bool Scaled; // This needs to go away.
|
||||
DVector2 defaultScale; // factor for fully scaled fullscreen display.
|
||||
bool ForcedScale = false;
|
||||
|
||||
bool Centering;
|
||||
bool FixedOrigin;
|
||||
|
@ -502,10 +446,6 @@ public:
|
|||
|
||||
player_t *CPlayer;
|
||||
|
||||
double Alpha = 1.;
|
||||
DVector2 drawOffset = { 0,0 }; // can be set by subclasses to offset drawing operations
|
||||
double drawClip[4] = { 0,0,0,0 }; // defines a clipping rectangle (not used yet)
|
||||
bool fullscreenOffsets = false; // current screen is displayed with fullscreen behavior.
|
||||
FMugShot mugshot;
|
||||
|
||||
private:
|
||||
|
@ -544,82 +484,4 @@ void C_MidPrint(FFont* font, const char* message, bool bold = false);
|
|||
|
||||
|
||||
|
||||
enum DI_Flags
|
||||
{
|
||||
DI_SKIPICON = 0x1,
|
||||
DI_SKIPALTICON = 0x2,
|
||||
DI_SKIPSPAWN = 0x4,
|
||||
DI_SKIPREADY = 0x8,
|
||||
DI_ALTICONFIRST = 0x10,
|
||||
DI_TRANSLATABLE = 0x20,
|
||||
DI_FORCESCALE = 0x40,
|
||||
DI_DIM = 0x80,
|
||||
DI_DRAWCURSORFIRST = 0x100, // only for DrawInventoryBar.
|
||||
DI_ALWAYSSHOWCOUNT = 0x200, // only for DrawInventoryBar.
|
||||
DI_DIMDEPLETED = 0x400,
|
||||
DI_DONTANIMATE = 0x800, // do not animate the texture
|
||||
DI_MIRROR = 0x1000, // flip the texture horizontally, like a mirror
|
||||
|
||||
DI_SCREEN_AUTO = 0, // decide based on given offsets.
|
||||
DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect
|
||||
|
||||
DI_SCREEN_TOP = DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_VCENTER = 0x8000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_BOTTOM = 0x10000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_VOFFSET = 0x18000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_VMASK = 0x18000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
|
||||
DI_SCREEN_LEFT = DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_HCENTER = 0x20000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_RIGHT = 0x40000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_HOFFSET = 0x60000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
DI_SCREEN_HMASK = 0x60000 | DI_SCREEN_MANUAL_ALIGN,
|
||||
|
||||
DI_SCREEN_LEFT_TOP = DI_SCREEN_TOP|DI_SCREEN_LEFT,
|
||||
DI_SCREEN_RIGHT_TOP = DI_SCREEN_TOP|DI_SCREEN_RIGHT,
|
||||
DI_SCREEN_LEFT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_LEFT,
|
||||
DI_SCREEN_RIGHT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_RIGHT,
|
||||
DI_SCREEN_CENTER = DI_SCREEN_VCENTER|DI_SCREEN_HCENTER,
|
||||
DI_SCREEN_CENTER_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_HCENTER,
|
||||
DI_SCREEN_OFFSETS = DI_SCREEN_HOFFSET|DI_SCREEN_VOFFSET,
|
||||
|
||||
DI_ITEM_AUTO = 0, // equivalent with bottom center, which is the default alignment.
|
||||
|
||||
DI_ITEM_TOP = 0x80000,
|
||||
DI_ITEM_VCENTER = 0x100000,
|
||||
DI_ITEM_BOTTOM = 0, // this is the default vertical alignment
|
||||
DI_ITEM_VOFFSET = 0x180000,
|
||||
DI_ITEM_VMASK = 0x180000,
|
||||
|
||||
DI_ITEM_LEFT = 0x200000,
|
||||
DI_ITEM_HCENTER = 0, // this is the deafault horizontal alignment
|
||||
DI_ITEM_RIGHT = 0x400000,
|
||||
DI_ITEM_HOFFSET = 0x600000,
|
||||
DI_ITEM_HMASK = 0x600000,
|
||||
|
||||
DI_ITEM_LEFT_TOP = DI_ITEM_TOP|DI_ITEM_LEFT,
|
||||
DI_ITEM_RIGHT_TOP = DI_ITEM_TOP|DI_ITEM_RIGHT,
|
||||
DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_LEFT,
|
||||
DI_ITEM_RIGHT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_RIGHT,
|
||||
DI_ITEM_CENTER = DI_ITEM_VCENTER|DI_ITEM_HCENTER,
|
||||
DI_ITEM_CENTER_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_HCENTER,
|
||||
DI_ITEM_OFFSETS = DI_ITEM_HOFFSET|DI_ITEM_VOFFSET,
|
||||
|
||||
DI_TEXT_ALIGN_LEFT = 0,
|
||||
DI_TEXT_ALIGN_RIGHT = 0x800000,
|
||||
DI_TEXT_ALIGN_CENTER = 0x1000000,
|
||||
DI_TEXT_ALIGN = 0x1800000,
|
||||
|
||||
DI_ALPHAMAPPED = 0x2000000,
|
||||
DI_NOSHADOW = 0x4000000,
|
||||
DI_ALWAYSSHOWCOUNTERS = 0x8000000,
|
||||
DI_ARTIFLASH = 0x10000000,
|
||||
DI_FORCEFILL = 0x20000000,
|
||||
|
||||
// These 2 flags are only used by SBARINFO so these duplicate other flags not used by SBARINFO
|
||||
DI_DRAWINBOX = DI_TEXT_ALIGN_RIGHT,
|
||||
DI_ALTERNATEONFAIL = DI_TEXT_ALIGN_CENTER,
|
||||
|
||||
};
|
||||
|
||||
#endif /* __SBAR_H__ */
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
#define XHAIRPICKUPSIZE (2+XHAIRSHRINKSIZE)
|
||||
#define POWERUPICONSIZE 32
|
||||
|
||||
IMPLEMENT_CLASS(DHUDFont, true, false);
|
||||
IMPLEMENT_CLASS(DBaseStatusBar, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DBaseStatusBar)
|
||||
|
@ -401,21 +400,6 @@ DBaseStatusBar::DBaseStatusBar ()
|
|||
CreateAltHUD();
|
||||
}
|
||||
|
||||
static void ValidateResolution(int &hres, int &vres)
|
||||
{
|
||||
if (hres == 0)
|
||||
{
|
||||
static const int HORIZONTAL_RESOLUTION_DEFAULT = 320;
|
||||
hres = HORIZONTAL_RESOLUTION_DEFAULT;
|
||||
}
|
||||
|
||||
if (vres == 0)
|
||||
{
|
||||
static const int VERTICAL_RESOLUTION_DEFAULT = 200;
|
||||
vres = VERTICAL_RESOLUTION_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
void DBaseStatusBar::SetSize(int reltop, int hres, int vres, int hhres, int hvres)
|
||||
{
|
||||
ValidateResolution(hres, vres);
|
||||
|
@ -1494,424 +1478,6 @@ uint32_t DBaseStatusBar::GetTranslation() const
|
|||
return TRANSLATION(TRANSLATION_Players, int(CPlayer - players));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DBaseStatusBar::StatusbarToRealCoords(double &x, double &y, double &w, double &h) const
|
||||
{
|
||||
if (SBarScale.X == -1 || ForcedScale)
|
||||
{
|
||||
int hres = HorizontalResolution;
|
||||
int vres = VerticalResolution;
|
||||
ValidateResolution(hres, vres);
|
||||
|
||||
VirtualToRealCoords(twod, x, y, w, h, hres, vres, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = ST_X + x * SBarScale.X;
|
||||
y = ST_Y + y * SBarScale.Y;
|
||||
w *= SBarScale.X;
|
||||
h *= SBarScale.Y;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY)
|
||||
{
|
||||
if (!texture.isValid())
|
||||
return;
|
||||
|
||||
FGameTexture *tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE));
|
||||
|
||||
double texwidth = tex->GetDisplayWidth() * scaleX;
|
||||
double texheight = tex->GetDisplayHeight() * scaleY;
|
||||
|
||||
if (boxwidth > 0 || boxheight > 0)
|
||||
{
|
||||
if (!(flags & DI_FORCEFILL))
|
||||
{
|
||||
double scale1 = 1., scale2 = 1.;
|
||||
|
||||
if (boxwidth > 0 && (boxwidth < texwidth || (flags & DI_FORCESCALE)))
|
||||
{
|
||||
scale1 = boxwidth / texwidth;
|
||||
}
|
||||
if (boxheight != -1 && (boxheight < texheight || (flags & DI_FORCESCALE)))
|
||||
{
|
||||
scale2 = boxheight / texheight;
|
||||
}
|
||||
|
||||
if (flags & DI_FORCESCALE)
|
||||
{
|
||||
if (boxwidth <= 0 || (boxheight > 0 && scale2 < scale1))
|
||||
scale1 = scale2;
|
||||
}
|
||||
else scale1 = MIN(scale1, scale2);
|
||||
|
||||
boxwidth = texwidth * scale1;
|
||||
boxheight = texheight * scale1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boxwidth = texwidth;
|
||||
boxheight = texheight;
|
||||
}
|
||||
|
||||
// resolve auto-alignment before making any adjustments to the position values.
|
||||
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
|
||||
{
|
||||
if (x < 0) flags |= DI_SCREEN_RIGHT;
|
||||
else flags |= DI_SCREEN_LEFT;
|
||||
if (y < 0) flags |= DI_SCREEN_BOTTOM;
|
||||
else flags |= DI_SCREEN_TOP;
|
||||
}
|
||||
|
||||
Alpha *= this->Alpha;
|
||||
if (Alpha <= 0) return;
|
||||
x += drawOffset.X;
|
||||
y += drawOffset.Y;
|
||||
|
||||
switch (flags & DI_ITEM_HMASK)
|
||||
{
|
||||
case DI_ITEM_HCENTER: x -= boxwidth / 2; break;
|
||||
case DI_ITEM_RIGHT: x -= boxwidth; break;
|
||||
case DI_ITEM_HOFFSET: x -= tex->GetDisplayLeftOffset() * boxwidth / texwidth; break;
|
||||
}
|
||||
|
||||
switch (flags & DI_ITEM_VMASK)
|
||||
{
|
||||
case DI_ITEM_VCENTER: y -= boxheight / 2; break;
|
||||
case DI_ITEM_BOTTOM: y -= boxheight; break;
|
||||
case DI_ITEM_VOFFSET: y -= tex->GetDisplayTopOffset() * boxheight / texheight; break;
|
||||
}
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
StatusbarToRealCoords(x, y, boxwidth, boxheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
double orgx, orgy;
|
||||
|
||||
switch (flags & DI_SCREEN_HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break;
|
||||
case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (flags & DI_SCREEN_VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||
}
|
||||
|
||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
||||
if ((flags & (DI_SCREEN_HMASK|DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
||||
|
||||
DVector2 Scale = GetHUDScale();
|
||||
|
||||
x *= Scale.X;
|
||||
y *= Scale.Y;
|
||||
boxwidth *= Scale.X;
|
||||
boxheight *= Scale.Y;
|
||||
x += orgx;
|
||||
y += orgy;
|
||||
}
|
||||
DrawTexture(twod, tex, x, y,
|
||||
DTA_TopOffset, 0,
|
||||
DTA_LeftOffset, 0,
|
||||
DTA_DestWidthF, boxwidth,
|
||||
DTA_DestHeightF, boxheight,
|
||||
DTA_TranslationIndex, (flags & DI_TRANSLATABLE) ? GetTranslation() : 0,
|
||||
DTA_ColorOverlay, (flags & DI_DIM) ? MAKEARGB(170, 0, 0, 0) : 0,
|
||||
DTA_Alpha, Alpha,
|
||||
DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED),
|
||||
DTA_FillColor, (flags & DI_ALPHAMAPPED) ? 0 : -1,
|
||||
DTA_FlipX, !!(flags & DI_MIRROR),
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw a string
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY)
|
||||
{
|
||||
bool monospaced = monospacing != EMonospacing::Off;
|
||||
double dx = 0;
|
||||
int spacingparm = monospaced ? -spacing : spacing;
|
||||
|
||||
switch (flags & DI_TEXT_ALIGN)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case DI_TEXT_ALIGN_RIGHT:
|
||||
dx = font->StringWidth(cstring, spacingparm);
|
||||
break;
|
||||
case DI_TEXT_ALIGN_CENTER:
|
||||
dx = font->StringWidth(cstring, spacingparm) / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Take text scale into account
|
||||
x -= dx * scaleX;
|
||||
|
||||
const uint8_t* str = (const uint8_t*)cstring.GetChars();
|
||||
const EColorRange boldTranslation = EColorRange(translation ? translation - 1 : NumTextColors - 1);
|
||||
int fontcolor = translation;
|
||||
double orgx = 0, orgy = 0;
|
||||
DVector2 Scale;
|
||||
|
||||
if (fullscreenOffsets)
|
||||
{
|
||||
Scale = GetHUDScale();
|
||||
shadowX *= (int)Scale.X;
|
||||
shadowY *= (int)Scale.Y;
|
||||
|
||||
switch (flags & DI_SCREEN_HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break;
|
||||
case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (flags & DI_SCREEN_VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||
}
|
||||
|
||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
Scale = { 1.,1. };
|
||||
}
|
||||
int ch;
|
||||
while (ch = GetCharFromString(str), ch != '\0')
|
||||
{
|
||||
if (ch == ' ')
|
||||
{
|
||||
x += monospaced ? spacing : font->GetSpaceWidth() + spacing;
|
||||
continue;
|
||||
}
|
||||
else if (ch == TEXTCOLOR_ESCAPE)
|
||||
{
|
||||
EColorRange newColor = V_ParseFontColor(str, translation, boldTranslation);
|
||||
if (newColor != CR_UNDEFINED)
|
||||
fontcolor = newColor;
|
||||
continue;
|
||||
}
|
||||
|
||||
int width;
|
||||
auto c = font->GetChar(ch, fontcolor, &width);
|
||||
if (c == NULL) //missing character.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!monospaced) //If we are monospaced lets use the offset
|
||||
x += (c->GetDisplayLeftOffset() + 1); //ignore x offsets since we adapt to character size
|
||||
|
||||
double rx, ry, rw, rh;
|
||||
rx = x + drawOffset.X;
|
||||
ry = y + drawOffset.Y;
|
||||
rw = c->GetDisplayWidth();
|
||||
rh = c->GetDisplayHeight();
|
||||
|
||||
if (monospacing == EMonospacing::CellCenter)
|
||||
rx += (spacing - rw) / 2;
|
||||
else if (monospacing == EMonospacing::CellRight)
|
||||
rx += (spacing - rw);
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
StatusbarToRealCoords(rx, ry, rw, rh);
|
||||
}
|
||||
else
|
||||
{
|
||||
rx *= Scale.X;
|
||||
ry *= Scale.Y;
|
||||
rw *= Scale.X;
|
||||
rh *= Scale.Y;
|
||||
|
||||
rx += orgx;
|
||||
ry += orgy;
|
||||
}
|
||||
|
||||
// Apply text scale
|
||||
rw *= scaleX;
|
||||
rh *= scaleY;
|
||||
|
||||
// This is not really such a great way to draw shadows because they can overlap with previously drawn characters.
|
||||
// This may have to be changed to draw the shadow text up front separately.
|
||||
if ((shadowX != 0 || shadowY != 0) && !(flags & DI_NOSHADOW))
|
||||
{
|
||||
DrawChar(twod, font, CR_UNTRANSLATED, rx + shadowX, ry + shadowY, ch,
|
||||
DTA_DestWidthF, rw,
|
||||
DTA_DestHeightF, rh,
|
||||
DTA_Alpha, (Alpha * HR_SHADOW),
|
||||
DTA_FillColor, 0,
|
||||
TAG_DONE);
|
||||
}
|
||||
DrawChar(twod, font, fontcolor, rx, ry, ch,
|
||||
DTA_DestWidthF, rw,
|
||||
DTA_DestHeightF, rh,
|
||||
DTA_Alpha, Alpha,
|
||||
TAG_DONE);
|
||||
|
||||
dx = monospaced
|
||||
? spacing
|
||||
: width + spacing - (c->GetDisplayLeftOffset() + 1);
|
||||
|
||||
// Take text scale into account
|
||||
x += dx * scaleX;
|
||||
}
|
||||
}
|
||||
|
||||
void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY)
|
||||
{
|
||||
if (font == nullptr) ThrowAbortException(X_READ_NIL, nullptr);
|
||||
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||
|
||||
// resolve auto-alignment before making any adjustments to the position values.
|
||||
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
|
||||
{
|
||||
if (x < 0) flags |= DI_SCREEN_RIGHT;
|
||||
else flags |= DI_SCREEN_LEFT;
|
||||
if (y < 0) flags |= DI_SCREEN_BOTTOM;
|
||||
else flags |= DI_SCREEN_TOP;
|
||||
}
|
||||
|
||||
if (wrapwidth > 0)
|
||||
{
|
||||
auto brk = V_BreakLines(font->mFont, int(wrapwidth * scaleX), string, true);
|
||||
for (auto &line : brk)
|
||||
{
|
||||
self->DrawString(font->mFont, line.Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY, scaleX, scaleY);
|
||||
y += (font->mFont->GetHeight() + linespacing) * scaleY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->DrawString(font->mFont, string, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY, scaleX, scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DBaseStatusBar::TransformRect(double &x, double &y, double &w, double &h, int flags)
|
||||
{
|
||||
// resolve auto-alignment before making any adjustments to the position values.
|
||||
if (!(flags & DI_SCREEN_MANUAL_ALIGN))
|
||||
{
|
||||
if (x < 0) flags |= DI_SCREEN_RIGHT;
|
||||
else flags |= DI_SCREEN_LEFT;
|
||||
if (y < 0) flags |= DI_SCREEN_BOTTOM;
|
||||
else flags |= DI_SCREEN_TOP;
|
||||
}
|
||||
|
||||
x += drawOffset.X;
|
||||
y += drawOffset.Y;
|
||||
|
||||
if (!fullscreenOffsets)
|
||||
{
|
||||
StatusbarToRealCoords(x, y, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
double orgx, orgy;
|
||||
|
||||
switch (flags & DI_SCREEN_HMASK)
|
||||
{
|
||||
default: orgx = 0; break;
|
||||
case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break;
|
||||
case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break;
|
||||
}
|
||||
|
||||
switch (flags & DI_SCREEN_VMASK)
|
||||
{
|
||||
default: orgy = 0; break;
|
||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||
}
|
||||
|
||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
||||
|
||||
DVector2 Scale = GetHUDScale();
|
||||
|
||||
x *= Scale.X;
|
||||
y *= Scale.Y;
|
||||
w *= Scale.X;
|
||||
h *= Scale.Y;
|
||||
x += orgx;
|
||||
y += orgy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DBaseStatusBar::Fill(PalEntry color, double x, double y, double w, double h, int flags)
|
||||
{
|
||||
double Alpha = color.a * this->Alpha / 255;
|
||||
if (Alpha <= 0) return;
|
||||
|
||||
TransformRect(x, y, w, h, flags);
|
||||
|
||||
int x1 = int(x);
|
||||
int y1 = int(y);
|
||||
int ww = int(x + w - x1); // account for scaling to non-integers. Truncating the values separately would fail for cases like
|
||||
int hh = int(y + h - y1); // y=3.5, height = 5.5 where adding both values gives a larger integer than adding the two integers.
|
||||
|
||||
Dim(twod, color, float(Alpha), x1, y1, ww, hh);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// draw stuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void DBaseStatusBar::SetClipRect(double x, double y, double w, double h, int flags)
|
||||
{
|
||||
TransformRect(x, y, w, h, flags);
|
||||
int x1 = int(x);
|
||||
int y1 = int(y);
|
||||
int ww = int(x + w - x1); // account for scaling to non-integers. Truncating the values separately would fail for cases like
|
||||
int hh = int(y + h - y1); // y=3.5, height = 5.5 where adding both values gives a larger integer than adding the two integers.
|
||||
twod->SetClipRect(x1, y1, ww, hh);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// CCMD showpop
|
||||
|
|
|
@ -2160,7 +2160,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, DrawImage, SBar_DrawImage)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY);
|
||||
void SBar_DrawString(DStatusBarCore *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY);
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, DrawString, SBar_DrawString)
|
||||
{
|
||||
|
@ -2241,6 +2241,22 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, SetClipRect, SBar_SetClipRect)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FormatNumber(int number, int minsize, int maxsize, int flags, const FString& prefix, FString* result);
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, FormatNumber, FormatNumber)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(number);
|
||||
PARAM_INT(minsize);
|
||||
PARAM_INT(maxsize);
|
||||
PARAM_INT(flags);
|
||||
PARAM_STRING(prefix);
|
||||
FString fmt;
|
||||
FormatNumber(number, minsize, maxsize, flags, prefix, &fmt);
|
||||
ACTION_RETURN_STRING(fmt);
|
||||
}
|
||||
|
||||
|
||||
static void GetGlobalACSString(int index, FString *result)
|
||||
{
|
||||
*result = primaryLevel->Behaviors.LookupString(ACS_GlobalVars[index]);
|
||||
|
|
Loading…
Reference in a new issue