move clip & origin into game-specific code
remove hint from brush; hint is technically a surface flag rather than a content flag, so we can infer it from the sides rather than needing to store it as a unique flag (we could still cache the result somewhere but this makes it consistent between q1 and q2)
This commit is contained in:
parent
be17bf7c7d
commit
10676603e9
|
|
@ -54,14 +54,10 @@ struct gamedef_generic_t : public gamedef_t
|
|||
|
||||
contentflags_t cluster_contents(const contentflags_t &, const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
int32_t get_content_type(const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
int32_t contents_priority(const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
bool chops(const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
contentflags_t create_extended_contents(const uint16_t &) const { throw std::bad_cast(); }
|
||||
|
||||
contentflags_t create_empty_contents(const uint16_t &) const { throw std::bad_cast(); }
|
||||
|
||||
contentflags_t create_solid_contents(const uint16_t &) const { throw std::bad_cast(); }
|
||||
|
|
@ -76,6 +72,8 @@ struct gamedef_generic_t : public gamedef_t
|
|||
|
||||
contentflags_t create_detail_solid_contents(const contentflags_t &original) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_are_equal(const contentflags_t &self, const contentflags_t &other) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_are_any_detail(const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_are_detail_solid(const contentflags_t &contents) const { throw std::bad_cast(); }
|
||||
|
|
@ -88,6 +86,10 @@ struct gamedef_generic_t : public gamedef_t
|
|||
|
||||
bool contents_are_mirrored(const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_are_origin(const contentflags_t &contents) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_are_clip(const contentflags_t &contents) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_clip_same_type(const contentflags_t &, const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
||||
bool contents_are_solid(const contentflags_t &) const { throw std::bad_cast(); }
|
||||
|
|
@ -118,6 +120,19 @@ struct gamedef_generic_t : public gamedef_t
|
|||
const std::vector<qvec3b> &get_default_palette() const { throw std::bad_cast(); };
|
||||
};
|
||||
|
||||
// extra data for contentflags_t for Quake-like
|
||||
struct q1_contentflags_data
|
||||
{
|
||||
bool origin = false; // is an origin brush
|
||||
|
||||
bool clip = false; // is a clip brush
|
||||
|
||||
constexpr bool operator==(const q1_contentflags_data &other) const { return origin == other.origin && clip == other.clip; }
|
||||
constexpr bool operator!=(const q1_contentflags_data &other) const { return !(*this == other); }
|
||||
|
||||
constexpr explicit operator bool() const { return origin && clip; }
|
||||
};
|
||||
|
||||
template<gameid_t ID>
|
||||
struct gamedef_q1_like_t : public gamedef_t
|
||||
{
|
||||
|
|
@ -161,8 +176,6 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
return create_solid_contents();
|
||||
}
|
||||
|
||||
int32_t get_content_type(const contentflags_t &contents) const { return contents.native; }
|
||||
|
||||
int32_t contents_priority(const contentflags_t &contents) const
|
||||
{
|
||||
if (contents.extended & CFLAGS_DETAIL) {
|
||||
|
|
@ -195,7 +208,7 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
return contents_are_solid(contents) || contents_are_sky(contents) || (contents.extended & CFLAGS_DETAIL);
|
||||
}
|
||||
|
||||
contentflags_t create_extended_contents(const uint16_t &cflags) const { return {0, cflags}; }
|
||||
inline contentflags_t create_extended_contents(const q1_contentflags_data &data) const { return {0, 0, data}; }
|
||||
|
||||
contentflags_t create_empty_contents(const uint16_t &cflags = 0) const
|
||||
{
|
||||
|
|
@ -238,6 +251,23 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
return {0, CFLAGS_DETAIL};
|
||||
}
|
||||
|
||||
bool contents_are_equal(const contentflags_t &self, const contentflags_t &other) const
|
||||
{
|
||||
if (self.game_data.has_value() != other.game_data.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self.game_data.has_value()) {
|
||||
if (std::any_cast<const q1_contentflags_data &>(self.game_data) !=
|
||||
std::any_cast<const q1_contentflags_data &>(other.game_data)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (self.extended & CFLAGS_CONTENTS_MASK) == (other.extended & CFLAGS_CONTENTS_MASK) &&
|
||||
self.native == other.native;
|
||||
}
|
||||
|
||||
bool contents_are_any_detail(const contentflags_t &contents) const
|
||||
{
|
||||
// in Q1, there are only CFLAGS_DETAIL, CFLAGS_DETAIL_ILLUSIONARY, or CFLAGS_DETAIL_FENCE
|
||||
|
|
@ -272,6 +302,16 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
|| (contents.native == CONTENTS_LAVA);
|
||||
}
|
||||
|
||||
bool contents_are_origin(const contentflags_t &contents) const
|
||||
{
|
||||
return contents.game_data.has_value() && std::any_cast<const q1_contentflags_data &>(contents.game_data).origin;
|
||||
}
|
||||
|
||||
bool contents_are_clip(const contentflags_t &contents) const
|
||||
{
|
||||
return contents.game_data.has_value() && std::any_cast<const q1_contentflags_data &>(contents.game_data).clip;
|
||||
}
|
||||
|
||||
bool contents_clip_same_type(const contentflags_t &self, const contentflags_t &other) const
|
||||
{
|
||||
return self == other && self.clips_same_type.value_or(true);
|
||||
|
|
@ -281,6 +321,8 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
{
|
||||
if (contents.extended & CFLAGS_CONTENTS_MASK)
|
||||
return false;
|
||||
else if (contents.game_data.has_value() && std::any_cast<const q1_contentflags_data &>(contents.game_data))
|
||||
return false;
|
||||
|
||||
return contents.native == CONTENTS_EMPTY;
|
||||
}
|
||||
|
|
@ -289,6 +331,8 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
{
|
||||
if (contents.extended & CFLAGS_CONTENTS_MASK)
|
||||
return false;
|
||||
else if (contents.game_data.has_value() && std::any_cast<const q1_contentflags_data &>(contents.game_data))
|
||||
return false;
|
||||
|
||||
return contents.native == CONTENTS_SOLID;
|
||||
}
|
||||
|
|
@ -297,6 +341,8 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
{
|
||||
if (contents.extended & CFLAGS_CONTENTS_MASK)
|
||||
return false;
|
||||
else if (contents.game_data.has_value() && std::any_cast<const q1_contentflags_data &>(contents.game_data))
|
||||
return false;
|
||||
|
||||
return contents.native == CONTENTS_SKY;
|
||||
}
|
||||
|
|
@ -305,6 +351,8 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
{
|
||||
if (contents.extended & CFLAGS_CONTENTS_MASK)
|
||||
return false;
|
||||
else if (contents.game_data.has_value() && std::any_cast<const q1_contentflags_data &>(contents.game_data))
|
||||
return false;
|
||||
|
||||
return contents.native <= CONTENTS_WATER && contents.native >= CONTENTS_LAVA;
|
||||
}
|
||||
|
|
@ -375,11 +423,11 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
{
|
||||
// check for strong content indicators
|
||||
if (!Q_strcasecmp(texname.data(), "origin")) {
|
||||
return create_extended_contents(CFLAGS_ORIGIN);
|
||||
return create_extended_contents({ true, false });
|
||||
} else if (!Q_strcasecmp(texname.data(), "hint") || !Q_strcasecmp(texname.data(), "hintskip")) {
|
||||
return create_extended_contents(CFLAGS_HINT);
|
||||
return create_empty_contents();
|
||||
} else if (!Q_strcasecmp(texname.data(), "clip")) {
|
||||
return create_extended_contents(CFLAGS_CLIP);
|
||||
return create_extended_contents({ false, true });
|
||||
} else if (texname[0] == '*') {
|
||||
if (!Q_strncasecmp(texname.data() + 1, "lava", 4)) {
|
||||
return create_liquid_contents(CONTENTS_LAVA);
|
||||
|
|
@ -390,10 +438,10 @@ struct gamedef_q1_like_t : public gamedef_t
|
|||
}
|
||||
} else if (!Q_strncasecmp(texname.data(), "sky", 3)) {
|
||||
return create_sky_contents();
|
||||
} else {
|
||||
// and anything else is assumed to be a regular solid.
|
||||
return create_solid_contents();
|
||||
}
|
||||
|
||||
// and anything else is assumed to be a regular solid.
|
||||
return create_solid_contents();
|
||||
}
|
||||
|
||||
void init_filesystem(const fs::path &, const settings::common_settings &) const
|
||||
|
|
@ -551,8 +599,9 @@ struct gamedef_q2_t : public gamedef_t
|
|||
return c;
|
||||
}
|
||||
|
||||
int32_t get_content_type(const contentflags_t &contents) const
|
||||
inline int32_t get_content_type(const contentflags_t &contents) const
|
||||
{
|
||||
// fixme-brushbsp: should TRANSLUCENT be here? does it need to be?
|
||||
return contents.native & (Q2_ALL_VISIBLE_CONTENTS |
|
||||
(Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP | Q2_CONTENTS_ORIGIN |
|
||||
Q2_CONTENTS_TRANSLUCENT | Q2_CONTENTS_AREAPORTAL));
|
||||
|
|
@ -587,8 +636,6 @@ struct gamedef_q2_t : public gamedef_t
|
|||
return !!(contents.native & Q2_CONTENTS_SOLID);
|
||||
}
|
||||
|
||||
contentflags_t create_extended_contents(const uint16_t &cflags) const { return {0, cflags}; }
|
||||
|
||||
contentflags_t create_empty_contents(const uint16_t &cflags) const { return {0, cflags}; }
|
||||
|
||||
contentflags_t create_solid_contents(const uint16_t &cflags) const { return {Q2_CONTENTS_SOLID, cflags}; }
|
||||
|
|
@ -625,6 +672,12 @@ struct gamedef_q2_t : public gamedef_t
|
|||
return result;
|
||||
}
|
||||
|
||||
bool contents_are_equal(const contentflags_t &self, const contentflags_t &other) const
|
||||
{
|
||||
return (self.extended & CFLAGS_CONTENTS_MASK) == (other.extended & CFLAGS_CONTENTS_MASK) &&
|
||||
get_content_type(self) == get_content_type(other);
|
||||
}
|
||||
|
||||
bool contents_are_any_detail(const contentflags_t &contents) const
|
||||
{
|
||||
return ((contents.native & Q2_CONTENTS_DETAIL) != 0);
|
||||
|
|
@ -672,6 +725,16 @@ struct gamedef_q2_t : public gamedef_t
|
|||
// contents to default to not mirroring the insides.
|
||||
return !(contents.native & (Q2_CONTENTS_SOLID | Q2_CONTENTS_AUX));
|
||||
}
|
||||
|
||||
bool contents_are_origin(const contentflags_t &contents) const
|
||||
{
|
||||
return contents.native & Q2_CONTENTS_ORIGIN;
|
||||
}
|
||||
|
||||
bool contents_are_clip(const contentflags_t &contents) const
|
||||
{
|
||||
return contents.native & (Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP);
|
||||
}
|
||||
|
||||
bool contents_clip_same_type(const contentflags_t &self, const contentflags_t &other) const
|
||||
{
|
||||
|
|
@ -803,10 +866,8 @@ struct gamedef_q2_t : public gamedef_t
|
|||
const std::string &texname, const surfflags_t &flags, const contentflags_t &contents) const
|
||||
{
|
||||
// hints and skips are never detail, and have no content
|
||||
if (flags.native & Q2_SURF_HINT) {
|
||||
return {0, CFLAGS_HINT};
|
||||
} else if (flags.native & Q2_SURF_SKIP) {
|
||||
return {0, 0};
|
||||
if (flags.native & (Q2_SURF_HINT | Q2_SURF_SKIP)) {
|
||||
return {Q2_CONTENTS_EMPTY};
|
||||
}
|
||||
|
||||
contentflags_t surf_contents = contents;
|
||||
|
|
@ -819,7 +880,7 @@ struct gamedef_q2_t : public gamedef_t
|
|||
// if we have TRANS33 or TRANS66, we have to be marked as WINDOW,
|
||||
// so unset SOLID, give us WINDOW, and give us TRANSLUCENT
|
||||
if (flags.native & (Q2_SURF_TRANS33 | Q2_SURF_TRANS66)) {
|
||||
surf_contents.native |= Q2_CONTENTS_TRANSLUCENT | Q2_CONTENTS_DETAIL;
|
||||
surf_contents.native |= Q2_CONTENTS_TRANSLUCENT;
|
||||
|
||||
if (surf_contents.native & Q2_CONTENTS_SOLID) {
|
||||
surf_contents.native = (surf_contents.native & ~Q2_CONTENTS_SOLID) | Q2_CONTENTS_WINDOW;
|
||||
|
|
@ -827,21 +888,16 @@ struct gamedef_q2_t : public gamedef_t
|
|||
}
|
||||
|
||||
// translucent objects are automatically classified as detail
|
||||
if (surf_contents.native & Q2_CONTENTS_WINDOW) {
|
||||
if (surf_contents.native & Q2_CONTENTS_TRANSLUCENT) {
|
||||
surf_contents.native |= Q2_CONTENTS_DETAIL;
|
||||
} else if (surf_contents.native & (Q2_CONTENTS_MIST | Q2_CONTENTS_AUX)) {
|
||||
surf_contents.native |= Q2_CONTENTS_DETAIL;
|
||||
}
|
||||
|
||||
if (surf_contents.native & (Q2_CONTENTS_MONSTERCLIP | Q2_CONTENTS_PLAYERCLIP)) {
|
||||
surf_contents.extended |= CFLAGS_CLIP;
|
||||
surf_contents.native |= Q2_CONTENTS_DETAIL;
|
||||
}
|
||||
|
||||
if (surf_contents.native & Q2_CONTENTS_ORIGIN) {
|
||||
surf_contents.extended |= CFLAGS_ORIGIN;
|
||||
}
|
||||
|
||||
return surf_contents;
|
||||
}
|
||||
|
||||
|
|
@ -1125,8 +1181,7 @@ bool surfflags_t::is_valid(const gamedef_t *game) const
|
|||
|
||||
bool contentflags_t::types_equal(const contentflags_t &other, const gamedef_t *game) const
|
||||
{
|
||||
return (extended & CFLAGS_CONTENTS_MASK) == (other.extended & CFLAGS_CONTENTS_MASK) &&
|
||||
game->get_content_type(*this) == game->get_content_type(other);
|
||||
return game->contents_are_equal(*this, other);
|
||||
}
|
||||
|
||||
int32_t contentflags_t::priority(const gamedef_t *game) const
|
||||
|
|
@ -1194,6 +1249,16 @@ bool contentflags_t::is_valid(const gamedef_t *game, bool strict) const
|
|||
return game->contents_are_valid(*this, strict);
|
||||
}
|
||||
|
||||
bool contentflags_t::is_clip(const gamedef_t *game) const
|
||||
{
|
||||
return game->contents_are_clip(*this);
|
||||
}
|
||||
|
||||
bool contentflags_t::is_origin(const gamedef_t *game) const
|
||||
{
|
||||
return game->contents_are_origin(*this);
|
||||
}
|
||||
|
||||
std::string contentflags_t::to_string(const gamedef_t *game) const
|
||||
{
|
||||
std::string s = game->get_contents_display(*this);
|
||||
|
|
@ -1203,15 +1268,15 @@ std::string contentflags_t::to_string(const gamedef_t *game) const
|
|||
|
||||
s += fmt::format("|CLIPS_SAME_TYPE[{}]", clips_same_type.has_value() ? (clips_same_type.value() ? "true" : "false") : "nullopt");
|
||||
|
||||
if (extended & CFLAGS_HINT) {
|
||||
s += "|HINT";
|
||||
}
|
||||
if (extended & CFLAGS_CLIP) {
|
||||
// FIXME: duped for Q2, move to Q1?
|
||||
if (is_clip(game)) {
|
||||
s += "|CLIP";
|
||||
}
|
||||
if (extended & CFLAGS_ORIGIN) {
|
||||
if (is_origin(game)) {
|
||||
s += "|ORIGIN";
|
||||
}
|
||||
|
||||
// FIXME: duped for Q2, move to Q1?
|
||||
if (extended & CFLAGS_DETAIL) {
|
||||
s += "|DETAIL";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <variant>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <any>
|
||||
|
||||
#include <common/cmdlib.hh>
|
||||
#include <common/log.hh>
|
||||
|
|
@ -523,6 +524,7 @@ enum q1_contents_t : int32_t
|
|||
// lower bits are stronger, and will eat weaker brushes completely
|
||||
enum q2_contents_t : int32_t
|
||||
{
|
||||
Q2_CONTENTS_EMPTY = 0,
|
||||
Q2_CONTENTS_SOLID = nth_bit(0), // an eye is never valid in a solid
|
||||
Q2_CONTENTS_WINDOW = nth_bit(1), // translucent, but not watery
|
||||
Q2_CONTENTS_AUX = nth_bit(2),
|
||||
|
|
@ -564,9 +566,6 @@ enum q2_contents_t : int32_t
|
|||
enum extended_cflags_t : uint16_t
|
||||
{
|
||||
// only one of these flags below should ever be set.
|
||||
CFLAGS_HINT = nth_bit(5),
|
||||
CFLAGS_CLIP = nth_bit(6),
|
||||
CFLAGS_ORIGIN = nth_bit(7),
|
||||
CFLAGS_DETAIL = nth_bit(8),
|
||||
CFLAGS_DETAIL_ILLUSIONARY = nth_bit(9),
|
||||
CFLAGS_DETAIL_FENCE = nth_bit(10),
|
||||
|
|
@ -575,7 +574,7 @@ enum extended_cflags_t : uint16_t
|
|||
CFLAGS_DETAIL_MASK = (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE),
|
||||
// all of the special content types
|
||||
CFLAGS_CONTENTS_MASK =
|
||||
(CFLAGS_HINT | CFLAGS_CLIP | CFLAGS_ORIGIN | CFLAGS_DETAIL_MASK | CFLAGS_ILLUSIONARY_VISBLOCKER)
|
||||
(CFLAGS_DETAIL_MASK | CFLAGS_ILLUSIONARY_VISBLOCKER)
|
||||
};
|
||||
|
||||
struct gamedef_t;
|
||||
|
|
@ -588,6 +587,9 @@ struct contentflags_t
|
|||
// extra flags, specific to BSP only
|
||||
uint16_t extended;
|
||||
|
||||
// extra data supplied by the game
|
||||
std::any game_data;
|
||||
|
||||
// the value set directly from `_mirrorinside` on the brush, if available.
|
||||
// don't check this directly, use `is_mirror_inside` to allow the game to decide.
|
||||
std::optional<bool> mirror_inside = std::nullopt;
|
||||
|
|
@ -619,7 +621,7 @@ struct contentflags_t
|
|||
bool is_empty(const gamedef_t *game) const;
|
||||
|
||||
// detail solid or structural solid
|
||||
bool is_any_solid(const gamedef_t *game) const {
|
||||
inline bool is_any_solid(const gamedef_t *game) const {
|
||||
return is_solid(game)
|
||||
|| is_detail_solid(game);
|
||||
}
|
||||
|
|
@ -629,14 +631,10 @@ struct contentflags_t
|
|||
bool is_sky(const gamedef_t *game) const;
|
||||
bool is_liquid(const gamedef_t *game) const;
|
||||
bool is_valid(const gamedef_t *game, bool strict = true) const;
|
||||
bool is_clip(const gamedef_t *game) const;
|
||||
bool is_origin(const gamedef_t *game) const;
|
||||
|
||||
constexpr bool is_hint() const { return extended & CFLAGS_HINT; }
|
||||
|
||||
constexpr bool is_clip() const { return extended & CFLAGS_CLIP; }
|
||||
|
||||
constexpr bool is_origin() const { return extended & CFLAGS_ORIGIN; }
|
||||
|
||||
bool is_fence(const gamedef_t *game) const {
|
||||
inline bool is_fence(const gamedef_t *game) const {
|
||||
return is_detail_fence(game) || is_detail_illusionary(game);
|
||||
}
|
||||
|
||||
|
|
@ -1810,10 +1808,8 @@ struct gamedef_t
|
|||
// FIXME: fix so that we don't have to pass a name here
|
||||
virtual bool texinfo_is_hintskip(const surfflags_t &flags, const std::string &name) const = 0;
|
||||
virtual contentflags_t cluster_contents(const contentflags_t &contents0, const contentflags_t &contents1) const = 0;
|
||||
virtual int32_t get_content_type(const contentflags_t &contents) const = 0;
|
||||
virtual int32_t contents_priority(const contentflags_t &contents) const = 0;
|
||||
virtual bool chops(const contentflags_t &) const = 0;
|
||||
virtual contentflags_t create_extended_contents(const uint16_t &cflags = 0) const = 0;
|
||||
virtual contentflags_t create_empty_contents(const uint16_t &cflags = 0) const = 0;
|
||||
virtual contentflags_t create_solid_contents(const uint16_t &cflags = 0) const = 0;
|
||||
virtual contentflags_t create_sky_contents(const uint16_t &cflags = 0) const = 0;
|
||||
|
|
@ -1821,11 +1817,14 @@ struct gamedef_t
|
|||
virtual contentflags_t create_detail_illusionary_contents(const contentflags_t &original) const = 0;
|
||||
virtual contentflags_t create_detail_fence_contents(const contentflags_t &original) const = 0;
|
||||
virtual contentflags_t create_detail_solid_contents(const contentflags_t &original) const = 0;
|
||||
virtual bool contents_are_equal(const contentflags_t &self, const contentflags_t &other) const = 0;
|
||||
virtual bool contents_are_any_detail(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_detail_solid(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_detail_fence(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_detail_illusionary(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_mirrored(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_origin(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_clip(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_empty(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_clip_same_type(const contentflags_t &self, const contentflags_t &other) const = 0;
|
||||
virtual bool contents_are_solid(const contentflags_t &contents) const = 0;
|
||||
|
|
|
|||
|
|
@ -333,6 +333,25 @@ void FixRotateOrigin(mapentity_t *entity)
|
|||
|
||||
SetKeyValue(entity, "origin", qv::to_string(offset).c_str());
|
||||
}
|
||||
|
||||
static bool Brush_IsHint(const hullbrush_t &brush)
|
||||
{
|
||||
for (auto &f : brush.faces)
|
||||
if (f.flags.is_hint)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool MapBrush_IsHint(const mapbrush_t &brush)
|
||||
{
|
||||
for (size_t i = 0; i < brush.numfaces; i++)
|
||||
if (brush.face(i).flags.is_hint)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CreateBrushFaces
|
||||
|
|
@ -354,7 +373,7 @@ static std::vector<face_t> CreateBrushFaces(const mapentity_t *src, hullbrush_t
|
|||
hullbrush->bounds = {};
|
||||
|
||||
for (auto &mapface : hullbrush->faces) {
|
||||
if (hullnum <= 0 && hullbrush->contents.is_hint()) {
|
||||
if (hullnum <= 0 && Brush_IsHint(*hullbrush)) {
|
||||
/* Don't generate hintskip faces */
|
||||
const mtexinfo_t &texinfo = map.mtexinfos.at(mapface.texinfo);
|
||||
|
||||
|
|
@ -802,7 +821,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
for (int i = 0; i < src->nummapbrushes; i++) {
|
||||
const mapbrush_t *mapbrush = &src->mapbrush(i);
|
||||
const contentflags_t contents = Brush_GetContents(mapbrush);
|
||||
if (contents.is_origin()) {
|
||||
if (contents.is_origin(options.target_game)) {
|
||||
if (dst == map.world_entity()) {
|
||||
logging::print("WARNING: Ignoring origin brush in worldspawn\n");
|
||||
continue;
|
||||
|
|
@ -888,7 +907,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
detail_fence |= all_detail_fence;
|
||||
|
||||
/* "origin" brushes always discarded */
|
||||
if (contents.is_origin())
|
||||
if (contents.is_origin(options.target_game))
|
||||
continue;
|
||||
|
||||
/* -omitdetail option omits all types of detail */
|
||||
|
|
@ -921,7 +940,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
* include them in the model bounds so collision detection works
|
||||
* correctly.
|
||||
*/
|
||||
if (contents.is_clip() && hullnum != HULL_COLLISION) {
|
||||
if (contents.is_clip(options.target_game) && hullnum != HULL_COLLISION) {
|
||||
if (hullnum == 0) {
|
||||
std::optional<brush_t> brush = LoadBrush(src, mapbrush, contents, rotate_offset, rottype, hullnum);
|
||||
|
||||
|
|
@ -937,7 +956,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
}
|
||||
|
||||
/* "hint" brushes don't affect the collision hulls */
|
||||
if (contents.is_hint()) {
|
||||
if (MapBrush_IsHint(*mapbrush)) {
|
||||
if (hullnum > 0)
|
||||
continue;
|
||||
contents = options.target_game->create_empty_contents();
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ static void ExportObjFace(std::ofstream &f, const face_t *face, int *vertcount)
|
|||
// not sure why -v is needed, .obj uses (0, 0) in the top left apparently?
|
||||
fmt::print(f, "vt {:.9} {:.9}\n", uv[0], -uv[1]);
|
||||
}
|
||||
|
||||
|
||||
// fixme-brushbsp
|
||||
fmt::print(f, "usemtl contents{}_{}\n", face->contents[0].native, face->contents[0].extended);
|
||||
f << 'f';
|
||||
for (int i = 0; i < face->w.size(); i++) {
|
||||
|
|
@ -108,8 +109,9 @@ void ExportObj_Faces(const std::string &filesuffix, const std::vector<const face
|
|||
WriteContentsMaterial(mtlfile, {CONTENTS_LAVA}, 0.2, 0.0, 0.0);
|
||||
|
||||
WriteContentsMaterial(mtlfile, {CONTENTS_SKY}, 0.8, 0.8, 1.0);
|
||||
WriteContentsMaterial(mtlfile, {CONTENTS_SOLID, CFLAGS_CLIP}, 1, 0.8, 0.8);
|
||||
WriteContentsMaterial(mtlfile, {CONTENTS_EMPTY, CFLAGS_HINT}, 1, 1, 1);
|
||||
// fixme-brushbsp
|
||||
//WriteContentsMaterial(mtlfile, {CONTENTS_SOLID, CFLAGS_CLIP}, 1, 0.8, 0.8);
|
||||
//WriteContentsMaterial(mtlfile, {CONTENTS_EMPTY, CFLAGS_HINT}, 1, 1, 1);
|
||||
|
||||
WriteContentsMaterial(mtlfile, {CONTENTS_SOLID, CFLAGS_DETAIL}, 0.5, 0.5, 0.5);
|
||||
|
||||
|
|
|
|||
|
|
@ -998,7 +998,7 @@ static void BSPX_Brushes_AddModel(
|
|||
case CONTENTS_SLIME:
|
||||
case CONTENTS_LAVA:
|
||||
case CONTENTS_SKY:
|
||||
if (b->contents.is_clip()) {
|
||||
if (b->contents.is_clip(options.target_game)) {
|
||||
perbrush.contents = -8;
|
||||
} else {
|
||||
perbrush.contents = b->contents.native;
|
||||
|
|
@ -1008,7 +1008,7 @@ static void BSPX_Brushes_AddModel(
|
|||
// perbrush.contents = -16;
|
||||
// break;
|
||||
default: {
|
||||
if (b->contents.is_clip()) {
|
||||
if (b->contents.is_clip(options.target_game)) {
|
||||
perbrush.contents = -8;
|
||||
} else {
|
||||
logging::print("WARNING: Unknown contents: {}. Translating to solid.\n",
|
||||
|
|
|
|||
Loading…
Reference in New Issue