Beispiel #1
0
/*
=================
ParseMapEntity

parses a single entity out of a map file
=================
*/
static bool ParseMapEntity( bool onlyLights )
{
	epair_t		*ep;
	token_t		token;
	const char	*classname, *value;
	float		lightmapScale;
	char		shader[ MAX_SHADERPATH ];
	shaderInfo_t	*celShader = NULL;
	brush_t		*brush;
	parseMesh_t	*patch;
	bool		funcGroup;
	int		castShadows, recvShadows;
	static bool	map_type = false;

	if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token ))
		return false; // end of .map file
	if( com.stricmp( token.string, "{" ))  Sys_Break( "ParseEntity: found %s instead {\n", token.string );
	if( numEntities >= MAX_MAP_ENTITIES ) Sys_Break( "MAX_MAP_ENTITIES limit exceeded\n" );	

	entitySourceBrushes = 0;
	mapEnt = &entities[numEntities];
	numEntities++;
	memset( mapEnt, 0, sizeof( *mapEnt ));
	
	mapEnt->mapEntityNum = numMapEntities;
	numMapEntities++;
	
	while( 1 )
	{
		if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token ))
			Sys_Break( "ParseEntity: EOF without closing brace\n" );

		if( !com.stricmp( token.string, "}" )) break;
		if( !com.stricmp( token.string, "{" ))
		{
			// parse a brush or patch
			if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES, &token )) break;
			
			if( !com.stricmp( token.string, "patchDef2" ))
			{
				numMapPatches++;
				ParsePatch( onlyLights );
				g_bBrushPrimit = BRUSH_RADIANT;
			}
			else if( !com.stricmp( token.string, "terrainDef" ))
			{
				MsgDev( D_WARN, "Terrain entity parsing not supported in this build.\n" );
				Com_SkipBracedSection( mapfile, 0 );
				g_bBrushPrimit = BRUSH_RADIANT;
			}
			else if( !com.stricmp( token.string, "brushDef" ))
			{
				// parse brush primitive
				g_bBrushPrimit = BRUSH_RADIANT;
				ParseBrush( onlyLights );
			}
			else
			{
				if( g_bBrushPrimit == BRUSH_RADIANT )
					Sys_Break( "mixed brush primitive with another format\n" );
				if( g_bBrushPrimit == BRUSH_UNKNOWN ) g_bBrushPrimit = BRUSH_WORLDCRAFT_21;
				
				// QuArK or WorldCraft map (unknown at this point)
				Com_SaveToken( mapfile, &token );
				ParseBrush( onlyLights );
			}
			entitySourceBrushes++;
		}
		else
		{
			// parse a key / value pair
			ep = ParseEpair( mapfile, &token );

			if( !com.strcmp( ep->key, "mapversion" ))
			{
				if( com.atoi( ep->value ) == VALVE_FORMAT )
				{
					Msg( "Valve Format Map detected\n" );
					g_bBrushPrimit = BRUSH_WORLDCRAFT_22;
				}
				else if( com.atoi( ep->value ) == GEARBOX_FORMAT )
				{
					Msg( "Gearcraft Format Map detected\n" );
					g_bBrushPrimit = BRUSH_GEARCRAFT_40;
				}
				else g_bBrushPrimit = BRUSH_WORLDCRAFT_21;
			}
			if( ep->key[0] != '\0' && ep->value[0] != '\0' )
			{
				ep->next = mapEnt->epairs;
				mapEnt->epairs = ep;
			}
		}
	}

	if( !map_type && g_bBrushPrimit != BRUSH_UNKNOWN )
	{
		MAPTYPE();
		map_type = true;
	}
	
	classname = ValueForKey( mapEnt, "classname" );
	
	if( onlyLights && com.strnicmp( classname, "light", 5 ))
	{
		numEntities--;
		return true;
	}
	
	if( !com.stricmp( "func_group", classname ))
		funcGroup = true;
	else funcGroup = false;
	
	// worldspawn (and func_groups) default to cast/recv shadows in worldspawn group
	if( funcGroup || mapEnt->mapEntityNum == 0 )
	{
		castShadows = WORLDSPAWN_CAST_SHADOWS;
		recvShadows = WORLDSPAWN_RECV_SHADOWS;
	}
	else // other entities don't cast any shadows, but recv worldspawn shadows
	{
		castShadows = ENTITY_CAST_SHADOWS;
		recvShadows = ENTITY_RECV_SHADOWS;
	}
	
	// get explicit shadow flags
	GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows );
	
	// get lightmap scaling value for this entity
	if( com.strcmp( "", ValueForKey( mapEnt, "lightmapscale" )) || com.strcmp( "", ValueForKey( mapEnt, "_lightmapscale" )))
	{
		// get lightmap scale from entity
		lightmapScale = FloatForKey( mapEnt, "lightmapscale" );
		if( lightmapScale <= 0.0f ) lightmapScale = FloatForKey( mapEnt, "_lightmapscale" );
		if( lightmapScale > 0.0f ) Msg( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale );
	}
	else lightmapScale = 0.0f;
	
	// get cel shader :) for this entity
	value = ValueForKey( mapEnt, "_celshader" );
	if( value[0] == '\0' ) value = ValueForKey( &entities[0], "_celshader" );
	if( value[0] != '\0' )
	{
		com.snprintf( shader, sizeof( shader ), "textures/%s", value );
		celShader = ShaderInfoForShader( shader );
		Msg( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader );
	}
	else celShader = NULL;
	
	// attach stuff to everything in the entity
	for( brush = mapEnt->brushes; brush != NULL; brush = brush->next )
	{
		brush->entityNum = mapEnt->mapEntityNum;
		brush->castShadows = castShadows;
		brush->recvShadows = recvShadows;
		brush->lightmapScale = lightmapScale;
		brush->celShader = celShader;
	}
	
	for( patch = mapEnt->patches; patch != NULL; patch = patch->next )
	{
		patch->entityNum = mapEnt->mapEntityNum;
		patch->castShadows = castShadows;
		patch->recvShadows = recvShadows;
		patch->lightmapScale = lightmapScale;
		patch->celShader = celShader;
	}
	
	SetEntityBounds( mapEnt );
	
	// load shader index map (equivalent to old terrain alphamap)
	LoadEntityIndexMap( mapEnt );
	
	// get entity origin and adjust brushes
	GetVectorForKey( mapEnt, "origin", mapEnt->origin );
	if( mapEnt->origin[0] || mapEnt->origin[1] || mapEnt->origin[2] )
		AdjustBrushesForOrigin( mapEnt );

	// group_info entities are just for editor grouping
	if( !com.stricmp( "group_info", classname ))
	{
		numEntities--;
		return true;
	}
	
	// group entities are just for editor convenience, toss all brushes into worldspawn
	if( funcGroup )
	{
		MoveBrushesToWorld( mapEnt );
		numEntities--;
		return true;
	}
	return true;
}
Beispiel #2
0
/*
 * @brief
 */
