- Added cybermind's HUD message clipping patch, with numerous changes. There is a new flag

and two new functions, both of which are intended for use in conjunction with SetHUDSize:
  * SetHUDClipRect(x, y, width, height[, wrapwidth]) - Set the clipping rectangle for future
    HUD messages. If you do not specify <wrapwidth>, the HUD message will be layed out as
    normal, but pixels outside the rectangle will not be drawn. If you specify <wrapwidth>,
    then the message will be wrapped to that width. Use SetHUDClipRect(0, 0, 0, 0[, 0]) to
    reset everything
    back to normal.
  * SetHUDWrapWidth(wrapwidth) - Sets the wrapping width for future HUD messages without
    altering the clipping rectangle. If you set the wrapping width to 0, messages will wrap
    to the full width of the HUD, as normal.
  * HUDMSG_NOWRAP - A HUDMessage() flag that disables wrapping for one message. It is
    functionally equivalent to SetHUDWrapWidth(0x7FFFFFFF), except that it only affects the
    message it's attached to.

SVN r3960 (trunk)
This commit is contained in:
Randy Heit 2012-11-10 03:18:52 +00:00
parent 955d929d5e
commit e398957a4c
4 changed files with 127 additions and 12 deletions

View file

@ -131,6 +131,9 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
Left = intpart - (float)(fracpart & 3) / 10.f;
}
}
NoWrap = false;
ClipX = ClipY = ClipWidth = ClipHeight = 0;
WrapWidth = 0;
Top = y;
Next = NULL;
Lines = NULL;
@ -182,6 +185,17 @@ void DHUDMessage::Serialize (FArchive &arc)
<< Tics << State << TextColor
<< SBarID << SourceText << Font << Next
<< HUDWidth << HUDHeight;
if (SaveVersion >= 3960)
{
arc << NoWrap;
arc << ClipX << ClipY << ClipWidth << ClipHeight;
arc << WrapWidth;
}
else
{
NoWrap = false;
ClipX = ClipY = ClipWidth = ClipHeight = WrapWidth = 0;
}
if (arc.IsLoading ())
{
Lines = NULL;
@ -220,6 +234,37 @@ void DHUDMessage::ScreenSizeChanged ()
}
}
//============================================================================
//
// DHUDMessage :: CalcClipCoords
//
// Take the clip rectangle in HUD coordinates (set via SetHudSize in ACS)
// and convert them to screen coordinates.
//
//============================================================================
void DHUDMessage::CalcClipCoords(int hudheight)
{
int x = ClipX, y = ClipY, w = ClipWidth, h = ClipHeight;
if ((x | y | w | h) == 0)
{ // No clipping rectangle set; use the full screen.
ClipLeft = 0;
ClipTop = 0;
ClipRight = screen->GetWidth();
ClipBot = screen->GetHeight();
}
else
{
screen->VirtualToRealCoordsInt(x, y, w, h,
HUDWidth, hudheight, false, true);
ClipLeft = x;
ClipTop = y;
ClipRight = x + w;
ClipBot = y + h;
}
}
//============================================================================
//
// DHUDMessage :: ResetText
@ -232,11 +277,11 @@ void DHUDMessage::ResetText (const char *text)
if (HUDWidth != 0)
{
width = HUDWidth;
width = ClipWidth == 0 ? HUDWidth : ClipWidth;
}
else
{
width = con_scaletext >=2 ? SCREENWIDTH/2 : (con_scaletext ? SCREENWIDTH / CleanXfac : SCREENWIDTH);
width = con_scaletext >= 2 ? SCREENWIDTH/2 : (con_scaletext ? SCREENWIDTH / CleanXfac : SCREENWIDTH);
}
if (Lines != NULL)
@ -244,7 +289,7 @@ void DHUDMessage::ResetText (const char *text)
V_FreeBrokenLines (Lines);
}
Lines = V_BreakLines (Font, width, (BYTE *)text);
Lines = V_BreakLines (Font, NoWrap ? INT_MAX : width, (BYTE *)text);
NumLines = 0;
Width = 0;
@ -377,15 +422,14 @@ void DHUDMessage::Draw (int bottom, int visibility)
ystep = Font->GetHeight() * yscale;
if (HUDHeight < 0)
{
// A negative height means the HUD size covers the status bar
{ // A negative height means the HUD size covers the status bar
hudheight = -HUDHeight;
}
else
{
// A positive height means the HUD size does not cover the status bar
{ // A positive height means the HUD size does not cover the status bar
hudheight = Scale (HUDHeight, screen_height, bottom);
}
CalcClipCoords(hudheight);
for (i = 0; i < NumLines; i++)
{
@ -441,6 +485,10 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_ClipLeft, ClipLeft,
DTA_ClipRight, ClipRight,
DTA_ClipTop, ClipTop,
DTA_ClipBottom, ClipBot,
DTA_Alpha, Alpha,
DTA_RenderStyle, Style,
TAG_DONE);
@ -541,6 +589,10 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_ClipLeft, ClipLeft,
DTA_ClipRight, ClipRight,
DTA_ClipTop, ClipTop,
DTA_ClipBottom, ClipBot,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
TAG_DONE);
@ -638,6 +690,10 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_ClipLeft, ClipLeft,
DTA_ClipRight, ClipRight,
DTA_ClipTop, ClipTop,
DTA_ClipBottom, ClipBot,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
TAG_DONE);
@ -814,6 +870,10 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_ClipLeft, ClipLeft,
DTA_ClipRight, ClipRight,
DTA_ClipTop, ClipTop,
DTA_ClipBottom, ClipBot,
DTA_Alpha, Alpha,
DTA_TextLen, LineVisible,
DTA_RenderStyle, Style,

