diff --git a/common/main/morph.h b/common/main/morph.h index 8214283b6..8d109909c 100644 --- a/common/main/morph.h +++ b/common/main/morph.h @@ -36,6 +36,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #ifdef dsx #include "object.h" +#include namespace dcx { @@ -51,11 +52,11 @@ struct morph_data : prohibit_void_ptr animating, visible, }; - object_base *obj = nullptr; // object which is morphing - uint8_t n_submodels_active; + object_base *const obj; // object which is morphing + const object_signature_t Morph_sig; uint8_t morph_save_control_type; uint8_t morph_save_movement_type; - object_signature_t Morph_sig; + uint8_t n_submodels_active; physics_info morph_save_phys_info; array submodel_active; // which submodels are active array morph_vecs, morph_deltas; @@ -63,14 +64,20 @@ struct morph_data : prohibit_void_ptr array n_morphing_points, // how many active points in each part submodel_startpoints; // first point for each submodel + explicit morph_data(object_base &o) : + obj(&o), Morph_sig(o.signature) + { + } }; struct d_level_unique_morph_object_state { - array morph_objects; + array, 5> morph_objects; }; extern d_level_unique_morph_object_state LevelUniqueMorphObjectState; + +std::unique_ptr *find_morph_data(object_base &obj); } void morph_start(vmobjptr_t obj); @@ -80,8 +87,6 @@ void do_morph_frame(object &obj); //called at the start of a level void init_morphs(); - -morph_data *find_morph_data(object &obj); #endif #endif diff --git a/similar/main/morph.cpp b/similar/main/morph.cpp index eef848b3b..9f064d077 100644 --- a/similar/main/morph.cpp +++ b/similar/main/morph.cpp @@ -52,23 +52,23 @@ namespace dcx { d_level_unique_morph_object_state LevelUniqueMorphObjectState; -} - //returns ptr to data for this object, or NULL if none -morph_data *find_morph_data(object &obj) +std::unique_ptr *find_morph_data(object_base &obj) { auto &morph_objects = LevelUniqueMorphObjectState.morph_objects; if (Newdemo_state == ND_STATE_PLAYBACK) { - morph_objects[0].obj = &obj; + morph_objects[0] = make_unique(obj); return &morph_objects[0]; } range_for (auto &i, morph_objects) - if (i.obj == &obj) + if (i && i->obj == &obj) return &i; return nullptr; } +} + static void assign_max(fix &a, const fix &b) { a = std::max(a, b); @@ -214,14 +214,13 @@ static void update_points(const polymodel *const pm, const unsigned submodel_num //process the morphing object for one frame void do_morph_frame(object &obj) { - morph_data *md; + const auto umd = find_morph_data(obj); - md = find_morph_data(obj); - - if (md == NULL) { //maybe loaded half-morphed from disk + if (!umd) { //maybe loaded half-morphed from disk obj.flags |= OF_SHOULD_BE_DEAD; //..so kill it return; } + const auto md = umd->get(); assert(md->obj == &obj); auto &Polygon_models = LevelSharedPolygonModelState.Polygon_models; @@ -252,7 +251,7 @@ void do_morph_frame(object &obj) obj.render_type = RT_POLYOBJ; obj.mtype.phys_info = md->morph_save_phys_info; - md->obj = NULL; + umd->reset(); } } @@ -261,8 +260,7 @@ constexpr vms_vector morph_rotvel{0x4000,0x2000,0x1000}; void init_morphs() { auto &morph_objects = LevelUniqueMorphObjectState.morph_objects; - range_for (auto &i, morph_objects) - i.obj = nullptr; + morph_objects = {}; } @@ -276,21 +274,22 @@ void morph_start(const vmobjptr_t obj) auto &morph_objects = LevelUniqueMorphObjectState.morph_objects; const auto mob = morph_objects.begin(); const auto moe = morph_objects.end(); - const auto mop = [](const morph_data &mo) { - return mo.obj == nullptr || mo.obj->type == OBJ_NONE || mo.obj->signature != mo.Morph_sig; + const auto mop = [](const std::unique_ptr &pmo) { + if (!pmo) + return true; + auto &mo = *pmo.get(); + return mo.obj->type == OBJ_NONE || mo.obj->signature != mo.Morph_sig; }; const auto moi = std::find_if(mob, moe, mop); if (moi == moe) //no free slots return; - morph_data *const md = &*moi; + *moi = make_unique(obj); + morph_data *const md = moi->get(); Assert(obj->render_type == RT_POLYOBJ); - md->obj = obj; - md->Morph_sig = obj->signature; - md->morph_save_control_type = obj->control_type; md->morph_save_movement_type = obj->movement_type; md->morph_save_phys_info = obj->mtype.phys_info; @@ -391,10 +390,11 @@ void draw_morph_object(grs_canvas &canvas, const d_level_unique_light_state &Lev { // int save_light; polymodel *po; - morph_data *md; - md = find_morph_data(obj); - Assert(md != NULL); + const auto umd = find_morph_data(obj); + if (!umd) + throw std::runtime_error("missing morph data"); + const auto md = umd->get(); auto &Polygon_models = LevelSharedPolygonModelState.Polygon_models; po=&Polygon_models[obj->rtype.pobj_info.model_num]; diff --git a/similar/main/state.cpp b/similar/main/state.cpp index 383da31ac..26f2b0c84 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -1120,14 +1120,14 @@ int state_save_all_sub(const char *filename, const char *desc) { if (objp->type != OBJ_NONE && objp->render_type == RT_MORPH) { - morph_data *md; - md = find_morph_data(objp); - if (md) { + if (const auto umd = find_morph_data(objp)) + { + const auto md = umd->get(); md->obj->control_type = md->morph_save_control_type; set_object_movement_type(*md->obj, md->morph_save_movement_type); md->obj->render_type = RT_POLYOBJ; md->obj->mtype.phys_info = md->morph_save_phys_info; - md->obj = NULL; + umd->reset(); } else { //maybe loaded half-morphed from disk objp->flags |= OF_SHOULD_BE_DEAD; objp->render_type = RT_POLYOBJ;