static _Bool ParseMapEntity(void) {
	entity_t *mapent;
	epair_t *e;
	side_t *s;
	int32_t i, j;
	vec_t newdist;
	map_brush_t *b;

	if (!GetToken(true))
		return false;

	if (g_strcmp0(token, "{"))
		Com_Error(ERR_FATAL, "\"{\" not found\n");

	if (num_entities == MAX_BSP_ENTITIES)
		Com_Error(ERR_FATAL, "MAX_BSP_ENTITIES\n");

	mapent = &entities[num_entities];
	num_entities++;
	memset(mapent, 0, sizeof(*mapent));
	mapent->first_brush = num_map_brushes;
	mapent->num_brushes = 0;

	do {
		if (!GetToken(true))
			Com_Error(ERR_FATAL, "EOF without closing brace\n");
		if (!g_strcmp0(token, "}"))
			break;
		if (!g_strcmp0(token, "{"))
			ParseBrush(mapent);
		else {
			e = ParseEpair();
			e->next = mapent->epairs;
			mapent->epairs = e;
		}
	} while (true);

	VectorForKey(mapent, "origin", mapent->origin);

	// if there was an origin brush, offset all of the planes and texinfo
	if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) {
		for (i = 0; i < mapent->num_brushes; i++) {
			b = &map_brushes[mapent->first_brush + i];
			for (j = 0; j < b->num_sides; j++) {

				s = &b->original_sides[j];

				newdist = map_planes[s->plane_num].dist
						- DotProduct(map_planes[s->plane_num].normal, mapent->origin);

				s->plane_num = FindPlane(map_planes[s->plane_num].normal, newdist);

				s->texinfo = TexinfoForBrushTexture(&map_planes[s->plane_num],
						&map_brush_textures[s - map_brush_sides], mapent->origin);
			}
			MakeBrushWindings(b);
		}
	}

	// group entities are just for editor convenience
	// toss all brushes into the world entity
	if (!g_strcmp0("func_group", ValueForKey(mapent, "classname"))) {
		MoveBrushesToWorld(mapent);
		mapent->num_brushes = 0;
		return true;
	}

	// areaportal entities move their brushes, but don't eliminate the entity
	if (!g_strcmp0("func_areaportal", ValueForKey(mapent, "classname"))) {
		char str[128];

		if (mapent->num_brushes != 1)
			Com_Error(
					ERR_FATAL,
					"ParseMapEntity: %i func_areaportal can only be a single brush\n",
					num_entities - 1);

		b = &map_brushes[num_map_brushes - 1];
		b->contents = CONTENTS_AREA_PORTAL;
		c_area_portals++;
		mapent->area_portal_num = c_area_portals;
		// set the portal number as "style"
		sprintf(str, "%i", c_area_portals);
		SetKeyValue(mapent, "areaportal", str);
		MoveBrushesToWorld(mapent);
		return true;
	}

	return true;
}
Beispiel #3
0
/*
================
ParseMapEntity
================
*/
qboolean	ParseMapEntity (void)
{
	entity_t	*mapent;
	epair_t		*e;
	side_t		*s;
	int			i, j;
	int			startbrush, startsides;
	vec_t		newdist;
	mapbrush_t	*b;

	if (!GetToken (true))
		return false;

	if (strcmp (token, "{") )
		Error ("ParseEntity: { not found");
	
	if (num_entities == MAX_MAP_ENTITIES)
		Error ("num_entities == MAX_MAP_ENTITIES");

	startbrush = nummapbrushes;
	startsides = nummapbrushsides;

	mapent = &entities[num_entities];
	num_entities++;
	memset (mapent, 0, sizeof(*mapent));
	mapent->firstbrush = nummapbrushes;
	mapent->numbrushes = 0;
//	mapent->portalareas[0] = -1;
//	mapent->portalareas[1] = -1;

	do
	{
		if (!GetToken (true))
			Error ("ParseEntity: EOF without closing brace");
		if (!strcmp (token, "}") )
			break;
		if (!strcmp (token, "{") )
			ParseBrush (mapent);
		else
		{
			e = ParseEpair ();
			e->next = mapent->epairs;
			mapent->epairs = e;
		}
	} while (1);

	GetVectorForKey (mapent, "origin", mapent->origin);

	//
	// if there was an origin brush, offset all of the planes and texinfo
	//
	if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
	{
		for (i=0 ; i<mapent->numbrushes ; i++)
		{
			b = &mapbrushes[mapent->firstbrush + i];
			for (j=0 ; j<b->numsides ; j++)
			{
				s = &b->original_sides[j];
				newdist = mapplanes[s->planenum].dist -
					DotProduct (mapplanes[s->planenum].normal, mapent->origin);
				s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
				s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
					&side_brushtextures[s-brushsides], mapent->origin);
			}
			MakeBrushWindings (b);
		}
	}

	// group entities are just for editor convenience
	// toss all brushes into the world entity
	if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
	{
		MoveBrushesToWorld (mapent);
		mapent->numbrushes = 0;
		return true;
	}

	// areaportal entities move their brushes, but don't eliminate
	// the entity
	if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
	{
		char	str[128];

		if (mapent->numbrushes != 1)
			Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);

		b = &mapbrushes[nummapbrushes-1];
		b->contents = CONTENTS_AREAPORTAL;
		c_areaportals++;
		mapent->areaportalnum = c_areaportals;
		// set the portal number as "style"
		sprintf (str, "%i", c_areaportals);
		SetKeyValue (mapent, "style", str);
		MoveBrushesToWorld (mapent);
		return true;
	}

	return true;
}
Beispiel #4
0
/**
 * @brief Parsed map entites and brushes
 * @sa ParseBrush
 * @param[in] filename The map filename
 * @param[in] entityString The body of the entity we are parsing
 */
