void CEntityDlg::OnCbnSelchangeComboClass()
{
    int index = comboClass.GetCurSel();
    if (index != LB_ERR) {
        CString str;
        comboClass.GetLBText(index, str);
        eclass_t *ent = Eclass_ForName (str, false);
        if (ent) {
            if (selected_brushes.next == &selected_brushes) {
                editEntity = world_entity;
                multipleEntities = false;
            } else {
                editEntity = selected_brushes.next->owner;
                for (brush_t *b = selected_brushes.next->next; b != &selected_brushes; b = b->next) {
                    if (b->owner != editEntity) {
                        multipleEntities = true;
                        break;
                    }
                }
            }
            listVars.ResetContent();
            CPropertyItem *pi = new CPropertyItem("Usage:", ent->desc.c_str(), PIT_VAR, "");
            listVars.AddPropItem(pi);

            int c = ent->vars.Num();
            for (int i = 0; i < c; i++) {
                pi = new CPropertyItem(ent->vars[i].name.c_str(), ent->vars[i].desc.c_str(), PIT_VAR, "");
                pi->SetData(ent->vars[i].type);
                listVars.AddPropItem(pi);
            }
            listVars.Invalidate();
            SetKeyValPairs();
        }
    }
}
Beispiel #2
0
/*
   ===========
   Map_New

   ===========
 */
void Map_New( void ){
	Sys_Printf( "Map_New\n" );
	Map_Free();

	strcpy( currentmap, "unnamed.map" );
	Sys_SetTitle( currentmap );

	world_entity = (entity_s*)qmalloc( sizeof( *world_entity ) );
	world_entity->brushes.onext =
		world_entity->brushes.oprev = &world_entity->brushes;
	SetKeyValue( world_entity, "classname", "worldspawn" );
	world_entity->eclass = Eclass_ForName( "worldspawn", true );

	g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] = 0;
	g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH] = 0;
	VectorCopy( vec3_origin, g_pParentWnd->GetCamWnd()->Camera()->origin );
	g_pParentWnd->GetCamWnd()->Camera()->origin[2] = 48;
	VectorCopy( vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin() );

	Map_RestoreBetween();

	Group_Init();

	Sys_UpdateWindows( W_ALL );
	modified = false;
}
Beispiel #3
0
/*
 =======================================================================================================================
	Map_New
 =======================================================================================================================
 */
