From ad40299da4faeca8e971e062b45764ae5bbfc9e6 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 22 Oct 2024 18:22:43 -0400 Subject: [PATCH] - add sprite/frame support for VisualThinkers --- src/playsim/p_effect.cpp | 5 ++++- src/playsim/p_effect.h | 2 +- src/rendering/hwrenderer/scene/hw_sprites.cpp | 21 ++++++++++++++++--- wadsrc/static/zscript/visualthinker.zs | 3 +++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index f96ec13011b..c3bdaa6fcd0 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1006,6 +1006,7 @@ void DVisualThinker::Construct() PT.subsector = nullptr; cursector = nullptr; PT.color = 0xffffff; + sprite = -1; AnimatedTexture.SetNull(); } @@ -1110,7 +1111,7 @@ void DVisualThinker::Tick() return; // There won't be a standard particle for this, it's only for graphics. - if (!PT.texture.isValid()) + if (!PT.texture.isValid() && (sprite == -1)) { Printf("No valid texture, destroyed"); Destroy(); @@ -1325,3 +1326,5 @@ DEFINE_FIELD(DVisualThinker, PrevRoll); DEFINE_FIELD(DVisualThinker, Translation); DEFINE_FIELD(DVisualThinker, LightLevel); DEFINE_FIELD(DVisualThinker, cursector); +DEFINE_FIELD(DVisualThinker, sprite); +DEFINE_FIELD(DVisualThinker, frame); diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 1e5ba270536..d0a38f44c95 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -147,4 +147,4 @@ struct SPortalHit void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = nullAngle, int duration = TICRATE, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270, DAngle pitch = nullAngle); void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int kind); void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind); -void P_DisconnectEffect (AActor *actor); \ No newline at end of file +void P_DisconnectEffect (AActor *actor); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index b7e1f20fe16..326749c165f 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -414,7 +414,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : gl_billboard_faces_camera || ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) && (actor->renderflags2 & RF2_BILLBOARDFACECAMERA))) - || (particle && particle->texture.isValid() && (!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); + || ((!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); @@ -1409,8 +1409,10 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s if (!particle || particle->alpha <= 0) return; - if (spr && spr->PT.texture.isNull()) + if (spr && spr->PT.texture.isNull() && (spr->sprite == -1)) + { return; + } lightlevel = hw_ClampLight(spr ? spr->GetLightLevel(sector) : sector->GetSpriteLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); @@ -1483,7 +1485,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s } else { - bool has_texture = particle->texture.isValid(); + bool has_texture = particle->texture.isValid() || !!spr; bool custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles @@ -1505,6 +1507,19 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s else if(has_texture) { lump = particle->texture; + if (spr && !lump.isValid()) + { + bool mirror = false; + DVector3 thingpos = (DVector3)spr->InterpolatedPosition(vp.TicFrac); + DAngle ang = (thingpos - vp.Pos).Angle(); + if (di->Viewpoint.IsOrtho()) ang = vp.Angles.Yaw; + + bool spriteflip = false; // !!(thing->renderflags & RF_SPRITEFLIP) + + int rot; + rot = -1; + lump = sprites[spr->sprite].GetSpriteFrame(spr->frame, rot, ang, &mirror, spriteflip); + } } else { diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index 45b32865cb2..46f9bb7d73b 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -30,6 +30,9 @@ Class VisualThinker : Thinker native native void SetRenderStyle(int mode); // see ERenderStyle native bool IsFrozen(); + native SpriteID sprite; + native uint8 frame; + native protected void UpdateSector(); // needs to be called if the thinker is set to a non-ticking statnum and the position is modified (or if Tick is overriden and doesn't call Super.Tick()) native protected void UpdateSpriteInfo(); // needs to be called every time the texture is updated if the thinker uses SPF_LOCAL_ANIM and is set to a non-ticking statnum (or if Tick is overriden and doesn't call Super.Tick())