light: entity warnings: print bbox for bmodel entities

fixes https://github.com/ericwa/tyrutils-ericw/issues/120
This commit is contained in:
Eric Wasylishen 2016-11-24 17:10:15 -07:00
parent a9b4e8233a
commit b46cba40a4
5 changed files with 64 additions and 27 deletions

View File

@ -126,3 +126,18 @@ Face_Contents(const bsp2_t *bsp, const bsp2_dface_t *face)
const char *texname = Face_TextureName(bsp, face);
return TextureName_Contents(texname);
}
const dmodel_t *BSP_DModelForModelString(const bsp2_t *bsp, const std::string &submodel_str)
{
int submodel = -1;
if (1 == sscanf(submodel_str.c_str(), "*%d", &submodel)) {
if (submodel < 0 || submodel >= bsp->nummodels) {
return nullptr;
}
return &bsp->dmodels[submodel];
}
return nullptr;
}

View File

@ -22,6 +22,7 @@
#include <common/bspfile.hh>
#include <common/mathlib.hh>
#include <string>
int Face_GetNum(const bsp2_t *bsp, const bsp2_dface_t *f);
int Face_VertexAtIndex(const bsp2_t *bsp, const bsp2_dface_t *f, int v);
@ -32,5 +33,6 @@ const char *Face_TextureName(const bsp2_t *bsp, const bsp2_dface_t *face);
const float *GetSurfaceVertexPoint(const bsp2_t *bsp, const bsp2_dface_t *f, int v);
int TextureName_Contents(const char *texname);
int Face_Contents(const bsp2_t *bsp, const bsp2_dface_t *face);
const dmodel_t *BSP_DModelForModelString(const bsp2_t *bsp, const std::string &submodel_str);
#endif /* __COMMON_BSPUTILS_HH__ */

View File

@ -173,10 +173,10 @@ bool Light_PointInSolid(const bsp2_t *bsp, const vec3_t point );
void EstimateVisibleBoundsAtPoint(const vec3_t point, vec3_t mins, vec3_t maxs);
bool EntDict_CheckNoEmptyValues(const entdict_t &entdict);
bool EntDict_CheckNoEmptyValues(const bsp2_t *bsp, const entdict_t &entdict);
bool EntDict_CheckTargetKeysMatched(const entdict_t &entity, const std::vector<entdict_t> &all_edicts);
bool EntDict_CheckTargetKeysMatched(const bsp2_t *bsp, const entdict_t &entity, const std::vector<entdict_t> &all_edicts);
bool EntDict_CheckTargetnameKeyMatched(const entdict_t &entity, const std::vector<entdict_t> &all_edicts);
bool EntDict_CheckTargetnameKeyMatched(const bsp2_t *bsp, const entdict_t &entity, const std::vector<entdict_t> &all_edicts);
#endif /* __LIGHT_ENTITIES_H__ */

View File

