Пример #1
0
/*
============
Select_Brush

============
*/
void Select_Brush( brush_s* brush, bool bComplete, bool bStatus )
{
	brush_s*    b;
	entity_s*   e;
	
	g_ptrSelectedFaces.RemoveAll();
	g_ptrSelectedFaceBrushes.RemoveAll();
	//selected_face = NULL;
	if ( g_qeglobals.d_select_count < 2 )
		g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush;
	g_qeglobals.d_select_count++;
	
	//if (brush->patchBrush)
	//  Patch_Select(brush->nPatchID);
	
	e = brush->owner;
	if ( e )
	{
		// select complete entity on first click
		if ( e != world_entity && bComplete == true )
		{
			for ( b = selected_brushes.next ; b != &selected_brushes ; b = b->next )
				if ( b->owner == e )
					goto singleselect;
			for ( b = e->brushes.onext ; b != &e->brushes ; b = b->onext )
			{
				Brush_RemoveFromList( b );
				Brush_AddToList( b, &selected_brushes );
			}
		}
		else
		{
singleselect:
			Brush_RemoveFromList( brush );
			Brush_AddToList( brush, &selected_brushes );
			UpdateSurfaceDialog();
			UpdatePatchInspector();
		}
		
		if ( e->eclass )
		{
			UpdateEntitySel( brush->owner->eclass );
		}
	}
	if ( bStatus )
	{
		edVec3_c vMin, vMax, vSize;
		Select_GetBounds( vMin, vMax );
		vSize = vMax - vMin;
		CString strStatus;
		strStatus.Format( "Selection X:: %.1f  Y:: %.1f  Z:: %.1f", vSize[0], vSize[1], vSize[2] );
		g_pParentWnd->SetStatusText( 2, strStatus );
	}
}
Пример #2
0
void Select_Inside( void )
{
	brush_s*    b, *next;
	int     i;
	edVec3_c    mins, maxs;
	
	if ( !QE_SingleBrush() )
		return;
		
	clearSelection();
	
	mins = selected_brushes.next->getMins();
	maxs = selected_brushes.next->getMaxs();
	Select_Delete();
	
	for ( b = active_brushes.next ; b != &active_brushes ; b = next )
	{
		next = b->next;
		
		if ( FilterBrush( b ) )
			continue;
			
		for ( i = 0 ; i < 3 ; i++ )
			if ( b->getMaxs()[i] > maxs[i] || b->getMins()[i] < mins[i] )
				break;
		if ( i == 3 )
		{
			Brush_RemoveFromList( b );
			Brush_AddToList( b, &selected_brushes );
		}
	}
	Sys_UpdateWindows( W_ALL );
}
Пример #3
0
/*	Turn the currently selected entity back into normal brushes
*/
void  Select_Ungroup (void)
{
	entity_t	*e;
	brush_t		*b;

	e = selected_brushes.next->owner;

	if (!e || e == world_entity || e->eclass->fixedsize)
	{
		Sys_Status ("Not a grouped entity.", 0);
		return;
	}

	for (b=e->brushes.onext ; b != &e->brushes ; b=e->brushes.onext)
	{
		Brush_RemoveFromList (b);
		Brush_AddToList (b, &active_brushes);
		Entity_UnlinkBrush (b);
		Entity_LinkBrush (world_entity, b);
		Brush_Build( b );
		b->owner = world_entity;
	}

	Entity_Free (e);
	Sys_UpdateWindows (W_ALL);
}
Пример #4
0
void Select_Inside (void)
{
	brush_t	*b, *next;
	int		i;
	vec3_t	mins, maxs;

	if (!QE_SingleBrush ())
		return;

	g_qeglobals.d_select_mode = sel_brush;

	Math_VectorCopy (selected_brushes.next->mins, mins);
	Math_VectorCopy (selected_brushes.next->maxs, maxs);

	Select_Delete ();

	for (b=active_brushes.next ; b != &active_brushes ; b=next)
	{
		next = b->next;
		for (i=0 ; i<3 ; i++)
			if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i])
				break;
		if (i == 3)
		{
			Brush_RemoveFromList (b);
			Brush_AddToList (b, &selected_brushes);
		}
	}
	Sys_UpdateWindows (W_ALL);
}
Пример #5
0
/*	Frees the brush with all of its faces and display list.
	Unlinks the brush from whichever chain it is in.
	Decrements the owner entity's brushcount.
	Removes owner entity if this was the last brush
	unless owner is the world.
*/
void Brush_Free (brush_t *b)
{
	face_t	*f, *next;

	// free faces
	for (f=b->brush_faces ; f ; f=next)
	{
		next = f->next;
		Face_Free( f );
	}

	/*
	for ( i = 0; i < b->d_numwindings; i++ )
	{
		if ( b->d_windings[i] )
		{
			FreeWinding( b->d_windings[i] );
			b->d_windings[i] = 0;
		}
	}
	*/

	// unlink from active/selected list
	if (b->next)
		Brush_RemoveFromList (b);

	// unlink from entity list
	if (b->onext)
		Entity_UnlinkBrush (b);

	free (b);
}
Пример #6
0
/*
   ===========
   Map_RegionOff

   Other filtering options may still be on
   ===========
 */
