From e827e9b0860f92beb4711226085e44b5e04e2411 Mon Sep 17 00:00:00 2001 From: Shiny Metagross <30511800+ShinyMetagross@users.noreply.github.com> Date: Thu, 30 Jun 2022 00:12:06 -0700 Subject: [PATCH] TArrays to TObjPtr - Made the 2 TArrays into a class called DActorModelData. - Removed the skinindex and now just uses one index - Replaced a bunch of nullptr for modelDef checking with NAME_None - Added some garbage cleanup to A_ChangeModel itself, as well as removing memory of modelData that is no longer needed - Attempted serialize code, putting up for review --- src/playsim/actor.h | 17 +++++-- src/playsim/p_actionfunctions.cpp | 46 +++++++++++++++---- src/playsim/p_mobj.cpp | 19 +++++++- src/r_data/models.cpp | 25 +++++----- src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 +- wadsrc/static/zscript/actors/actor.zs | 2 +- 6 files changed, 84 insertions(+), 27 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index a2a5250894..2b8b3f84e5 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -673,6 +673,18 @@ enum EViewPosFlags // [MC] Flags for SetViewPos. VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position. }; +class DActorModelData : public DObject +{ + DECLARE_CLASS(DActorModelData, DObject); +public: + bool hasModel; + TArray modelIDs; + TArray skinIDs; + + DActorModelData() = default; + virtual void Serialize(FSerializer& arc) override; +}; + class DViewPosition : public DObject { DECLARE_CLASS(DViewPosition, DObject); @@ -1068,9 +1080,8 @@ public: DVector3 WorldOffset; double Speed; double FloatSpeed; - FName modelDef; - TArray models; - TArray skins; + FName modelDef; + TObjPtr modelData; // interaction info FBlockNode *BlockNode; // links in blocks (if needed) diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 56d61451d2..eea576fb20 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -5037,12 +5037,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel) { PARAM_ACTION_PROLOGUE(AActor); PARAM_NAME(modeldef) + PARAM_INT(index) PARAM_STRING_VAL(modelpath) PARAM_NAME(model) - PARAM_INT(modelindex) PARAM_STRING_VAL(skinpath) PARAM_NAME(skin) - PARAM_INT(skinindex) PARAM_INT(flags) if (self == nullptr) @@ -5053,15 +5052,42 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel) if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/'; if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/'; - mobj->hasmodel = modeldef == nullptr && !mobj->hasmodel ? 1 : 0; - mobj->modelDef = modeldef; + if (mobj->modelData == nullptr) + { + auto ptr = Create(); + ptr->hasModel = modeldef != NAME_None && !mobj->hasmodel ? 0 : 1; + ptr->modelIDs = *new TArray(); + ptr->skinIDs = *new TArray(); + mobj->modelData = ptr; + mobj->hasmodel = mobj->modelData->hasModel; + GC::WriteBarrier(mobj, ptr); + } - mobj->models.Delete(modelindex); - mobj->skins.Delete(skinindex); - if(model != nullptr) mobj->models.Insert(modelindex, FindModel(modelpath.GetChars(), model.GetChars())); - else mobj->models.Insert(modelindex, -1); - if(skin != nullptr) mobj->skins.Insert(skinindex, LoadSkin(skinpath.GetChars(), skin.GetChars())); - else mobj->skins.Insert(skinindex, FNullTextureID()); + mobj->modelDef = modeldef; + mobj->modelData->modelIDs.Delete(index); + mobj->modelData->skinIDs.Delete(index); + mobj->modelData->modelIDs.Insert(index, model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1); + mobj->modelData->skinIDs.Insert(index, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID()); + + //[SM] - if an indice of modelIDs or skinIDs comes up blank and it's the last one, just delete it. For using very large amounts of indices, common sense says to just not run this repeatedly. + int i = 0; + int maxModels = mobj->modelData->modelIDs.Size(); + int maxSkins = mobj->modelData->modelIDs.Size(); + for (i = 0; i < maxModels; i++) + { + if (mobj->modelData->modelIDs[mobj->modelData->modelIDs.Size()-1] == -1) + mobj->modelData->modelIDs.Delete(mobj->modelData->modelIDs.Size()-1); + } + for (i = 0; i < maxSkins; i++) + { + if (mobj->modelData->skinIDs[mobj->modelData->skinIDs.Size()-1] == FNullTextureID()) + mobj->modelData->skinIDs.Delete(mobj->modelData->skinIDs.Size()-1); + } + if (mobj->modelData->modelIDs.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && modeldef == NAME_None) + { + mobj->hasmodel = mobj->modelData->hasModel; + mobj->modelData = nullptr; + } return 0; } diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index f9e306dc3b..ae5e3dc883 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -158,6 +158,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- +IMPLEMENT_CLASS(DActorModelData, false, false); IMPLEMENT_CLASS(AActor, false, true) IMPLEMENT_POINTERS_START(AActor) @@ -374,7 +375,9 @@ void AActor::Serialize(FSerializer &arc) ("viewpos", ViewPos) A("lightlevel", LightLevel) A("userlights", UserLights) - A("WorldOffset", WorldOffset); + A("WorldOffset", WorldOffset) + A("modelData", modelData) + A("modelDef", modelDef); SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain); SerializeArgs(arc, "args", args, def->args, special); @@ -1353,6 +1356,20 @@ bool AActor::Massacre () return false; } +//---------------------------------------------------------------------------- +// +// Serialize DActorModelData +// +//---------------------------------------------------------------------------- + +void DActorModelData::Serialize(FSerializer& arc) +{ + Super::Serialize(arc); + arc ("modelIDs", modelIDs) + ("skinIDs", skinIDs) + ("hasModel", hasModel); +} + //---------------------------------------------------------------------------- // // PROC P_ExplodeMissile diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 3bc5e22487..effe9a8842 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -176,14 +176,14 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod float orientation = scaleFactorX * scaleFactorY * scaleFactorZ; renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0); - RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->modelDef != nullptr ? PClass::FindActor(actor->modelDef) : actor->GetClass(), translation, actor); + RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->modelDef != NAME_None ? PClass::FindActor(actor->modelDef) : actor->GetClass(), translation, actor); renderer->EndDrawModel(actor->RenderStyle, smf); } void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float ofsY) { AActor * playermo = players[consoleplayer].camera; - FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelDef != nullptr ? PClass::FindActor(psp->Caller->modelDef) : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; + FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelDef) : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; // [BB] No model found for this sprite, so we can't render anything. if (smf == nullptr) @@ -224,7 +224,7 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float o renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0); uint32_t trans = psp->GetTranslation() != 0 ? psp->GetTranslation() : 0; if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation; - RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), psp->Caller->modelDef != nullptr ? PClass::FindActor(psp->Caller->modelDef) : psp->Caller->GetClass(), trans, psp->Caller); + RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), psp->Caller->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelDef) : psp->Caller->GetClass(), trans, psp->Caller); renderer->EndDrawHUDModel(playermo->RenderStyle); } @@ -281,19 +281,22 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr TArray tempSkinIDs = smf->skinIDs; for (int i = 0; i < smf->modelsAmount; i++) { - if (i < actor->models.Size()) + if (actor->modelData != nullptr) { - if (actor->models[i] >= 0) - tempModelIDs[i] = actor->models[i]; + if (i < (int)actor->modelData->modelIDs.Size()) + { + if(actor->modelData->modelIDs[i] >= 0) + tempModelIDs[i] = actor->modelData->modelIDs[i]; + } + if (i < (int)actor->modelData->skinIDs.Size()) + { + if (actor->modelData->skinIDs[i].isValid()) + tempSkinIDs[i] = actor->modelData->skinIDs[i]; + } } if (tempModelIDs[i] != -1) { FModel * mdl = Models[tempModelIDs[i]]; - if (i < actor->skins.Size()) - { - if (actor->skins[i].isValid()) - tempSkinIDs[i] = actor->skins[i]; - } auto tex = tempSkinIDs[i].isValid() ? TexMan.GetGameTexture(tempSkinIDs[i], true) : nullptr; mdl->BuildVertexBuffer(renderer); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 003bf3604e..40c261cc93 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -834,7 +834,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t z += fz; } - modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->modelDef != nullptr ? PClass::FindActor(thing->modelDef) : thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->modelDef != NAME_None ? PClass::FindActor(thing->modelDef) : thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); // don't bother drawing sprite shadows if this is a model (it will never look right) if (modelframe && isSpriteShadow) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index e95963cca7..1fc8f14d1c 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1132,7 +1132,7 @@ class Actor : Thinker native native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.); deprecated("2.3", "Use 'b = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); - action native void A_ChangeModel(name modeldef, string modelpath = "", name model = "", int modelindex = 0, string skinpath = "", name skin = "", int skinindex = 0, int flags = 0); + action native void A_ChangeModel(name modeldef, int index = 0, string modelpath = "", name model = "", string skinpath = "", name skin = "", int flags = 0); void A_SetFriendly (bool set) {