From 87704fc81794300e5b5df6ae91f21cbe6725716d Mon Sep 17 00:00:00 2001 From: BMagnu <6238428+BMagnu@users.noreply.github.com> Date: Wed, 22 May 2024 00:18:32 +0900 Subject: [PATCH] Refactor replacement texture to a modelinstance parameter (#6154) * Move replacement textures from ship to modelinstance * Actually set pmi * Fix texture replace in fred as well * Fix bad indent * incorporate feedback --- code/asteroid/asteroid.cpp | 2 + code/debris/debris.cpp | 3 + code/hud/hudshield.cpp | 2 +- code/hud/hudtargetbox.cpp | 16 +- code/model/model.h | 43 +++-- code/model/modelrender.cpp | 70 ++++---- code/model/modelrender.h | 10 +- code/scripting/api/objs/cockpit_display.cpp | 2 +- code/scripting/api/objs/modelinstance.cpp | 121 ++++++++++++++ code/scripting/api/objs/modelinstance.h | 1 + code/scripting/api/objs/ship.cpp | 123 ++------------ code/scripting/api/objs/ship.h | 2 - code/ship/ship.cpp | 173 ++++++++------------ code/ship/ship.h | 5 +- code/ship/shipfx.cpp | 4 +- code/starfield/starfield.cpp | 3 + code/weapon/weapons.cpp | 3 + fred2/fredrender.cpp | 2 +- qtfred/src/mission/FredRenderer.cpp | 2 +- 19 files changed, 293 insertions(+), 294 deletions(-) diff --git a/code/asteroid/asteroid.cpp b/code/asteroid/asteroid.cpp index 2b3e56d2637..f3378e4ae1e 100644 --- a/code/asteroid/asteroid.cpp +++ b/code/asteroid/asteroid.cpp @@ -1523,6 +1523,8 @@ void asteroid_render(object * obj, model_draw_list *scene) render_info.set_object_number( OBJ_INDEX(obj) ); render_info.set_flags(MR_IS_ASTEROID); + if (asp->model_instance_num >= 0) + render_info.set_replacement_textures(model_get_instance(asp->model_instance_num)->texture_replace); model_render_queue(&render_info, scene, Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype], &obj->orient, &obj->pos); // Replace MR_NORMAL with 0x07 for big yellow blobs } diff --git a/code/debris/debris.cpp b/code/debris/debris.cpp index 8405d18f5ff..64320568b9c 100644 --- a/code/debris/debris.cpp +++ b/code/debris/debris.cpp @@ -1197,6 +1197,9 @@ void debris_render(object * obj, model_draw_list *scene) // render_info.set_flags(MR_NO_LIGHTING); } + if (db->model_instance_num >= 0) + render_info.set_replacement_textures(model_get_instance(db->model_instance_num)->texture_replace); + submodel_render_queue( &render_info, scene, pm, pmi, db->submodel_num, &obj->orient, &obj->pos ); if (tbase != NULL && (swapped!=-1) && pm) { diff --git a/code/hud/hudshield.cpp b/code/hud/hudshield.cpp index 7f0904506c4..f262056505c 100644 --- a/code/hud/hudshield.cpp +++ b/code/hud/hudshield.cpp @@ -641,7 +641,7 @@ void HudGaugeShield::showShields(object *objp, int mode) model_render_params render_info; render_info.set_flags(MR_NO_LIGHTING | MR_AUTOCENTER | MR_NO_FOGGING); - render_info.set_replacement_textures(sp->ship_replacement_textures); + render_info.set_replacement_textures(model_get_instance(sp->model_instance_num)->texture_replace); render_info.set_detail_level_lock(1); render_info.set_object_number(OBJ_INDEX(objp)); diff --git a/code/hud/hudtargetbox.cpp b/code/hud/hudtargetbox.cpp index 175a7931462..83889ffb30a 100644 --- a/code/hud/hudtargetbox.cpp +++ b/code/hud/hudtargetbox.cpp @@ -677,7 +677,7 @@ void HudGaugeTargetBox::renderTargetShip(object *target_objp) if(target_sip->model_num_hud >= 0){ model_render_immediate( &render_info, target_sip->model_num_hud, &target_objp->orient, &obj_pos); } else { - render_info.set_replacement_textures(target_shipp->ship_replacement_textures); + render_info.set_replacement_textures(model_get_instance(target_shipp->model_instance_num)->texture_replace); model_render_immediate( &render_info, target_sip->model_num, &target_objp->orient, &obj_pos); } @@ -777,6 +777,9 @@ void HudGaugeTargetBox::renderTargetDebris(object *target_objp) model_render_params render_info; + if (debrisp->model_instance_num >= 0) + render_info.set_replacement_textures(model_get_instance(debrisp->model_instance_num)->texture_replace); + color thisColor = GaugeWirecolor; bool thisOverride = GaugeWirecolorOverride; @@ -863,7 +866,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp) weapon_info *target_wip = NULL; weapon *wp = NULL; object *viewer_obj, *viewed_obj; - int *replacement_textures = NULL; + std::shared_ptr replacement_textures = nullptr; int target_team, is_homing, is_player_missile, missile_view, viewed_model_num, hud_target_lod, w, h; int flags=0; @@ -902,10 +905,13 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp) viewed_obj = wp->homing_object; missile_view = TRUE; viewed_model_num = homing_sip->model_num; - replacement_textures = homing_shipp->ship_replacement_textures; hud_target_lod = homing_sip->hud_target_lod; } + int pmi_id = object_get_model_instance(viewed_obj); + if (pmi_id >= 0) + replacement_textures = model_get_instance(pmi_id)->texture_replace; + // take the forward orientation to be the vector from the player to the current target vm_vec_sub(&orient_vec, &viewed_obj->pos, &viewer_obj->pos); vm_vec_normalize(&orient_vec); @@ -1068,7 +1074,6 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp) model_render_immediate( &render_info, homing_sip->model_num_hud, &viewed_obj->orient, &obj_pos); } else { render_info.set_flags(flags | MR_NO_FOGGING); - render_info.set_replacement_textures(homing_shipp->ship_replacement_textures); model_render_immediate( &render_info, homing_sip->model_num, &viewed_obj->orient, &obj_pos ); } @@ -1170,6 +1175,9 @@ void HudGaugeTargetBox::renderTargetAsteroid(object *target_objp) model_render_params render_info; + if (asteroidp->model_instance_num >= 0) + render_info.set_replacement_textures(model_get_instance(asteroidp->model_instance_num)->texture_replace); + color thisColor = GaugeWirecolor; bool thisOverride = GaugeWirecolorOverride; diff --git a/code/model/model.h b/code/model/model.h index 2fdfb9a44e9..7bda9ddee77 100644 --- a/code/model/model.h +++ b/code/model/model.h @@ -140,6 +140,31 @@ struct submodel_instance } }; +#define TM_BASE_TYPE 0 // the standard base map +#define TM_GLOW_TYPE 1 // optional glow map +#define TM_SPECULAR_TYPE 2 // optional specular map +#define TM_NORMAL_TYPE 3 // optional normal map +#define TM_HEIGHT_TYPE 4 // optional height map (for parallax mapping) +#define TM_MISC_TYPE 5 // optional utility map +#define TM_SPEC_GLOSS_TYPE 6 // optional reflectance map (specular and gloss) +#define TM_AMBIENT_TYPE 7 // optional ambient occlusion map with ambient occlusion and cavity occlusion factors for red and green channels. +#define TM_NUM_TYPES 8 //WMC - Number of texture_info objects in texture_map + //Used by scripting - if you change this, do a search + //to update switch() statement in lua.cpp + +#define MAX_REPLACEMENT_TEXTURES MAX_MODEL_TEXTURES * TM_NUM_TYPES + +// Goober5000 - since we need something < 0 +#define REPLACE_WITH_INVISIBLE -47 + +class model_texture_replace : public std::array { +public: + model_texture_replace() : std::array() { + for (int& tex : *this) + tex = -1; + } +}; + // Data specific to a particular instance of a model. struct polymodel_instance { @@ -147,6 +172,8 @@ struct polymodel_instance int model_num = -1; // global model num index, same as polymodel->id submodel_instance *submodel = nullptr; // array of submodel instances; mirrors the polymodel->submodel array + std::shared_ptr texture_replace = nullptr; + int objnum; // id of the object using this pmi, or -1 if no object (e.g. skybox) }; @@ -730,17 +757,6 @@ class texture_info int SetTexture(int n_tex); }; -#define TM_BASE_TYPE 0 // the standard base map -#define TM_GLOW_TYPE 1 // optional glow map -#define TM_SPECULAR_TYPE 2 // optional specular map -#define TM_NORMAL_TYPE 3 // optional normal map -#define TM_HEIGHT_TYPE 4 // optional height map (for parallax mapping) -#define TM_MISC_TYPE 5 // optional utility map -#define TM_SPEC_GLOSS_TYPE 6 // optional reflectance map (specular and gloss) -#define TM_AMBIENT_TYPE 7 // optional ambient occlusion map with ambient occlusion and cavity occlusion factors for red and green channels. -#define TM_NUM_TYPES 8 //WMC - Number of texture_info objects in texture_map - //Used by scripting - if you change this, do a search - //to update switch() statement in lua.cpp // taylor //WMC - OOPified class texture_map @@ -765,11 +781,6 @@ class texture_map {} }; -#define MAX_REPLACEMENT_TEXTURES MAX_MODEL_TEXTURES * TM_NUM_TYPES - -// Goober5000 - since we need something < 0 -#define REPLACE_WITH_INVISIBLE -47 - //used to describe a polygon model // NOTE: Because WMC OOPified the textures, this must now be treated as a class, rather than a struct. // Additionally, a lot of model initialization and de-initialization is currently done in model_load or model_unload. diff --git a/code/model/modelrender.cpp b/code/model/modelrender.cpp index 81ba803b380..2439c2f8020 100644 --- a/code/model/modelrender.cpp +++ b/code/model/modelrender.cpp @@ -64,8 +64,7 @@ model_render_params::model_render_params() : Xparent_alpha(1.0f), Forced_bitmap(-1), Insignia_bitmap(-1), - Replacement_textures(NULL), - Manage_replacement_textures(false), + Replacement_textures(nullptr), Team_color_set(false), Clip_plane_set(false), Animated_effect(-1), @@ -91,12 +90,6 @@ model_render_params::model_render_params() : gr_init_color(&Color, 0, 0, 0); } -model_render_params::~model_render_params() -{ - if (Manage_replacement_textures) - vm_free(const_cast(Replacement_textures)); -} - uint model_render_params::get_model_flags() const { return Model_flags; @@ -157,7 +150,7 @@ int model_render_params::get_insignia_bitmap() const return Insignia_bitmap; } -const int* model_render_params::get_replacement_textures() const +std::shared_ptr model_render_params::get_replacement_textures() const { return Replacement_textures; } @@ -223,19 +216,14 @@ bool model_render_params::is_team_color_set() const return Team_color_set; } -void model_render_params::set_replacement_textures(const int *textures) +void model_render_params::set_replacement_textures(std::shared_ptr textures) { - Replacement_textures = textures; + Replacement_textures = std::move(textures); } void model_render_params::set_replacement_textures(int modelnum, const SCP_vector& replacement_textures) { - auto textures = (int*)vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int)); - - for (int i = 0; i < MAX_REPLACEMENT_TEXTURES; i++) - textures[i] = -1; - - Manage_replacement_textures = true; + auto textures = make_shared(); polymodel* pm = model_get(modelnum); @@ -247,11 +235,11 @@ void model_render_params::set_replacement_textures(int modelnum, const SCP_vecto int tnum = tmap->FindTexture(tr.old_texture); if (tnum > -1) - textures[i * TM_NUM_TYPES + tnum] = bm_load(tr.new_texture); + (*textures)[i * TM_NUM_TYPES + tnum] = bm_load(tr.new_texture); } } - Replacement_textures = textures; + Replacement_textures = std::move(textures); } void model_render_params::set_insignia_bitmap(int bitmap) @@ -1054,7 +1042,7 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate int texture_maps[TM_NUM_TYPES] = { -1 }; size_t buffer_size = buffer->tex_buf.size(); - const int *replacement_textures = interp->get_replacement_textures(); + const auto& replacement_textures = interp->get_replacement_textures(); for ( size_t i = 0; i < buffer_size; i++ ) { int tmap_num = buffer->tex_buf[i].texture; @@ -1081,12 +1069,12 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate } else if ( !no_texturing ) { // pick the texture, animating it if necessary - if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_BASE_TYPE] == REPLACE_WITH_INVISIBLE) ) { + if ( (replacement_textures != nullptr) && ((*replacement_textures)[rt_begin_index + TM_BASE_TYPE] == REPLACE_WITH_INVISIBLE) ) { // invisible textures aren't rendered, but we still have to skip assigning the underlying model texture texture_maps[TM_BASE_TYPE] = -1; - } else if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_BASE_TYPE] >= 0) ) { + } else if ( (replacement_textures != nullptr) && ((*replacement_textures)[rt_begin_index + TM_BASE_TYPE] >= 0) ) { // an underlying texture is replaced with a real new texture - tex_replace[TM_BASE_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_BASE_TYPE]); + tex_replace[TM_BASE_TYPE] = texture_info((*replacement_textures)[rt_begin_index + TM_BASE_TYPE]); texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tex_replace[TM_BASE_TYPE], elapsed_time); } else { // we just use the underlying texture @@ -1101,8 +1089,8 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate if ( !(model_flags & MR_NO_GLOWMAPS) ) { auto tglow = &tmap->textures[TM_GLOW_TYPE]; - if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_GLOW_TYPE] >= 0) ) { - tex_replace[TM_GLOW_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_GLOW_TYPE]); + if ( (replacement_textures != nullptr) && ((*replacement_textures)[rt_begin_index + TM_GLOW_TYPE] >= 0) ) { + tex_replace[TM_GLOW_TYPE] = texture_info((*replacement_textures)[rt_begin_index + TM_GLOW_TYPE]); texture_maps[TM_GLOW_TYPE] = model_interp_get_texture(&tex_replace[TM_GLOW_TYPE], elapsed_time); } else if (tglow->GetTexture() >= 0) { // shockwaves are special, their current frame has to come out of the shockwave code to get the timing correct @@ -1115,8 +1103,8 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate } if (!(debug_flags & MR_DEBUG_NO_SPEC)) { - if (replacement_textures != NULL && replacement_textures[rt_begin_index + TM_SPECULAR_TYPE] >= 0) { - tex_replace[TM_SPECULAR_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_SPECULAR_TYPE]); + if (replacement_textures != nullptr && (*replacement_textures)[rt_begin_index + TM_SPECULAR_TYPE] >= 0) { + tex_replace[TM_SPECULAR_TYPE] = texture_info((*replacement_textures)[rt_begin_index + TM_SPECULAR_TYPE]); texture_maps[TM_SPECULAR_TYPE] = model_interp_get_texture(&tex_replace[TM_SPECULAR_TYPE], elapsed_time); } else { @@ -1124,8 +1112,8 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate } } - if ( replacement_textures != NULL && replacement_textures[rt_begin_index + TM_SPEC_GLOSS_TYPE] >= 0 ) { - tex_replace[TM_SPEC_GLOSS_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_SPEC_GLOSS_TYPE]); + if ( replacement_textures != nullptr && (*replacement_textures)[rt_begin_index + TM_SPEC_GLOSS_TYPE] >= 0 ) { + tex_replace[TM_SPEC_GLOSS_TYPE] = texture_info((*replacement_textures)[rt_begin_index + TM_SPEC_GLOSS_TYPE]); texture_maps[TM_SPEC_GLOSS_TYPE] = model_interp_get_texture(&tex_replace[TM_SPEC_GLOSS_TYPE], elapsed_time); } else { texture_maps[TM_SPEC_GLOSS_TYPE] = model_interp_get_texture(&tmap->textures[TM_SPEC_GLOSS_TYPE], elapsed_time); @@ -1138,24 +1126,25 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate auto ambient_map = &tmap->textures[TM_AMBIENT_TYPE]; auto misc_map = &tmap->textures[TM_MISC_TYPE]; - if (replacement_textures != NULL) { - if (replacement_textures[rt_begin_index + TM_NORMAL_TYPE] >= 0) { - tex_replace[TM_NORMAL_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_NORMAL_TYPE]); + if (replacement_textures != nullptr) { + const auto& replacement_textures_deref = *replacement_textures; + if (replacement_textures_deref[rt_begin_index + TM_NORMAL_TYPE] >= 0) { + tex_replace[TM_NORMAL_TYPE] = texture_info(replacement_textures_deref[rt_begin_index + TM_NORMAL_TYPE]); norm_map = &tex_replace[TM_NORMAL_TYPE]; } - if (replacement_textures[rt_begin_index + TM_HEIGHT_TYPE] >= 0) { - tex_replace[TM_HEIGHT_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_HEIGHT_TYPE]); + if (replacement_textures_deref[rt_begin_index + TM_HEIGHT_TYPE] >= 0) { + tex_replace[TM_HEIGHT_TYPE] = texture_info(replacement_textures_deref[rt_begin_index + TM_HEIGHT_TYPE]); height_map = &tex_replace[TM_HEIGHT_TYPE]; } - if (replacement_textures[rt_begin_index + TM_AMBIENT_TYPE] >= 0) { - tex_replace[TM_AMBIENT_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_AMBIENT_TYPE]); + if (replacement_textures_deref[rt_begin_index + TM_AMBIENT_TYPE] >= 0) { + tex_replace[TM_AMBIENT_TYPE] = texture_info(replacement_textures_deref[rt_begin_index + TM_AMBIENT_TYPE]); ambient_map = &tex_replace[TM_AMBIENT_TYPE]; } - if (replacement_textures[rt_begin_index + TM_MISC_TYPE] >= 0) { - tex_replace[TM_MISC_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_MISC_TYPE]); + if (replacement_textures_deref[rt_begin_index + TM_MISC_TYPE] >= 0) { + tex_replace[TM_MISC_TYPE] = texture_info(replacement_textures_deref[rt_begin_index + TM_MISC_TYPE]); misc_map = &tex_replace[TM_MISC_TYPE]; } } @@ -1174,8 +1163,8 @@ void model_render_buffers(model_draw_list* scene, model_material *rendering_mate //Check for invisible or transparent textures so they don't show up in the shadow maps - Valathil if ( Rendering_to_shadow_map ) { - if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_BASE_TYPE] >= 0) ) { - tex_replace[TM_BASE_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_BASE_TYPE]); + if ( (replacement_textures != nullptr) && ((*replacement_textures)[rt_begin_index + TM_BASE_TYPE] >= 0) ) { + tex_replace[TM_BASE_TYPE] = texture_info((*replacement_textures)[rt_begin_index + TM_BASE_TYPE]); texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tex_replace[TM_BASE_TYPE], elapsed_time); } else { texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tmap->textures[TM_BASE_TYPE], elapsed_time); @@ -3113,6 +3102,7 @@ bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int // Make sure model is loaded model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0], 0); + render_info.set_replacement_textures(model_num, sip->replacement_textures); break; diff --git a/code/model/modelrender.h b/code/model/modelrender.h index b41ce78f5a0..8cc3040733e 100644 --- a/code/model/modelrender.h +++ b/code/model/modelrender.h @@ -83,10 +83,7 @@ class model_render_params int Insignia_bitmap; - const int *Replacement_textures; - bool Manage_replacement_textures; // This is set when we are rendering a model without an associated ship object; - // in that case, model_render_params is responsible for allocating and destroying - // the Replacement_textures array (this is handled elsewhere otherwise) + std::shared_ptr Replacement_textures; bool Team_color_set; team_color Current_team_color; @@ -109,7 +106,6 @@ class model_render_params model_render_params& operator=(const model_render_params&) = delete; public: model_render_params(); - ~model_render_params(); void set_flags(uint flags); void set_debug_flags(uint flags); @@ -122,7 +118,7 @@ class model_render_params void set_alpha(float alpha); void set_forced_bitmap(int bitmap); void set_insignia_bitmap(int bitmap); - void set_replacement_textures(const int *textures); + void set_replacement_textures(std::shared_ptr textures); void set_replacement_textures(int modelnum, const SCP_vector& replacement_textures); void set_team_color(const team_color &clr); void set_team_color(const SCP_string &team, const SCP_string &secondaryteam, fix timestamp, int fadetime); @@ -149,7 +145,7 @@ class model_render_params float get_alpha() const; int get_forced_bitmap() const; int get_insignia_bitmap() const; - const int* get_replacement_textures() const; + std::shared_ptr get_replacement_textures() const; const team_color& get_team_color() const; const vec3d& get_clip_plane_pos() const; const vec3d& get_clip_plane_normal() const; diff --git a/code/scripting/api/objs/cockpit_display.cpp b/code/scripting/api/objs/cockpit_display.cpp index 37999b4b822..02cd6dfb6a6 100644 --- a/code/scripting/api/objs/cockpit_display.cpp +++ b/code/scripting/api/objs/cockpit_display.cpp @@ -512,7 +512,7 @@ bool cockpit_displays_h::isValid() const { return false; } - if ( Player_cockpit_textures == NULL ) { + if ( Player_cockpit_textures == nullptr ) { return false; } diff --git a/code/scripting/api/objs/modelinstance.cpp b/code/scripting/api/objs/modelinstance.cpp index ba541393bab..a4f5aeb3c51 100644 --- a/code/scripting/api/objs/modelinstance.cpp +++ b/code/scripting/api/objs/modelinstance.cpp @@ -5,10 +5,108 @@ #include "modelinstance.h" #include "object.h" #include "vecmath.h" +#include "texture.h" namespace scripting { namespace api { +//**********HANDLE: modelinstancetextures (compatible with preceding shiptextures) +ADE_OBJ(l_ModelInstanceTextures, modelinstance_h, "modelinstancetextures", "Model instance textures handle"); + +ADE_FUNC(__len, l_ModelInstanceTextures, nullptr, "Number of textures on a model instance", "number", "Number of textures on the model instance, or 0 if handle is invalid") +{ + modelinstance_h *mih; + if(!ade_get_args(L, "o", l_ModelInstanceTextures.GetPtr(&mih))) + return ade_set_error(L, "i", 0); + + if(!mih->isValid()) + return ade_set_error(L, "i", 0); + + polymodel *pm = model_get(mih->Get()->model_num); + + if(pm == nullptr) + return ade_set_error(L, "i", 0); + + return ade_set_args(L, "i", pm->n_textures*TM_NUM_TYPES); +} + +ADE_INDEXER(l_ModelInstanceTextures, "number/string IndexOrTextureFilename", "Array of model instance textures", "texture", "Texture, or invalid texture handle on failure") +{ + modelinstance_h *mih; + const char* s; + texture_h* tdx = nullptr; + if (!ade_get_args(L, "os|o", l_ModelInstanceTextures.GetPtr(&mih), &s, l_Texture.GetPtr(&tdx))) + return ade_set_error(L, "o", l_Texture.Set(texture_h())); + + if (!mih->isValid() || s == nullptr) + return ade_set_error(L, "o", l_Texture.Set(texture_h())); + + polymodel_instance *pmi = mih->Get(); + polymodel *pm = model_get(pmi->model_num); + int final_index = -1; + int i; + + char fname[MAX_FILENAME_LEN]; + if (pmi->texture_replace != nullptr) + { + for(i = 0; i < MAX_REPLACEMENT_TEXTURES; i++) + { + bm_get_filename((*pmi->texture_replace)[i], fname); + + if(!strextcmp(fname, s)) { + final_index = i; + break; + } + } + } + + if(final_index < 0) + { + for (i = 0; i < pm->n_textures; i++) + { + int tm_num = pm->maps[i].FindTexture(s); + if(tm_num > -1) + { + final_index = i*TM_NUM_TYPES+tm_num; + break; + } + } + } + + if (final_index < 0) + { + final_index = atoi(s) - 1; //Lua->FS2 + + if (final_index < 0 || final_index >= MAX_REPLACEMENT_TEXTURES) + return ade_set_error(L, "o", l_Texture.Set(texture_h())); + } + + if (ADE_SETTING_VAR) { + if (pmi->texture_replace == nullptr) { + pmi->texture_replace = make_shared(); + } + + if (tdx != nullptr) { + (*pmi->texture_replace)[final_index] = tdx->isValid() ? tdx->handle : -1; + } + } + + if (pmi->texture_replace != nullptr && (*pmi->texture_replace)[final_index] >= 0) + return ade_set_args(L, "o", l_Texture.Set(texture_h((*pmi->texture_replace)[final_index]))); + else + return ade_set_args(L, "o", l_Texture.Set(texture_h(pm->maps[final_index / TM_NUM_TYPES].textures[final_index % TM_NUM_TYPES].GetTexture()))); +} + +ADE_FUNC(isValid, l_ModelInstanceTextures, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") +{ + modelinstance_h *mih; + if(!ade_get_args(L, "o", l_ModelInstanceTextures.GetPtr(&mih))) + return ADE_RETURN_NIL; + + return ade_set_args(L, "b", mih->isValid()); +} + + ADE_OBJ(l_ModelInstance, modelinstance_h, "model_instance", "Model instance handle"); modelinstance_h::modelinstance_h(int pmi_id) @@ -94,6 +192,29 @@ ADE_FUNC(getObject, l_ModelInstance, nullptr, "Returns the object that this inst return ade_set_object_with_breed(L, mih->Get()->objnum); } +ADE_VIRTVAR(Textures, l_ModelInstance, "modelinstancetextures", "Gets model instance textures", "modelinstancetextures", "Model instance textures, or invalid modelinstancetextures handle if modelinstance handle is invalid") +{ + modelinstance_h *sh = nullptr; + modelinstance_h *dh; + if(!ade_get_args(L, "o|o", l_ModelInstance.GetPtr(&dh), l_ModelInstance.GetPtr(&sh))) + return ade_set_error(L, "o", l_ModelInstanceTextures.Set(modelinstance_h())); + + if(!dh->isValid()) + return ade_set_error(L, "o", l_ModelInstanceTextures.Set(modelinstance_h())); + + if(ADE_SETTING_VAR && sh && sh->isValid()) { + polymodel_instance *src = sh->Get(); + polymodel_instance *dest = dh->Get(); + + if (src->texture_replace != nullptr) + { + dest->texture_replace = std::make_shared(*src->texture_replace); + } + } + + return ade_set_args(L, "o", l_ModelInstanceTextures.Set(modelinstance_h(dh->Get()))); +} + ADE_VIRTVAR(SubmodelInstances, l_ModelInstance, nullptr, "Submodel instances", "submodel_instances", "Model submodel instances, or an invalid modelsubmodelinstances handle if the model instance handle is invalid") { modelinstance_h *mih = nullptr; diff --git a/code/scripting/api/objs/modelinstance.h b/code/scripting/api/objs/modelinstance.h index eb6a64abb68..a8a2d6a92ca 100644 --- a/code/scripting/api/objs/modelinstance.h +++ b/code/scripting/api/objs/modelinstance.h @@ -21,6 +21,7 @@ class modelinstance_h bool isValid() const; }; +DECLARE_ADE_OBJ(l_ModelInstanceTextures, modelinstance_h); DECLARE_ADE_OBJ(l_ModelInstance, modelinstance_h); class submodelinstance_h diff --git a/code/scripting/api/objs/ship.cpp b/code/scripting/api/objs/ship.cpp index d8a87839e6c..390b039f22d 100644 --- a/code/scripting/api/objs/ship.cpp +++ b/code/scripting/api/objs/ship.cpp @@ -6,6 +6,7 @@ #include "cockpit_display.h" #include "enums.h" #include "message.h" +#include "modelinstance.h" #include "object.h" #include "order.h" #include "parse_object.h" @@ -41,108 +42,6 @@ extern void sexp_alter_ship_flag_helper(object_ship_wing_point_team &oswpt, bool namespace scripting { namespace api { -//**********HANDLE: shiptextures -ADE_OBJ(l_ShipTextures, object_h, "shiptextures", "Ship textures handle"); - -ADE_FUNC(__len, l_ShipTextures, NULL, "Number of textures on ship", "number", "Number of textures on ship, or 0 if handle is invalid") -{ - object_h *objh; - if(!ade_get_args(L, "o", l_ShipTextures.GetPtr(&objh))) - return ade_set_error(L, "i", 0); - - if(!objh->isValid()) - return ade_set_error(L, "i", 0); - - polymodel *pm = model_get(Ship_info[Ships[objh->objp->instance].ship_info_index].model_num); - - if(pm == NULL) - return ade_set_error(L, "i", 0); - - return ade_set_args(L, "i", pm->n_textures*TM_NUM_TYPES); -} - -ADE_INDEXER(l_ShipTextures, "number/string IndexOrTextureFilename", "Array of ship textures", "texture", "Texture, or invalid texture handle on failure") -{ - object_h *oh; - const char* s; - texture_h* tdx = nullptr; - if (!ade_get_args(L, "os|o", l_ShipTextures.GetPtr(&oh), &s, l_Texture.GetPtr(&tdx))) - return ade_set_error(L, "o", l_Texture.Set(texture_h())); - - if (!oh->isValid() || s==NULL) - return ade_set_error(L, "o", l_Texture.Set(texture_h())); - - ship *shipp = &Ships[oh->objp->instance]; - polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num); - int final_index = -1; - int i; - - char fname[MAX_FILENAME_LEN]; - if (shipp->ship_replacement_textures != NULL) - { - for(i = 0; i < MAX_REPLACEMENT_TEXTURES; i++) - { - bm_get_filename(shipp->ship_replacement_textures[i], fname); - - if(!strextcmp(fname, s)) { - final_index = i; - break; - } - } - } - - if(final_index < 0) - { - for (i = 0; i < pm->n_textures; i++) - { - int tm_num = pm->maps[i].FindTexture(s); - if(tm_num > -1) - { - final_index = i*TM_NUM_TYPES+tm_num; - break; - } - } - } - - if (final_index < 0) - { - final_index = atoi(s) - 1; //Lua->FS2 - - if (final_index < 0 || final_index >= MAX_REPLACEMENT_TEXTURES) - return ade_set_error(L, "o", l_Texture.Set(texture_h())); - } - - if (ADE_SETTING_VAR) { - if (shipp->ship_replacement_textures == NULL) { - shipp->ship_replacement_textures = (int *) vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int)); - - for (i = 0; i < MAX_REPLACEMENT_TEXTURES; i++) - shipp->ship_replacement_textures[i] = -1; - } - - if (tdx != nullptr) { - if (tdx->isValid()) - shipp->ship_replacement_textures[final_index] = tdx->handle; - else - shipp->ship_replacement_textures[final_index] = -1; - } - } - - if (shipp->ship_replacement_textures != NULL && shipp->ship_replacement_textures[final_index] >= 0) - return ade_set_args(L, "o", l_Texture.Set(texture_h(shipp->ship_replacement_textures[final_index]))); - else - return ade_set_args(L, "o", l_Texture.Set(texture_h(pm->maps[final_index / TM_NUM_TYPES].textures[final_index % TM_NUM_TYPES].GetTexture()))); -} - -ADE_FUNC(isValid, l_ShipTextures, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs") -{ - object_h *oh; - if(!ade_get_args(L, "o", l_ShipTextures.GetPtr(&oh))) - return ADE_RETURN_NIL; - - return ade_set_args(L, "b", oh->isValid()); -} - //**********HANDLE: Ship ADE_OBJ_DERIV(l_Ship, object_h, "ship", "Ship handle", l_Object); @@ -919,30 +818,28 @@ ADE_VIRTVAR(PersonaIndex, l_Ship, "number", "Persona index", "number", "The inde return ade_set_args(L, "i", shipp->persona_index + 1); } -ADE_VIRTVAR(Textures, l_Ship, "shiptextures", "Gets ship textures", "shiptextures", "Ship textures, or invalid shiptextures handle if ship handle is invalid") +ADE_VIRTVAR(Textures, l_Ship, "modelinstancetextures", "Gets ship textures", "modelinstancetextures", "Ship textures, or invalid shiptextures handle if ship handle is invalid") { object_h *sh = nullptr; object_h *dh; if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&dh), l_Ship.GetPtr(&sh))) - return ade_set_error(L, "o", l_ShipTextures.Set(object_h())); + return ade_set_error(L, "o", l_ModelInstanceTextures.Set(modelinstance_h())); if(!dh->isValid()) - return ade_set_error(L, "o", l_ShipTextures.Set(object_h())); + return ade_set_error(L, "o", l_ModelInstanceTextures.Set(modelinstance_h())); + + polymodel_instance *dest = model_get_instance(Ships[dh->objp->instance].model_instance_num); if(ADE_SETTING_VAR && sh && sh->isValid()) { - ship *src = &Ships[sh->objp->instance]; - ship *dest = &Ships[dh->objp->instance]; + polymodel_instance *src = model_get_instance(Ships[sh->objp->instance].model_instance_num); - if (src->ship_replacement_textures != NULL) + if (src->texture_replace != nullptr) { - if (dest->ship_replacement_textures == NULL) - dest->ship_replacement_textures = (int *) vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int)); - - memcpy(dest->ship_replacement_textures, src->ship_replacement_textures, MAX_REPLACEMENT_TEXTURES * sizeof(int)); + dest->texture_replace = std::make_shared(*src->texture_replace); } } - return ade_set_args(L, "o", l_ShipTextures.Set(object_h(dh->objp))); + return ade_set_args(L, "o", l_ModelInstanceTextures.Set(modelinstance_h(dest))); } ADE_VIRTVAR(FlagAffectedByGravity, l_Ship, "boolean", "Checks for the \"affected-by-gravity\" flag", "boolean", "True if flag is set, false if flag is not set and nil on error") diff --git a/code/scripting/api/objs/ship.h b/code/scripting/api/objs/ship.h index 195a45bda77..cc723367339 100644 --- a/code/scripting/api/objs/ship.h +++ b/code/scripting/api/objs/ship.h @@ -6,8 +6,6 @@ namespace scripting { namespace api { -DECLARE_ADE_OBJ(l_ShipTextures, object_h); - //**********HANDLE: Ship DECLARE_ADE_OBJ(l_Ship, object_h); } diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 8c150a6ad30..2b9d454afaa 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -132,7 +132,7 @@ int Num_reinforcements = 0; ship Ships[MAX_SHIPS]; ship *Player_ship; -int *Player_cockpit_textures; +std::shared_ptr Player_cockpit_textures; SCP_vector Player_displays; bool Disable_cockpits = false; bool Disable_cockpit_sway = false; @@ -6831,11 +6831,6 @@ void ship::clear() primitive_sensor_range = DEFAULT_SHIP_PRIMITIVE_SENSOR_RANGE; - if (ship_replacement_textures != nullptr) { - vm_free(ship_replacement_textures); - } - ship_replacement_textures = nullptr; - current_viewpoint = -1; for (int i = 0; i < MAX_SHIP_CONTRAILS; i++) @@ -6913,13 +6908,12 @@ const char* ship::get_display_name() const { void ship::apply_replacement_textures(const SCP_vector &replacements) { - if (!replacements.empty()) - { - ship_replacement_textures = (int *) vm_malloc( MAX_REPLACEMENT_TEXTURES * sizeof(int)); + if (replacements.empty()) + return; - for (auto i = 0; i < MAX_REPLACEMENT_TEXTURES; i++) - ship_replacement_textures[i] = -1; - } + polymodel_instance* pmi = model_get_instance(model_instance_num); + + pmi->texture_replace = make_shared(); auto pm = model_get(Ship_info[ship_info_index].model_num); @@ -6932,8 +6926,8 @@ void ship::apply_replacement_textures(const SCP_vector &replace texture_map *tmap = &pm->maps[j]; int tnum = tmap->FindTexture(tr.old_texture); - if(tnum > -1) - ship_replacement_textures[j * TM_NUM_TYPES + tnum] = tr.new_texture_id; + if (tnum > -1) + (*pmi->texture_replace)[j * TM_NUM_TYPES + tnum] = tr.new_texture_id; } } } @@ -7883,6 +7877,7 @@ extern bool Rendering_to_shadow_map; void ship_render_player_ship(object* objp, const vec3d* cam_offset, const matrix* rot_offset, const fov_t* fov_override) { ship* shipp = &Ships[objp->instance]; ship_info* sip = &Ship_info[shipp->ship_info_index]; + polymodel_instance* pmi = model_get_instance(shipp->model_instance_num); const bool hasCockpitModel = sip->cockpit_model_num >= 0; @@ -7939,7 +7934,7 @@ void ship_render_player_ship(object* objp, const vec3d* cam_offset, const matrix render_info.set_object_number(OBJ_INDEX(objp)); // update any replacement and/or team color textures (wookieejedi), then render - render_info.set_replacement_textures(shipp->ship_replacement_textures); + render_info.set_replacement_textures(pmi->texture_replace); if (sip->uses_team_colors) render_info.set_team_color(shipp->team_name, shipp->secondary_team_name, 0, 0); @@ -8032,7 +8027,7 @@ void ship_render_player_ship(object* objp, const vec3d* cam_offset, const matrix model_render_params render_info; render_info.set_detail_level_lock(0); render_info.set_flags(render_flags); - render_info.set_replacement_textures(shipp->ship_replacement_textures); + render_info.set_replacement_textures(pmi->texture_replace); render_info.set_object_number(OBJ_INDEX(objp)); if (sip->uses_team_colors) render_info.set_team_color(shipp->team_name, shipp->secondary_team_name, 0, 0); @@ -8103,21 +8098,15 @@ void ship_init_cockpit_displays(ship *shipp) return; } - if ( Player_cockpit_textures != NULL) { + if ( Player_cockpit_textures != nullptr) { return; } // ship's cockpit texture replacements haven't been setup yet, so do it. - Player_cockpit_textures = (int *) vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int)); - - int i; - - for ( i = 0; i < MAX_REPLACEMENT_TEXTURES; i++ ) { - Player_cockpit_textures[i] = -1; - } + Player_cockpit_textures = make_shared(); - for ( i = 0; i < (int)sip->displays.size(); i++ ) { - ship_add_cockpit_display(&sip->displays[i], cockpit_model_num); + for ( auto& display : sip->displays ) { + ship_add_cockpit_display(&display, cockpit_model_num); } ship_set_hud_cockpit_targets(); @@ -8144,11 +8133,7 @@ void ship_close_cockpit_displays(ship* shipp) } Player_displays.clear(); - - if ( Player_cockpit_textures != NULL ) { - vm_free(Player_cockpit_textures); - Player_cockpit_textures = NULL; - } + Player_cockpit_textures.reset(); } static void ship_add_cockpit_display(cockpit_display_info *display, int cockpit_model_num) @@ -8181,13 +8166,13 @@ static void ship_add_cockpit_display(cockpit_display_info *display, int cockpit_ } // create a render target for this cockpit texture - if ( Player_cockpit_textures[glow_target] < 0) { - + auto& glow_texture = (*Player_cockpit_textures)[glow_target]; + if ( glow_texture == -1) { bm_get_info(diffuse_handle, &w, &h); - Player_cockpit_textures[glow_target] = bm_make_render_target(w, h, BMP_FLAG_RENDER_TARGET_DYNAMIC); + glow_texture = bm_make_render_target(w, h, BMP_FLAG_RENDER_TARGET_DYNAMIC); // if no render target was made, bail - if ( Player_cockpit_textures[glow_target] < 0 ) { + if ( glow_texture < 0 ) { return; } } @@ -8216,7 +8201,7 @@ static void ship_add_cockpit_display(cockpit_display_info *display, int cockpit_ new_display.size[0] = display->size[0]; new_display.size[1] = display->size[1]; new_display.source = glow_handle; - new_display.target = Player_cockpit_textures[glow_target]; + new_display.target = glow_texture; Player_displays.push_back(new_display); } @@ -8243,7 +8228,7 @@ int ship_start_render_cockpit_display(size_t cockpit_display_num) return -1; } - if ( Player_cockpit_textures == NULL ) { + if ( Player_cockpit_textures == nullptr ) { return -1; } @@ -8289,7 +8274,7 @@ void ship_end_render_cockpit_display(size_t cockpit_display_num) return; } - if ( Player_cockpit_textures == NULL ) { + if ( Player_cockpit_textures == nullptr ) { return; } @@ -8357,11 +8342,6 @@ void ship_delete( object * obj ) animation::ModelAnimationSet::stopAnimations(model_get_instance(shipp->model_instance_num)); - if (shipp->ship_replacement_textures != NULL) { - vm_free(shipp->ship_replacement_textures); - shipp->ship_replacement_textures = NULL; - } - // glow point banks shipp->glow_point_bank_active.clear(); @@ -11089,15 +11069,14 @@ static void ship_model_change(int n, int ship_type) ship_info *sip; ship *sp; polymodel * pm; + polymodel_instance * pmi; object *objp; Assert( n >= 0 && n < MAX_SHIPS ); sp = &Ships[n]; sip = &(Ship_info[ship_type]); objp = &Objects[sp->objnum]; - - //Stop Animation on the old model - animation::ModelAnimationSet::stopAnimations(model_get_instance(sp->model_instance_num)); + pmi = model_get_instance(sp->model_instance_num); // get new model if (sip->model_num == -1) { @@ -11113,41 +11092,6 @@ static void ship_model_change(int n, int ship_type) pm = model_get(sip->model_num); Objects[sp->objnum].radius = model_get_radius(pm->id); - // Goober5000 - deal with texture replacement by re-applying the same code we used during parsing - // wookieejedi - replacement textures are loaded in mission parse, so need to load any new textures here - if ( !sip->replacement_textures.empty() ) { - - // clear and reset replacement textures because the new positions may be different - if (sp->ship_replacement_textures == nullptr) - sp->ship_replacement_textures = (int*)vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int)); - for (auto k = 0; k < MAX_REPLACEMENT_TEXTURES; k++) - sp->ship_replacement_textures[k] = -1; - - // now fill them in according to texture name - for (const auto& tr : sip->replacement_textures) { - // look for textures - for (auto j = 0; j < pm->n_textures; j++) { - - texture_map* tmap = &pm->maps[j]; - int tnum = tmap->FindTexture(tr.old_texture); - - if (tnum > -1) { - // load new texture - int new_tex = bm_load_either(tr.new_texture); - if (new_tex > -1) { - sp->ship_replacement_textures[j * TM_NUM_TYPES + tnum] = new_tex; - } - } - } - } - } else { - // ensure that any texture replacements are cleared from old ship - if (sp->ship_replacement_textures != nullptr) { - vm_free(sp->ship_replacement_textures); - sp->ship_replacement_textures = nullptr; - } - } - // page in nondims in game if ( !Fred_running ) model_page_in_textures(sip->model_num, ship_type); @@ -11208,6 +11152,41 @@ static void ship_model_change(int n, int ship_type) // reset texture animations sp->base_texture_anim_timestamp = _timestamp(); + + model_delete_instance(sp->model_instance_num); + + // create new model instance data + // note: this is needed for both subsystem stuff and submodel animation stuff + sp->model_instance_num = model_create_instance(OBJ_INDEX(objp), sip->model_num); + pmi = model_get_instance(sp->model_instance_num); + + // Goober5000 - deal with texture replacement by re-applying the same code we used during parsing + // wookieejedi - replacement textures are loaded in mission parse, so need to load any new textures here + // Lafiel - this now has to happen last, as the texture replacement stuff is stored in the pmi + if ( !sip->replacement_textures.empty() ) { + + // clear and reset replacement textures because the new positions may be different + pmi->texture_replace = make_shared(); + auto& texture_replace_deref = *pmi->texture_replace; + + // now fill them in according to texture name + for (const auto& tr : sip->replacement_textures) { + // look for textures + for (auto j = 0; j < pm->n_textures; j++) { + + texture_map* tmap = &pm->maps[j]; + int tnum = tmap->FindTexture(tr.old_texture); + + if (tnum > -1) { + // load new texture + int new_tex = bm_load_either(tr.new_texture); + if (new_tex > -1) { + texture_replace_deref[j * TM_NUM_TYPES + tnum] = new_tex; + } + } + } + } + } } /** @@ -11475,10 +11454,6 @@ void change_ship_type(int n, int ship_type, int by_sexp) ship_model_change(n, ship_type); sp->ship_info_index = ship_type; - // create new model instance data - // note: this is needed for both subsystem stuff and submodel animation stuff - sp->model_instance_num = model_create_instance(objnum, sip->model_num); - // if we have the same warp parameters as the ship class, we will need to update them to point to the new class if (sp->warpin_params_index == sip_orig->warpin_params_index) { sp->warpin_params_index = sip->warpin_params_index; @@ -15734,11 +15709,6 @@ void ship_close() for (i=0; iship_replacement_textures != NULL) { - vm_free(shipp->ship_replacement_textures); - shipp->ship_replacement_textures = NULL; - } - if(shipp->warpin_effect != NULL) delete shipp->warpin_effect; shipp->warpin_effect = NULL; @@ -18314,15 +18284,15 @@ void ship_page_in() // is this a valid ship? if (Ships[i].objnum >= 0) { + polymodel_instance* pmi = model_get_instance(object_get_model_instance(&Objects[Ships[i].objnum])); // do we have any textures? - if (Ships[i].ship_replacement_textures != NULL) + if (pmi->texture_replace != nullptr) { // page in replacement textures - for (j=0; jtexture_replace) { - if (Ships[i].ship_replacement_textures[j] > -1) - { - bm_page_in_texture( Ships[i].ship_replacement_textures[j] ); + if (texture >= 0) { + bm_page_in_texture(texture); } } } @@ -18451,6 +18421,8 @@ void ship_replace_active_texture(int ship_index, const char* old_name, const cha { ship* shipp = &Ships[ship_index]; polymodel* pm = model_get(Ship_info[shipp->ship_info_index].model_num); + polymodel_instance* pmi = model_get_instance(shipp->model_instance_num); + int final_index = -1; for (int i = 0; i < pm->n_textures; i++) @@ -18472,14 +18444,11 @@ void ship_replace_active_texture(int ship_index, const char* old_name, const cha else texture = bm_load_either(new_name); - if (shipp->ship_replacement_textures == nullptr) { - shipp->ship_replacement_textures = (int*)vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int)); - - for (int i = 0; i < MAX_REPLACEMENT_TEXTURES; i++) - shipp->ship_replacement_textures[i] = -1; + if (pmi->texture_replace == nullptr) { + pmi->texture_replace = make_shared(); } - shipp->ship_replacement_textures[final_index] = texture; + (*pmi->texture_replace)[final_index] = texture; } else Warning(LOCATION, "Invalid texture '%s' used for replacement texture", old_name); } @@ -20999,7 +20968,7 @@ void ship_render(object* obj, model_draw_list* scene) ship_render_weapon_models(&render_info, scene, obj, render_flags); render_info.set_object_number(OBJ_INDEX(obj)); - render_info.set_replacement_textures(shipp->ship_replacement_textures); + render_info.set_replacement_textures(pmi->texture_replace); // small ships if ( !( shipp->flags[Ship_Flags::Cloaked] ) ) { diff --git a/code/ship/ship.h b/code/ship/ship.h index 077f6192013..7d5d680c0b7 100644 --- a/code/ship/ship.h +++ b/code/ship/ship.h @@ -761,9 +761,6 @@ class ship // Goober5000 - range of primitive sensors int primitive_sensor_range; - - // Goober5000 - revised nameplate implementation - int *ship_replacement_textures; // Goober5000 - index into pm->view_positions[] // apparently, early in FS1 development, there was a field called current_eye_index @@ -1538,7 +1535,7 @@ extern const size_t Num_subsystem_flags; extern int Num_wings; extern ship Ships[MAX_SHIPS]; extern ship *Player_ship; -extern int *Player_cockpit_textures; +extern std::shared_ptr Player_cockpit_textures; // Data structure to track the active missiles typedef struct ship_obj { diff --git a/code/ship/shipfx.cpp b/code/ship/shipfx.cpp index 345af20266a..f10b495817c 100644 --- a/code/ship/shipfx.cpp +++ b/code/ship/shipfx.cpp @@ -1662,7 +1662,7 @@ void shipfx_queue_render_ship_halves_and_debris(model_draw_list *scene, clip_shi model_render_params render_info; render_info.set_clip_plane(debris_clip_plane_pt, clip_plane_norm); - render_info.set_replacement_textures(shipp->ship_replacement_textures); + render_info.set_replacement_textures(pmi->texture_replace); render_info.set_flags(render_flags); submodel_render_queue(&render_info, scene, pm, pmi, pm->debris_objects[i], &half_ship->orient, &tmp); @@ -1706,7 +1706,7 @@ void shipfx_queue_render_ship_halves_and_debris(model_draw_list *scene, clip_shi render_info.set_flags(render_flags); render_info.set_clip_plane(model_clip_plane_pt, clip_plane_norm); - render_info.set_replacement_textures(shipp->ship_replacement_textures); + render_info.set_replacement_textures(pmi->texture_replace); render_info.set_object_number(shipp->objnum); if (Ship_info[shipp->ship_info_index].uses_team_colors && !shipp->flags[Ship::Ship_Flags::Render_without_miscmap]) { diff --git a/code/starfield/starfield.cpp b/code/starfield/starfield.cpp index bd7f71b777d..4ccd48e99a6 100644 --- a/code/starfield/starfield.cpp +++ b/code/starfield/starfield.cpp @@ -2311,6 +2311,9 @@ void stars_draw_background() render_info.set_alpha_mult(Nmodel_alpha); render_info.set_flags(Nmodel_flags | MR_SKYBOX); + if (Nmodel_instance_num >= 0) + render_info.set_replacement_textures(model_get_instance(Nmodel_instance_num)->texture_replace); + model_render_immediate(&render_info, Nmodel_num, Nmodel_instance_num, &Nmodel_orient, &Eye_position, MODEL_RENDER_ALL, false); } diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 65dde15f456..c7b233e78c2 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -9021,6 +9021,9 @@ void weapon_render(object* obj, model_draw_list *scene) render_info.set_flags(render_flags); + if (wp->model_instance_num >= 0) + render_info.set_replacement_textures(model_get_instance(wp->model_instance_num)->texture_replace); + model_render_queue(&render_info, scene, wip->model_num, &obj->orient, &obj->pos); break; diff --git a/fred2/fredrender.cpp b/fred2/fredrender.cpp index b1aaf9b12e4..b05b00559c1 100644 --- a/fred2/fredrender.cpp +++ b/fred2/fredrender.cpp @@ -1876,7 +1876,7 @@ void render_one_model_htl(object *objp) { model_render_params render_info; render_info.set_debug_flags(debug_flags); - render_info.set_replacement_textures(Ships[z].ship_replacement_textures); + render_info.set_replacement_textures(model_get_instance(Ships[z].model_instance_num)->texture_replace); if (Fred_outline) { render_info.set_color(Fred_outline >> 16, (Fred_outline >> 8) & 0xff, Fred_outline & 0xff); diff --git a/qtfred/src/mission/FredRenderer.cpp b/qtfred/src/mission/FredRenderer.cpp index a897fd56622..1eb24d68950 100644 --- a/qtfred/src/mission/FredRenderer.cpp +++ b/qtfred/src/mission/FredRenderer.cpp @@ -874,7 +874,7 @@ void FredRenderer::render_one_model_htl(object* objp, model_render_params render_info; render_info.set_debug_flags(debug_flags); render_info.set_color(Fred_outline >> 16, (Fred_outline >> 8) & 0xff, Fred_outline & 0xff); - render_info.set_replacement_textures(Ships[z].ship_replacement_textures); + render_info.set_replacement_textures(model_get_instance(Ships[z].model_instance_num)->texture_replace); render_info.set_flags(j); g3_done_instance(0);