diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 238412bb6d..41abd254a1 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -120,6 +120,8 @@ DEFINE_FIELD(DPSprite, oldx) DEFINE_FIELD(DPSprite, oldy) DEFINE_FIELD(DPSprite, firstTic) DEFINE_FIELD(DPSprite, Tics) +DEFINE_FIELD(DPSprite, alpha) +DEFINE_FIELD(DPSprite, RenderStyle) DEFINE_FIELD_BIT(DPSprite, Flags, bAddWeapon, PSPF_ADDWEAPON) DEFINE_FIELD_BIT(DPSprite, Flags, bAddBob, PSPF_ADDBOB) DEFINE_FIELD_BIT(DPSprite, Flags, bPowDouble, PSPF_POWDOUBLE) @@ -141,7 +143,9 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) Caller(caller), Owner(owner), ID(id), - processPending(true) + processPending(true), + alpha(1), + RenderStyle(STYLE_Normal) { DPSprite *prev = nullptr; DPSprite *next = Owner->psprites; @@ -1056,7 +1060,7 @@ void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags) player_t *player = self->player; DPSprite *psp; - if (player && (player->playerstate != PST_DEAD)) + if (player) { psp = player->FindPSprite(layer); @@ -1203,7 +1207,69 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID) ACTION_RETURN_INT(0); } +//--------------------------------------------------------------------------- +// +// PROC A_OverlayAlpha +// Sets the alpha of an overlay. +//--------------------------------------------------------------------------- +DEFINE_ACTION_FUNCTION(AActor, A_OverlayAlpha) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(layer); + PARAM_FLOAT(alph); + + if (ACTION_CALL_FROM_PSPRITE()) + { + DPSprite *pspr = self->player->FindPSprite((layer != 0) ? layer : stateinfo->mPSPIndex); + + if (pspr != nullptr) + pspr->alpha = clamp(alph, 0.0, 1.0); + } + return 0; +} + +// NON-ACTION function to get the overlay alpha of a layer. +DEFINE_ACTION_FUNCTION(AActor, OverlayAlpha) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT_DEF(layer); + + if (ACTION_CALL_FROM_PSPRITE()) + { + DPSprite *pspr = self->player->FindPSprite((layer != 0) ? layer : stateinfo->mPSPIndex); + + if (pspr != nullptr) + { + ACTION_RETURN_FLOAT(pspr->alpha); + } + } + ACTION_RETURN_FLOAT(0.0); +} + +//--------------------------------------------------------------------------- +// +// PROC A_OverlayRenderStyle +// +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AActor, A_OverlayRenderStyle) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(layer); + PARAM_INT(style); + + if (ACTION_CALL_FROM_PSPRITE()) + { + DPSprite *pspr = self->player->FindPSprite((layer != 0) ? layer : stateinfo->mPSPIndex); + + if (pspr == nullptr || style >= STYLE_Count || style < 0) + return 0; + + pspr->RenderStyle = style; + } + return 0; +} //--------------------------------------------------------------------------- // @@ -1577,7 +1643,9 @@ void DPSprite::Serialize(FSerializer &arc) ("x", x) ("y", y) ("oldx", oldx) - ("oldy", oldy); + ("oldy", oldy) + ("alpha", alpha) + ("renderstyle", RenderStyle); } //------------------------------------------------------------------------ diff --git a/src/p_pspr.h b/src/p_pspr.h index d6eb2a82d7..48c67be952 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -49,11 +49,15 @@ enum PSPLayers enum PSPFlags { - PSPF_ADDWEAPON = 1 << 0, - PSPF_ADDBOB = 1 << 1, - PSPF_POWDOUBLE = 1 << 2, - PSPF_CVARFAST = 1 << 3, - PSPF_FLIP = 1 << 6, + PSPF_ADDWEAPON = 1 << 0, + PSPF_ADDBOB = 1 << 1, + PSPF_POWDOUBLE = 1 << 2, + PSPF_CVARFAST = 1 << 3, + PSPF_ALPHA = 1 << 4, + PSPF_RENDERSTYLE = 1 << 5, + PSPF_FLIP = 1 << 6, + PSPF_FORCEALPHA = 1 << 7, + PSPF_FORCESTYLE = 1 << 8, }; class DPSprite : public DObject @@ -75,11 +79,12 @@ public: void SetCaller(AActor *newcaller) { Caller = newcaller; } void ResetInterpolation() { oldx = x; oldy = y; } - double x, y; + double x, y, alpha; double oldx, oldy; bool firstTic; int Tics; int Flags; + int RenderStyle; private: DPSprite () {} diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index 501c14c5f9..63e0856cd7 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -125,6 +125,9 @@ enum ERenderFlags // Actors only: Ignore sector fade and fade to black. To fade to white, // combine this with STYLEF_InvertOverlay. STYLEF_FadeToBlack = 64, + + // Force alpha. + STYLEF_ForceAlpha = 128, }; union FRenderStyle diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 8206c23918..2d320af6c1 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -387,7 +387,11 @@ namespace swrenderer color = 0; } - if (style.Flags & STYLEF_TransSoulsAlpha) + if (style.Flags & STYLEF_ForceAlpha) + { + alpha = clamp(alpha, 0, OPAQUE); + } + else if (style.Flags & STYLEF_TransSoulsAlpha) { alpha = fixed_t(transsouls * OPAQUE); } @@ -1196,7 +1200,7 @@ namespace swrenderer DrawerCommandQueue::QueueCommand(y, x1, x2); } } - + void R_DrawFogBoundary(int x1, int x2, short *uclip, short *dclip) { // This is essentially the same as R_MapVisPlane but with an extra step diff --git a/src/r_things.cpp b/src/r_things.cpp index ce356808ed..43a4dd15f6 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1293,6 +1293,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double FTexture* tex; vissprite_t* vis; bool noaccel; + double alpha = owner->Alpha; static TArray avis; if (avis.Size() < vispspindex + 1) @@ -1316,7 +1317,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double flip = sprframe->Flip & 1; tex = TexMan(picnum); - if (tex->UseType == FTexture::TEX_Null) + if (tex->UseType == FTexture::TEX_Null || pspr->RenderStyle == STYLE_None) return; if (pspr->firstTic) @@ -1353,10 +1354,10 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double tx += tex->GetScaledWidth(); x2 = xs_RoundToInt(CenterX + tx * pspritexscale); - + // off the left side if (x2 <= 0) - return; + return; // store information in a vissprite vis = &avis[vispspindex]; @@ -1394,6 +1395,8 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double vis->pic = tex; vis->ColormapNum = 0; + // If flip is used, provided that it's not already flipped (that would just invert itself) + // (It's an XOR...) if (!(flip) != !(pspr->Flags & PSPF_FLIP)) { vis->xiscale = -FLOAT2FIXED(pspritexiscale * tex->Scale.X); @@ -1412,8 +1415,114 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double FDynamicColormap *colormap_to_use = nullptr; if (pspr->GetID() < PSP_TARGETCENTER) { - vis->Style.Alpha = float(owner->Alpha); - vis->Style.RenderStyle = owner->RenderStyle; + // [MC] Set the render style + + if (pspr->Flags & PSPF_RENDERSTYLE) + { + const int rs = clamp(pspr->RenderStyle, 0, STYLE_Count); + + if (pspr->Flags & PSPF_FORCESTYLE) + { + vis->Style.RenderStyle = LegacyRenderStyles[rs]; + } + else if (owner->RenderStyle == LegacyRenderStyles[STYLE_Fuzzy]) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Fuzzy]; + } + else if (owner->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_OptFuzzy]; + vis->Style.RenderStyle.CheckFuzz(); + } + else if (owner->RenderStyle == LegacyRenderStyles[STYLE_Subtract]) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Subtract]; + } + else + { + vis->Style.RenderStyle = LegacyRenderStyles[rs]; + } + } + else + { + vis->Style.RenderStyle = owner->RenderStyle; + } + + // Set the alpha based on if using the overlay's own or not. Also adjust + // and override the alpha if not forced. + if (pspr->Flags & PSPF_ALPHA) + { + if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Fuzzy]) + { + alpha = owner->Alpha; + } + else if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]) + { + FRenderStyle style = vis->Style.RenderStyle; + style.CheckFuzz(); + switch (style.BlendOp) + { + default: + alpha = pspr->alpha * owner->Alpha; + break; + case STYLEOP_Fuzz: + case STYLEOP_Sub: + alpha = owner->Alpha; + break; + } + + } + else if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Subtract]) + { + alpha = owner->Alpha; + } + else if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Translucent] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_TranslucentStencil] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_AddStencil] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_AddShaded]) + { + alpha = owner->Alpha * pspr->alpha; + } + else + { + alpha = owner->Alpha; + } + } + + // Should normal renderstyle come out on top at the end and we desire alpha, + // switch it to translucent. Normal never applies any sort of alpha. + if ((pspr->Flags & PSPF_ALPHA) && + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Normal] && + vis->Style.Alpha < 1.0) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + alpha = owner->Alpha * pspr->alpha; + } + + // ALWAYS take priority if asked for, except fuzz. Fuzz does absolutely nothing + // no matter what way it's changed. + if (pspr->Flags & PSPF_FORCEALPHA) + { + //Due to lack of != operators... + if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Fuzzy] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_SoulTrans] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Stencil]) + { } + else + { + alpha = pspr->alpha; + vis->Style.RenderStyle.Flags |= STYLEF_ForceAlpha; + } + } + vis->Style.Alpha = clamp(float(alpha), 0.f, 1.f); + + // Due to how some of the effects are handled, going to 0 or less causes some + // weirdness to display. There's no point rendering it anyway if it's 0. + if (vis->Style.Alpha <= 0.) + return; + + //----------------------------------------------------------------------------- // The software renderer cannot invert the source without inverting the overlay // too. That means if the source is inverted, we need to do the reverse of what @@ -1517,7 +1626,6 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double { colormap_to_use = basecolormap; vis->Style.colormap = basecolormap->Maps; - vis->Style.RenderStyle = STYLE_Normal; } // Check for hardware-assisted 2D. If it's available, and this sprite is not @@ -1538,6 +1646,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double return; } } + R_DrawVisSprite(vis); } @@ -1652,6 +1761,7 @@ void R_DrawPlayerSprites () // It's possible this psprite's caller is now null but the layer itself hasn't been destroyed // because it didn't tick yet (if we typed 'take all' while in the console for example). // In this case let's simply not draw it to avoid crashing. + if ((psp->GetID() != PSP_TARGETCENTER || CrosshairImage == nullptr) && psp->GetCaller() != nullptr) { R_DrawPSprite(psp, camera, bobx, boby, wx, wy, r_TicFracF); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2ced709aee..aaf88b6fea 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -452,6 +452,7 @@ class Actor : Thinker native action native int OverlayID(); action native double OverlayX(int layer = 0); action native double OverlayY(int layer = 0); + action native double OverlayAlpha(int layer = 0); // DECORATE setters - it probably makes more sense to set these values directly now... void A_SetMass(int newmass) { mass = newmass; } @@ -805,6 +806,8 @@ class Actor : Thinker native native void A_WeaponOffset(double wx = 0, double wy = 32, int flags = 0); action native void A_OverlayOffset(int layer = PSP_WEAPON, double wx = 0, double wy = 32, int flags = 0); action native void A_OverlayFlags(int layer, int flags, bool set); + action native void A_OverlayAlpha(int layer, double alph); + action native void A_OverlayRenderStyle(int layer, int style); int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0) { diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 1d2064aa1a..9b3e222524 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -714,7 +714,11 @@ enum EPSpriteFlags PSPF_ADDBOB = 1 << 1, PSPF_POWDOUBLE = 1 << 2, PSPF_CVARFAST = 1 << 3, + PSPF_ALPHA = 1 << 4, + PSPF_RENDERSTYLE= 1 << 5, PSPF_FLIP = 1 << 6, + PSPF_FORCEALPHA = 1 << 7, + PSPF_FORCESTYLE = 1 << 8, }; // Default psprite layers diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 2f6dc4bc19..0b0c67c2ee 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -133,12 +133,14 @@ class PSprite : Object native native readonly PlayerInfo Owner; native SpriteID Sprite; native int Frame; + native readonly int RenderStyle; native readonly int ID; native Bool processPending; native double x; native double y; native double oldx; native double oldy; + native double alpha; native Bool firstTic; native int Tics; native bool bAddWeapon;