From e398957a4c96b0f3f52ba02b2abba29ccf5a4408 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 10 Nov 2012 03:18:52 +0000 Subject: [PATCH] - 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 , the HUD message will be layed out as normal, but pixels outside the rectangle will not be drawn. If you specify , 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) --- src/g_shared/hudmessages.cpp | 74 ++++++++++++++++++++++++++++++++---- src/g_shared/sbar.h | 22 ++++++++++- src/p_acs.cpp | 41 ++++++++++++++++++-- src/p_acs.h | 2 + 4 files changed, 127 insertions(+), 12 deletions(-) diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 76eaedcec..21b5e2c4d 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -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, diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index df3daf597..d45f88cdf 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -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: diff --git a/src/p_acs.cpp b/src/p_acs.cpp index c87f41816..607b68265 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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(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 diff --git a/src/p_acs.h b/src/p_acs.h index d2ae2038b..44786e260 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -707,6 +707,8 @@ protected: bool backSide; FFont *activefont; int hudwidth, hudheight; + int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight; + int WrapWidth; FBehavior *activeBehavior; void Link ();