View file

@ -85,22 +85,42 @@ public:
{
Alpha = alpha;
}
void SetNoWrap(bool nowrap)
{
NoWrap = nowrap;
ResetText(SourceText);
}
void SetClipRect(int x, int y, int width, int height)
{
ClipX = x;
ClipY = y;
ClipWidth = width;
ClipHeight = height;
}
void SetWrapWidth(int wrap)
{
WrapWidth = wrap;
ResetText(SourceText);
}
protected:
FBrokenLines *Lines;
int Width, Height, NumLines;
float Left, Top;
bool CenterX;
bool CenterX, NoWrap;
int HoldTics;
int Tics;
int State;
int VisibilityFlags;
int HUDWidth, HUDHeight;
int ClipX, ClipY, ClipWidth, ClipHeight, WrapWidth; // in HUD coords
int ClipLeft, ClipTop, ClipRight, ClipBot; // in screen coords
EColorRange TextColor;
FFont *Font;
FRenderStyle Style;
fixed_t Alpha;
void CalcClipCoords(int hudheight);
DHUDMessage () : SourceText(NULL) {}
private:

View file

@ -93,6 +93,7 @@ FRandom pr_acs ("ACS");
#define HUDMSG_COLORSTRING (0x40000000)
#define HUDMSG_ADDBLEND (0x20000000)
#define HUDMSG_ALPHA (0x10000000)
#define HUDMSG_NOWRAP (0x08000000)
// HUD message layers; these are not flags
#define HUDMSG_LAYER_SHIFT 12
@ -2169,6 +2170,15 @@ void DLevelScript::Serialize (FArchive &arc)
arc << activefont
<< hudwidth << hudheight;
if (SaveVersion >= 3960)
{
arc << ClipRectLeft << ClipRectTop << ClipRectWidth << ClipRectHeight
<< WrapWidth;
}
else
{
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
}
}
DLevelScript::DLevelScript ()
@ -3382,10 +3392,12 @@ enum EACSFunctions
ACSF_Sqrt,
ACSF_FixedSqrt,
ACSF_VectorLength,
ACSF_SetHUDClipRect,
ACSF_SetHUDWrapWidth,
// ZDaemon
ACSF_GetTeamScore = 19620,
ACSF_SetTeamScore,
ACSF_GetTeamScore = 19620, // (int team)
ACSF_SetTeamScore, // (int team, int value)
};
int DLevelScript::SideFromID(int id, int side)
@ -3900,11 +3912,9 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
case ACSF_UniqueTID:
return P_FindUniqueTID(argCount > 0 ? args[0] : 0, argCount > 1 ? args[1] : 0);
break;
case ACSF_IsTIDUsed:
return P_IsTIDUsed(args[0]);
break;
case ACSF_Sqrt:
return xs_FloorToInt(sqrt(double(args[0])));
@ -3915,6 +3925,18 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
case ACSF_VectorLength:
return FLOAT2FIXED(TVector2<double>(FIXED2DBL(args[0]), FIXED2DBL(args[1])).Length());
case ACSF_SetHUDClipRect:
ClipRectLeft = argCount > 0 ? args[0] : 0;
ClipRectTop = argCount > 1 ? args[1] : 0;
ClipRectWidth = argCount > 2 ? args[2] : 0;
ClipRectHeight = argCount > 3 ? args[3] : 0;
WrapWidth = argCount > 4 ? args[4] : 0;
break;
case ACSF_SetHUDWrapWidth:
WrapWidth = argCount > 0 ? args[0] : 0;
break;
default:
break;
}
@ -5737,7 +5759,16 @@ scriptwait:
}
break;
}
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight);
if (WrapWidth != 0)
{
msg->SetWrapWidth(WrapWidth);
}
msg->SetVisibility((type & HUDMSG_VISIBILITY_MASK) >> HUDMSG_VISIBILITY_SHIFT);
if (type & HUDMSG_NOWRAP)
{
msg->SetNoWrap(true);
}
if (type & HUDMSG_ALPHA)
{
msg->SetAlpha(alpha);
@ -7351,7 +7382,9 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr
backSide = flags & ACS_BACKSIDE;
activefont = SmallFont;
hudwidth = hudheight = 0;
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
state = SCRIPT_Running;
// Hexen waited one second before executing any open scripts. I didn't realize
// this when I wrote my ACS implementation. Now that I know, it's still best to
// run them right away because there are several map properties that can't be

View file

@ -707,6 +707,8 @@ protected:
bool backSide;
FFont *activefont;
int hudwidth, hudheight;
int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight;
int WrapWidth;
FBehavior *activeBehavior;
void Link ();