entity.cpp

来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 913 行 · 第 1/2 页

CPP
913
字号
#include "stdafx.h"
#include "qe3.h"

//
int g_entityId = 1;

char *ValueForKey ( epair_t *&e, const char *key)
{
  epair_t *ep;
  for (ep=e ; ep ; ep=ep->next)
  {
		if (!strcmp (ep->key, key) )
    {
      return ep->value;
    }
  }
  return "";
}


char *ValueForKey (entity_t *ent, const char *key)
{
  return ValueForKey(ent->epairs, key);
}

void TrackMD3Angles(entity_t *e, const char *key, const char *value)
{
  if (strcmpi(key, "angle") != 0)
  {
    return;
  }

  if (e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL)
  {
    float a = FloatForKey (e, "angle");
    float b = atof(value);
    if (a != b)
    {
      vec3_t vAngle;
      vAngle[0] = vAngle[1] = 0;
      vAngle[2] = -a;
      Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
      vAngle[2] = b;
      Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
    }
  }
}

void 	SetKeyValue (epair_t *&e, const char *key, const char *value)
{
	epair_t	*ep;
  for (ep=e ; ep ; ep=ep->next)
  {
		if (!strcmp (ep->key, key) )
		{
			free (ep->value);
			ep->value = (char*)qmalloc(strlen(value)+1);
			strcpy (ep->value, value);
			return;
		}
  }
	ep = (epair_t*)qmalloc (sizeof(*ep));
	ep->next = e;
	e = ep;
	ep->key = (char*)qmalloc(strlen(key)+1);
	strcpy (ep->key, key);
	ep->value = (char*)qmalloc(strlen(value)+1);
	strcpy (ep->value, value);

}


void 	SetKeyValue (entity_t *ent, const char *key, const char *value)
{

	if (ent == NULL)
		return;

	if (!key || !key[0])
		return;

  TrackMD3Angles(ent, key, value);

  SetKeyValue(ent->epairs, key, value);

}

void 	DeleteKey (epair_t *&e, const char *key)
{
	epair_t	**ep, *next;
	
	ep = &e;
	while (*ep)
	{
		next = *ep;
		if ( !strcmp (next->key, key) )
		{
			*ep = next->next;
			free(next->key);
			free(next->value);
			free(next);
			return;
		}
		ep = &next->next;
	}
}


void 	DeleteKey (entity_t *ent, const char *key)
{
  DeleteKey(ent->epairs, key);
}




float	FloatForKey (entity_t *ent, const char *key)
{
	char	*k;
	
	k = ValueForKey (ent, key);
	return atof(k);
}

int IntForKey (entity_t *ent, const char *key)
{
	char	*k;
	
	k = ValueForKey (ent, key);
	return atoi(k);
}

void 	GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
{
	char	*k;
	
	k = ValueForKey (ent, key);
	sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
}

/*
===============
Entity_FreeEpairs

Frees the entity epairs.
===============
*/
void Entity_FreeEpairs(entity_t *e)
{
	epair_t	*ep, *next;

	for (ep = e->epairs; ep; ep = next)
	{
		next = ep->next;
		free (ep->key);
		free (ep->value);
		free (ep);
	}
	e->epairs = NULL;
}

/*
===========
Entity_AddToList
===========
*/
void Entity_AddToList(entity_t *e, entity_t *list)
{
	if (e->next || e->prev)
		Error ("Entity_AddToList: allready linked");
	e->next = list->next;
	list->next->prev = e;
	list->next = e;
	e->prev = list;
}

/*
===========
Entity_RemoveFromList
===========
*/
void Entity_RemoveFromList (entity_t *e)
{
	if (!e->next || !e->prev)
		Error ("Entity_RemoveFromList: not linked");
	e->next->prev = e->prev;
	e->prev->next = e->next;
	e->next = e->prev = NULL;
}



/*
===============
Entity_Free

Frees the entity and any brushes is has.
The entity is removed from the global entities list.
===============
*/
void Entity_Free (entity_t *e)
{
	// do we have a plugin entity ?
	if ( e->pPlugEnt )
	{
		e->pPlugEnt->DecRef();
		e->pPlugEnt = NULL;
	}

	while (e->brushes.onext != &e->brushes)
		Brush_Free (e->brushes.onext);

	if (e->next)
	{
		e->next->prev = e->prev;
		e->prev->next = e->next;
	}

	Entity_FreeEpairs(e);

	free (e);
}

/*
=================
Entity_MemorySize
=================
*/
int Entity_MemorySize(entity_t *e)
{
	epair_t	*ep;
	int size = 0;

	for (ep = e->epairs; ep; ep = ep->next)
	{
		size += _msize(ep->key);
		size += _msize(ep->value);
		size += _msize(ep);
	}
	size += _msize(e);
	return size;
}

/*
=================
ParseEpair
=================
*/
epair_t *ParseEpair (void)
{
	epair_t	*e;
	
	e = (epair_t*)qmalloc (sizeof(*e));
	
	e->key = (char*)qmalloc(strlen(token)+1);
	strcpy (e->key, token);

	GetToken (false);
	e->value = (char*)qmalloc(strlen(token)+1);
	strcpy (e->value, token);

	return e;
}

