Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions code/model/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,26 @@ struct submodel_instance
//Used by scripting - if you change this, do a search
//to update switch() statement in lua.cpp

inline const SCP_map<int, SCP_string> MODEL_TEXTURE_SUFFIXES = {
{ TM_GLOW_TYPE, "-glow" },
{ TM_SPECULAR_TYPE, "-shine" },
{ TM_NORMAL_TYPE, "-normal" },
{ TM_HEIGHT_TYPE, "-height" },
{ TM_MISC_TYPE, "-misc" },
{ TM_SPEC_GLOSS_TYPE, "-reflect" },
{ TM_AMBIENT_TYPE, "-ao" }
};

inline const SCP_string MODEL_TEXTURE_SUFFIX_TRANS = "-trans"; // -trans is a special case as other suffixes can be appended to it

inline const SCP_string& model_texture_longest_suffix() {
return std::max_element(MODEL_TEXTURE_SUFFIXES.begin(),
MODEL_TEXTURE_SUFFIXES.end(),
[](const std::pair<int, SCP_string>& left, const std::pair<int, SCP_string>& right) {
return left.second.size() < right.second.size();
})->second;
}

#define MAX_REPLACEMENT_TEXTURES MAX_MODEL_TEXTURES * TM_NUM_TYPES

// Goober5000 - since we need something < 0
Expand Down
20 changes: 10 additions & 10 deletions code/model/modelread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2584,10 +2584,10 @@ modelread_status read_model_file_no_subsys(polymodel * pm, const char* filename,
{
char tmp_name[127];
cfread_string_len(tmp_name,127,fp);
constexpr int max_buffer_size = MAX_FILENAME_LEN - 8; // leave room for the longest suffix, "-reflect"
const auto max_buffer_size = static_cast<size_t>(MAX_FILENAME_LEN) - model_texture_longest_suffix().size();
if (strlen(tmp_name) >= max_buffer_size)
{
Warning(LOCATION, "Model '%s', texture '%s' filename is too long! Truncating to %d characters.", pm->filename, tmp_name, max_buffer_size - 1);
Warning(LOCATION, "Model '%s', texture '%s' filename is too long! Truncating to %d characters.", pm->filename, tmp_name, static_cast<int>(max_buffer_size - 1));
tmp_name[max_buffer_size - 1] = '\0';
}
model_load_texture(pm, i, tmp_name);
Expand Down Expand Up @@ -3074,7 +3074,7 @@ void model_load_texture(polymodel *pm, int i, const char *file)
else
{
// check if we should be transparent, include "-trans" but make sure to skip anything that might be "-transport"
if ( (strstr(tmp_name, "-trans") && !strstr(tmp_name, "-transpo")) || strstr(tmp_name, "shockwave") || !strcmp(tmp_name, "nameplate") ) {
if ((strstr(tmp_name, MODEL_TEXTURE_SUFFIX_TRANS.c_str()) && !strstr(tmp_name, "-transpo")) || strstr(tmp_name, "shockwave") || !strcmp(tmp_name, "nameplate")) {
tmap->is_transparent = true;
}

Expand All @@ -3099,7 +3099,7 @@ void model_load_texture(polymodel *pm, int i, const char *file)
else
{
strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-glow" );
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_GLOW_TYPE).c_str());
strlwr(tmp_name);

tglow->LoadTexture(tmp_name, pm->filename);
Expand All @@ -3118,14 +3118,14 @@ void model_load_texture(polymodel *pm, int i, const char *file)
{
// look for reflectance map
strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-reflect");
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_SPEC_GLOSS_TYPE).c_str());
strlwr(tmp_name);

tspecgloss->LoadTexture(tmp_name, pm->filename);

// look for a legacy shine map as well
strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-shine");
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_SPECULAR_TYPE).c_str());
strlwr(tmp_name);

tspec->LoadTexture(tmp_name, pm->filename);
Expand All @@ -3139,7 +3139,7 @@ void model_load_texture(polymodel *pm, int i, const char *file)
tnorm->clear();
} else {
strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-normal");
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_NORMAL_TYPE).c_str());
strlwr(tmp_name);

tnorm->LoadTexture(tmp_name, pm->filename);
Expand All @@ -3151,7 +3151,7 @@ void model_load_texture(polymodel *pm, int i, const char *file)
theight->clear();
} else {
strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-height");
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_HEIGHT_TYPE).c_str());
strlwr(tmp_name);

theight->LoadTexture(tmp_name, pm->filename);
Expand All @@ -3161,7 +3161,7 @@ void model_load_texture(polymodel *pm, int i, const char *file)
texture_info *tambient = &tmap->textures[TM_AMBIENT_TYPE];

strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-ao");
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_AMBIENT_TYPE).c_str());
strlwr(tmp_name);

tambient->LoadTexture(tmp_name, pm->filename);
Expand All @@ -3170,7 +3170,7 @@ void model_load_texture(polymodel *pm, int i, const char *file)
texture_info *tmisc = &tmap->textures[TM_MISC_TYPE];

strcpy_s(tmp_name, file);
strcat_s(tmp_name, "-misc");
strcat_s(tmp_name, MODEL_TEXTURE_SUFFIXES.at(TM_MISC_TYPE).c_str());
strlwr(tmp_name);

tmisc->LoadTexture(tmp_name, pm->filename);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
#include "ShipTextureReplacementDialogModel.h"

#include "mission/object.h"

// Sub-texture type suffixes, mirroring the strcat_s calls in modelread.cpp.
// Used both when detecting sub-texture slots in initSubTypes and when parsing
// new_texture strings on dialog reload.
static const SCP_string SUBTEXTURE_SUFFIXES[] = { "misc", "shine", "glow", "normal", "height", "ao", "reflect" };
#include "model/model.h"

namespace {
const SCP_vector<SCP_string>& get_replaceable_texture_types()
{
static const SCP_vector<SCP_string> types = []() {
SCP_vector<SCP_string> out;
out.reserve(MODEL_TEXTURE_SUFFIXES.size());
for (const auto& suffix : MODEL_TEXTURE_SUFFIXES) {
out.emplace_back(suffix.second.substr(1)); // strip leading '-'
}
return out;
}();
return types;
}

bool is_known_subtexture_type(const SCP_string& type)
{
return std::any_of(get_replaceable_texture_types().begin(),
get_replaceable_texture_types().end(),
[&type](const SCP_string& knownType) { return lcase_equal(type, knownType); });
}
}

namespace fso {
namespace fred {
Expand Down Expand Up @@ -122,7 +140,7 @@ namespace fso {
// Only treat the suffix as a type if it's a known sub-texture type.
// Texture names themselves can contain hyphens (e.g. "fighter01-01a"),
// so we must not blindly strip the last segment.
for (const auto& kt : SUBTEXTURE_SUFFIXES) {
for (const auto& kt : get_replaceable_texture_types()) {
if (lcase_equal(possibleType, kt)) {
type = possibleType;
newText = newText.substr(0, npos);
Expand Down Expand Up @@ -187,37 +205,12 @@ namespace fso {
}
void ShipTextureReplacementDialogModel::initSubTypes(polymodel* model, int MapNum)
{
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("misc", false));
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("shine", false));
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("glow", false));
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("normal", false));
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("height", false));
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("ao", false));
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>("reflect", false));

currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("misc", ""));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("shine", ""));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("glow", ""));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("normal", ""));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("height", ""));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("ao", ""));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>("reflect", ""));

replaceMap[MapNum].insert(std::pair<SCP_string, bool>("misc", false));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>("shine", false));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>("glow", false));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>("normal", false));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>("height", false));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>("ao", false));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>("reflect", false));

inheritMap[MapNum].insert(std::pair<SCP_string, bool>("misc", true));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>("shine", true));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>("glow", true));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>("normal", true));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>("height", true));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>("ao", true));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>("reflect", true));
for (const auto& type : get_replaceable_texture_types()) {
subTypesAvailable[MapNum].insert(std::pair<SCP_string, bool>(type, false));
currentTextures[MapNum].insert(std::pair<SCP_string, SCP_string>(type, ""));
replaceMap[MapNum].insert(std::pair<SCP_string, bool>(type, false));
inheritMap[MapNum].insert(std::pair<SCP_string, bool>(type, true));
}
char subMap[MAX_FILENAME_LEN];
//init saftly, probly not necessary
for (int j = 1; j < TM_NUM_TYPES; j++) {
Expand All @@ -239,18 +232,12 @@ namespace fso {
continue;
}
if (!type.empty()) {
if (type == "trans") {
if (lcase_equal(type, MODEL_TEXTURE_SUFFIX_TRANS.substr(1))) {
// transparency map, not a replaceable subtype
} else {
bool known = false;
for (const auto& kt : SUBTEXTURE_SUFFIXES) {
if (lcase_equal(type, kt)) {
subTypesAvailable[MapNum][kt] = true;
known = true;
break;
}
}
if (!known) {
if (is_known_subtexture_type(type)) {
subTypesAvailable[MapNum][type] = true;
} else {
error_display(1, "Invalid Map type %s. Check your model's texture names or get a programmer", type.c_str());
}
}
Expand Down
Loading