void Map_RegionOff( void ){
	brush_t *b, *next;
	int i;

	region_active = false;
	for ( i = 0 ; i < 3 ; i++ )
	{
		region_maxs[i] = g_MaxWorldCoord - 64;
		region_mins[i] = g_MinWorldCoord + 64;
	}

	for ( b = filtered_brushes.next ; b != &filtered_brushes ; b = next )
	{
		next = b->next;
		if ( Map_IsBrushFiltered( b ) ) {
			continue;       // still filtered
		}
		Brush_RemoveFromList( b );
		if ( active_brushes.next == NULL || active_brushes.prev == NULL ) {
			active_brushes.next = &active_brushes;
			active_brushes.prev = &active_brushes;
		}
		Brush_AddToList( b, &active_brushes );
		b->bFiltered = FilterBrush( b );
	}
	Sys_UpdateWindows( W_ALL );
}
Пример #7
0
/*
============
Select_Ray

If the origin is inside a brush, that brush will be ignored.
============
*/
void Select_Ray (vec3_t origin, vec3_t dir, int flags)
{
	trace_t	t;

	t = Test_Ray (origin, dir, flags);
	if (!t.brush)
		return;

	if (flags == SF_SINGLEFACE)
	{
		selected_face = t.face;
		selected_face_brush = t.brush;
		Sys_UpdateWindows (W_ALL);
		g_qeglobals.d_select_mode = sel_brush;
		Texture_SetTexture (&t.face->texdef);
    UpdateSurfaceDialog();
		return;
	}

	// move the brush to the other list

	g_qeglobals.d_select_mode = sel_brush;

	if (t.selected)
	{		
		Brush_RemoveFromList (t.brush);
		Brush_AddToList (t.brush, &active_brushes);
	} else
	{
		Select_Brush (t.brush, !(GetKeyState(VK_MENU) & 0x8000));
	}

	Sys_UpdateWindows (W_ALL);
}
Пример #8
0
void Select_Touching (void)
{
	brush_t	*b, *next;
	int		i;
	vec3_t	mins, maxs;

	if (!QE_SingleBrush ())
		return;

	g_qeglobals.d_select_mode = sel_brush;

	VectorCopy (selected_brushes.next->mins, mins);
	VectorCopy (selected_brushes.next->maxs, maxs);

	for (b=active_brushes.next ; b != &active_brushes ; b=next)
	{
		next = b->next;

	 	if (FilterBrush (b))
	 		continue;

		for (i=0 ; i<3 ; i++)
			if (b->mins[i] > maxs[i]+1 || b->maxs[i] < mins[i]-1)
				break;

		if (i == 3)
		{
			Brush_RemoveFromList (b);
			Brush_AddToList (b, &selected_brushes);
		}
	}
	Sys_UpdateWindows (W_ALL);
}
Пример #9
0
/*
 =======================================================================================================================
	Map_RegionOff Other filtering options may still be on
 =======================================================================================================================
 */
void Map_RegionOff(void) {
	brush_t *b, *next;
	int		i;

	region_active = false;
	for (i = 0; i < 3; i++) {
		region_maxs[i] = MAX_WORLD_COORD;	// 4096;
		region_mins[i] = MIN_WORLD_COORD;	// -4096;
	}

	for (b = filtered_brushes.next; b != &filtered_brushes; b = next) {
		next = b->next;
		if (Map_IsBrushFiltered(b)) {
			continue;						// still filtered
		}

		Brush_RemoveFromList(b);
		if (active_brushes.next == NULL || active_brushes.prev == NULL) {
			active_brushes.next = &active_brushes;
			active_brushes.prev = &active_brushes;
		}

		Brush_AddToList(b, &active_brushes);
	}

	Sys_UpdateWindows(W_ALL);
}
Пример #10
0
void Select_PartialTall( void )
{
	brush_s*    b, *next;
	//int       i;
	edVec3_c    mins, maxs;
	
	if ( !QE_SingleBrush() )
		return;
		
	clearSelection();
	
	mins = selected_brushes.next->getMins();
	maxs = selected_brushes.next->getMaxs();
	Select_Delete();
	
	int nDim1 = ( g_pParentWnd->ActiveXY()->GetViewType() == YZ ) ? 1 : 0;
	int nDim2 = ( g_pParentWnd->ActiveXY()->GetViewType() == XY ) ? 1 : 2;
	
	for ( b = active_brushes.next ; b != &active_brushes ; b = next )
	{
		next = b->next;
		
		if ( ( b->getMins()[nDim1] > maxs[nDim1] || b->getMaxs()[nDim1] < mins[nDim1] )
				|| ( b->getMins()[nDim2] > maxs[nDim2] || b->getMaxs()[nDim2] < mins[nDim2] ) )
			continue;
			
		if ( FilterBrush( b ) )
			continue;
			
		Brush_RemoveFromList( b );
		Brush_AddToList( b, &selected_brushes );
		
		
#if 0
		// old stuff
		for ( i = 0 ; i < 2 ; i++ )
			if ( b->mins[i] > maxs[i] || b->maxs[i] < mins[i] )
				break;
		if ( i == 2 )
		{
			Brush_RemoveFromList( b );
			Brush_AddToList( b, &selected_brushes );
		}
#endif
	}
	Sys_UpdateWindows( W_ALL );
}
Пример #11
0
void Select_CompleteTall (void)
{
	brush_t	*b, *next;
	//int		i;
	vec3_t	mins, maxs;

	if (!QE_SingleBrush ())
		return;

	g_qeglobals.d_select_mode = sel_brush;

	VectorCopy (selected_brushes.next->mins, mins);
	VectorCopy (selected_brushes.next->maxs, maxs);
	Select_Delete ();

  int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
  int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;

	for (b=active_brushes.next ; b != &active_brushes ; b=next)
	{
		next = b->next;

    if ( (b->maxs[nDim1] > maxs[nDim1] || b->mins[nDim1] < mins[nDim1]) 
      || (b->maxs[nDim2] > maxs[nDim2] || b->mins[nDim2] < mins[nDim2]) )
      continue;

	 	if (FilterBrush (b))
	 		continue;

		Brush_RemoveFromList (b);
		Brush_AddToList (b, &selected_brushes);
#if 0
    // old stuff
    for (i=0 ; i<2 ; i++)
			if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i])
				break;
		if (i == 2)
		{
			Brush_RemoveFromList (b);
			Brush_AddToList (b, &selected_brushes);
		}
#endif
	}
	Sys_UpdateWindows (W_ALL);
}
Пример #12
0
void SelectBrush (int entitynum, int brushnum)
{
	entity_t	*e;
	brush_t		*b;
	int			i;

	if (entitynum == 0)
		e = world_entity;
	else
	{
		e = entities.next;
		while (--entitynum)
		{
			e=e->next;
			if (e == &entities)
			{
				Sys_Status ("No such entity.", 0);
				return;
			}
		}
	}

	b = e->brushes.onext;
	if (b == &e->brushes)
	{
		Sys_Status ("No such brush.", 0);
		return;
	}
	while (brushnum--)
	{
		b=b->onext;
		if (b == &e->brushes)
		{
			Sys_Status ("No such brush.", 0);
			return;
		}
	}

	Brush_RemoveFromList (b);
	Brush_AddToList (b, &selected_brushes);


	Sys_UpdateWindows (W_ALL);
	for (i=0 ; i<3 ; i++)
  {
    if (g_pParentWnd->GetXYWnd())
      g_pParentWnd->GetXYWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;

    if (g_pParentWnd->GetXZWnd())
      g_pParentWnd->GetXZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
    
    if (g_pParentWnd->GetYZWnd())
      g_pParentWnd->GetYZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
  }

	Sys_Status ("Selected.", 0);
}
Пример #13
0
/*
============
Select_Ray

If the origin is inside a brush, that brush will be ignored.
============
*/
void Select_Ray( vec3_t origin, vec3_t dir, int flags )
{
	trace_t t;
	
	t = Test_Ray( origin, dir, flags );
	if ( !t.brush )
		return;
		
	if ( flags == SF_SINGLEFACE )
	{
		int nCount = g_SelectedFaces.GetSize();
		bool bOk = true;
		for ( int i = 0; i < nCount; i++ )
		{
			if ( t.face == reinterpret_cast<face_s*>( g_SelectedFaces.GetAt( i ) ) )
			{
				bOk = false;
				// need to move remove i'th entry
				g_SelectedFaces.RemoveAt( i, 1 );
				g_SelectedFaceBrushes.RemoveAt( i, 1 );
			}
		}
		if ( bOk )
		{
			g_SelectedFaces.Add( t.face );
			g_SelectedFaceBrushes.Add( t.brush );
		}
		//selected_face = t.face;
		//selected_face_brush = t.brush;
		Sys_UpdateWindows( W_ALL );
		clearSelection();
		// Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2 height=2 texture
		brushprimit_texdef_s brushprimit_texdef;
		ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &brushprimit_texdef, NULL );
		Texture_SetTexture( &t.face->texdef, &brushprimit_texdef, false, false );
		UpdateSurfaceDialog();
		return;
	}
	
	// move the brush to the other list
	
	clearSelection();
	
	if ( t.selected )
	{
		Brush_RemoveFromList( t.brush );
		Brush_AddToList( t.brush, &active_brushes );
		UpdatePatchInspector();
	}
	else
	{
		Select_Brush( t.brush, !( GetKeyState( VK_MENU ) & 0x8000 ) );
	}
	
	Sys_UpdateWindows( W_ALL );
}
/*
 =======================================================================================================================
 =======================================================================================================================
 */
