From e5ca3caa6cc816b6e840dc57dbd459cf89ad02e1 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Wed, 30 Sep 2020 10:11:53 -0500 Subject: [PATCH] Setting everything up. --- src/playsim/p_pspr.cpp | 162 +++++++++++++++++- src/playsim/p_pspr.h | 12 +- src/rendering/hwrenderer/scene/hw_drawinfo.h | 2 +- src/rendering/hwrenderer/scene/hw_weapon.cpp | 66 ++++++- src/rendering/hwrenderer/scene/hw_weapon.h | 5 +- wadsrc/static/zscript/actors/actor.zs | 3 + wadsrc/static/zscript/actors/player/player.zs | 12 ++ 7 files changed, 241 insertions(+), 21 deletions(-) diff --git a/src/playsim/p_pspr.cpp b/src/playsim/p_pspr.cpp index ebfe99b744..e49e652578 100644 --- a/src/playsim/p_pspr.cpp +++ b/src/playsim/p_pspr.cpp @@ -132,6 +132,18 @@ DEFINE_FIELD(DPSprite, x) DEFINE_FIELD(DPSprite, y) DEFINE_FIELD(DPSprite, oldx) DEFINE_FIELD(DPSprite, oldy) +DEFINE_FIELD(DPSprite, px) +DEFINE_FIELD(DPSprite, py) +DEFINE_FIELD(DPSprite, oldpx) +DEFINE_FIELD(DPSprite, oldpy) +DEFINE_FIELD(DPSprite, scalex) +DEFINE_FIELD(DPSprite, scaley) +DEFINE_FIELD(DPSprite, oldscalex) +DEFINE_FIELD(DPSprite, oldscaley) +DEFINE_FIELD(DPSprite, rotation) +DEFINE_FIELD(DPSprite, oldrotation) +DEFINE_FIELD(DPSprite, PivotPercent) +DEFINE_FIELD(DPSprite, PivotScreen) DEFINE_FIELD(DPSprite, firstTic) DEFINE_FIELD(DPSprite, Tics) DEFINE_FIELD(DPSprite, Translation) @@ -143,6 +155,8 @@ DEFINE_FIELD_BIT(DPSprite, Flags, bCVarFast, PSPF_CVARFAST) DEFINE_FIELD_BIT(DPSprite, Flags, bFlip, PSPF_FLIP) DEFINE_FIELD_BIT(DPSprite, Flags, bMirror, PSPF_MIRROR) DEFINE_FIELD_BIT(DPSprite, Flags, bPlayerTranslated, PSPF_PLAYERTRANSLATED) +DEFINE_FIELD_BIT(DPSprite, Flags, bPivotPercent, PSPF_PIVOTPERCENT) +DEFINE_FIELD_BIT(DPSprite, Flags, bPivotScreen, PSPF_PIVOTSCREEN) //------------------------------------------------------------------------ // @@ -163,7 +177,15 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) Sprite(0), Frame(0), ID(id), - processPending(true) + processPending(true), + scalex(1.0), scaley(1.0), + px(.0), py(.0), + rotation(.0), + oldscalex(.0), oldscaley(.0), + oldpx(.0), oldpy(.0), + oldrotation(.0), + PivotPercent(true), + PivotScreen(false) { alpha = 1; Renderstyle = STYLE_Normal; @@ -192,7 +214,7 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) Next->Destroy(); // Replace it. if (Caller->IsKindOf(NAME_Weapon) || Caller->IsKindOf(NAME_PlayerPawn)) - Flags = (PSPF_ADDWEAPON|PSPF_ADDBOB|PSPF_POWDOUBLE|PSPF_CVARFAST); + Flags = (PSPF_ADDWEAPON|PSPF_ADDBOB|PSPF_POWDOUBLE|PSPF_CVARFAST|PSPF_PIVOTPERCENT); } //------------------------------------------------------------------------ @@ -637,18 +659,140 @@ DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponButtons) return 0; } +//--------------------------------------------------------------------------- +// +// PROC A_OverlayScale +// +//--------------------------------------------------------------------------- + +enum WOFFlags +{ + WOF_KEEPX = 1, + WOF_KEEPY = 1 << 1, + WOF_ADD = 1 << 2, + WOF_INTERPOLATE = 1 << 3, +}; + +DEFINE_ACTION_FUNCTION(AActor, A_OverlayScale) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(layer) + PARAM_FLOAT(wx) + PARAM_FLOAT(wy) + PARAM_INT(flags) + + if (!ACTION_CALL_FROM_PSPRITE()) + return 0; + + DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex)); + + if (pspr == nullptr) + return 0; + + if (flags & WOF_ADD) + { + if (!(flags & WOF_KEEPX)) + pspr->scalex += wx; + if (!(flags & WOF_KEEPY)) + pspr->scaley += (wy != 0.0 ? wy : wx); + } + else + { + if (!(flags & WOF_KEEPX)) + pspr->scalex = wx; + if (!(flags & WOF_KEEPY)) + pspr->scaley = (wy != 0.0 ? wy : wx); + } + + if (!(flags & WOF_INTERPOLATE)) + { + pspr->oldscalex = pspr->scalex; + pspr->oldscaley = pspr->scaley; + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +// PROC A_OverlayRotate +// +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AActor, A_OverlayRotate) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(layer) + PARAM_FLOAT(degrees) + PARAM_INT(flags) + + if (!ACTION_CALL_FROM_PSPRITE()) + return 0; + + DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex)); + + if (pspr == nullptr) + return 0; + + pspr->rotation = (flags & WOF_ADD) ? pspr->rotation + degrees : degrees; + + if (!(flags & WOF_INTERPOLATE)) + pspr->oldrotation = degrees; + + return 0; +} + +//--------------------------------------------------------------------------- +// +// PROC A_OverlayPivot +// +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AActor, A_OverlayPivot) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(layer) + PARAM_FLOAT(wx) + PARAM_FLOAT(wy) + PARAM_INT(flags) + + if (!ACTION_CALL_FROM_PSPRITE()) + return 0; + + DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex)); + + if (pspr == nullptr) + return 0; + + if (flags & WOF_ADD) + { + if (!(flags & WOF_KEEPX)) + pspr->px += wx; + if (!(flags & WOF_KEEPY)) + pspr->py += (wy != 0.0 ? wy : wx); + } + else + { + if (!(flags & WOF_KEEPX)) + pspr->px = wx; + if (!(flags & WOF_KEEPY)) + pspr->py = (wy != 0.0 ? wy : wx); + } + + if (!(flags & WOF_INTERPOLATE)) + { + pspr->oldpx = pspr->px; + pspr->oldpy = pspr->py; + } + + return 0; +} + //--------------------------------------------------------------------------- // // PROC A_OverlayOffset // //--------------------------------------------------------------------------- -enum WOFFlags -{ - WOF_KEEPX = 1, - WOF_KEEPY = 1 << 1, - WOF_ADD = 1 << 2, - WOF_INTERPOLATE = 1 << 3, -}; void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags) { diff --git a/src/playsim/p_pspr.h b/src/playsim/p_pspr.h index 83a860e5d6..e5d7ad10bb 100644 --- a/src/playsim/p_pspr.h +++ b/src/playsim/p_pspr.h @@ -70,7 +70,9 @@ enum PSPFlags PSPF_FORCEALPHA = 1 << 7, PSPF_FORCESTYLE = 1 << 8, PSPF_MIRROR = 1 << 9, - PSPF_PLAYERTRANSLATED = 1 << 10 + PSPF_PLAYERTRANSLATED = 1 << 10, + PSPF_PIVOTPERCENT = 1 << 11, + PSPF_PIVOTSCREEN = 1 << 12, }; class DPSprite : public DObject @@ -97,6 +99,14 @@ public: std::pair GetRenderStyle(FRenderStyle ownerstyle, double owneralpha); float GetYAdjust(bool fullscreen); + bool PivotScreen; // If true, the pivot is based on the entire screen width/height instead of the image's dimensions/position. + bool PivotPercent; // If true, the pivot goes between [0.0, 1.0]. Otherwise, it's a pixel position offset from the image size. + double px, py; // pivot points + double oldpx, oldpy; + double rotation; // How much rotation to apply. + double oldrotation; + double scalex, scaley; // Scale + double oldscalex, oldscaley; double x, y, alpha; double oldx, oldy; bool firstTic; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 262fee3f56..fa5c5b3580 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -291,7 +291,7 @@ public: void GetDynSpriteLight(AActor *thing, particle_t *particle, float *out); void PreparePlayerSprites(sector_t * viewsector, area_t in_area); - void PrepareTargeterSprites(); + void PrepareTargeterSprites(WeaponPosition *weap); void UpdateCurrentMapSection(); void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror); diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index 0fe4a1c16c..cbe4015c36 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -169,17 +169,32 @@ static WeaponPosition GetWeaponPosition(player_t *player, double ticFrac) { w.wx = (float)w.weapon->x; w.wy = (float)w.weapon->y; + w.sx = (float)w.weapon->scalex; + w.sy = (float)w.weapon->scaley; + w.px = (float)w.weapon->px; + w.py = (float)w.weapon->py; + w.r = (float)w.weapon->rotation; } else { w.wx = (float)(w.weapon->oldx + (w.weapon->x - w.weapon->oldx) * ticFrac); w.wy = (float)(w.weapon->oldy + (w.weapon->y - w.weapon->oldy) * ticFrac); + w.px = (float)(w.weapon->oldpx + (w.weapon->px - w.weapon->oldpx) * ticFrac); + w.py = (float)(w.weapon->oldpy + (w.weapon->py - w.weapon->oldpy) * ticFrac); + w.sx = (float)(w.weapon->oldscalex + (w.weapon->scalex - w.weapon->oldscalex) * ticFrac); + w.sy = (float)(w.weapon->oldscaley + (w.weapon->scaley - w.weapon->oldscaley) * ticFrac); + w.r = (float)(w.weapon->oldrotation + (w.weapon->rotation - w.weapon->oldrotation) * ticFrac); } } else { w.wx = 0; w.wy = 0; + w.px = 0; + w.py = 0; + w.sx = 0; + w.sy = 0; + w.r = 0; } return w; } @@ -407,7 +422,7 @@ bool HUDSprite::GetWeaponRenderStyle(DPSprite *psp, AActor *playermo, sector_t * // //========================================================================== -bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, player_t *player) +bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, player_t *player, WeaponPosition *weap) { float tx; float scale; @@ -470,10 +485,42 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, auto verts = screen->mVertexData->AllocVertices(4); mx = verts.second; - verts.first[0].Set(x1, y1, 0, u1, v1); - verts.first[1].Set(x1, y2, 0, u1, v2); - verts.first[2].Set(x2, y1, 0, u2, v1); - verts.first[3].Set(x2, y2, 0, u2, v2); + + if (psp->rotation != 0.0 || psp->scalex != 1.0 || psp->scaley != 1.0) + { + double radang = psp->rotation * (pi::pi() / 180.); + double cosang = cos(radang); + double sinang = sin(radang); + + double xcenter = psp->x; + double ycenter = psp->y; + + + double xx1 = xcenter + psp->scalex * (x1 * cosang + y1 * sinang); + double yy1 = ycenter + psp->scaley * (x1 * sinang - y1 * cosang); + + double xx2 = xcenter + psp->scalex * (x1 * cosang + y2 * sinang); + double yy2 = ycenter + psp->scaley * (x1 * sinang - y2 * cosang); + + double xx3 = xcenter + psp->scalex * (x2 * cosang + y1 * sinang); + double yy3 = ycenter + psp->scaley * (x2 * sinang - y1 * cosang); + + double xx4 = xcenter + psp->scalex * (x2 * cosang + y2 * sinang); + double yy4 = ycenter + psp->scaley * (x2 * sinang - y2 * cosang); + + verts.first[0].Set(xx1, yy1, 0, u1, v1); + verts.first[1].Set(xx2, yy2, 0, u1, v2); + verts.first[2].Set(xx3, yy3, 0, u2, v1); + verts.first[3].Set(xx4, yy4, 0, u2, v2); + } + else + { + + verts.first[0].Set(x1, y1, 0, u1, v1); + verts.first[1].Set(x1, y2, 0, u1, v2); + verts.first[2].Set(x2, y1, 0, u2, v1); + verts.first[3].Set(x2, y2, 0, u2, v2); + } texture = tex; return true; @@ -554,12 +601,12 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area) } else { - if (!hudsprite.GetWeaponRect(this, psp, spos.X, spos.Y, player)) continue; + if (!hudsprite.GetWeaponRect(this, psp, spos.X, spos.Y, player, &weap)) continue; } hudsprites.Push(hudsprite); } lightmode = oldlightmode; - PrepareTargeterSprites(); + PrepareTargeterSprites(&weap); } @@ -569,7 +616,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area) // //========================================================================== -void HWDrawInfo::PrepareTargeterSprites() +void HWDrawInfo::PrepareTargeterSprites(WeaponPosition *weap) { AActor * playermo = players[consoleplayer].camera; player_t * player = playermo->player; @@ -601,7 +648,8 @@ void HWDrawInfo::PrepareTargeterSprites() if (psp->GetState() != nullptr && (psp->GetID() != PSP_TARGETCENTER || CrosshairImage == nullptr)) { hudsprite.weapon = psp; - if (hudsprite.GetWeaponRect(this, psp, psp->x, psp->y, player)) + + if (hudsprite.GetWeaponRect(this, psp, psp->x, psp->y, player, weap)) { hudsprites.Push(hudsprite); } diff --git a/src/rendering/hwrenderer/scene/hw_weapon.h b/src/rendering/hwrenderer/scene/hw_weapon.h index d77337e427..d9817bbaa5 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.h +++ b/src/rendering/hwrenderer/scene/hw_weapon.h @@ -15,6 +15,9 @@ struct WeaponPosition { float wx, wy; float bobx, boby; + float sx, sy; + float px, py; + float r; DPSprite *weapon; }; @@ -47,6 +50,6 @@ struct HUDSprite void SetBright(bool isbelow); bool GetWeaponRenderStyle(DPSprite *psp, AActor *playermo, sector_t *viewsector, WeaponLighting &light); - bool GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, player_t *player); + bool GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, player_t *player, WeaponPosition *weap); }; diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 1eb9bd2e2a..2d0818b2b9 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1183,6 +1183,9 @@ class Actor : Thinker native action native bool A_Overlay(int layer, statelabel start = null, bool nooverride = false); native void A_WeaponOffset(double wx = 0, double wy = 32, int flags = 0); + action native void A_OverlayScale(int layer, double wx = 1, double wy = 0, int flags = 0); + action native void A_OverlayRotate(int layer, double degrees = 0, int flags = 0); + action native void A_OverlayPivot(int layer, double wx = 0.5, double wy = 0.5, 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); diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index e6252a5c72..f076e680a4 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2557,6 +2557,16 @@ class PSprite : Object native play native double y; native double oldx; native double oldy; + native double px; + native double py; + native double oldpx; + native double oldpy; + native double scalex; + native double scaley; + native double oldscalex; + native double oldscaley; + native double rotation; + native double oldrotation; native double alpha; native Bool firstTic; native int Tics; @@ -2568,6 +2578,8 @@ class PSprite : Object native play native bool bFlip; native bool bMirror; native bool bPlayerTranslated; + native bool bPivotPercent; + native bool bPivotScreen; native void SetState(State newstate, bool pending = false);