@ -156,8 +156,28 @@ MatchTargets(void)
}
static std::string
EntDict_PrettyDescription(const entdict_t &entity)
EntDict_PrettyDescription(const bsp2_t *bsp, const entdict_t &entity)
{
// get the submodel's bbox if it's a brush entity
if (bsp != nullptr
&& EntDict_StringForKey(entity, "origin") == ""
&& EntDict_StringForKey(entity, "model") != "") {
const std::string submodel_str = EntDict_StringForKey(entity, "model");
const dmodel_t *info = BSP_DModelForModelString(bsp, submodel_str);
if (info) {
std::stringstream s;
s << "brush entity with mins (";
s << VecStrf(info->mins);
s << ") maxs (";
s << VecStrf(info->maxs);
s << ") (" <<
EntDict_StringForKey(entity, "classname") << ")";
return s.str();
}
}
std::stringstream s;
s << "entity at (" <<
EntDict_StringForKey(entity, "origin") << ") (" <<
@ -166,14 +186,14 @@ EntDict_PrettyDescription(const entdict_t &entity)
}
bool
EntDict_CheckNoEmptyValues(const entdict_t &entdict)
EntDict_CheckNoEmptyValues(const bsp2_t *bsp, const entdict_t &entdict)
{
bool ok = true;
// empty values warning
for (const auto &keyval : entdict) {
if (keyval.first.empty() || keyval.second.empty()) {
logprint("WARNING: %s has empty key/value \"%s\" \"%s\"\n",
EntDict_PrettyDescription(entdict).c_str(),
EntDict_PrettyDescription(bsp, entdict).c_str(),
keyval.first.c_str(), keyval.second.c_str());
ok = false;
}
@ -185,7 +205,7 @@ EntDict_CheckNoEmptyValues(const entdict_t &entdict)
* Checks `edicts` for unmatched targets/targetnames and prints warnings
*/
bool
EntDict_CheckTargetKeysMatched(const entdict_t &entity, const std::vector<entdict_t> &all_edicts)
EntDict_CheckTargetKeysMatched(const bsp2_t *bsp, const entdict_t &entity, const std::vector<entdict_t> &all_edicts)
{
bool ok = true;
@ -205,7 +225,7 @@ EntDict_CheckTargetKeysMatched(const entdict_t &entity, const std::vector<entdic
if (targetVal == targetname) {
logprint("WARNING: %s has \"%s\" set to itself\n",
EntDict_PrettyDescription(entity).c_str(),
EntDict_PrettyDescription(bsp, entity).c_str(),
targetKey.c_str());
ok = false;
continue;
@ -225,7 +245,7 @@ EntDict_CheckTargetKeysMatched(const entdict_t &entity, const std::vector<entdic
if (!found) {
logprint("WARNING: %s has unmatched \"%s\" (%s)\n",
EntDict_PrettyDescription(entity).c_str(),
EntDict_PrettyDescription(bsp, entity).c_str(),
targetKey.c_str(),
targetVal.c_str());
ok = false;
@ -236,7 +256,7 @@ EntDict_CheckTargetKeysMatched(const entdict_t &entity, const std::vector<entdic
}
bool
EntDict_CheckTargetnameKeyMatched(const entdict_t &entity, const std::vector<entdict_t> &all_edicts)
EntDict_CheckTargetnameKeyMatched(const bsp2_t *bsp, const entdict_t &entity, const std::vector<entdict_t> &all_edicts)
{
// search for "targetname" values such that no entity has a matching "target"
// accept any key name as a target, so we don't print false positive
@ -266,7 +286,7 @@ EntDict_CheckTargetnameKeyMatched(const entdict_t &entity, const std::vector<ent
if (!found) {
logprint("WARNING: %s has targetname \"%s\" which is not targetted by anything.\n",
EntDict_PrettyDescription(entity).c_str(),
EntDict_PrettyDescription(bsp, entity).c_str(),
targetnameVal.c_str());
ok = false;
}
@ -963,9 +983,9 @@ LoadEntities(const globalconfig_t &cfg, const bsp2_t *bsp)
// Make warnings
for (auto &entdict : entdicts) {
EntDict_CheckNoEmptyValues(entdict);
EntDict_CheckTargetKeysMatched(entdict, entdicts);
EntDict_CheckTargetnameKeyMatched(entdict, entdicts);
EntDict_CheckNoEmptyValues(bsp, entdict);
EntDict_CheckTargetKeysMatched(bsp, entdict, entdicts);
EntDict_CheckTargetnameKeyMatched(bsp, entdict, entdicts);
}
// First pass: make permanent changes to the bsp entdata that we will write out

View File

@ -10,11 +10,11 @@ TEST(entities, CheckEmptyValues) {
entdict_t bad2 {{"", "bar"}};
entdict_t bad3 {{"", ""}};
EXPECT_TRUE(EntDict_CheckNoEmptyValues(good1));
EXPECT_TRUE(EntDict_CheckNoEmptyValues(good2));
EXPECT_FALSE(EntDict_CheckNoEmptyValues(bad1));
EXPECT_FALSE(EntDict_CheckNoEmptyValues(bad2));
EXPECT_FALSE(EntDict_CheckNoEmptyValues(bad3));
EXPECT_TRUE(EntDict_CheckNoEmptyValues(nullptr, good1));
EXPECT_TRUE(EntDict_CheckNoEmptyValues(nullptr, good2));
EXPECT_FALSE(EntDict_CheckNoEmptyValues(nullptr, bad1));
EXPECT_FALSE(EntDict_CheckNoEmptyValues(nullptr, bad2));
EXPECT_FALSE(EntDict_CheckNoEmptyValues(nullptr, bad3));
}
TEST(entities, CheckTargetKeysMatched) {
@ -38,11 +38,11 @@ TEST(entities, CheckTargetKeysMatched) {
{"targetname", "targets_self" }
}
};
EXPECT_TRUE(EntDict_CheckTargetKeysMatched(edicts.at(0), edicts));
EXPECT_TRUE(EntDict_CheckTargetKeysMatched(edicts.at(1), edicts));
EXPECT_TRUE(EntDict_CheckTargetKeysMatched(edicts.at(2), edicts));
EXPECT_FALSE(EntDict_CheckTargetKeysMatched(edicts.at(3), edicts));
EXPECT_FALSE(EntDict_CheckTargetKeysMatched(edicts.at(4), edicts));
EXPECT_TRUE(EntDict_CheckTargetKeysMatched(nullptr, edicts.at(0), edicts));
EXPECT_TRUE(EntDict_CheckTargetKeysMatched(nullptr, edicts.at(1), edicts));
EXPECT_TRUE(EntDict_CheckTargetKeysMatched(nullptr, edicts.at(2), edicts));
EXPECT_FALSE(EntDict_CheckTargetKeysMatched(nullptr, edicts.at(3), edicts));
EXPECT_FALSE(EntDict_CheckTargetKeysMatched(nullptr, edicts.at(4), edicts));
}
TEST(entities, CheckTargetnameKeyMatched) {
@ -59,7 +59,7 @@ TEST(entities, CheckTargetnameKeyMatched) {
{ "targetname", "unmatched" }
}
};
EXPECT_TRUE(EntDict_CheckTargetnameKeyMatched(edicts.at(0), edicts));
EXPECT_TRUE(EntDict_CheckTargetnameKeyMatched(edicts.at(1), edicts));
EXPECT_FALSE(EntDict_CheckTargetnameKeyMatched(edicts.at(2), edicts));
EXPECT_TRUE(EntDict_CheckTargetnameKeyMatched(nullptr, edicts.at(0), edicts));
EXPECT_TRUE(EntDict_CheckTargetnameKeyMatched(nullptr, edicts.at(1), edicts));
EXPECT_FALSE(EntDict_CheckTargetnameKeyMatched(nullptr, edicts.at(2), edicts));
}