void Map_ApplyRegion( void ) {
	brush_t *b, *next;
	region_active = true;
	for( b = active_brushes.next; b != &active_brushes; b = next ) {
		next = b->next;
		if( !Map_IsBrushFiltered( b ) ) {
			continue;	// still filtered
		}
		Brush_RemoveFromList( b );
		Brush_AddToList( b, &filtered_brushes );
	}
	Sys_UpdateWindows( W_ALL );
}
Пример #15
0
void Select_Brush (brush_t *brush)
{
	brush_t	*b;
	entity_t	*e;

	selected_face = NULL;
	if (g_qeglobals.d_select_count < 2)
		g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush;
	g_qeglobals.d_select_count++;

	e = brush->owner;
	if (e)
	{
		// select complete entity on first click
		if (e != world_entity)
		{
			for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
				if (b->owner == e)
					goto singleselect;
			for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
			{
				Brush_RemoveFromList (b);
				Brush_AddToList (b, &selected_brushes);
			}
		}
		else
		{
singleselect:
			Brush_RemoveFromList (brush);
			Brush_AddToList (brush, &selected_brushes);
		}

		if (e->eclass)
			UpdateEntitySel(brush->owner->eclass);
	}
}
Пример #16
0
void SelectBrush (int entitynum, int brushnum)
{
	entity_t	*e;
	brush_t		*b;
	int			i;

	if (entitynum == 0)
		e = world_entity;
	else
	{
		e = entities.next;
		while (--entitynum)
		{
			e=e->next;
			if (e == &entities)
			{
				Sys_Printf ("No such entity.\n");
				return;
			}
		}
	}

	b = e->brushes.onext;
	if (b == &e->brushes)
	{
		Sys_Printf ("No such brush.\n");
		return;
	}
	while (brushnum--)
	{
		b=b->onext;
		if (b == &e->brushes)
		{
			Sys_Printf ("No such brush.\n");
			return;
		}
	}

	Brush_RemoveFromList (b);
	Brush_AddToList (b, &selected_brushes);


	Sys_UpdateWindows (W_ALL);
	for (i=0 ; i<3 ; i++)
		g_qeglobals.d_xyz.origin[i] = (b->mins[i] + b->maxs[i])/2;

	Sys_Printf ("Selected.\n");
}
Пример #17
0
/*	If the origin is inside a brush, that brush will be ignored.
*/
void Select_Ray (vec3_t origin, vec3_t dir, int flags)
{
	trace_t		t;

	t = Test_Ray (origin, dir, flags);
	if(!t.brush)
		return;

	if (flags == SF_SINGLEFACE)
	{
		// [12/8/2012] Don't let them select entity faces ~hogsy
		// [22/8/2012] Simplified ~hogsy
		if(t.brush->owner->eclass->fixedsize)
			return;

		selected_face		= t.face;
		selected_face_brush = t.brush;
		Sys_UpdateWindows (W_ALL);
		g_qeglobals.d_select_mode = sel_brush;

		return;
	}

	// move the brush to the other list

	g_qeglobals.d_select_mode = sel_brush;

	if (t.selected)
	{		
		Brush_RemoveFromList (t.brush);
		Brush_AddToList (t.brush, &active_brushes);
	} 
	else
		Select_Brush (t.brush);

	Sys_UpdateWindows (W_ALL);
}
Пример #18
0
/*
=============
Undo_Redo
=============
*/
void Undo_Redo(void)
{
	undo_t *redo;
	brush_t *pBrush, *pNextBrush;
	entity_t *pEntity, *pNextEntity, *pRedoEntity;

	if (!g_lastredo)
	{
		Sys_Status("Nothing left to redo.\n");
		return;
	}
	if (g_lastundo)
	{
		if (!g_lastundo->done)
		{
			Sys_Status("WARNING: last undo not finished.\n");
		}
	}
	// get the last redo
	redo = g_lastredo;
	if (g_lastredo->prev) g_lastredo->prev->next = NULL;
	else g_redolist = NULL;
	g_lastredo = g_lastredo->prev;
	//
	Undo_GeneralStart(redo->operation);
	// remove current selection
	Select_Deselect();
	// move "created" brushes back to the last undo
	for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pNextBrush)
	{
		pNextBrush = pBrush->next;
		if (pBrush->redoId == redo->id)
		{
			//move the brush to the undo
			Brush_RemoveFromList(pBrush);
			Brush_AddToList(pBrush, &g_lastundo->brushlist);
			g_undoMemorySize += Brush_MemorySize(pBrush);
			pBrush->ownerId = pBrush->owner->entityId;
			Entity_UnlinkBrush(pBrush);
		}
	}
	// move "created" entities back to the last undo
	for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
	{
		pNextEntity = pEntity->next;
		if (pEntity->redoId == redo->id)
		{
			// check if this entity is in the redo
			for (pRedoEntity = redo->entitylist.next; pRedoEntity != NULL && pRedoEntity != &redo->entitylist; pRedoEntity = pRedoEntity->next)
			{
				// move brushes to the redo entity
				if (pRedoEntity->entityId == pEntity->entityId)
				{
					pRedoEntity->brushes.next = pEntity->brushes.next;
					pRedoEntity->brushes.prev = pEntity->brushes.prev;
					pEntity->brushes.next = &pEntity->brushes;
					pEntity->brushes.prev = &pEntity->brushes;
				}
			}
			//
			//Entity_Free(pEntity);
			//move the entity to the redo
			Entity_RemoveFromList(pEntity);
			Entity_AddToList(pEntity, &g_lastundo->entitylist);
			g_undoMemorySize += Entity_MemorySize(pEntity);
		}
	}
	// add the undo entities back into the entity list
	for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = redo->entitylist.next)
	{
		//if this is the world entity
		if (pEntity->entityId == world_entity->entityId)
		{
			//free the epairs of the world entity
			Entity_FreeEpairs(world_entity);
			//set back the original epairs
			world_entity->epairs = pEntity->epairs;
			//free the world_entity clone that stored the epairs
			Entity_Free(pEntity);
		}
		else
		{
			Entity_RemoveFromList(pEntity);
			Entity_AddToList(pEntity, &entities);
		}
	}
	// add the redo brushes back into the selected brushes
	for (pBrush = redo->brushlist.next; pBrush != NULL && pBrush != &redo->brushlist; pBrush = redo->brushlist.next)
	{
		Brush_RemoveFromList(pBrush);
    	Brush_AddToList(pBrush, &active_brushes);
		for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
		{
			if (pEntity->entityId == pBrush->ownerId)
			{
				Entity_LinkBrush(pEntity, pBrush);
				break;
			}
		}
		//if the brush is not linked then it should be linked into the world entity
		if (pEntity == NULL || pEntity == &entities)
		{
			Entity_LinkBrush(world_entity, pBrush);
		}
		//build the brush
		//Brush_Build(pBrush);
		Select_Brush(pBrush);
    }
	//
	Undo_End();
	//
	common->Printf("%s redone.\n", redo->operation);
	//
	g_redoId--;
	// free the undo
	Mem_Free(redo);
	//
    g_bScreenUpdates = true; 
    Sys_UpdateWindows(W_ALL);
}
Пример #19
0
/*
=============
Undo_Undo
=============
*/
void Undo_Undo(void)
{
	undo_t *undo, *redo;
	brush_t *pBrush, *pNextBrush;
	entity_t *pEntity, *pNextEntity, *pUndoEntity;

	if (!g_lastundo)
	{
		Sys_Status("Nothing left to undo.\n");
		return;
	}
	if (!g_lastundo->done)
	{
		Sys_Status("Undo_Undo: WARNING: last undo not yet finished!\n");
	}
	// get the last undo
	undo = g_lastundo;
	if (g_lastundo->prev) g_lastundo->prev->next = NULL;
	else g_undolist = NULL;
	g_lastundo = g_lastundo->prev;

	//allocate a new redo
	redo = (undo_t *) Mem_ClearedAlloc(sizeof(undo_t), TAG_TOOLS);
	if (!redo) return;
	memset(redo, 0, sizeof(undo_t));
	redo->brushlist.next = &redo->brushlist;
	redo->brushlist.prev = &redo->brushlist;
	redo->entitylist.next = &redo->entitylist;
	redo->entitylist.prev = &redo->entitylist;
	if (g_lastredo) g_lastredo->next = redo;
	else g_redolist = redo;
	redo->prev = g_lastredo;
	redo->next = NULL;
	g_lastredo = redo;
	redo->time = Sys_DoubleTime();
	redo->id = g_redoId++;
	redo->done = true;
	redo->operation = undo->operation;

	//reset the redo IDs of all brushes using the new ID
	for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
	{
		if (pBrush->redoId == redo->id)
		{
			pBrush->redoId = 0;
		}
	}
	for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
	{
		if (pBrush->redoId == redo->id)
		{
			pBrush->redoId = 0;
		}
	}
	//reset the redo IDs of all entities using thew new ID
	for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
	{
		if (pEntity->redoId == redo->id)
		{
			pEntity->redoId = 0;
		}
	}

	// remove current selection
	Select_Deselect();
	// move "created" brushes to the redo
	for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush=pNextBrush)
	{
		pNextBrush = pBrush->next;
		if (pBrush->undoId == undo->id)
		{
			//Brush_Free(pBrush);
			//move the brush to the redo
			Brush_RemoveFromList(pBrush);
			Brush_AddToList(pBrush, &redo->brushlist);
			//make sure the ID of the owner is stored
			pBrush->ownerId = pBrush->owner->entityId;
			//unlink the brush from the owner entity
			Entity_UnlinkBrush(pBrush);
		}
	}
	// move "created" entities to the redo
	for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
	{
		pNextEntity = pEntity->next;
		if (pEntity->undoId == undo->id)
		{
			// check if this entity is in the undo
			for (pUndoEntity = undo->entitylist.next; pUndoEntity != NULL && pUndoEntity != &undo->entitylist; pUndoEntity = pUndoEntity->next)
			{
				// move brushes to the undo entity
				if (pUndoEntity->entityId == pEntity->entityId)
				{
					pUndoEntity->brushes.next = pEntity->brushes.next;
					pUndoEntity->brushes.prev = pEntity->brushes.prev;
					pEntity->brushes.next = &pEntity->brushes;
					pEntity->brushes.prev = &pEntity->brushes;
				}
			}
			//
			//Entity_Free(pEntity);
			//move the entity to the redo
			Entity_RemoveFromList(pEntity);
			Entity_AddToList(pEntity, &redo->entitylist);
		}
	}
	// add the undo entities back into the entity list
	for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = undo->entitylist.next)
	{
		g_undoMemorySize -= Entity_MemorySize(pEntity);
		//if this is the world entity
		if (pEntity->entityId == world_entity->entityId)
		{
			//free the epairs of the world entity
			Entity_FreeEpairs(world_entity);
			//set back the original epairs
			world_entity->epairs = pEntity->epairs;
			//free the world_entity clone that stored the epairs
			Entity_Free(pEntity);
		}
		else
		{
			Entity_RemoveFromList(pEntity);
			Entity_AddToList(pEntity, &entities);
			pEntity->redoId = redo->id;
		}
	}
	// add the undo brushes back into the selected brushes
	for (pBrush = undo->brushlist.next; pBrush != NULL && pBrush != &undo->brushlist; pBrush = undo->brushlist.next)
	{
		g_undoMemorySize -= Brush_MemorySize(pBrush);
		Brush_RemoveFromList(pBrush);
    	Brush_AddToList(pBrush, &active_brushes);
		for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
		{
			if (pEntity->entityId == pBrush->ownerId)
			{
				Entity_LinkBrush(pEntity, pBrush);
				break;
			}
		}
		//if the brush is not linked then it should be linked into the world entity
		if (pEntity == NULL || pEntity == &entities)
		{
			Entity_LinkBrush(world_entity, pBrush);
		}
		//build the brush
		//Brush_Build(pBrush);
		Select_Brush(pBrush);
		pBrush->redoId = redo->id;
    }
	//
	common->Printf("%s undone.\n", undo->operation);
	// free the undo
	g_undoMemorySize -= sizeof(undo_t);
	Mem_Free(undo);
	g_undoSize--;
	g_undoId--;
	if (g_undoId <= 0) g_undoId = 2 * g_undoMaxSize;
	//

	Sys_BeginWait();
	brush_t *b, *next;
	for (b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next) {
		next = b->next;
		Brush_Build( b, true, false, false );
	}
	for (b = selected_brushes.next ; b != NULL && b != &selected_brushes ; b=next) {
		next = b->next;
		Brush_Build( b, true, false, false );
	}
	Sys_EndWait();

    g_bScreenUpdates = true; 
    Sys_UpdateWindows(W_ALL);
}
Пример #20
0
/*
=============
Undo_Undo
=============
*/
void Undo_Undo(boolean bSilent)
{
	// spog - disable undo if undo levels = 0
	if (g_PrefsDlg.m_nUndoLevels == 0)
	{
		Sys_Printf("Undo_Undo: undo is disabled.\n");
		return;
	}

	undo_t *undo, *redo;
	brush_t *pBrush, *pNextBrush;
	entity_t *pEntity, *pNextEntity, *pUndoEntity;

	if (!g_lastundo)
	{
		Sys_Printf("Nothing left to undo.\n");
		return;
	}
	if (!g_lastundo->done)
	{
		Sys_Printf("Undo_Undo: WARNING: last undo not yet finished!\n");
	}
	// get the last undo
	undo = g_lastundo;
	if (g_lastundo->prev) g_lastundo->prev->next = NULL;
	else g_undolist = NULL;
	g_lastundo = g_lastundo->prev;

	//allocate a new redo
	redo = (undo_t *) malloc(sizeof(undo_t));
	if (!redo) return;
	memset(redo, 0, sizeof(undo_t));
	redo->brushlist.next = &redo->brushlist;
	redo->brushlist.prev = &redo->brushlist;
	redo->entitylist.next = &redo->entitylist;
	redo->entitylist.prev = &redo->entitylist;
	if (g_lastredo) g_lastredo->next = redo;
	else g_redolist = redo;
	redo->prev = g_lastredo;
	redo->next = NULL;
	g_lastredo = redo;
	redo->time = Sys_DoubleTime();
	redo->id = g_redoId++;
	redo->done = true;
	redo->operation = undo->operation;

	//reset the redo IDs of all brushes using the new ID
	for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
	{
		if (pBrush->redoId == redo->id)
		{
			pBrush->redoId = 0;
		}
	}
	for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
	{
		if (pBrush->redoId == redo->id)
		{
			pBrush->redoId = 0;
		}
	}
	//reset the redo IDs of all entities using thew new ID
	for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
	{
		if (pEntity->redoId == redo->id)
		{
			pEntity->redoId = 0;
		}
	}

	// deselect current sutff
	Select_Deselect();
	// move "created" brushes to the redo
	for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush=pNextBrush)
	{
		pNextBrush = pBrush->next;
		if (pBrush->undoId == undo->id)
		{
			//Brush_Free(pBrush);
			//move the brush to the redo
			Brush_RemoveFromList(pBrush);
			Brush_AddToList(pBrush, &redo->brushlist);
			//make sure the ID of the owner is stored
			pBrush->ownerId = pBrush->owner->entityId;
			//unlink the brush from the owner entity
			Entity_UnlinkBrush(pBrush);
		}
	}
	// move "created" entities to the redo
	for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
	{
		pNextEntity = pEntity->next;
		if (pEntity->undoId == undo->id)
		{
			// check if this entity is in the undo
			for (pUndoEntity = undo->entitylist.next; pUndoEntity != NULL && pUndoEntity != &undo->entitylist; pUndoEntity = pUndoEntity->next)
			{
				// move brushes to the undo entity
				if (pUndoEntity->entityId == pEntity->entityId)
				{
					pUndoEntity->brushes.next = pEntity->brushes.next;
					pUndoEntity->brushes.prev = pEntity->brushes.prev;
					pEntity->brushes.next = &pEntity->brushes;
					pEntity->brushes.prev = &pEntity->brushes;
				}
			}
			//
			//Entity_Free(pEntity);
			//move the entity to the redo
			Entity_RemoveFromList(pEntity);
			Entity_AddToList(pEntity, &redo->entitylist);
		}
	}
	// add the undo entities back into the entity list
	for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = undo->entitylist.next)
	{
		g_undoMemorySize -= Entity_MemorySize(pEntity);
		//if this is the world entity
		if (pEntity->entityId == world_entity->entityId)
		{
			epair_t* tmp = world_entity->epairs;
			world_entity->epairs = pEntity->epairs;
      pEntity->epairs = tmp;
			Entity_Free(pEntity);
		}
		else
		{
			Entity_RemoveFromList(pEntity);
			Entity_AddToList(pEntity, &entities);
			pEntity->redoId = redo->id;
		}
	}
	// add the undo brushes back into the selected brushes
	for (pBrush = undo->brushlist.next; pBrush != NULL && pBrush != &undo->brushlist; pBrush = undo->brushlist.next)
	{
		//Sys_Printf("Owner ID: %i\n",pBrush->ownerId);
		g_undoMemorySize -= Brush_MemorySize(pBrush);
		Brush_RemoveFromList(pBrush);
    	Brush_AddToList(pBrush, &active_brushes);
		for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next) // fixes broken undo on entities
		{
			//Sys_Printf("Entity ID: %i\n",pEntity->entityId);
			if (pEntity->entityId == pBrush->ownerId)
			{
				Entity_LinkBrush(pEntity, pBrush);
				break;
			}
		}
		//if the brush is not linked then it should be linked into the world entity
		//++timo FIXME: maybe not, maybe we've lost this entity's owner!
		if (pEntity == NULL || pEntity == &entities)
		{
			Entity_LinkBrush(world_entity, pBrush);
		}
		//build the brush
		//Brush_Build(pBrush);
		Select_Brush(pBrush);
		pBrush->redoId = redo->id;
    }
	if (!bSilent)
		Sys_Printf("%s undone.\n", undo->operation);
	// free the undo
	g_undoMemorySize -= sizeof(undo_t);
	free(undo);
	g_undoSize--;
	g_undoId--;
	if (g_undoId <= 0) g_undoId = 2 * g_undoMaxSize;
	//
    g_bScreenUpdates = true;
    UpdateSurfaceDialog();
    Sys_UpdateWindows(W_ALL);
}
Пример #21
0
/*
=============
CSG_Merge
=============
*/
void CSG_Merge(void)
{
	brush_t *b, *next, *newlist, *newbrush;
	struct entity_s	*owner;

	Sys_Printf ("Merging...\n");

	if (selected_brushes.next == &selected_brushes)
	{
		Sys_Printf ("No brushes selected.\n");
		return;
	}

	if (selected_brushes.next->next == &selected_brushes)
	{
		Sys_Printf ("At least two brushes have to be selected.\n");
		return;
	}

	owner = selected_brushes.next->owner;

	for (b = selected_brushes.next; b != &selected_brushes; b = next)
	{
		next = b->next;

		if (b->owner->eclass->fixedsize)
		{
			// can't use texture from a fixed entity, so don't subtract
			Sys_Printf ("Cannot add fixed size entities.\n");
			return;
		}

		if (b->owner != owner)
		{
			Sys_Printf ("Cannot add brushes from different entities.\n");
			return;
		}

	}

	newlist = NULL;
	for (b = selected_brushes.next; b != &selected_brushes; b = next)
	{
		next = b->next;

		Brush_RemoveFromList(b);
		b->next = newlist;
		b->prev = NULL;
		newlist = b;
	}

	newbrush = Brush_MergeList(newlist, true);
	// if the new brush would not be convex
	if (!newbrush)
	{
		// add the brushes back into the selection
		for (b = newlist; b; b = next)
		{
			next = b->next;
			b->next = NULL;
			b->prev = NULL;
			Brush_AddToList(b, &selected_brushes);
		}
		Sys_Printf ("Cannot add a set of brushes with a concave hull.\n");
		return;
	}
	// free the original brushes
	for (b = newlist; b; b = next)
	{
		next = b->next;
		b->next = NULL;
		b->prev = NULL;
		Brush_Free(b);
	}
	Brush_AddToList(newbrush, &selected_brushes);

	Sys_Printf ("Done.\n");
	Sys_UpdateWindows (W_ALL);
}
Пример #22
0
/*
=============
CSG_Subtract
=============
*/
void CSG_Subtract (void)
{
	brush_t		*b, *s, *fragments, *nextfragment, *frag, *next, *snext;
	brush_t		fragmentlist;
	int			i, numfragments, numbrushes;

	Sys_Printf ("Subtracting...\n");

	if (selected_brushes.next == &selected_brushes)
	{
		Sys_Printf ("No brushes selected.\n");
		return;
	}

	fragmentlist.next = &fragmentlist;
	fragmentlist.prev = &fragmentlist;

	numfragments = 0;
	numbrushes = 0;
	for (b = selected_brushes.next ; b != &selected_brushes ; b=next)
	{
		next = b->next;

		if (b->owner->eclass->fixedsize)
			continue;	// can't use texture from a fixed entity, so don't subtract

		// chop all fragments further up
		for (s = fragmentlist.next; s != &fragmentlist; s = snext)
		{
			snext = s->next;

			for (i=0 ; i<3 ; i++)
				if (b->mins[i] >= s->maxs[i] - ON_EPSILON 
				|| b->maxs[i] <= s->mins[i] + ON_EPSILON)
					break;
			if (i != 3)
				continue;	// definately don't touch
			fragments = Brush_Subtract(s, b);
			// if the brushes did not really intersect
			if (fragments == s)
				continue;
			// try to merge fragments
			fragments = Brush_MergeListPairs(fragments, true);
			// add the fragments to the list
			for (frag = fragments; frag; frag = nextfragment)
			{
				nextfragment = frag->next;
				frag->next = NULL;
				frag->owner = s->owner;
				Brush_AddToList(frag, &fragmentlist);
			}
			// free the original brush
			Brush_Free(s);
		}

		// chop any active brushes up
		for (s = active_brushes.next; s != &active_brushes; s = snext)
		{
			snext = s->next;

			if (s->owner->eclass->fixedsize || s->hiddenBrush)
				continue;

			for (i=0 ; i<3 ; i++)
				if (b->mins[i] >= s->maxs[i] - ON_EPSILON 
				|| b->maxs[i] <= s->mins[i] + ON_EPSILON)
					break;
			if (i != 3)
				continue;	// definately don't touch

			fragments = Brush_Subtract(s, b);
			// if the brushes did not really intersect
			if (fragments == s)
				continue;

			// one extra brush chopped up
			numbrushes++;
			// try to merge fragments
			fragments = Brush_MergeListPairs(fragments, true);
			// add the fragments to the list
			for (frag = fragments; frag; frag = nextfragment)
			{
				nextfragment = frag->next;
				frag->next = NULL;
				frag->owner = s->owner;
				Brush_AddToList(frag, &fragmentlist);
			}
			// free the original brush
			Brush_Free(s);
		}
	}

	// move all fragments to the active brush list
	for (frag = fragmentlist.next; frag != &fragmentlist; frag = nextfragment)
	{
		nextfragment = frag->next;
		numfragments++;
		Brush_RemoveFromList(frag);
		Brush_AddToList(frag, &active_brushes);
	}

	if (numfragments == 0)
	{
		Sys_Printf ("Selected brush%s did not intersect with any other brushes.\n",
					(selected_brushes.next->next == &selected_brushes) ? "":"es");
		return;
	}
	Sys_Printf ("Done. (created %d fragment%s out of %d brush%s)\n", numfragments, (numfragments == 1)?"":"s",
							numbrushes, (numbrushes == 1)?"":"es");
	Sys_UpdateWindows(W_ALL);
}
Пример #23
0
/*
============
Select_Clone

Creates an exact duplicate of the selection in place, then moves
the selected brushes off of their old positions
============
*/
void Select_Clone (void)
{
	brush_t		*b, *b2, *n, *next, *next2;
	vec3_t		delta;
	entity_t	*e;

	g_qeglobals.d_workcount++;
	g_qeglobals.d_select_mode = sel_brush;

	delta[0] = g_qeglobals.d_gridsize;
	delta[1] = g_qeglobals.d_gridsize;
	delta[2] = 0;

	for (b=selected_brushes.next ; b != &selected_brushes ; b=next)
	{
		next = b->next;
		// if the brush is a world brush, handle simply
		if (b->owner == world_entity)
		{
			n = Brush_Clone (b);
			Brush_AddToList (n, &active_brushes);
			Entity_LinkBrush (world_entity, n);
			Brush_Build( n );
			Brush_Move (b, delta);
			continue;
		}

		e = Entity_Clone (b->owner);
		// clear the target / targetname
		DeleteKey (e, "target");
		DeleteKey (e, "targetname");

		// if the brush is a fixed size entity, create a new entity
		if (b->owner->eclass->fixedsize)
		{
			n = Brush_Clone (b);
			Brush_AddToList (n, &active_brushes);
			Entity_LinkBrush (e, n);
			Brush_Build( n );
			Brush_Move (b, delta);
			continue;
		}
        
		// brush is a complex entity, grab all the other ones now

		next = &selected_brushes;

		for ( b2 = b ; b2 != &selected_brushes ; b2=next2)
		{
			next2 = b2->next;
			if (b2->owner != b->owner)
			{
				if (next == &selected_brushes)
					next = b2;
				continue;
			}

			// move b2 to the start of selected_brushes,
			// so it won't be hit again
			Brush_RemoveFromList (b2);
			Brush_AddToList (b2, &selected_brushes);
			
			n = Brush_Clone (b2);
			Brush_AddToList (n, &active_brushes);
			Entity_LinkBrush (e, n);
			Brush_Build( n );
			Brush_Move (b2, delta);
		}

	}
	Sys_UpdateWindows (W_ALL);
}
Пример #24
0
/*
============
Select_Clone

Creates an exact duplicate of the selection in place, then moves
the selected brushes off of their old positions
============
*/
void Select_Clone( void )
{
#if 1
	ASSERT( g_pParentWnd->ActiveXY() );
	g_bScreenUpdates = false;
	g_pParentWnd->ActiveXY()->Copy();
	g_pParentWnd->ActiveXY()->Paste();
	g_pParentWnd->NudgeSelection( 2, g_qeglobals.d_gridsize );
	g_pParentWnd->NudgeSelection( 3, g_qeglobals.d_gridsize );
	g_bScreenUpdates = true;
	Sys_UpdateWindows( W_ALL );
#else
	
	brush_s*        b, *b2, *n, *next, *next2;
	vec3_t      delta;
	entity_s*   e;
	
	g_qeglobals.d_workcount++;
	clearSelection();
	
	delta[0] = g_qeglobals.d_gridsize;
	delta[1] = g_qeglobals.d_gridsize;
	delta[2] = 0;
	
	for ( b = selected_brushes.next ; b != &selected_brushes ; b = next )
	{
		next = b->next;
		// if the brush is a world brush, handle simply
		if ( b->owner == world_entity )
		{
			n = Brush_Clone( b );
			Brush_AddToList( n, &active_brushes );
			Entity_LinkBrush( world_entity, n );
			Brush_Build( n );
			Brush_Move( b, delta );
			continue;
		}
	
		e = Entity_Clone( b->owner );
		// clear the target / targetname
		DeleteKey( e, "target" );
		DeleteKey( e, "targetname" );
	
		// if the brush is a fixed size entity, create a new entity
		if ( b->owner->eclass->fixedsize )
		{
			n = Brush_Clone( b );
			Brush_AddToList( n, &active_brushes );
			Entity_LinkBrush( e, n );
			Brush_Build( n );
			Brush_Move( b, delta );
			continue;
		}
	
		// brush is a complex entity, grab all the other ones now
	
		next = &selected_brushes;
	
		for ( b2 = b ; b2 != &selected_brushes ; b2 = next2 )
		{
			next2 = b2->next;
			if ( b2->owner != b->owner )
			{
				if ( next == &selected_brushes )
					next = b2;
				continue;
			}
	
			// move b2 to the start of selected_brushes,
			// so it won't be hit again
			Brush_RemoveFromList( b2 );
			Brush_AddToList( b2, &selected_brushes );
	
			n = Brush_Clone( b2 );
			Brush_AddToList( n, &active_brushes );
			Entity_LinkBrush( e, n );
			Brush_Build( n );
			Brush_Move( b2, delta, true );
		}
	
	}
	Sys_UpdateWindows( W_ALL );
#endif
}
Пример #25
0
void Select_AllOfType()
{
	brush_s*    b, *next;
	entity_s*   e;
	if ( ( selected_brushes.next == &selected_brushes )
			|| ( selected_brushes.next->next != &selected_brushes ) )
	{
	
		CString strName;
		if ( g_ptrSelectedFaces.GetSize() == 0 )
		{
			strName = g_qeglobals.d_texturewin.texdef.name;
		}
		else
		{
			face_s* selFace = reinterpret_cast<face_s*>( g_ptrSelectedFaces.GetAt( 0 ) );
			strName = selFace->texdef.name;
		}
		
		Select_Deselect();
		for ( b = active_brushes.next ; b != &active_brushes ; b = next )
		{
			next = b->next;
			
			if ( FilterBrush( b ) )
				continue;
				
			if ( b->patchBrush )
			{
				if ( strcmpi( strName, b->pPatch->d_texture->name ) == 0 )
				{
					Brush_RemoveFromList( b );
					Brush_AddToList( b, &selected_brushes );
				}
			}
			else
			{
				for ( face_s* pFace = b->brush_faces; pFace; pFace = pFace->next )
				{
					if ( strcmpi( strName, pFace->texdef.name ) == 0 )
					{
						Brush_RemoveFromList( b );
						Brush_AddToList( b, &selected_brushes );
					}
				}
			}
		}
		Sys_UpdateWindows( W_ALL );
		return;
	}
	
	
	b = selected_brushes.next;
	e = b->owner;
	
	if ( e != NULL )
	{
		if ( e != world_entity )
		{
			CString strName = e->eclass->name;
			CString strKey, strVal;
			bool bCriteria = GetSelectAllCriteria( strKey, strVal );
			Sys_Printf( "Selecting all %s(s)\n", strName );
			Select_Deselect();
			
			for ( b = active_brushes.next ; b != &active_brushes ; b = next )
			{
				next = b->next;
				
				if ( FilterBrush( b ) )
					continue;
					
				e = b->owner;
				if ( e != NULL )
				{
					if ( strcmpi( e->eclass->name, strName ) == 0 )
					{
						bool doIt = true;
						if ( bCriteria )
						{
							CString str = ValueForKey( e, strKey );
							if ( str.CompareNoCase( strVal ) != 0 )
							{
								doIt = false;
							}
						}
						if ( doIt )
						{
							Brush_RemoveFromList( b );
							Brush_AddToList( b, &selected_brushes );
						}
					}
				}
			}
		}
	}
	Sys_UpdateWindows( W_ALL );
	
}
Пример #26
0
/*
   =============
   Undo_Redo
   =============
 */