/*
================
Entity_Parse

If onlypairs is set, the classname info will not
be looked up, and the entity will not be added
to the global list.  Used for parsing the project.
================
*/
entity_t	*Entity_Parse (qboolean onlypairs, brush_t* pList)
{
	entity_t	*ent;
	eclass_t	*e;
	brush_t		*b;
	vec3_t		mins, maxs;
	epair_t		*ep;
	qboolean	has_brushes;
	
	if (!GetToken (true))
		return NULL;
	
	if (strcmp (token, "{") )
		Error ("ParseEntity: { not found");
	
	ent = (entity_t*)qmalloc (sizeof(*ent));
	ent->entityId = g_entityId++;
	ent->brushes.onext = ent->brushes.oprev = &ent->brushes;

  int n = 0;
	do
	{
		if (!GetToken (true))
		{
			Warning ("ParseEntity: EOF without closing brace");
			return NULL;
		}
		if (!strcmp (token, "}") )
			break;
		if (!strcmp (token, "{") )
		{
			b = Brush_Parse ();
			if (b != NULL)
			{
				b->owner = ent;
				// add to the end of the entity chain
				b->onext = &ent->brushes;
				b->oprev = ent->brushes.oprev;
				ent->brushes.oprev->onext = b;
				ent->brushes.oprev = b;
			}
			else
			{
				break;
			}
		}
		else
		{
			ep = ParseEpair ();
			ep->next = ent->epairs;
			ent->epairs = ep;
		}
	} while (1);
	
  // group info entity?
  if (strcmp(ValueForKey (ent, "classname"), "group_info") == 0)
    return ent;

	if (onlypairs)
		return ent;
	
	if (ent->brushes.onext == &ent->brushes)
		has_brushes = false;
	else
		has_brushes = true;
	
	GetVectorForKey (ent, "origin", ent->origin);
	
	e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
	ent->eclass = e;
	if ( e->nShowFlags & ECLASS_PLUGINENTITY )
	{
		// locate the plugin
		CPlugIn * pPlug = g_pParentWnd->GetPlugInMgr().PluginForModule( e->hPlug );
		if (pPlug)
		{
			// create the plugin entity
			IPluginEntity* pPlugEnt = pPlug->CreatePluginEntity( ent );
			if (pPlugEnt)
			{
				ent->pPlugEnt = pPlugEnt;
				// the brush is used to select and move
				pPlugEnt->GetBounds( mins, maxs );
			}
			else
			{
				// give it a default bounding box
				SetKeyValue (ent, "model", "");
				mins[0] = -4; mins[1] = -4; mins[2] = -4;
				maxs[0] = 4; maxs[1] = 4; maxs[2] = 4;
				VectorAdd( mins, ent->origin, mins );
				VectorAdd( maxs, ent->origin, maxs );
			}
			b = Brush_Create (mins, maxs, &ent->eclass->texdef);
			Entity_LinkBrush (ent, b);
			Brush_Build( b, true );
		}
		else
			Sys_Printf("WARNING: plugin lookup failed for plugin entities\n");
	}
	else if (e->fixedsize)
	{	// fixed size entity
		if (ent->brushes.onext != &ent->brushes)
		{
			printf ("Warning: Fixed size entity with brushes\n");
#if 0
			while (ent->brushes.onext != &ent->brushes)
			{	// FIXME: this will free the entity and crash!
				Brush_Free (b);
			}
#endif
			ent->brushes.next = ent->brushes.prev = &ent->brushes;
		}
		
		// create a custom brush
		VectorAdd (e->mins, ent->origin, mins);
		VectorAdd (e->maxs, ent->origin, maxs);
		
		float a = 0;
		if (e->nShowFlags & ECLASS_MISCMODEL)
		{
			char* p = ValueForKey(ent, "model");
			if (p != NULL && strlen(p) > 0)
			{
				vec3_t vMin, vMax;
				a = FloatForKey (ent, "angle");
				if (GetCachedModel(ent, p, vMin, vMax))
				{
					// create a custom brush
					VectorAdd (ent->md3Class->mins, ent->origin, mins);
					VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
				}
			}
		}
		
		b = Brush_Create (mins, maxs, &e->texdef);
		
		if (a)
		{
			vec3_t vAngle;
			vAngle[0] = vAngle[1] = 0;
			vAngle[2] = a;
			Brush_Rotate(b, vAngle, ent->origin, false);
		}
		
		
		b->owner = ent;
		
		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
	}
	else
	{	// brush entity
		if (ent->brushes.next == &ent->brushes)
			printf ("Warning: Brush entity with no brushes\n");
	}
	
	// add all the brushes to the main list
	if (pList)
	{
		for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
		{
			b->next = pList->next;
			pList->next->prev = b;
			b->prev = pList;
			pList->next = b;
		}
	}
	
	return ent;
}

void VectorMidpoint(vec3_t va, vec3_t vb, vec3_t& out)
{
  for (int i = 0; i < 3; i++)
    out[i] = va[i] + ((vb[i] - va[i]) / 2);
}


/*
============
Entity_Write

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?