You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
7.7 KiB
306 lines
7.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// tf_nav_mesh_edit.cpp |
|
// TF specific nav mesh editing |
|
// Michael Booth, May 2009 |
|
|
|
#include "cbase.h" |
|
#include "tf_nav_mesh.h" |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
class CTFAttributeClearer |
|
{ |
|
public: |
|
CTFAttributeClearer( TFNavAttributeType attribute ) |
|
{ |
|
m_attribute = attribute; |
|
} |
|
|
|
bool operator() ( CNavArea *baseArea ) |
|
{ |
|
CTFNavArea *area = (CTFNavArea *)baseArea; |
|
|
|
area->ClearAttributeTF( m_attribute ); |
|
|
|
return true; |
|
} |
|
|
|
TFNavAttributeType m_attribute; |
|
}; |
|
|
|
void TF_EditClearAllAttributes( void ) |
|
{ |
|
CTFAttributeClearer clear( (TFNavAttributeType)0xFFFFFFFF ); |
|
TheNavMesh->ForAllSelectedAreas( clear ); |
|
TheNavMesh->ClearSelectedSet(); |
|
} |
|
static ConCommand ClearAllAttributes( "tf_wipe_attributes", TF_EditClearAllAttributes, "Clear all TF-specific attributes of selected area.", FCVAR_CHEAT ); |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
struct AttributeLookup |
|
{ |
|
const char *name; |
|
TFNavAttributeType attribute; |
|
}; |
|
|
|
static AttributeLookup s_TFAttributeTable[] = |
|
{ |
|
{ "BLUE_SETUP_GATE", TF_NAV_BLUE_SETUP_GATE }, |
|
{ "RED_SETUP_GATE", TF_NAV_RED_SETUP_GATE }, |
|
{ "BLOCKED_AFTER_POINT_CAPTURE", TF_NAV_BLOCKED_AFTER_POINT_CAPTURE }, |
|
{ "BLOCKED_UNTIL_POINT_CAPTURE", TF_NAV_BLOCKED_UNTIL_POINT_CAPTURE }, |
|
{ "BLUE_ONE_WAY_DOOR", TF_NAV_BLUE_ONE_WAY_DOOR }, |
|
{ "RED_ONE_WAY_DOOR", TF_NAV_RED_ONE_WAY_DOOR }, |
|
|
|
{ "SNIPER_SPOT", TF_NAV_SNIPER_SPOT }, |
|
{ "SENTRY_SPOT", TF_NAV_SENTRY_SPOT }, |
|
{ "NO_SPAWNING", TF_NAV_NO_SPAWNING }, |
|
{ "RESCUE_CLOSET", TF_NAV_RESCUE_CLOSET }, |
|
|
|
{ "DOOR_ALWAYS_BLOCKS", TF_NAV_DOOR_ALWAYS_BLOCKS }, |
|
{ "DOOR_NEVER_BLOCKS", TF_NAV_DOOR_NEVER_BLOCKS }, |
|
{ "UNBLOCKABLE", TF_NAV_UNBLOCKABLE }, |
|
|
|
{ "WITH_SECOND_POINT", TF_NAV_WITH_SECOND_POINT }, |
|
{ "WITH_THIRD_POINT", TF_NAV_WITH_THIRD_POINT }, |
|
{ "WITH_FOURTH_POINT", TF_NAV_WITH_FOURTH_POINT }, |
|
{ "WITH_FIFTH_POINT", TF_NAV_WITH_FIFTH_POINT }, |
|
|
|
{ NULL, TF_NAV_INVALID } |
|
}; |
|
|
|
|
|
/** |
|
* Can be used with any command that takes an attribute as its 2nd argument |
|
*/ |
|
static int AttributeAutocomplete( const char *input, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) |
|
{ |
|
if ( Q_strlen( input ) >= COMMAND_COMPLETION_ITEM_LENGTH ) |
|
{ |
|
return 0; |
|
} |
|
|
|
char command[ COMMAND_COMPLETION_ITEM_LENGTH+1 ]; |
|
Q_strncpy( command, input, sizeof( command ) ); |
|
|
|
// skip to start of argument |
|
char *partialArg = Q_strrchr( command, ' ' ); |
|
if ( partialArg == NULL ) |
|
{ |
|
return 0; |
|
} |
|
|
|
// chop command from partial argument |
|
*partialArg = '\000'; |
|
++partialArg; |
|
|
|
int partialArgLength = Q_strlen( partialArg ); |
|
|
|
int count = 0; |
|
for( unsigned int i=0; s_TFAttributeTable[i].name && count < COMMAND_COMPLETION_MAXITEMS; ++i ) |
|
{ |
|
if ( !Q_strnicmp( s_TFAttributeTable[i].name, partialArg, partialArgLength ) ) |
|
{ |
|
// Add to the autocomplete array |
|
Q_snprintf( commands[ count++ ], COMMAND_COMPLETION_ITEM_LENGTH, "%s %s", command, s_TFAttributeTable[i].name ); |
|
} |
|
} |
|
|
|
/* all of these are deprecated |
|
for( unsigned int i=0; TheNavAttributeTable[i].name && count < COMMAND_COMPLETION_MAXITEMS; ++i ) |
|
{ |
|
if ( !Q_strnicmp( TheNavAttributeTable[i].name, partialArg, partialArgLength ) ) |
|
{ |
|
// Add to the autocomplete array |
|
Q_snprintf( commands[ count++ ], COMMAND_COMPLETION_ITEM_LENGTH, "%s %s", command, TheNavAttributeTable[i].name ); |
|
} |
|
} |
|
*/ |
|
|
|
return count; |
|
} |
|
|
|
|
|
TFNavAttributeType NameToTFAttribute( const char *name ) |
|
{ |
|
for( unsigned int i=0; s_TFAttributeTable[i].name; ++i ) |
|
{ |
|
if ( !Q_stricmp( s_TFAttributeTable[i].name, name ) ) |
|
{ |
|
return s_TFAttributeTable[i].attribute; |
|
} |
|
} |
|
|
|
return TF_NAV_INVALID; |
|
} |
|
|
|
|
|
const char *TFAttributeToName( TFNavAttributeType attribute ) |
|
{ |
|
for( unsigned int i=0; s_TFAttributeTable[i].name; ++i ) |
|
{ |
|
if ( s_TFAttributeTable[i].attribute == attribute ) |
|
{ |
|
return s_TFAttributeTable[i].name; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
void TF_EditClearAttribute( const CCommand &args ) |
|
{ |
|
if ( args.ArgC() < 2 ) |
|
{ |
|
Msg( "Usage: %s <attribute1> [attribute2...]\n", args[0] ); |
|
return; |
|
} |
|
|
|
for ( int i = 1; i < args.ArgC(); ++i ) |
|
{ |
|
TFNavAttributeType spawnAttribute = NameToTFAttribute( args[i] ); |
|
NavAttributeType navAttribute = NameToNavAttribute( args[i] ); |
|
|
|
if ( spawnAttribute != TF_NAV_INVALID ) |
|
{ |
|
CTFAttributeClearer clear( spawnAttribute ); |
|
TheNavMesh->ForAllSelectedAreas( clear ); |
|
} |
|
else if ( navAttribute != NAV_MESH_INVALID ) |
|
{ |
|
NavAttributeClearer clear( navAttribute ); |
|
TheNavMesh->ForAllSelectedAreas( clear ); |
|
} |
|
else |
|
{ |
|
Msg( "Unknown attribute '%s'", args[i] ); |
|
} |
|
} |
|
|
|
TheNavMesh->ClearSelectedSet(); |
|
} |
|
static ConCommand ClearAttributeTF( "tf_clear_attribute", TF_EditClearAttribute, "Remove given attribute from all areas in the selected set.", FCVAR_CHEAT, AttributeAutocomplete ); |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
class CTFAttributeToggler |
|
{ |
|
public: |
|
CTFAttributeToggler( TFNavAttributeType attribute ) |
|
{ |
|
m_attribute = attribute; |
|
} |
|
|
|
bool operator() ( CNavArea *baseArea ) |
|
{ |
|
CTFNavArea *area = (CTFNavArea *)baseArea; |
|
|
|
// only toggle if dealing with a single selected area |
|
if ( TheNavMesh->IsSelectedSetEmpty() && area->HasAttributeTF( m_attribute ) ) |
|
{ |
|
area->ClearAttributeTF( m_attribute ); |
|
} |
|
else |
|
{ |
|
area->SetAttributeTF( m_attribute ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
TFNavAttributeType m_attribute; |
|
}; |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
void TF_EditMarkAttribute( const CCommand &args ) |
|
{ |
|
if ( args.ArgC() < 2 ) |
|
{ |
|
Msg( "Usage: %s <attribute> [attribute2...]\n", args[0] ); |
|
return; |
|
} |
|
|
|
for ( int i = 1; i < args.ArgC(); ++i ) |
|
{ |
|
TFNavAttributeType spawnAttribute = NameToTFAttribute( args[i] ); |
|
NavAttributeType navAttribute = NameToNavAttribute( args[i] ); |
|
|
|
if ( spawnAttribute != TF_NAV_INVALID ) |
|
{ |
|
CTFAttributeToggler toggle( spawnAttribute ); |
|
TheNavMesh->ForAllSelectedAreas( toggle ); |
|
} |
|
else if ( navAttribute != NAV_MESH_INVALID ) |
|
{ |
|
NavAttributeToggler clear( navAttribute ); |
|
TheNavMesh->ForAllSelectedAreas( clear ); |
|
} |
|
else |
|
{ |
|
Msg( "Unknown attribute '%s'", args[i] ); |
|
} |
|
} |
|
|
|
TheNavMesh->ClearSelectedSet(); |
|
} |
|
static ConCommand MarkAttribute( "tf_mark", TF_EditMarkAttribute, "Set attribute of selected area.", FCVAR_CHEAT, AttributeAutocomplete ); |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
void TF_EditSelectWithAttribute( const CCommand &args ) |
|
{ |
|
TheNavMesh->ClearSelectedSet(); |
|
|
|
if ( args.ArgC() != 2 ) |
|
{ |
|
Msg( "Usage: %s <attribute>\n", args[0] ); |
|
return; |
|
} |
|
|
|
TFNavAttributeType spawnAttribute = NameToTFAttribute( args[1] ); |
|
|
|
int count = 0; |
|
|
|
if ( spawnAttribute != TF_NAV_INVALID ) |
|
{ |
|
FOR_EACH_VEC( TheNavAreas, it ) |
|
{ |
|
CTFNavArea *area = (CTFNavArea *)TheNavAreas[ it ]; |
|
|
|
if ( area->HasAttributeTF( spawnAttribute ) ) |
|
{ |
|
TheNavMesh->AddToSelectedSet( area ); |
|
++count; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
NavAttributeType navAttribute = NameToNavAttribute( args[1] ); |
|
if ( navAttribute != NAV_MESH_INVALID ) |
|
{ |
|
FOR_EACH_VEC( TheNavAreas, it ) |
|
{ |
|
CNavArea *area = TheNavAreas[ it ]; |
|
|
|
if ( area->GetAttributes() & navAttribute ) |
|
{ |
|
TheNavMesh->AddToSelectedSet( area ); |
|
++count; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
Msg( "Unknown attribute '%s'", args[1] ); |
|
} |
|
} |
|
|
|
Msg( "%d areas added to selection\n", count ); |
|
} |
|
static ConCommand SelectWithAttribute( "tf_select_with_attribute", TF_EditSelectWithAttribute, "Selects areas with the given attribute.", FCVAR_CHEAT, AttributeAutocomplete ); |
|
|
|
|