void Undo_Redo( void ){
	// spog - disable undo if undo levels = 0
	if ( g_PrefsDlg.m_nUndoLevels == 0 ) {
		Sys_Printf( "Undo_Redo: undo is disabled.\n" );
		return;
	}

	undo_t *redo;
	brush_t *pBrush, *pNextBrush;
	entity_t *pEntity, *pNextEntity, *pRedoEntity;

	if ( !g_lastredo ) {
		Sys_Printf( "Nothing left to redo.\n" );
		return;
	}
	if ( g_lastundo ) {
		if ( !g_lastundo->done ) {
			Sys_Printf( "WARNING: last undo not finished.\n" );
		}
	}
	// get the last redo
	redo = g_lastredo;
	if ( g_lastredo->prev ) {
		g_lastredo->prev->next = NULL;
	}
	else{g_redolist = NULL; }
	g_lastredo = g_lastredo->prev;
	//
	Undo_GeneralStart( redo->operation );
	// remove current selection
	Select_Deselect();
	// move "created" brushes back to the last undo
	for ( pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pNextBrush )
	{
		pNextBrush = pBrush->next;
		if ( pBrush->redoId == redo->id ) {
			//move the brush to the undo
			Brush_RemoveFromList( pBrush );
			Brush_AddToList( pBrush, &g_lastundo->brushlist );
			g_undoMemorySize += Brush_MemorySize( pBrush );
			pBrush->ownerId = pBrush->owner->entityId;
			Entity_UnlinkBrush( pBrush );
		}
	}
	// move "created" entities back to the last undo
	for ( pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity )
	{
		pNextEntity = pEntity->next;
		if ( pEntity->redoId == redo->id ) {
			// check if this entity is in the redo
			for ( pRedoEntity = redo->entitylist.next; pRedoEntity != NULL && pRedoEntity != &redo->entitylist; pRedoEntity = pRedoEntity->next )
			{
				// move brushes to the redo entity
				if ( pRedoEntity->entityId == pEntity->entityId ) {
					pRedoEntity->brushes.next = pEntity->brushes.next;
					pRedoEntity->brushes.prev = pEntity->brushes.prev;
					pEntity->brushes.next = &pEntity->brushes;
					pEntity->brushes.prev = &pEntity->brushes;
				}
			}
			//
			//Entity_Free(pEntity);
			//move the entity to the redo
			Entity_RemoveFromList( pEntity );
			Entity_AddToList( pEntity, &g_lastundo->entitylist );
			g_undoMemorySize += Entity_MemorySize( pEntity );
		}
	}
	// add the undo entities back into the entity list
	for ( pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = redo->entitylist.next )
	{
		//if this is the world entity
		if ( pEntity->entityId == world_entity->entityId ) {
			epair_t* tmp = world_entity->epairs;
			world_entity->epairs = pEntity->epairs;
			pEntity->epairs = tmp;
			Entity_Free( pEntity );
		}
		else
		{
			Entity_RemoveFromList( pEntity );
			Entity_AddToList( pEntity, &entities );
		}
	}
	// add the redo brushes back into the selected brushes
	for ( pBrush = redo->brushlist.next; pBrush != NULL && pBrush != &redo->brushlist; pBrush = redo->brushlist.next )
	{
		Brush_RemoveFromList( pBrush );
		Brush_AddToList( pBrush, &active_brushes );
		for ( pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next ) // fixes broken undo on entities
		{
			if ( pEntity->entityId == pBrush->ownerId ) {
				Entity_LinkBrush( pEntity, pBrush );
				break;
			}
		}
		//if the brush is not linked then it should be linked into the world entity
		if ( pEntity == NULL || pEntity == &entities ) {
			Entity_LinkBrush( world_entity, pBrush );
		}
		//build the brush
		//Brush_Build(pBrush);
		Select_Brush( pBrush );
	}
	//
	Undo_End();
	//
	Sys_Printf( "%s redone.\n", redo->operation );
	//
	g_redoId--;
	// free the undo
	free( redo );
	//
	g_bScreenUpdates = true;
	UpdateSurfaceDialog();
	Sys_UpdateWindows( W_ALL );
}
//
// =======================================================================================================================
//    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);
}
Пример #28
0
/*
=============
CSG_Merge
=============
*/
void CSG_Merge(void)
{
	brush_t *b, *next, *newlist, *newbrush;
	entity_t	*owner;

	Sys_Status("Merging...\n");

	if (selected_brushes.next == &selected_brushes)
	{
		Sys_Status("No brushes selected.\n");
		return;
	}

	if (selected_brushes.next->next == &selected_brushes)
	{
		Sys_Status("At least two brushes have to be selected.\n");
		return;
	}

	owner = selected_brushes.next->owner;

	for (b = selected_brushes.next; b != &selected_brushes; b = next)
	{
		next = b->next;

		if (b->owner->eclass->fixedsize || b->modelHandle > 0)
		{
			// can't use texture from a fixed entity, so don't subtract
			Sys_Status("Cannot add fixed size entities.\n");
			return;
		}

		if (b->pPatch)
		{
			Sys_Status("Cannot add patches.\n");
			return;
		}

		if ( b->brush_faces->d_texture && ( b->brush_faces->d_texture->GetContentFlags() & CONTENTS_NOCSG ) )
		{
			Sys_Status("Cannot add brushes using shaders that don't allows CSG operations.\n");
			return;
		}

		if (b->owner != owner)
		{
			Sys_Status("Cannot add brushes from different entities.\n");
			return;
		}

	}

	newlist = NULL;
	for (b = selected_brushes.next; b != &selected_brushes; b = next)
	{
		next = b->next;

		Brush_RemoveFromList(b);
		b->next = newlist;
		b->prev = NULL;
		newlist = b;
	}

	newbrush = Brush_MergeList(newlist, true);
	// if the new brush would not be convex
	if (!newbrush)
	{
		// add the brushes back into the selection
		for (b = newlist; b; b = next)
		{
			next = b->next;
			b->next = NULL;
			b->prev = NULL;
			Brush_AddToList(b, &selected_brushes);
		}
		Sys_Status("Cannot add a set of brushes with a concave hull.\n");
		return;
	}
	// free the original brushes
	for (b = newlist; b; b = next)
	{
		next = b->next;
		b->next = NULL;
		b->prev = NULL;
		Brush_Free(b);
	}
	Brush_AddToList(newbrush, &selected_brushes);

	Sys_Status ("done.\n");
	Sys_UpdateWindows (W_ALL);
}