mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-04-09 11:31:56 +00:00
Merged https://github.com/coelckers/gzdoom/pull/1196 (PSprite Scale/Rotation/Pivot/Vertex)
This commit is contained in:
parent
8ef49d36be
commit
55554ce4d1
11 changed files with 435 additions and 64 deletions
|
@ -132,10 +132,20 @@ DEFINE_FIELD(DPSprite, x)
|
|||
DEFINE_FIELD(DPSprite, y)
|
||||
DEFINE_FIELD(DPSprite, oldx)
|
||||
DEFINE_FIELD(DPSprite, oldy)
|
||||
DEFINE_FIELD(DPSprite, pivot)
|
||||
DEFINE_FIELD(DPSprite, scale)
|
||||
DEFINE_FIELD(DPSprite, rotation)
|
||||
DEFINE_FIELD_NAMED(DPSprite, Coord[0], Coord0)
|
||||
DEFINE_FIELD_NAMED(DPSprite, Coord[1], Coord1)
|
||||
DEFINE_FIELD_NAMED(DPSprite, Coord[2], Coord2)
|
||||
DEFINE_FIELD_NAMED(DPSprite, Coord[3], Coord3)
|
||||
DEFINE_FIELD(DPSprite, firstTic)
|
||||
DEFINE_FIELD(DPSprite, Tics)
|
||||
DEFINE_FIELD(DPSprite, Translation)
|
||||
DEFINE_FIELD(DPSprite, HAlign)
|
||||
DEFINE_FIELD(DPSprite, VAlign)
|
||||
DEFINE_FIELD(DPSprite, alpha)
|
||||
DEFINE_FIELD(DPSprite, InterpolateTic)
|
||||
DEFINE_FIELD_BIT(DPSprite, Flags, bAddWeapon, PSPF_ADDWEAPON)
|
||||
DEFINE_FIELD_BIT(DPSprite, Flags, bAddBob, PSPF_ADDBOB)
|
||||
DEFINE_FIELD_BIT(DPSprite, Flags, bPowDouble, PSPF_POWDOUBLE)
|
||||
|
@ -143,6 +153,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, bInterpolate, PSPF_INTERPOLATE)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -163,8 +175,20 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id)
|
|||
Sprite(0),
|
||||
Frame(0),
|
||||
ID(id),
|
||||
processPending(true)
|
||||
processPending(true),
|
||||
HAlign(0),
|
||||
VAlign(0),
|
||||
InterpolateTic(false)
|
||||
{
|
||||
rotation = 0.;
|
||||
scale = {1.0, 1.0};
|
||||
pivot = {0.0, 0.0};
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Coord[i] = DVector2(0, 0);
|
||||
Prev.v[i] = Vert.v[i] = FVector2(0,0);
|
||||
}
|
||||
|
||||
alpha = 1;
|
||||
Renderstyle = STYLE_Normal;
|
||||
|
||||
|
@ -192,7 +216,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);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -294,7 +318,7 @@ DPSprite *player_t::GetPSprite(PSPLayers layer)
|
|||
}
|
||||
else
|
||||
{
|
||||
pspr->Flags = (PSPF_ADDWEAPON|PSPF_ADDBOB|PSPF_CVARFAST|PSPF_POWDOUBLE);
|
||||
pspr->Flags = (PSPF_ADDWEAPON|PSPF_ADDBOB|PSPF_CVARFAST|PSPF_POWDOUBLE|PSPF_PIVOTPERCENT);
|
||||
}
|
||||
if (layer == PSP_STRIFEHANDS)
|
||||
{
|
||||
|
@ -637,18 +661,160 @@ DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponButtons)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum WOFFlags
|
||||
{
|
||||
WOF_KEEPX = 1,
|
||||
WOF_KEEPY = 1 << 1,
|
||||
WOF_ADD = 1 << 2,
|
||||
WOF_INTERPOLATE = 1 << 3,
|
||||
WOF_RELATIVE = 1 << 4,
|
||||
WOF_ZEROY = 1 << 5,
|
||||
};
|
||||
|
||||
void HandleOverlayRelative(DPSprite *psp, double *x, double *y)
|
||||
{
|
||||
double wx = *x;
|
||||
double wy = *y;
|
||||
|
||||
double c = psp->rotation.Cos(), s = psp->rotation.Sin();
|
||||
double nx = wx * c + wy * s;
|
||||
double ny = wx * s - wy * c;
|
||||
*x = nx; *y = ny;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_OverlayVertexOffset
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_OverlayVertexOffset)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_INT(layer)
|
||||
PARAM_INT(index)
|
||||
PARAM_FLOAT(x)
|
||||
PARAM_FLOAT(y)
|
||||
PARAM_INT(flags)
|
||||
|
||||
if (index < 0 || index > 3 || ((flags & WOF_KEEPX) && (flags & WOF_KEEPY)) || !ACTION_CALL_FROM_PSPRITE())
|
||||
return 0;
|
||||
|
||||
DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
|
||||
|
||||
if (pspr == nullptr)
|
||||
return 0;
|
||||
|
||||
if (!(flags & WOF_KEEPX)) pspr->Coord[index].X = (flags & WOF_ADD) ? pspr->Coord[index].X + x : x;
|
||||
if (!(flags & WOF_KEEPY)) pspr->Coord[index].Y = (flags & WOF_ADD) ? pspr->Coord[index].Y + y : y;
|
||||
|
||||
if (flags & (WOF_ADD | WOF_INTERPOLATE)) pspr->InterpolateTic = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_OverlayScale
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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() || ((flags & WOF_KEEPX) && (flags & WOF_KEEPY)))
|
||||
return 0;
|
||||
|
||||
DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
|
||||
|
||||
if (pspr == nullptr)
|
||||
return 0;
|
||||
|
||||
if (!(flags & WOF_ZEROY) && wy == 0.0)
|
||||
wy = wx;
|
||||
|
||||
if (!(flags & WOF_KEEPX)) pspr->scale.X = (flags & WOF_ADD) ? pspr->scale.X + wx : wx;
|
||||
if (!(flags & WOF_KEEPY)) pspr->scale.Y = (flags & WOF_ADD) ? pspr->scale.Y + wy : wy;
|
||||
|
||||
if (flags & (WOF_ADD | WOF_INTERPOLATE)) pspr->InterpolateTic = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_OverlayRotate
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_OverlayRotate)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_INT(layer)
|
||||
PARAM_ANGLE(degrees)
|
||||
PARAM_INT(flags)
|
||||
|
||||
if (!ACTION_CALL_FROM_PSPRITE())
|
||||
return 0;
|
||||
|
||||
DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
|
||||
|
||||
if (pspr != nullptr)
|
||||
{
|
||||
pspr->rotation = (flags & WOF_ADD) ? pspr->rotation + degrees : degrees;
|
||||
if (flags & (WOF_ADD | WOF_INTERPOLATE)) pspr->InterpolateTic = true;
|
||||
}
|
||||
|
||||
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() || ((flags & WOF_KEEPX) && (flags & WOF_KEEPY)))
|
||||
return 0;
|
||||
|
||||
DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
|
||||
|
||||
if (pspr == nullptr)
|
||||
return 0;
|
||||
|
||||
if (flags & WOF_RELATIVE)
|
||||
{
|
||||
HandleOverlayRelative(pspr, &wx, &wy);
|
||||
}
|
||||
|
||||
if (!(flags & WOF_KEEPX)) pspr->pivot.X = (flags & WOF_ADD) ? pspr->pivot.X + wx : wx;
|
||||
if (!(flags & WOF_KEEPY)) pspr->pivot.Y = (flags & WOF_ADD) ? pspr->pivot.Y + wy : wy;
|
||||
|
||||
if (flags & (WOF_ADD | WOF_INTERPOLATE)) pspr->InterpolateTic = true;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -667,30 +833,16 @@ void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags)
|
|||
if (psp == nullptr)
|
||||
return;
|
||||
|
||||
if (!(flags & WOF_KEEPX))
|
||||
if (flags & WOF_RELATIVE)
|
||||
{
|
||||
if (flags & WOF_ADD)
|
||||
{
|
||||
psp->x += wx;
|
||||
}
|
||||
else
|
||||
{
|
||||
psp->x = wx;
|
||||
if (!(flags & WOF_INTERPOLATE)) psp->oldx = psp->x;
|
||||
}
|
||||
}
|
||||
if (!(flags & WOF_KEEPY))
|
||||
{
|
||||
if (flags & WOF_ADD)
|
||||
{
|
||||
psp->y += wy;
|
||||
}
|
||||
else
|
||||
{
|
||||
psp->y = wy;
|
||||
if (!(flags & WOF_INTERPOLATE)) psp->oldy = psp->y;
|
||||
}
|
||||
HandleOverlayRelative(psp, &wx, &wy);
|
||||
}
|
||||
|
||||
if (!(flags & WOF_KEEPX)) psp->x = (flags & WOF_ADD) ? psp->x + wx : wx;
|
||||
if (!(flags & WOF_KEEPY)) psp->y = (flags & WOF_ADD) ? psp->y + wy : wy;
|
||||
|
||||
if (!(flags & (WOF_ADD | WOF_INTERPOLATE)))
|
||||
psp->ResetInterpolation();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -739,8 +891,36 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags)
|
|||
if (set)
|
||||
pspr->Flags |= flags;
|
||||
else
|
||||
{
|
||||
pspr->Flags &= ~flags;
|
||||
|
||||
// This is the only way to shut off the temporary interpolation tic
|
||||
// in the event another mod is causing potential interference
|
||||
if (flags & PSPF_INTERPOLATE)
|
||||
pspr->ResetInterpolation();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_OverlayPivotAlign)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_INT(layer);
|
||||
PARAM_INT(halign);
|
||||
PARAM_INT(valign);
|
||||
|
||||
if (!ACTION_CALL_FROM_PSPRITE())
|
||||
return 0;
|
||||
|
||||
DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
|
||||
|
||||
if (pspr != nullptr)
|
||||
{
|
||||
if (halign >= PSPA_LEFT && halign <= PSPA_RIGHT)
|
||||
pspr->HAlign |= halign;
|
||||
if (valign >= PSPA_TOP && valign <= PSPA_BOTTOM)
|
||||
pspr->VAlign |= valign;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1052,6 +1232,11 @@ void DPSprite::Serialize(FSerializer &arc)
|
|||
("oldx", oldx)
|
||||
("oldy", oldy)
|
||||
("alpha", alpha)
|
||||
("pivot", pivot)
|
||||
("scale", scale)
|
||||
("rotation", rotation)
|
||||
("halign", HAlign)
|
||||
("valign", VAlign)
|
||||
("renderstyle_", Renderstyle); // The underscore is intentional to avoid problems with old savegames which had this as an ERenderStyle (which is not future proof.)
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,23 @@ 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_INTERPOLATE = 1 << 12,
|
||||
};
|
||||
|
||||
enum PSPAlign
|
||||
{
|
||||
PSPA_TOP = 0,
|
||||
PSPA_CENTER,
|
||||
PSPA_BOTTOM,
|
||||
PSPA_LEFT = PSPA_TOP,
|
||||
PSPA_RIGHT = 2
|
||||
};
|
||||
|
||||
struct WeaponInterp
|
||||
{
|
||||
FVector2 v[4];
|
||||
};
|
||||
|
||||
class DPSprite : public DObject
|
||||
|
@ -92,13 +108,21 @@ public:
|
|||
DPSprite* GetNext() { return Next; }
|
||||
AActor* GetCaller() { return Caller; }
|
||||
void SetCaller(AActor *newcaller) { Caller = newcaller; }
|
||||
void ResetInterpolation() { oldx = x; oldy = y; }
|
||||
void ResetInterpolation() { oldx = x; oldy = y; Prev = Vert; InterpolateTic = false; }
|
||||
void OnDestroy() override;
|
||||
std::pair<FRenderStyle, float> GetRenderStyle(FRenderStyle ownerstyle, double owneralpha);
|
||||
float GetYAdjust(bool fullscreen);
|
||||
|
||||
int HAlign, VAlign; // Horizontal and vertical alignment
|
||||
DAngle rotation; // How much rotation to apply.
|
||||
DVector2 pivot; // pivot points
|
||||
DVector2 scale; // Scale
|
||||
double x, y, alpha;
|
||||
double oldx, oldy;
|
||||
bool InterpolateTic; // One tic interpolation (WOF_INTERPOLATE)
|
||||
DVector2 Coord[4]; // Offsets
|
||||
WeaponInterp Prev; // Interpolation
|
||||
WeaponInterp Vert; // Current Position
|
||||
bool firstTic;
|
||||
int Tics;
|
||||
uint32_t Translation;
|
||||
|
|
|
@ -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(double ticfrac);
|
||||
|
||||
void UpdateCurrentMapSection();
|
||||
void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
|
|
|
@ -195,8 +195,7 @@ static FVector2 BobWeapon(WeaponPosition &weap, DPSprite *psp, double ticFrac)
|
|||
if (psp->firstTic)
|
||||
{ // Can't interpolate the first tic.
|
||||
psp->firstTic = false;
|
||||
psp->oldx = psp->x;
|
||||
psp->oldy = psp->y;
|
||||
psp->ResetInterpolation();
|
||||
}
|
||||
|
||||
float sx = float(psp->oldx + (psp->x - psp->oldx) * ticFrac);
|
||||
|
@ -407,7 +406,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, double ticfrac)
|
||||
{
|
||||
float tx;
|
||||
float scale;
|
||||
|
@ -435,13 +434,14 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy,
|
|||
|
||||
tx = (psp->Flags & PSPF_MIRROR) ? ((160 - r.width) - (sx + r.left)) : (sx - (160 - r.left));
|
||||
x1 = tx * scalex + vw / 2;
|
||||
if (x1 > vw) return false; // off the right side
|
||||
// [MC] Disabled these because vertices can be manipulated now.
|
||||
//if (x1 > vw) return false; // off the right side
|
||||
x1 += viewwindowx;
|
||||
|
||||
|
||||
tx += r.width;
|
||||
x2 = tx * scalex + vw / 2;
|
||||
if (x2 < 0) return false; // off the left side
|
||||
//if (x2 < 0) return false; // off the left side
|
||||
x2 += viewwindowx;
|
||||
|
||||
// killough 12/98: fix psprite positioning problem
|
||||
|
@ -451,8 +451,8 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy,
|
|||
y1 = viewwindowy + vh / 2 - (ftexturemid * scale);
|
||||
y2 = y1 + (r.height * scale) + 1;
|
||||
|
||||
|
||||
if (!(mirror) != !(psp->Flags & (PSPF_FLIP)))
|
||||
const bool flip = (psp->Flags & PSPF_FLIP);
|
||||
if (!(mirror) != !(flip))
|
||||
{
|
||||
u2 = spi.GetSpriteUL();
|
||||
v1 = spi.GetSpriteVT();
|
||||
|
@ -467,13 +467,111 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy,
|
|||
v2 = spi.GetSpriteVB();
|
||||
}
|
||||
|
||||
// [MC] Code copied from DTA_Rotate.
|
||||
// Big thanks to IvanDobrovski who helped me modify this.
|
||||
|
||||
WeaponInterp Vert;
|
||||
Vert.v[0] = FVector2(x1, y1);
|
||||
Vert.v[1] = FVector2(x1, y2);
|
||||
Vert.v[2] = FVector2(x2, y1);
|
||||
Vert.v[3] = FVector2(x2, y2);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
const float cx = (flip) ? -psp->Coord[i].X : psp->Coord[i].X;
|
||||
Vert.v[i] += FVector2(cx * scalex, psp->Coord[i].Y * scale);
|
||||
}
|
||||
if (psp->rotation != 0.0 || !psp->scale.isZero())
|
||||
{
|
||||
// [MC] Sets up the alignment for starting the pivot at, in a corner.
|
||||
float anchorx, anchory;
|
||||
switch (psp->VAlign)
|
||||
{
|
||||
default:
|
||||
case PSPA_TOP: anchory = 0.0; break;
|
||||
case PSPA_CENTER: anchory = 0.5; break;
|
||||
case PSPA_BOTTOM: anchory = 1.0; break;
|
||||
}
|
||||
|
||||
switch (psp->HAlign)
|
||||
{
|
||||
default:
|
||||
case PSPA_LEFT: anchorx = 0.0; break;
|
||||
case PSPA_CENTER: anchorx = 0.5; break;
|
||||
case PSPA_RIGHT: anchorx = 1.0; break;
|
||||
}
|
||||
// Handle PSPF_FLIP.
|
||||
if (flip) anchorx = 1.0 - anchorx;
|
||||
|
||||
FAngle rot = float((flip) ? -psp->rotation.Degrees : psp->rotation.Degrees);
|
||||
const float cosang = rot.Cos();
|
||||
const float sinang = rot.Sin();
|
||||
|
||||
float xcenter, ycenter;
|
||||
const float width = x2 - x1;
|
||||
const float height = y2 - y1;
|
||||
const float px = float((flip) ? -psp->pivot.X : psp->pivot.X);
|
||||
const float py = float(psp->pivot.Y);
|
||||
|
||||
// Set up the center and offset accordingly. PivotPercent changes it to be a range [0.0, 1.0]
|
||||
// instead of pixels and is enabled by default.
|
||||
if (psp->Flags & PSPF_PIVOTPERCENT)
|
||||
{
|
||||
xcenter = x1 + (width * anchorx + width * px);
|
||||
ycenter = y1 + (height * anchory + height * py);
|
||||
}
|
||||
else
|
||||
{
|
||||
xcenter = x1 + (width * anchorx + scalex * px);
|
||||
ycenter = y1 + (height * anchory + scale * py);
|
||||
}
|
||||
|
||||
// Now adjust the position, rotation and scale of the image based on the latter two.
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Vert.v[i] -= {xcenter, ycenter};
|
||||
const float xx = xcenter + psp->scale.X * (Vert.v[i].X * cosang + Vert.v[i].Y * sinang);
|
||||
const float yy = ycenter - psp->scale.Y * (Vert.v[i].X * sinang - Vert.v[i].Y * cosang);
|
||||
Vert.v[i] = {xx, yy};
|
||||
}
|
||||
}
|
||||
psp->Vert = Vert;
|
||||
|
||||
if (psp->scale.X == 0.0 || psp->scale.Y == 0.0)
|
||||
return false;
|
||||
|
||||
const bool interp = (psp->InterpolateTic || psp->Flags & PSPF_INTERPOLATE);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
FVector2 t = Vert.v[i];
|
||||
if (interp)
|
||||
t = psp->Prev.v[i] + (psp->Vert.v[i] - psp->Prev.v[i]) * ticfrac;
|
||||
|
||||
Vert.v[i] = t;
|
||||
}
|
||||
|
||||
// [MC] If this is absolutely necessary, uncomment it. It just checks if all the vertices
|
||||
// are all off screen either to the right or left, but is it honestly needed?
|
||||
/*
|
||||
if ((
|
||||
Vert.v[0].X > 0.0 &&
|
||||
Vert.v[1].X > 0.0 &&
|
||||
Vert.v[2].X > 0.0 &&
|
||||
Vert.v[3].X > 0.0) || (
|
||||
Vert.v[0].X < vw &&
|
||||
Vert.v[1].X < vw &&
|
||||
Vert.v[2].X < vw &&
|
||||
Vert.v[3].X < vw))
|
||||
return false;
|
||||
*/
|
||||
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);
|
||||
verts.first[0].Set(Vert.v[0].X, Vert.v[0].Y, 0, u1, v1);
|
||||
verts.first[1].Set(Vert.v[1].X, Vert.v[1].Y, 0, u1, v2);
|
||||
verts.first[2].Set(Vert.v[2].X, Vert.v[2].Y, 0, u2, v1);
|
||||
verts.first[3].Set(Vert.v[3].X, Vert.v[3].Y, 0, u2, v2);
|
||||
|
||||
texture = tex;
|
||||
return true;
|
||||
|
@ -554,12 +652,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, vp.TicFrac)) continue;
|
||||
}
|
||||
hudsprites.Push(hudsprite);
|
||||
}
|
||||
lightmode = oldlightmode;
|
||||
PrepareTargeterSprites();
|
||||
PrepareTargeterSprites(vp.TicFrac);
|
||||
}
|
||||
|
||||
|
||||
|
@ -569,7 +667,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWDrawInfo::PrepareTargeterSprites()
|
||||
void HWDrawInfo::PrepareTargeterSprites(double ticfrac)
|
||||
{
|
||||
AActor * playermo = players[consoleplayer].camera;
|
||||
player_t * player = playermo->player;
|
||||
|
@ -601,7 +699,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, ticfrac))
|
||||
{
|
||||
hudsprites.Push(hudsprite);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,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, double ticfrac);
|
||||
|
||||
};
|
||||
|
|
|
@ -1188,6 +1188,11 @@ 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_OverlayPivotAlign(int layer, int halign, int valign);
|
||||
action native void A_OverlayVertexOffset(int layer, int index, double x, double y, 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);
|
||||
|
|
|
@ -60,6 +60,7 @@ class Beak : Weapon
|
|||
if (psp)
|
||||
{
|
||||
psp.y = WEAPONTOP;
|
||||
ResetPSprite(psp);
|
||||
}
|
||||
player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState());
|
||||
}
|
||||
|
|
|
@ -213,6 +213,22 @@ class Weapon : StateProvider
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
action void ResetPSprite(PSprite psp)
|
||||
{
|
||||
if (!psp) return;
|
||||
psp.rotation = 0;
|
||||
psp.scale.x = 1;
|
||||
psp.scale.y = 1;
|
||||
psp.pivot.x = 0;
|
||||
psp.pivot.y = 0;
|
||||
psp.valign = 0;
|
||||
psp.halign = 0;
|
||||
psp.Coord0 = (0,0);
|
||||
psp.Coord1 = (0,0);
|
||||
psp.Coord2 = (0,0);
|
||||
psp.Coord3 = (0,0);
|
||||
}
|
||||
|
||||
action void A_Lower(int lowerspeed = 6)
|
||||
{
|
||||
let player = player;
|
||||
|
@ -240,6 +256,8 @@ class Weapon : StateProvider
|
|||
{ // Not lowered all the way yet
|
||||
return;
|
||||
}
|
||||
ResetPSprite(psp);
|
||||
|
||||
if (player.playerstate == PST_DEAD)
|
||||
{ // Player is dead, so don't bring up a pending weapon
|
||||
// Player is dead, so keep the weapon off screen
|
||||
|
@ -278,12 +296,18 @@ class Weapon : StateProvider
|
|||
}
|
||||
let psp = player.GetPSprite(PSP_WEAPON);
|
||||
if (!psp) return;
|
||||
|
||||
if (psp.y <= WEAPONBOTTOM)
|
||||
{
|
||||
ResetPSprite(psp);
|
||||
}
|
||||
psp.y -= raisespeed;
|
||||
if (psp.y > WEAPONTOP)
|
||||
{ // Not raised all the way yet
|
||||
return;
|
||||
}
|
||||
psp.y = WEAPONTOP;
|
||||
|
||||
psp.SetState(player.ReadyWeapon.GetReadyState());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1664,7 +1664,11 @@ class PlayerPawn : Actor
|
|||
if (player.ReadyWeapon != null)
|
||||
{
|
||||
let psp = player.GetPSprite(PSP_WEAPON);
|
||||
if (psp) psp.y = WEAPONTOP;
|
||||
if (psp)
|
||||
{
|
||||
psp.y = WEAPONTOP;
|
||||
player.ReadyWeapon.ResetPSprite(psp);
|
||||
}
|
||||
player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState());
|
||||
}
|
||||
return;
|
||||
|
@ -2557,8 +2561,17 @@ class PSprite : Object native play
|
|||
native double y;
|
||||
native double oldx;
|
||||
native double oldy;
|
||||
native Vector2 pivot;
|
||||
native Vector2 scale;
|
||||
native double rotation;
|
||||
native int HAlign, VAlign;
|
||||
native Vector2 Coord0; // [MC] Not the actual coordinates. Just the offsets by A_OverlayVertexOffset.
|
||||
native Vector2 Coord1;
|
||||
native Vector2 Coord2;
|
||||
native Vector2 Coord3;
|
||||
native double alpha;
|
||||
native Bool firstTic;
|
||||
native bool InterpolateTic;
|
||||
native int Tics;
|
||||
native uint Translation;
|
||||
native bool bAddWeapon;
|
||||
|
@ -2568,6 +2581,8 @@ class PSprite : Object native play
|
|||
native bool bFlip;
|
||||
native bool bMirror;
|
||||
native bool bPlayerTranslated;
|
||||
native bool bPivotPercent;
|
||||
native bool bInterpolate;
|
||||
|
||||
native void SetState(State newstate, bool pending = false);
|
||||
|
||||
|
|
|
@ -60,7 +60,11 @@ extend class PlayerPawn
|
|||
if (player.ReadyWeapon != null)
|
||||
{
|
||||
let psp = player.GetPSprite(PSP_WEAPON);
|
||||
if (psp) psp.y = WEAPONTOP;
|
||||
if (psp)
|
||||
{
|
||||
psp.y = WEAPONTOP;
|
||||
player.ReadyWeapon.ResetPSprite(psp);
|
||||
}
|
||||
}
|
||||
|
||||
if (morphweaponcls == null || !(morphweaponcls is 'Weapon'))
|
||||
|
|
|
@ -739,22 +739,36 @@ enum EWeaponOffsetFlags
|
|||
WOF_KEEPY = 1 << 1,
|
||||
WOF_ADD = 1 << 2,
|
||||
WOF_INTERPOLATE = 1 << 3,
|
||||
WOF_RELATIVE = 1 << 4,
|
||||
WOF_ZEROY = 1 << 5,
|
||||
};
|
||||
|
||||
// Flags for psprite layers
|
||||
enum EPSpriteFlags
|
||||
{
|
||||
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,
|
||||
PSPF_MIRROR = 1 << 9,
|
||||
PSPF_PLAYERTRANSLATED = 1 << 10
|
||||
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,
|
||||
PSPF_MIRROR = 1 << 9,
|
||||
PSPF_PLAYERTRANSLATED = 1 << 10,
|
||||
PSPF_PIVOTPERCENT = 1 << 11,
|
||||
PSPF_INTERPOLATE = 1 << 12,
|
||||
};
|
||||
|
||||
// Alignment constants for A_OverlayPivotAlign
|
||||
enum EPSpriteAlign
|
||||
{
|
||||
PSPA_TOP = 0,
|
||||
PSPA_CENTER,
|
||||
PSPA_BOTTOM,
|
||||
PSPA_LEFT = PSPA_TOP,
|
||||
PSPA_RIGHT = 2
|
||||
};
|
||||
|
||||
// Default psprite layers
|
||||
|
|
Loading…
Reference in a new issue