static bool ParseMapEntity (const char* filename, const char* entityString)
{
	entity_t* mapent;
	const char* entName;
	static int worldspawnCount = 0;
	int notCheckOrFix = !(config.performMapCheck || config.fixMap);

	if (Q_strnull(GetToken()))
		return false;

	if (*parsedToken != '{')
		Sys_Error("ParseMapEntity: { not found");

	if (num_entities == MAX_MAP_ENTITIES)
		Sys_Error("num_entities == MAX_MAP_ENTITIES (%i)", num_entities);

	mapent = &entities[num_entities++];
	OBJZERO(*mapent);
	mapent->firstbrush = nummapbrushes;
	mapent->numbrushes = 0;

	do {
		if (Q_strnull(GetToken()))
			Sys_Error("ParseMapEntity: EOF without closing brace");
		if (*parsedToken == '}')
			break;
		if (*parsedToken == '{')
			ParseBrush(mapent, filename);
		else {
			epair_t* e = ParseEpair(num_entities);
			e->next = mapent->epairs;
			mapent->epairs = e;
		}
	} while (true);

	GetVectorForKey(mapent, "origin", mapent->origin);

	entName = ValueForKey(mapent, "classname");

	/* offset all of the planes and texinfo if needed */
	if (IsInlineModelEntity(entName) && VectorNotEmpty(mapent->origin))
		AdjustBrushesForOrigin(mapent);

	if (num_entities == 1 && !Q_streq("worldspawn", entName))
		Sys_Error("The first entity must be worldspawn, it is: %s", entName);
	if (notCheckOrFix && Q_streq("func_group", entName)) {
		/* group entities are just for editor convenience
		 * toss all brushes into the world entity */
		MoveBrushesToWorld(mapent);
		num_entities--;
	} else if (IsInlineModelEntity(entName)) {
		if (mapent->numbrushes == 0 && notCheckOrFix) {
			Com_Printf("Warning: %s has no brushes assigned (entnum: %i)\n", entName, num_entities);
			num_entities--;
		}
	} else if (Q_streq("worldspawn", entName)) {
		worldspawnCount++;
		if (worldspawnCount > 1)
			Com_Printf("Warning: more than one %s in one map\n", entName);

		const char* text = entityString;
		do {
			const char* token = Com_Parse(&text);
			if (Q_strnull(token))
				break;
			const char* key = Mem_StrDup(token);
			token = Com_Parse(&text);
			if (Q_strnull(token))
				break;
			const char* value = Mem_StrDup(token);
			epair_t* e = AddEpair(key, value, num_entities);
			e->next = mapent->epairs;
			mapent->epairs = e;
		} while (true);
	}
	return true;
}