void Map_New(void) {
	common->Printf("Map_New\n");
	Map_Free();

	Patch_Cleanup();
	g_Inspectors->entityDlg.SetEditEntity ( NULL );

	world_entity = Entity_New();
	world_entity->brushes.onext = world_entity->brushes.oprev = &world_entity->brushes;
	SetKeyValue(world_entity, "classname", "worldspawn");
	world_entity->eclass = Eclass_ForName("worldspawn", true);

	g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
	g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
	VectorCopy(vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
	g_pParentWnd->GetCamera()->Camera().origin[2] = 48;
	VectorCopy(vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());

	Map_RestoreBetween();

	Sys_UpdateWindows(W_ALL);
	mapModified = 0;

	g_qeglobals.mapVersion = MAP_VERSION;

}
Beispiel #4
0
/*
   ===========
   AddRegionBrushes
   a regioned map will have temp walls put up at the region boundary
   \todo TODO TTimo old implementation of region brushes
   we still add them straight in the worldspawn and take them out after the map is saved
   with the new implementation we should be able to append them in a temporary manner to the data we pass to the map module
   ===========
 */
void AddRegionBrushes( void ){
	vec3_t mins, maxs;
	int i;
	texdef_t td;

	if ( !region_active ) {
#ifdef _DEBUG
		Sys_FPrintf( SYS_WRN, "Unexpected AddRegionBrushes call.\n" );
#endif
		return;
	}

	memset( &td, 0, sizeof( td ) );
	td.SetName( SHADER_NOT_FOUND );

	// set mins
	VectorSet( mins, region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 );

	// vary maxs
	for ( i = 0; i < 3; i++ )
	{
		VectorSet( maxs, region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 );
		maxs[i] = region_mins[i];
		region_sides[i] = Brush_Create( mins, maxs, &td );
	}

	// set maxs
	VectorSet( maxs, region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 );

	// vary mins
	for ( i = 0; i < 3; i++ )
	{
		VectorSet( mins, region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 );
		mins[i] = region_maxs[i];
		region_sides[i + 3] = Brush_Create( mins, maxs, &td );
	}


	// this is a safe check, but it should not really happen anymore
	vec3_t vOrig;
	VectorSet( vOrig,
			   (int)g_pParentWnd->GetCamWnd()->Camera()->origin[0],
			   (int)g_pParentWnd->GetCamWnd()->Camera()->origin[1],
			   (int)g_pParentWnd->GetCamWnd()->Camera()->origin[2] );

	for ( i = 0 ; i < 3 ; i++ )
	{
		if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) {
			Sys_FPrintf( SYS_ERR, "Camera is NOT in the region, it's likely that the region won't compile correctly\n" );
		}
	}

	// write the info_playerstart
	region_startpoint = Entity_Alloc();
	SetKeyValue( region_startpoint, "classname", "info_player_start" );
	region_startpoint->eclass = Eclass_ForName( "info_player_start", false );
	char sTmp[1024];
	sprintf( sTmp, "%d %d %d", (int)vOrig[0], (int)vOrig[1], (int)vOrig[2] );
	SetKeyValue( region_startpoint, "origin", sTmp );
	sprintf( sTmp, "%d", (int)g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] );
	SetKeyValue( region_startpoint, "angle", sTmp );
	// empty array of children
	region_startpoint->pData = new CPtrArray;
}
Beispiel #5
0
/*!\todo Possibly make the import Undo-friendly by calling Undo_End for new brushes and ents */
void Map_ImportEntities( CPtrArray *ents, bool bAddSelected = false ){
	int num_ents, num_brushes;
	CPtrArray *brushes;
	vec3_t mins, maxs;
	entity_t *e;
	brush_t *b;
	face_t *f;
	int i,j;

	GPtrArray *new_ents = g_ptr_array_new();

	g_qeglobals.bPrimitBrushes = false;

	brush_t *pBrushList = ( bAddSelected ) ? &selected_brushes : &active_brushes;

	bool bDoneBPCheck = false;
	g_qeglobals.bNeedConvert = false;
	// HACK: find out if this map file was a BP one
	// check the first brush in the file that is NOT a patch
	// this will not be necessary when we allow both formats in the same file
	num_ents = ents->GetSize();
	for ( i = 0; !bDoneBPCheck && i < num_ents; i++ )
	{
		e = (entity_t*)ents->GetAt( i );
		brushes = (CPtrArray*)e->pData;
		num_brushes = brushes->GetSize();
		for ( j = 0; !bDoneBPCheck && j < num_brushes; j++ )
		{
			/*!todo Allow mixing texdef formats per-face. */
			b = (brush_t *)brushes->GetAt( j );
			if ( b->patchBrush ) {
				continue;
			}
			bDoneBPCheck = true;
			int BP_param = -1;
			if ( b->bBrushDef && !g_qeglobals.m_bBrushPrimitMode ) {
				BP_param = 0;
			}
			else if ( !b->bBrushDef && g_qeglobals.m_bBrushPrimitMode ) {
				BP_param = 1;
			}

			if ( BP_param != -1 ) {
				switch ( BP_MessageBox( BP_param ) )
				{
				case 0:
					Map_FreeEntities( ents );
					return;
				case 1:
					g_qeglobals.bNeedConvert = true;
					break;
				case 2:
					g_qeglobals.bNeedConvert = false;
					break;
				}
			}
		}
	}

	// process the entities into the world geometry
	num_ents = ents->GetSize();
	for ( i = 0; i < num_ents; i++ )
	{
		num_brushes = 0;
		e = (entity_t*)ents->GetAt( i );
		brushes = (CPtrArray*)e->pData;

		num_brushes = brushes->GetSize();
		// link brushes into entity
		for ( j = 0; j < num_brushes; j++ )
		{
			Entity_LinkBrush( e, (brush_t *)brushes->GetAt( j ) );
			g_qeglobals.d_parsed_brushes++;
		}
		brushes->RemoveAll();
		delete brushes;
		e->pData = NULL;

		// set entity origin
		GetVectorForKey( e, "origin", e->origin );
		// set entity eclass
		/*!\todo Make SetKeyValue check for "classname" change and assign appropriate eclass */
		e->eclass = Eclass_ForName( ValueForKey( e, "classname" ),
									( e->brushes.onext != &e->brushes ) );

		// go through all parsed brushes and build stuff
		for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
		{
			for ( f = b->brush_faces; f != NULL; f = f->next )
			{
				f->pShader = QERApp_Shader_ForName( f->texdef.GetName() );
				f->d_texture = f->pShader->getTexture();
			}

			// when brushes are in final state, build the planes and windings
			// NOTE: also converts BP brushes if g_qeglobals.bNeedConvert is true
			Brush_Build( b );
		}

//#define TERRAIN_HACK
#undef TERRAIN_HACK

#ifdef TERRAIN_HACK
		if ( ( strcmp( ValueForKey( e, "terrain" ),"1" ) == 0 && strcmp( e->eclass->name,"func_group" ) == 0 ) ) {

			// two aux pointers to the shaders used in the terrain entity
			// we don't keep refcount on them since they are only temporary
			// this avoids doing expensive lookups by name for all faces
			IShader *pTerrainShader, *pCaulk;

			pTerrainShader = NULL;
			pCaulk = QERApp_Shader_ForName( SHADER_CAULK );

			for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
			{
				if ( pTerrainShader == NULL ) {
					for ( f = b->brush_faces; f != NULL; f = f->next )
						if ( strcmp( f->texdef.GetName(), SHADER_CAULK ) != 0 ) {
							pTerrainShader = f->pShader;
						}
				}

				if ( pTerrainShader ) {
					for ( f = b->brush_faces; f != NULL; f = f->next )
					{
						if ( strcmp( f->texdef.GetName(), SHADER_CAULK ) != 0 ) { // not caulk
							Face_SetShader( f, pTerrainShader->getName() );
						}
						else{
							Face_SetShader( f, pCaulk->getName() );
						}
					}
				}
				else{
					Sys_FPrintf( SYS_WRN, "WARNING: no terrain shader found for brush\n" );
				}
			}
		}
#endif

#define PATCH_HACK
#ifdef PATCH_HACK
		for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
		{
			// patch hack, to be removed when dependency on brush_faces is removed
			if ( b->patchBrush ) {
				Patch_CalcBounds( b->pPatch, mins, maxs );
				for ( int i = 0; i < 3; i++ )
				{
					if ( (int)mins[i] == (int)maxs[i] ) {
						mins[i] -= 4;
						maxs[i] += 4;
					}
				}
				Brush_Resize( b, mins, maxs );
				Brush_Build( b );
			}
		}
#endif
		// add brush for fixedsize entity
		if ( e->eclass->fixedsize ) {
			vec3_t mins, maxs;
			VectorAdd( e->eclass->mins, e->origin, mins );
			VectorAdd( e->eclass->maxs, e->origin, maxs );
			b = Brush_Create( mins, maxs, &e->eclass->texdef );
			Entity_LinkBrush( e, b );
			Brush_Build( b );
		}

		for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
			Brush_AddToList( b, pBrushList );

		if ( strcmp( e->eclass->name, "worldspawn" ) == 0 ) {
			if ( world_entity ) {
				while ( e->brushes.onext != &e->brushes )
				{
					b = e->brushes.onext;
					Entity_UnlinkBrush( b );
					Entity_LinkBrush( world_entity, b );
				}
				Entity_Free( e );
			}
			else
			{
				world_entity = e;
			}
		}
		else if ( strcmp( e->eclass->name, "group_info" ) == 0 ) {
			// it's a group thing!
			Group_Add( e );
			Entity_Free( e );
		}
		else
		{
			// fix target/targetname collisions
			if ( ( g_PrefsDlg.m_bDoTargetFix ) && ( strcmp( ValueForKey( e, "target" ), "" ) != 0 ) ) {
				GPtrArray *t_ents = g_ptr_array_new();
				entity_t *e_target;
				const char *target = ValueForKey( e, "target" );
				qboolean bCollision = FALSE;

				// check the current map entities for an actual collision
				for ( e_target = entities.next; e_target != &entities; e_target = e_target->next )
				{
					if ( !strcmp( target, ValueForKey( e_target, "target" ) ) ) {
						bCollision = TRUE;
						// make sure the collision is not between two imported entities
						for ( j = 0; j < (int)new_ents->len; j++ )
						{
							if ( e_target == g_ptr_array_index( new_ents, j ) ) {
								bCollision = FALSE;
							}
						}
					}
				}

				// find the matching targeted entity(s)
				if ( bCollision ) {
					for ( j = num_ents - 1; j > 0; j-- )
					{
						e_target = (entity_t*)ents->GetAt( j );
						if ( e_target != NULL && e_target != e ) {
							const char *targetname = ValueForKey( e_target, "targetname" );
							if ( ( targetname != NULL ) && ( strcmp( target, targetname ) == 0 ) ) {
								g_ptr_array_add( t_ents, (gpointer)e_target );
							}
						}
					}
					if ( t_ents->len > 0 ) {
						// link the first to get a unique target/targetname
						Entity_Connect( e, (entity_t*)g_ptr_array_index( t_ents,0 ) );
						// set the targetname of the rest of them manually
						for ( j = 1; j < (int)t_ents->len; j++ )
							SetKeyValue( (entity_t*)g_ptr_array_index( t_ents, j ), "targetname", ValueForKey( e, "target" ) );
					}
					g_ptr_array_free( t_ents, FALSE );
				}
			}

			// add the entity to the end of the entity list
			Entity_AddToList( e, &entities );
			g_qeglobals.d_num_entities++;

			// keep a list of ents added to avoid testing collisions against them
			g_ptr_array_add( new_ents, (gpointer)e );
		}
	}
	g_ptr_array_free( new_ents, FALSE );

	ents->RemoveAll();

	g_qeglobals.bNeedConvert = false;
}
//
// =======================================================================================================================
//    CreateEntity Creates a new entity based on the currently selected brush and entity type.
// =======================================================================================================================
//
void CEntityDlg::CreateEntity() {
    entity_t	*petNew;
    bool		forceFixed = false;

    // check to make sure we have a brush
    CXYWnd	*pWnd = g_pParentWnd->ActiveXY();
    if (pWnd) {
        CRect	rctZ;
        pWnd->GetClientRect(rctZ);

        brush_t *pBrush;
        if (selected_brushes.next == &selected_brushes) {
            pBrush = CreateEntityBrush(g_nSmartX, rctZ.Height() - 1 - g_nSmartY, pWnd);
            forceFixed = true;
        }
    }
    else {
        if (selected_brushes.next == &selected_brushes) {
            MessageBox("You must have a selected brush to create an entity", "info", 0);
            return;
        }
    }

    int index = comboClass.GetCurSel();
    if (index == LB_ERR) {
        MessageBox("You must have a selected class to create an entity", "info", 0);
        return;
    }

    CString str;
    comboClass.GetLBText(index, str);

    if (!stricmp(str, "worldspawn")) {
        MessageBox("Can't create an entity with worldspawn.", "info", 0);
        return;
    }

    eclass_t *pecNew = Eclass_ForName (str, false);

    // create it
    if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
        // MAJOR hack for xian
        extern void Brush_CopyList(brush_t *pFrom, brush_t *pTo);
        brush_t temp_brushes;
        temp_brushes.next = &temp_brushes;
        Brush_CopyList(&selected_brushes, &temp_brushes);
        Select_Deselect();
        brush_t *pBrush = temp_brushes.next;
        while (pBrush != NULL && pBrush != &temp_brushes) {
            brush_t *pNext = pBrush->next;
            Brush_RemoveFromList(pBrush);
            Brush_AddToList(pBrush, &selected_brushes);
            pBrush = pNext;
            petNew = Entity_Create(pecNew, forceFixed);
            Select_Deselect();
        }
    } else if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
        Select_Ungroup();
        petNew = Entity_Create(pecNew, forceFixed);
    } else {
        petNew = Entity_Create(pecNew, forceFixed);
    }

    if (petNew == NULL) {
        MessageBox("Failed to create entity.", "info", 0);
        return;
    }

    if (selected_brushes.next == &selected_brushes) {
        editEntity = world_entity;
    }
    else {
        editEntity = selected_brushes.next->owner;
    }

    SetKeyValPairs();
    Select_Deselect();
    Select_Brush(editEntity->brushes.onext);
    Sys_UpdateWindows(W_ALL);
}
void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity)
{
	entity_t *pe;
	eclass_t *e;
	brush_t		*b;
	vec3_t mins,maxs;
	bool has_brushes;
	for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
	{
		if (vpEntity == m_EntityHandles.GetAt(i))
		{
			m_EntityHandles.RemoveAt(i);
			pe = reinterpret_cast<entity_t*>(vpEntity);
			// fill additional fields
			// straight copy from Entity_Parse
			// entity_t::origin
			GetVectorForKey (pe, "origin", pe->origin);
			// entity_t::eclass
			if (pe->brushes.onext == &pe->brushes)
				has_brushes = false;
			else
				has_brushes = true;
			e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
			pe->eclass = e;
			// fixedsize
			if (e->fixedsize)
			{
				if (pe->brushes.onext != &pe->brushes)
				{
					Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
				}
				// create a custom brush
				VectorAdd(e->mins, pe->origin, mins);
				VectorAdd(e->maxs, pe->origin, maxs);
				float a = 0;
				if (e->nShowFlags & ECLASS_MISCMODEL)
				{
					char* p = ValueForKey(pe, "model");
					if (p != NULL && strlen(p) > 0)
					{
						vec3_t vMin, vMax;
						a = FloatForKey (pe, "angle");
				        if (GetCachedModel(pe, p, vMin, vMax))
				        {
						      // create a custom brush
						      VectorAdd (pe->md3Class->mins, pe->origin, mins);
						      VectorAdd (pe->md3Class->maxs, pe->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, pe->origin, false);
				}

				b->owner = pe;

				b->onext = pe->brushes.onext;
				b->oprev = &pe->brushes;
				pe->brushes.onext->oprev = b;
				pe->brushes.onext = b;
			}
			else
			{	// brush entity
				if (pe->brushes.next == &pe->brushes)
					Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
			}

			// add brushes to the active brushes list
			// and build them along the way
			for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
			{
				// convert between old brushes and brush primitive
				if (g_qeglobals.m_bBrushPrimitMode)
				{
					// we only filled the shift scale rot fields, needs conversion
					Brush_Build( b, true, true, true );
				}
				else
				{
					// we are using old brushes
					Brush_Build( b );
				}
				b->next = active_brushes.next;
				active_brushes.next->prev = b;
				b->prev = &active_brushes;
				active_brushes.next = b;
			}

			// handle worldspawn entities
			// if worldspawn has no brushes, use the new one
			if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
			{
				if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
				{
					// worldspawn already has brushes
					Sys_Printf ("Commiting worldspawn as func_group\n");
					SetKeyValue(pe, "classname", "func_group");
					// add the entity to the end of the entity list
					pe->next = &entities;
					pe->prev = entities.prev;
					entities.prev->next = pe;
					entities.prev = pe;
					g_qeglobals.d_num_entities++;
				}
				else
				{
					// there's a worldspawn with no brushes, we assume the map is empty
					if ( world_entity )
					{
						Entity_Free( world_entity );
						world_entity = pe;
					}
					else
						Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
				}
			}
			else
			{
				// add the entity to the end of the entity list
				pe->next = &entities;
				pe->prev = entities.prev;
				entities.prev->next = pe;
				entities.prev = pe;
				g_qeglobals.d_num_entities++;
			}
		}
	}
}
void CreateEntity(void)
{
	eclass_t *pecNew;
	entity_t *petNew;
	int i;
	HWND hwnd;
	char sz[1024];

	// check to make sure we have a brush

	if (selected_brushes.next == &selected_brushes)
	{
	    MessageBox(g_qeglobals.d_hwndMain, "You must have a selected brush to create an entity"
			, "info", 0);
		return;
	}


	// find out what type of entity we are trying to create

	hwnd = hwndEnt[EntList];

	i = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0);

	if (i < 0)
	{
	    MessageBox(g_qeglobals.d_hwndMain, "You must have a selected class to create an entity"
			, "info", 0);
		return;
	}

	SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz);

	if (!stricmp(sz, "worldspawn"))
	{
	    MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0);
		return;
	}

	pecNew = Eclass_ForName(sz, false);

	// create it

	petNew = Entity_Create(pecNew);

	if (petNew == NULL)
	{
	    MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0);
		return;
	}

	if (selected_brushes.next == &selected_brushes)
		edit_entity = world_entity;
	else
		edit_entity = selected_brushes.next->owner;

	SetKeyValuePairs();
	Select_Deselect ();
	Select_Brush (edit_entity->brushes.onext);
  Sys_UpdateWindows(W_ALL);

}
entity_t *Entity_PostParse(entity_t *ent, brush_t *pList)
{
    bool		has_brushes;
    eclass_t	*e;
    brush_t		*b;
    idVec3		mins, maxs, zero;
    idBounds bo;

    zero.Zero();

    Entity_SetCurveData( ent );

    if (ent->brushes.onext == &ent->brushes)
    {
        has_brushes = false;
    }
    else
    {
        has_brushes = true;
    }

    bool needsOrigin = !GetVectorForKey(ent, "origin", ent->origin);
    const char	*pModel = ValueForKey(ent, "model");

    const char *cp = ValueForKey(ent, "classname");

    if (strlen(cp))
    {
        e = Eclass_ForName(cp, has_brushes);
    }
    else
    {
        const char *cp2 = ValueForKey(ent, "name");
        if (strlen(cp2))
        {
            char buff[1024];
            strcpy(buff, cp2);
            int len = strlen(buff);
            while ((isdigit(buff[len-1]) || buff[len-1] == '_') && len > 0)
            {
                buff[len-1] = '\0';
                len--;
            }
            e = Eclass_ForName(buff, has_brushes);
            SetKeyValue(ent, "classname", buff, false);
        }
        else
        {
            e = Eclass_ForName("", has_brushes);
        }
    }

    idStr str;

    if (e->defArgs.GetString("model", "", str) && e->entityModel == NULL)
    {
        e->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &e->defArgs );
    }

    ent->eclass = e;

    bool hasModel = EntityHasModel(ent);

    if (hasModel)
    {
        ent->eclass->defArgs.GetString("model", "", str);
        if (str.Length())
        {
            hasModel = false;
            ent->epairs.Delete("model");
        }
    }

    if (e->nShowFlags & ECLASS_WORLDSPAWN)
    {
        ent->origin.Zero();
        needsOrigin = false;
        ent->epairs.Delete( "model" );
    }
    else if (e->nShowFlags & ECLASS_LIGHT)
    {
        if (GetVectorForKey(ent, "light_origin", ent->lightOrigin))
        {
            GetMatrixForKey(ent, "light_rotation", ent->lightRotation);
            ent->trackLightOrigin = true;
        }
        else if (hasModel)
        {
            SetKeyValue(ent, "light_origin", ValueForKey(ent, "origin"));
            ent->lightOrigin = ent->origin;
            if (GetMatrixForKey(ent, "rotation", ent->lightRotation))
            {
                SetKeyValue(ent, "light_rotation", ValueForKey(ent, "rotation"));
            }
            ent->trackLightOrigin = true;
        }
    }
    else if ( e->nShowFlags & ECLASS_ENV )
    {
        // need to create an origin from the bones here
        idVec3 org;
        idAngles ang;
        bo.Clear();
        bool hasBody = false;
        const idKeyValue *arg = ent->epairs.MatchPrefix( "body ", NULL );
        while ( arg )
        {
            sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll );
            bo.AddPoint( org );
            arg = ent->epairs.MatchPrefix( "body ", arg );
            hasBody = true;
        }
        if (hasBody)
        {
            ent->origin = bo.GetCenter();
        }
    }

    if (e->fixedsize || hasModel)  			// fixed size entity
    {
        if (ent->brushes.onext != &ent->brushes)
        {
            for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext)
            {
                b->entityModel = true;
            }
        }

        if (hasModel)
        {
            // model entity
            idRenderModel *modelHandle = renderModelManager->FindModel( pModel );

            if ( dynamic_cast<idRenderModelPrt*>( modelHandle ) || dynamic_cast<idRenderModelLiquid*>( modelHandle ) )
            {
                bo.Zero();
                bo.ExpandSelf( 12.0f );
            }
            else
            {
                bo = modelHandle->Bounds( NULL );
            }

            VectorCopy(bo[0], mins);
            VectorCopy(bo[1], maxs);
            for (int i = 0; i < 3; i++)
            {
                if (mins[i] == maxs[i])
                {
                    mins[i]--;
                    maxs[i]++;
                }
            }
            VectorAdd(mins, ent->origin, mins);
            VectorAdd(maxs, ent->origin, maxs);
            b = Brush_Create(mins, maxs, &e->texdef);
            b->modelHandle = modelHandle;

            float		yaw = 0;
            bool		convertAngles = GetFloatForKey(ent, "angle", &yaw);
            extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild);
            extern void Brush_Rotate(brush_t *b, idVec3 rot, idVec3 origin, bool bBuild);

            if (convertAngles)
            {
                idVec3	rot(0, 0, yaw);
                Brush_Rotate(b, rot, ent->origin, false);
            }

            if (GetMatrixForKey(ent, "rotation", ent->rotation))
            {
                idBounds bo2;
                bo2.FromTransformedBounds(bo, ent->origin, ent->rotation);
                b->owner = ent;
                Brush_Resize(b, bo2[0], bo2[1]);
            }
            Entity_LinkBrush(ent, b);
        }

        if (!hasModel || (ent->eclass->nShowFlags & ECLASS_LIGHT && hasModel))
        {
            // create a custom brush
            if (ent->trackLightOrigin)
            {
                mins = e->mins + ent->lightOrigin;
                maxs = e->maxs + ent->lightOrigin;
            }
            else
            {
                mins = e->mins + ent->origin;
                maxs = e->maxs + ent->origin;
            }

            b = Brush_Create(mins, maxs, &e->texdef);
            GetMatrixForKey(ent, "rotation", ent->rotation);
            Entity_LinkBrush(ent, b);
            b->trackLightOrigin = ent->trackLightOrigin;
            if ( e->texdef.name == NULL )
            {
                brushprimit_texdef_t bp;
                texdef_t td;
                td.SetName( ent->eclass->defMaterial );
                Brush_SetTexture( b, &td, &bp, false );
            }
        }
    }
    else  	// brush entity
    {
        if (ent->brushes.next == &ent->brushes)
        {
            printf("Warning: Brush entity with no brushes\n");
        }

        if (!needsOrigin)
        {
            idStr cn = ValueForKey(ent, "classname");
            idStr name = ValueForKey(ent, "name");
            idStr model = ValueForKey(ent, "model");
            if (cn.Icmp("func_static") == 0)
            {
                if (name.Icmp(model) == 0)
                {
                    needsOrigin = true;
                }
            }
        }

        if (needsOrigin)
        {
            idVec3	mins, maxs, mid;
            int		i;
            char	text[32];
            mins[0] = mins[1] = mins[2] = 999999;
            maxs[0] = maxs[1] = maxs[2] = -999999;

            // add in the origin
            for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext)
            {
                Brush_Build(b, true, false, false);
                for (i = 0; i < 3; i++)
                {
                    if (b->mins[i] < mins[i])
                    {
                        mins[i] = b->mins[i];
                    }

                    if (b->maxs[i] > maxs[i])
                    {
                        maxs[i] = b->maxs[i];
                    }
                }
            }

            for (i = 0; i < 3; i++)
            {
                ent->origin[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
            }

            sprintf(text, "%i %i %i", (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
            SetKeyValue(ent, "origin", text);
        }

        if (!(e->nShowFlags & ECLASS_WORLDSPAWN))
        {
            if (e->defArgs.FindKey("model") == NULL && (pModel == NULL || (pModel && strlen(pModel) == 0)))
            {
                SetKeyValue(ent, "model", ValueForKey(ent, "name"));
            }
        }
        else
        {
            DeleteKey(ent, "origin");
        }
    }

    // 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;
        }
    }

    FixFloats(&ent->epairs);

    return ent;

}
Beispiel #10
0
/*
================
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;
#ifdef SOF
	float		scale;
#endif

	if (!GetToken (true))
		return NULL;

	if (strcmp (token, "{") )
		Error ("ParseEntity: { not found");
	
	ent = (entity_t*)qmalloc (sizeof(*ent));
	ent->brushes.onext = ent->brushes.oprev = &ent->brushes;

	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 ();
			{
				// update: the original code here may have been simple, but it meant that every map load/save
				//	the key/value pair fields were reversed in the save file, which messes up SourceSafe when it
				//	tries to delta the two versions during check-in... -slc
#if 0
				ep->next = ent->epairs;
				ent->epairs = ep;
#else
				// join this onto the END of the chain instead...
				//
				if (ent->epairs == NULL)	// special case for if there isn't a chain yet... :-)
				{
					ep->next = ent->epairs;
					ent->epairs = ep;
				}
				else
				{						
					for (epair_t* ep2 = ent->epairs ; ep2 ; ep2=ep2->next)
					{
						if (ep2->next == NULL)
						{
							// found the end, so...
							//
							ep2->next = ep;							
							ep->next = NULL;
							break;
						}
					}
				}
#endif
			}
		}
	} while (1);

	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->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 (strnicmp(e->name, "misc_model",10) == 0)
    {
      char* p = ValueForKey(ent, "model");
      if (p != NULL && strlen(p) > 0)
      {
        vec3_t vMin, vMax;
        a = FloatForKey (ent, "angle");
		gEntityToSetBoundsOf = ent;
        if (GetCachedModel(ent, p, vMin, vMax))
        {
	      // create a custom brush
	      VectorAdd (ent->md3Class->mins, ent->origin, mins);
	      VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
        }
      }
    }
#ifdef SOF
	if (strnicmp(e->name, "misc_",			5) == 0 ||
		strnicmp(e->name, "light_",			6) == 0 ||
		strnicmp(e->name, "m_",				2) == 0 ||
		strnicmp(e->name, "item_weapon_",	12)== 0 ||
		strnicmp(e->name, "item_ammo_",		10)== 0
		)
		a = FloatForKey (ent, "angle");
#endif		
		b = Brush_Create (mins, maxs, &e->texdef);
///////
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
///////
		Brush_Build(b);

#ifdef SOF
		scale = FloatForKey (ent, "scale");
		if (scale)
		{
		  Brush_Scale2(e, b, scale, ent->origin,false);
		}
#endif

//		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;
*/
		// do this AFTER doing the brush stuff just above, so don't join to the other "if (a)"...
		//
		if (a)
		{
			// pick any old value to rotate away to, then back from, to avoid 0/360 weirdness on key-compares
			//
			SetKeyValue(ent, "angle", "0",			false);	// false = no tracking, ie just set the angle and nothing else			
			SetKeyValue(ent, "angle", va("%g",a),	true);	// true = do tracking, ie actually do the brush rotate
		}
	}
	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;
}