qbsp: add func_group support

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-03-04 21:18:55 +10:30
parent 4063d8aade
commit 3426e7e8c2
4 changed files with 64 additions and 28 deletions

View File

@ -2,6 +2,7 @@
* qbsp: respect floating point texture rotation and shift in map files
* qbsp: support for Valve's 220 map format used in later Worldcraft/Hammer
* qbsp: support func_group entities used by Radiant and similar editors
* light: fixed a race condition in multithreaded coloured light processing
* light: fixed bug preventing use of all 4 light styles in a common case
* light: implemented attenutation formulae "delay" 4+5, ala Bengt's tools

View File

@ -849,8 +849,9 @@ Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum)
* 3. detail solid
* 4. solid
*
* We can always just put water on the head of the list, but will need to
* insert solid brushes between any existing water and solids on the list.
* We will add func_group brushes first and detail brushes last, so we can
* always just put water on the head of the list, but will need to insert
* solid brushes between any existing water and solids on the list.
*/
solid = NULL;
water = dst->brushes;

View File

@ -556,6 +556,23 @@ PreParseFile(const char *buf)
texinfo->count = map.maxfaces;
}
/*
* Special world entities are entities which have their brushes added to the
* world before being removed from the map. Currently func_detail and
* func_group.
*/
static bool
IsWorldBrushEntity(const mapentity_t *entity)
{
const char *classname = ValueForKey(entity, "classname");
if (!strcmp(classname, "func_detail"))
return true;
if (!strcmp(classname, "func_group"))
return true;
return false;
}
void
LoadMapFile(void)
@ -565,7 +582,7 @@ LoadMapFile(void)
int i, j, length, cAxis;
void *pTemp;
struct lumpdata *texinfo;
mapentity_t *ent;
mapentity_t *entity;
mapbrush_t *brush;
mapface_t *face, *face2;
@ -576,16 +593,15 @@ LoadMapFile(void)
ParserInit(&parser, buf);
map.numfaces = map.numbrushes = map.numentities = 0;
ent = map.entities;
while (ParseEntity(&parser, ent)) {
entity = map.entities;
while (ParseEntity(&parser, entity)) {
/* Allocate memory for the bmodel, if needed. */
const char *classname = ValueForKey(ent, "classname");
if (strcmp(classname, "func_detail") && ent->nummapbrushes) {
ent->lumps[BSPMODEL].data = AllocMem(BSPMODEL, 1, true);
ent->lumps[BSPMODEL].count = 1;
if (!IsWorldBrushEntity(entity) && entity->nummapbrushes) {
entity->lumps[BSPMODEL].data = AllocMem(BSPMODEL, 1, true);
entity->lumps[BSPMODEL].count = 1;
}
map.numentities++;
ent++;
entity++;
}
/* Double check the entity count matches our pre-parse count */
@ -741,7 +757,6 @@ WriteEntitiesToString(void)
int cLen;
struct lumpdata *entities;
const mapentity_t *ent;
const char *classname;
map.cTotal[BSPENT] = 0;
@ -749,8 +764,7 @@ WriteEntitiesToString(void)
entities = &map.entities[i].lumps[BSPENT];
/* Check if entity needs to be removed */
classname = ValueForKey(ent, "classname");
if (!ent->epairs || !strcmp(classname, "func_detail")) {
if (!ent->epairs || IsWorldBrushEntity(ent)) {
entities->count = 0;
entities->data = NULL;
continue;

View File

@ -40,15 +40,20 @@ ProcessEntity(mapentity_t *ent, const int hullnum)
int i, numportals;
surface_t *surfs;
node_t *nodes;
const char *class;
const char *classname;
/* No map brushes means non-bmodel entity */
if (!ent->nummapbrushes)
return;
/* func_detail entities get their brushes added to the worldspawn */
class = ValueForKey(ent, "classname");
if (!strcmp(class, "func_detail"))
/*
* func_group and func_detail entities get their brushes added to the
* worldspawn
*/
classname = ValueForKey(ent, "classname");
if (!strcmp(classname, "func_group"))
return;
if (!strcmp(classname, "func_detail"))
return;
if (ent != pWorldEnt) {
@ -84,23 +89,38 @@ ProcessEntity(mapentity_t *ent, const int hullnum)
PrintEntity(ent);
Error(errNoValidBrushes);
}
Message(msgStat, "%5i brushes", ent->numbrushes);
/*
* If this is the world entity, find all func_detail entities and
* add their brushes with the detail flag set.
* If this is the world entity, find all func_group and func_detail
* entities and add their brushes with the appropriate contents flag set.
*/
if (ent == pWorldEnt) {
const mapentity_t *detail;
const int detailstart = ent->numbrushes;
const mapentity_t *source;
int detailcount;
detail = map.entities + 1;
for (i = 1; i < map.numentities; i++, detail++) {
class = ValueForKey(detail, "classname");
if (!strcmp(class, "func_detail"))
Brush_LoadEntity(ent, detail, hullnum);
/* Add func_group brushes first */
source = map.entities + 1;
for (i = 1; i < map.numentities; i++, source++) {
classname = ValueForKey(source, "classname");
if (!strcmp(classname, "func_group"))
Brush_LoadEntity(ent, source, hullnum);
}
Message(msgStat, "%5i detail", ent->numbrushes - detailstart);
/* Add detail brushes next */
detailcount = 0;
source = map.entities + 1;
for (i = 1; i < map.numentities; i++, source++) {
classname = ValueForKey(source, "classname");
if (!strcmp(classname, "func_detail")) {
int detailstart = ent->numbrushes;
Brush_LoadEntity(ent, source, hullnum);
detailcount += ent->numbrushes - detailstart;
}
}
Message(msgStat, "%5i brushes", ent->numbrushes - detailcount);
Message(msgStat, "%5i detail", detailcount);
} else {
Message(msgStat, "%5i brushes", ent->numbrushes);
}
/*