diff --git a/code/hud/hudtargetbox.cpp b/code/hud/hudtargetbox.cpp index fb1237cecf1..2edd689179d 100644 --- a/code/hud/hudtargetbox.cpp +++ b/code/hud/hudtargetbox.cpp @@ -1322,13 +1322,11 @@ void HudGaugeTargetBox::renderTargetJumpNode(object *target_objp) matrix camera_orient = IDENTITY_MATRIX; float factor, dist; int hx = 0, hy = 0, w, h; - SCP_list::iterator jnp; - - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - if(jnp->GetSCPObject() != target_objp) + for (auto &jnp : Jump_nodes) { + if(jnp.GetSCPObject() != target_objp) continue; - - if ( jnp->IsHidden() ) { + + if ( jnp.IsHidden() ) { set_target_objnum( Player_ai, -1 ); return; } @@ -1357,7 +1355,7 @@ void HudGaugeTargetBox::renderTargetJumpNode(object *target_objp) gr_stencil_set(GR_STENCIL_READ); } - jnp->Render( &obj_pos ); + jnp.Render( &obj_pos ); if ( Monitor_mask >= 0 ) { gr_stencil_set(GR_STENCIL_NONE); @@ -1370,7 +1368,7 @@ void HudGaugeTargetBox::renderTargetJumpNode(object *target_objp) renderTargetIntegrity(1); setGaugeColor(); - renderString(position[0] + Name_offsets[0], position[1] + Name_offsets[1], EG_TBOX_NAME, jnp->GetDisplayName()); + renderString(position[0] + Name_offsets[0], position[1] + Name_offsets[1], EG_TBOX_NAME, jnp.GetDisplayName()); dist = Player_ai->current_target_distance; if ( Hud_unit_multiplier > 0.0f ) { // use a different displayed distance scale diff --git a/code/jumpnode/jumpnode.cpp b/code/jumpnode/jumpnode.cpp index c0e68ff40b8..14c6afca734 100644 --- a/code/jumpnode/jumpnode.cpp +++ b/code/jumpnode/jumpnode.cpp @@ -13,7 +13,7 @@ #include "model/model.h" #include "model/modelrender.h" -SCP_list Jump_nodes; +SCP_vector Jump_nodes; /** * Constructor for CJumpNode class, default @@ -77,6 +77,14 @@ CJumpNode& CJumpNode::operator=(CJumpNode&& other) noexcept { if (this != &other) { + // Release this node's resources before overwriting them, mirroring the destructor. + if (m_polymodel_instance_num >= 0) + model_delete_instance(m_polymodel_instance_num); + if (m_modelnum >= 0) + model_unload(m_modelnum); + if (m_objnum >= 0 && Objects[m_objnum].type != OBJ_NONE) + obj_delete(m_objnum); + m_radius = std::exchange(other.m_radius, 0.0f); m_modelnum = std::exchange(other.m_modelnum, -1); m_objnum = std::exchange(other.m_objnum, -1); @@ -98,15 +106,14 @@ CJumpNode& CJumpNode::operator=(CJumpNode&& other) noexcept */ CJumpNode::~CJumpNode() { + if (m_polymodel_instance_num >= 0) + model_delete_instance(m_polymodel_instance_num); + if (m_modelnum >= 0) - { model_unload(m_modelnum); - } if (m_objnum >= 0 && Objects[m_objnum].type != OBJ_NONE) - { obj_delete(m_objnum); - } } // Accessor functions for private variables @@ -235,9 +242,11 @@ void CJumpNode::SetModel(const char *model_name, bool show_polys) Warning(LOCATION, "Couldn't load model file %s for jump node %s", model_name, m_name); return; } - + //If there's an old model, unload it - if(m_modelnum != -1) + if (m_polymodel_instance_num >= 0) + model_delete_instance(m_polymodel_instance_num); + if (m_modelnum >= 0) model_unload(m_modelnum); //Now actually set stuff @@ -260,6 +269,13 @@ void CJumpNode::SetModel(const char *model_name, bool show_polys) m_flags |= JN_SHOW_POLYS; else m_flags &= ~JN_SHOW_POLYS; + + // refresh the model instance + auto pm = model_get(m_modelnum); + if (pm->flags & PM_FLAG_HAS_INTRINSIC_MOTION) + m_polymodel_instance_num = model_create_instance(m_objnum, m_modelnum); + else + m_polymodel_instance_num = -1; } /** @@ -471,16 +487,32 @@ void CJumpNode::Render(model_draw_list *scene, const vec3d *pos, const vec3d *vi CJumpNode *jumpnode_get_by_name(const char* name) { Assert(name != NULL); - SCP_list::iterator jnp; - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - if(!stricmp(jnp->GetName(), name)) - return &(*jnp); + for (auto &jnp : Jump_nodes) { + if(!stricmp(jnp.GetName(), name)) + return &jnp; } return NULL; } +/** + * Get jump node index by given name + * + * @param name Name of jump node + * @return Jump node index + */ +int jumpnode_lookup(const char *name) +{ + Assert(name != nullptr); + + for (size_t i = 0; i < Jump_nodes.size(); i++) + if (!stricmp(Jump_nodes[i].GetName(), name)) + return sz2i(i); + + return -1; +} + /** * Get jump node object by the object number * @@ -526,17 +558,15 @@ CJumpNode *jumpnode_get_by_objp(const object *objp) CJumpNode *jumpnode_get_which_in(const object *objp) { Assert(objp != NULL); - SCP_list::iterator jnp; - float radius, dist; - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - if(jnp->GetModelNumber() < 0) + for (auto &jnp : Jump_nodes) { + if(jnp.GetModelNumber() < 0) continue; - radius = jnp->GetRadius(); - dist = vm_vec_dist( &objp->pos, &jnp->GetSCPObject()->pos ); + float radius = jnp.GetRadius(); + float dist = vm_vec_dist( &objp->pos, &jnp.GetSCPObject()->pos ); if ( dist <= radius ) { - return &(*jnp); + return &jnp; } } @@ -550,10 +580,8 @@ CJumpNode *jumpnode_get_which_in(const object *objp) */ void jumpnode_render_all() { - SCP_list::iterator jnp; - - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - jnp->Render(&jnp->GetSCPObject()->pos); + for (auto &jnp : Jump_nodes) { + jnp.Render(&jnp.GetSCPObject()->pos); } } diff --git a/code/jumpnode/jumpnode.h b/code/jumpnode/jumpnode.h index 05fadd320a9..6479fdaa845 100644 --- a/code/jumpnode/jumpnode.h +++ b/code/jumpnode/jumpnode.h @@ -94,10 +94,11 @@ class CJumpNode }; //-----Globals------ -extern SCP_list Jump_nodes; +extern SCP_vector Jump_nodes; //-----Functions----- CJumpNode *jumpnode_get_by_name(const char *name); + int jumpnode_lookup(const char *name); CJumpNode *jumpnode_get_by_objnum(int objnum); CJumpNode *jumpnode_get_by_objp(const object *objp); CJumpNode *jumpnode_get_which_in(const object *objp); diff --git a/code/missioneditor/missionsave.cpp b/code/missioneditor/missionsave.cpp index 7941def3103..efced502ff2 100644 --- a/code/missioneditor/missionsave.cpp +++ b/code/missioneditor/missionsave.cpp @@ -4920,57 +4920,56 @@ int Fred_mission_save::save_waypoints() parse_comments(2); fout("\t\t;! %d lists total\n", Waypoint_lists.size()); - SCP_list::iterator jnp; - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { + for (auto &jn : Jump_nodes) { required_string_fred("$Jump Node:", "$Jump Node Name:"); parse_comments(2); - save_vector(jnp->GetSCPObject()->pos); + save_vector(jn.GetSCPObject()->pos); required_string_fred("$Jump Node Name:", "$Jump Node:"); parse_comments(); - fout(" %s", jnp->GetName()); + fout(" %s", jn.GetName()); if (save_config.save_format != MissionFormat::RETAIL) { // (If we are always saving display names, the "only/not written" comments do not apply) // The display name is only written if it currently exists, to avoid introducing inconsistencies - if (save_config.always_save_display_names || jnp->HasDisplayName()) { + if (save_config.always_save_display_names || jn.HasDisplayName()) { char truncated_name[NAME_LENGTH]; - strcpy_s(truncated_name, jnp->GetName()); + strcpy_s(truncated_name, jn.GetName()); end_string_at_first_hash_symbol(truncated_name); // Also, the display name is not written if it's just the truncation of the name at the hash - if (save_config.always_save_display_names || strcmp(jnp->GetDisplayName(), truncated_name) != 0) { + if (save_config.always_save_display_names || strcmp(jn.GetDisplayName(), truncated_name) != 0) { if (optional_string_fred("+Display Name:", "$Jump Node:")) { parse_comments(); } else { fout("\n+Display Name:"); } - fout_ext("", "%s", jnp->GetDisplayName()); + fout_ext("", "%s", jn.GetDisplayName()); } } - if (jnp->IsSpecialModel()) { + if (jn.IsSpecialModel()) { if (optional_string_fred("+Model File:", "$Jump Node:")) { parse_comments(); } else { fout("\n+Model File:"); } - int model = jnp->GetModelNumber(); + int model = jn.GetModelNumber(); polymodel* pm = model_get(model); fout(" %s", pm->filename); } - if (jnp->IsColored()) { + if (jn.IsColored()) { if (optional_string_fred("+Alphacolor:", "$Jump Node:")) { parse_comments(); } else { fout("\n+Alphacolor:"); } - const auto& jn_color = jnp->GetColor(); + const auto& jn_color = jn.GetColor(); fout(" %u %u %u %u", jn_color.red, jn_color.green, jn_color.blue, jn_color.alpha); } @@ -4978,17 +4977,17 @@ int Fred_mission_save::save_waypoints() if (hidden_is_there) parse_comments(); - if (hidden_is_there || jnp->IsHidden()) { + if (hidden_is_there || jn.IsHidden()) { if (!hidden_is_there) fout("\n+Hidden:"); - if (jnp->IsHidden()) + if (jn.IsHidden()) fout(" %s", "true"); else fout(" %s", "false"); } - const SCP_string& jn_layer = jnp->GetFredLayer(); + const SCP_string& jn_layer = jn.GetFredLayer(); if (!jn_layer.empty() && !lcase_equal(jn_layer, "Default")) { if (optional_string_fred("+Layer:", "$Jump Node:")) parse_comments(); diff --git a/code/missioneditor/sexp_tree_opf.cpp b/code/missioneditor/sexp_tree_opf.cpp index 331318f65e0..dc29f09fa04 100644 --- a/code/missioneditor/sexp_tree_opf.cpp +++ b/code/missioneditor/sexp_tree_opf.cpp @@ -1026,9 +1026,8 @@ sexp_list_item *SexpTreeOPF::get_listing_opf_jump_nodes() { sexp_list_item head; - SCP_list::iterator jnp; - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - head.add_data( jnp->GetName()); + for (auto &jn : Jump_nodes) { + head.add_data(jn.GetName()); } return head.next; diff --git a/code/object/object.cpp b/code/object/object.cpp index 06bbf7cb240..40530fb5394 100644 --- a/code/object/object.cpp +++ b/code/object/object.cpp @@ -1941,12 +1941,12 @@ void obj_queue_render(object* obj, model_draw_list* scene) asteroid_render(obj, scene); break; case OBJ_JUMP_NODE: - for ( SCP_list::iterator jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp ) { - if ( jnp->GetSCPObject() != obj ) { + for ( auto &jnp : Jump_nodes ) { + if ( jnp.GetSCPObject() != obj ) { continue; } - jnp->Render(scene, &obj->pos, &Eye_position); + jnp.Render(scene, &obj->pos, &Eye_position); } break; case OBJ_WAYPOINT: diff --git a/fred2/dumpstats.cpp b/fred2/dumpstats.cpp index 1f3cf4d8b30..53545264944 100644 --- a/fred2/dumpstats.cpp +++ b/fred2/dumpstats.cpp @@ -395,9 +395,8 @@ void DumpStats::get_object_stats(CString &buffer) // Jumpnodes buffer += "\r\nJUMPNODES\r\n"; - SCP_list::iterator jnp; - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - temp.Format("\tJumpnode: %s\r\n", jnp->GetName()); + for (auto &jnp : Jump_nodes) { + temp.Format("\tJumpnode: %s\r\n", jnp.GetName()); buffer += temp; } diff --git a/fred2/jumpnodedlg.cpp b/fred2/jumpnodedlg.cpp index 45c3400385e..ef4c916d2b3 100644 --- a/fred2/jumpnodedlg.cpp +++ b/fred2/jumpnodedlg.cpp @@ -86,20 +86,18 @@ BOOL jumpnode_dlg::Create() void jumpnode_dlg::OnInitMenu(CMenu* pMenu) { int i; - SCP_list::iterator jnp; CMenu *m; m = pMenu->GetSubMenu(0); clear_menu(m); - i = 0; - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - m->AppendMenu(MF_ENABLED | MF_STRING, ID_JUMP_NODE_MENU + i, jnp->GetName()); - if (jnp->GetSCPObjectNumber() == cur_object_index) { + i = 0; + for (auto &jnp : Jump_nodes) { + m->AppendMenu(MF_ENABLED | MF_STRING, ID_JUMP_NODE_MENU + i, jnp.GetName()); + if (jnp.GetSCPObjectNumber() == cur_object_index) { m->CheckMenuItem(ID_JUMP_NODE_MENU + i, MF_BYCOMMAND | MF_CHECKED); } i++; - } m->DeleteMenu(ID_PLACEHOLDER, MF_BYCOMMAND); diff --git a/fred2/management.cpp b/fred2/management.cpp index 462b408b1c0..08b38a971a0 100644 --- a/fred2/management.cpp +++ b/fred2/management.cpp @@ -10,6 +10,7 @@ #include "stdafx.h" +#include #include "FRED.h" #include "MainFrm.h" #include "FREDDoc.h" @@ -1235,7 +1236,6 @@ int common_object_delete(int obj) char msg[255]; const char *name; int i, z, r, type; - SCP_list::iterator jnp; type = Objects[obj].type; if (type == OBJ_START) { @@ -1357,15 +1357,13 @@ int common_object_delete(int obj) return 0; } else if (type == OBJ_JUMP_NODE) { - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - if(jnp->GetSCPObject() == &Objects[obj]) - break; - } + auto jnp = std::find_if(Jump_nodes.begin(), Jump_nodes.end(), + [obj](const CJumpNode &jn) { return jn.GetSCPObject() == &Objects[obj]; }); // come on, WMC, we don't want to call obj_delete twice... // fool the destructor into not calling obj_delete yet Objects[obj].type = OBJ_NONE; - + // now call the destructor if (jnp != Jump_nodes.end()) Jump_nodes.erase(jnp); diff --git a/qtfred/src/mission/Editor.cpp b/qtfred/src/mission/Editor.cpp index 8fd9ec659b2..dbf67061a06 100644 --- a/qtfred/src/mission/Editor.cpp +++ b/qtfred/src/mission/Editor.cpp @@ -1,5 +1,6 @@ #include "Editor.h" +#include #include #include #include @@ -974,7 +975,6 @@ int Editor::common_object_delete(int obj) { char msg[255]; const char *name; int i, z, r, type; - SCP_list::iterator jnp; type = Objects[obj].type; if (type == OBJ_START) { @@ -1096,11 +1096,8 @@ int Editor::common_object_delete(int obj) { } } else if (type == OBJ_JUMP_NODE) { - for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { - if (jnp->GetSCPObject() == &Objects[obj]) { - break; - } - } + auto jnp = std::find_if(Jump_nodes.begin(), Jump_nodes.end(), + [obj](const CJumpNode &jn) { return jn.GetSCPObject() == &Objects[obj]; }); // come on, WMC, we don't want to call obj_delete twice... // fool the destructor into not calling obj_delete yet