mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 07:32:28 +00:00
Updated VisualThinker render linkage
Now uses its own self-managed linked list with its level tracking the head pointer. Allows for VisualThinkers to be moved to any desired stat instead of being stuck in STAT_VISUALTHINKER.
This commit is contained in:
parent
61df13306f
commit
c87dc5ccad
6 changed files with 42 additions and 28 deletions
|
@ -427,11 +427,6 @@ public:
|
|||
DThinker *CreateThinker(PClass *cls, int statnum = STAT_DEFAULT)
|
||||
{
|
||||
DThinker *thinker = static_cast<DThinker*>(cls->CreateNew());
|
||||
if (thinker->IsKindOf(RUNTIME_CLASS(DVisualThinker)))
|
||||
{
|
||||
statnum = STAT_VISUALTHINKER;
|
||||
}
|
||||
|
||||
assert(thinker->IsKindOf(RUNTIME_CLASS(DThinker)));
|
||||
thinker->ObjectFlags |= OF_JustSpawned;
|
||||
Thinkers.Link(thinker, statnum);
|
||||
|
@ -708,6 +703,7 @@ public:
|
|||
int ImpactDecalCount;
|
||||
|
||||
FDynamicLight *lights;
|
||||
DVisualThinker* VisualThinkerHead = nullptr;
|
||||
|
||||
// links to global game objects
|
||||
TArray<TObjPtr<AActor *>> CorpseQueue;
|
||||
|
|
|
@ -990,7 +990,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
|
|||
("scrolls", Scrolls)
|
||||
("automap", automap)
|
||||
("interpolator", interpolator)
|
||||
("frozenstate", frozenstate);
|
||||
("frozenstate", frozenstate)
|
||||
("visualthinkerhead", VisualThinkerHead);
|
||||
|
||||
|
||||
// Hub transitions must keep the current total time
|
||||
|
|
|
@ -810,11 +810,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DThinker, ChangeStatNum, ChangeStatNum)
|
|||
PARAM_SELF_PROLOGUE(DThinker);
|
||||
PARAM_INT(stat);
|
||||
|
||||
// do not allow ZScript to reposition thinkers in or out of particle ticking.
|
||||
if (stat != STAT_VISUALTHINKER && !dynamic_cast<DVisualThinker*>(self))
|
||||
{
|
||||
ChangeStatNum(self, stat);
|
||||
}
|
||||
ChangeStatNum(self, stat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -214,15 +214,13 @@ void P_FindParticleSubsectors (FLevelLocals *Level)
|
|||
{
|
||||
Level->subsectors[i].sprites.Clear();
|
||||
}
|
||||
// [MC] Not too happy about using an iterator for this but I can't think of another way to handle it.
|
||||
// At least it's on its own statnum for maximum efficiency.
|
||||
auto it = Level->GetThinkerIterator<DVisualThinker>(NAME_None, STAT_VISUALTHINKER);
|
||||
DVisualThinker* sp;
|
||||
while (sp = it.Next())
|
||||
auto sp = Level->VisualThinkerHead;
|
||||
while (sp != nullptr)
|
||||
{
|
||||
if (!sp->PT.subsector) sp->PT.subsector = Level->PointInRenderSubsector(sp->PT.Pos);
|
||||
|
||||
sp->PT.subsector->sprites.Push(sp);
|
||||
sp = sp->GetNext();
|
||||
}
|
||||
// End VisualThinker hitching. Now onto the particles.
|
||||
if (Level->ParticlesInSubsec.Size() < Level->subsectors.Size())
|
||||
|
@ -1007,26 +1005,38 @@ void DVisualThinker::Construct()
|
|||
cursector = nullptr;
|
||||
PT.color = 0xffffff;
|
||||
AnimatedTexture.SetNull();
|
||||
}
|
||||
|
||||
DVisualThinker::DVisualThinker()
|
||||
{
|
||||
Construct();
|
||||
_prev = _next = nullptr;
|
||||
if (Level->VisualThinkerHead != nullptr)
|
||||
{
|
||||
Level->VisualThinkerHead->_prev = this;
|
||||
_next = Level->VisualThinkerHead;
|
||||
}
|
||||
Level->VisualThinkerHead = this;
|
||||
}
|
||||
|
||||
void DVisualThinker::OnDestroy()
|
||||
{
|
||||
if (_prev != nullptr)
|
||||
_prev->_next = _next;
|
||||
if (_next != nullptr)
|
||||
_next->_prev = _prev;
|
||||
if (Level->VisualThinkerHead == this)
|
||||
Level->VisualThinkerHead = _next;
|
||||
|
||||
PT.alpha = 0.0; // stops all rendering.
|
||||
Super::OnDestroy();
|
||||
}
|
||||
|
||||
DVisualThinker* DVisualThinker::GetNext() const
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* type)
|
||||
{
|
||||
if (type == nullptr)
|
||||
return nullptr;
|
||||
else if (type->bAbstract)
|
||||
{
|
||||
Printf("Attempt to spawn an instance of abstract VisualThinker class %s\n", type->TypeName.GetChars());
|
||||
return nullptr;
|
||||
}
|
||||
else if (!type->IsDescendantOf(RUNTIME_CLASS(DVisualThinker)))
|
||||
|
@ -1034,8 +1044,13 @@ DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* ty
|
|||
Printf("Attempt to spawn class not inherent to VisualThinker: %s\n", type->TypeName.GetChars());
|
||||
return nullptr;
|
||||
}
|
||||
else if (type->bAbstract)
|
||||
{
|
||||
Printf("Attempt to spawn an instance of abstract VisualThinker class %s\n", type->TypeName.GetChars());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DVisualThinker *zs = static_cast<DVisualThinker*>(Level->CreateThinker(type, STAT_VISUALTHINKER));
|
||||
auto zs = static_cast<DVisualThinker*>(Level->CreateThinker(type, DVisualThinker::DEFAULT_STAT));
|
||||
zs->Construct();
|
||||
return zs;
|
||||
}
|
||||
|
@ -1284,7 +1299,7 @@ void DVisualThinker::Serialize(FSerializer& arc)
|
|||
{
|
||||
Super::Serialize(arc);
|
||||
|
||||
arc ("pos", PT.Pos)
|
||||
arc("pos", PT.Pos)
|
||||
("vel", PT.Vel)
|
||||
("prev", Prev)
|
||||
("scale", Scale)
|
||||
|
@ -1300,7 +1315,9 @@ void DVisualThinker::Serialize(FSerializer& arc)
|
|||
("lightlevel", LightLevel)
|
||||
("animData", PT.animData)
|
||||
("flags", PT.flags)
|
||||
("visualThinkerFlags", flags);
|
||||
("visualThinkerFlags", flags)
|
||||
("next", _next)
|
||||
("prev", _prev);
|
||||
|
||||
if(arc.isReading())
|
||||
{
|
||||
|
|
|
@ -26,7 +26,11 @@ class DVisualThinker : public DThinker
|
|||
{
|
||||
DECLARE_CLASS(DVisualThinker, DThinker);
|
||||
void UpdateSector(subsector_t * newSubsector);
|
||||
|
||||
DVisualThinker* _next, * _prev;
|
||||
public:
|
||||
static const int DEFAULT_STAT = STAT_VISUALTHINKER;
|
||||
|
||||
DVector3 Prev;
|
||||
DVector2 Scale,
|
||||
Offset;
|
||||
|
@ -41,9 +45,9 @@ public:
|
|||
// internal only variables
|
||||
particle_t PT;
|
||||
|
||||
DVisualThinker();
|
||||
void Construct();
|
||||
void OnDestroy() override;
|
||||
DVisualThinker* GetNext() const;
|
||||
|
||||
static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type);
|
||||
void SetTranslation(FName trname);
|
||||
|
|
|
@ -33,7 +33,7 @@ Class VisualThinker : Thinker native
|
|||
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())
|
||||
|
||||
static VisualThinker Spawn(Class<VisualThinker> type, TextureID tex, Vector3 pos, Vector3 vel, double alpha = 1.0, int flags = 0,
|
||||
static VisualThinker Spawn(Class<VisualThinker> type, TextureID tex, Vector3 pos, Vector3 vel = (0,0,0), double alpha = 1.0, int flags = 0,
|
||||
double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0, int VisualThinkerFlags = 0)
|
||||
{
|
||||
if (!Level) return null;
|
||||
|
|
Loading…
Reference in a new issue