2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
32 #include "Game_local.h"
36 ===============================================================================
40 ===============================================================================
43 CLASS_DECLARATION( idEntity, idCursor3D )
48 idCursor3D::idCursor3D
51 idCursor3D::idCursor3D( void ) {
52 draggedPosition.Zero();
57 idCursor3D::~idCursor3D
60 idCursor3D::~idCursor3D( void ) {
68 void idCursor3D::Spawn( void ) {
76 void idCursor3D::Present( void ) {
77 // don't present to the renderer if the entity hasn't changed
78 if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
81 BecomeInactive( TH_UPDATEVISUALS );
83 const idVec3 &origin = GetPhysics()->GetOrigin();
84 const idMat3 &axis = GetPhysics()->GetAxis();
85 gameRenderWorld->DebugArrow( colorYellow, origin + axis[1] * -5.0f + axis[2] * 5.0f, origin, 2 );
86 gameRenderWorld->DebugArrow( colorRed, origin, draggedPosition, 2 );
94 void idCursor3D::Think( void ) {
95 if ( thinkFlags & TH_THINK ) {
96 drag.Evaluate( gameLocal.time );
103 ===============================================================================
105 Allows entities to be dragged through the world with physics.
107 ===============================================================================
110 #define MAX_DRAG_TRACE_DISTANCE 2048.0f
114 idDragEntity::idDragEntity
117 idDragEntity::idDragEntity( void ) {
124 idDragEntity::~idDragEntity
127 idDragEntity::~idDragEntity( void ) {
140 void idDragEntity::Clear() {
142 joint = INVALID_JOINT;
144 localEntityPoint.Zero();
145 localPlayerPoint.Zero();
152 idDragEntity::StopDrag
155 void idDragEntity::StopDrag( void ) {
158 cursor->BecomeInactive( TH_THINK );
167 void idDragEntity::Update( idPlayer *player ) {
168 idVec3 viewPoint, origin;
169 idMat3 viewAxis, axis;
173 jointHandle_t newJoint;
176 player->GetViewPos( viewPoint, viewAxis );
178 // if no entity selected for dragging
179 if ( !dragEnt.GetEntity() ) {
181 if ( player->usercmd.buttons & BUTTON_ATTACK ) {
183 gameLocal.clip.TracePoint( trace, viewPoint, viewPoint + viewAxis[0] * MAX_DRAG_TRACE_DISTANCE, (CONTENTS_SOLID|CONTENTS_RENDERMODEL|CONTENTS_BODY), player );
184 if ( trace.fraction < 1.0f ) {
186 newEnt = gameLocal.entities[ trace.c.entityNum ];
189 if ( newEnt->GetBindMaster() ) {
190 if ( newEnt->GetBindJoint() ) {
191 trace.c.id = JOINT_HANDLE_TO_CLIPMODEL_ID( newEnt->GetBindJoint() );
193 trace.c.id = newEnt->GetBindBody();
195 newEnt = newEnt->GetBindMaster();
198 if ( newEnt->IsType( idAFEntity_Base::Type ) && static_cast<idAFEntity_Base *>(newEnt)->IsActiveAF() ) {
199 idAFEntity_Base *af = static_cast<idAFEntity_Base *>(newEnt);
201 // joint being dragged
202 newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
203 // get the body id from the trace model id which might be a joint handle
204 trace.c.id = af->BodyForClipModelId( trace.c.id );
205 // get the name of the body being dragged
206 newBodyName = af->GetAFPhysics()->GetBody( trace.c.id )->GetName();
208 } else if ( !newEnt->IsType( idWorldspawn::Type ) ) {
210 if ( trace.c.id < 0 ) {
211 newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
213 newJoint = INVALID_JOINT;
219 newJoint = INVALID_JOINT;
228 bodyName = newBodyName;
231 cursor = ( idCursor3D * )gameLocal.SpawnEntityType( idCursor3D::Type );
234 idPhysics *phys = dragEnt.GetEntity()->GetPhysics();
235 localPlayerPoint = ( trace.c.point - viewPoint ) * viewAxis.Transpose();
236 origin = phys->GetOrigin( id );
237 axis = phys->GetAxis( id );
238 localEntityPoint = ( trace.c.point - origin ) * axis.Transpose();
240 cursor->drag.Init( g_dragDamping.GetFloat() );
241 cursor->drag.SetPhysics( phys, id, localEntityPoint );
244 if ( phys->IsType( idPhysics_AF::Type ) ||
245 phys->IsType( idPhysics_RigidBody::Type ) ||
246 phys->IsType( idPhysics_Monster::Type ) ) {
247 cursor->BecomeActive( TH_THINK );
254 // if there is an entity selected for dragging
255 idEntity *drag = dragEnt.GetEntity();
258 if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) {
263 cursor->SetOrigin( viewPoint + localPlayerPoint * viewAxis );
264 cursor->SetAxis( viewAxis );
266 cursor->drag.SetDragPosition( cursor->GetPhysics()->GetOrigin() );
268 renderEntity_t *renderEntity = drag->GetRenderEntity();
269 idAnimator *dragAnimator = drag->GetAnimator();
271 if ( joint != INVALID_JOINT && renderEntity && dragAnimator ) {
272 dragAnimator->GetJointTransform( joint, gameLocal.time, cursor->draggedPosition, axis );
273 cursor->draggedPosition = renderEntity->origin + cursor->draggedPosition * renderEntity->axis;
274 gameRenderWorld->DrawText( va( "%s\n%s\n%s, %s", drag->GetName(), drag->GetType()->classname, dragAnimator->GetJointName( joint ), bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 );
276 cursor->draggedPosition = cursor->GetPhysics()->GetOrigin();
277 gameRenderWorld->DrawText( va( "%s\n%s\n%s", drag->GetName(), drag->GetType()->classname, bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 );
281 // if there is a selected entity
282 if ( selected.GetEntity() && g_dragShowSelection.GetBool() ) {
283 // draw the bbox of the selected entity
284 renderEntity_t *renderEntity = selected.GetEntity()->GetRenderEntity();
285 if ( renderEntity ) {
286 gameRenderWorld->DebugBox( colorYellow, idBox( renderEntity->bounds, renderEntity->origin, renderEntity->axis ) );
293 idDragEntity::SetSelected
296 void idDragEntity::SetSelected( idEntity *ent ) {
303 idDragEntity::DeleteSelected
306 void idDragEntity::DeleteSelected( void ) {
307 delete selected.GetEntity();
314 idDragEntity::BindSelected
317 void idDragEntity::BindSelected( void ) {
320 idToken type, bodyName;
321 idStr key, value, bindBodyName;
322 const idKeyValue *kv;
325 af = static_cast<idAFEntity_Base *>(dragEnt.GetEntity());
327 if ( !af || !af->IsType( idAFEntity_Base::Type ) || !af->IsActiveAF() ) {
331 bindBodyName = af->GetAFPhysics()->GetBody( id )->GetName();
334 // parse all the bind constraints
335 kv = af->spawnArgs.MatchPrefix( "bindConstraint ", NULL );
338 key.Strip( "bindConstraint " );
339 if ( sscanf( key, "bind%d", &num ) ) {
340 if ( num >= largestNum ) {
341 largestNum = num + 1;
345 lexer.LoadMemory( kv->GetValue(), kv->GetValue().Length(), kv->GetKey() );
346 lexer.ReadToken( &type );
347 lexer.ReadToken( &bodyName );
350 // if there already exists a bind constraint for this body
351 if ( bodyName.Icmp( bindBodyName ) == 0 ) {
352 // delete the bind constraint
353 af->spawnArgs.Delete( kv->GetKey() );
357 kv = af->spawnArgs.MatchPrefix( "bindConstraint ", kv );
360 sprintf( key, "bindConstraint bind%d", largestNum );
361 sprintf( value, "ballAndSocket %s %s", bindBodyName.c_str(), af->GetAnimator()->GetJointName( joint ) );
363 af->spawnArgs.Set( key, value );
364 af->spawnArgs.Set( "bind", "worldspawn" );
365 af->Bind( gameLocal.world, true );
370 idDragEntity::UnbindSelected
373 void idDragEntity::UnbindSelected( void ) {
374 const idKeyValue *kv;
377 af = static_cast<idAFEntity_Base *>(selected.GetEntity());
379 if ( !af || !af->IsType( idAFEntity_Base::Type ) || !af->IsActiveAF() ) {
383 // unbind the selected entity
386 // delete all the bind constraints
387 kv = selected.GetEntity()->spawnArgs.MatchPrefix( "bindConstraint ", NULL );
389 selected.GetEntity()->spawnArgs.Delete( kv->GetKey() );
390 kv = selected.GetEntity()->spawnArgs.MatchPrefix( "bindConstraint ", NULL );
393 // delete any bind information
394 af->spawnArgs.Delete( "bind" );
395 af->spawnArgs.Delete( "bindToJoint" );
396 af->spawnArgs.Delete( "bindToBody" );
401 ===============================================================================
403 Handles ingame entity editing.
405 ===============================================================================
410 idEditEntities::idEditEntities
413 idEditEntities::idEditEntities( void ) {
414 selectableEntityClasses.Clear();
420 idEditEntities::SelectEntity
423 bool idEditEntities::SelectEntity( const idVec3 &origin, const idVec3 &dir, const idEntity *skip ) {
427 if ( !g_editEntityMode.GetInteger() || selectableEntityClasses.Num() == 0 ) {
431 if ( gameLocal.time < nextSelectTime ) {
434 nextSelectTime = gameLocal.time + 300;
436 end = origin + dir * 4096.0f;
439 for ( int i = 0; i < selectableEntityClasses.Num(); i++ ) {
440 ent = gameLocal.FindTraceEntity( origin, end, *selectableEntityClasses[i].typeInfo, skip );
446 ClearSelectedEntities();
447 if ( EntityIsSelectable( ent ) ) {
448 AddSelectedEntity( ent );
449 gameLocal.Printf( "entity #%d: %s '%s'\n", ent->entityNumber, ent->GetClassname(), ent->name.c_str() );
450 ent->ShowEditingDialog();
459 idEditEntities::AddSelectedEntity
462 void idEditEntities::AddSelectedEntity(idEntity *ent) {
463 ent->fl.selected = true;
464 selectedEntities.AddUnique(ent);
469 idEditEntities::RemoveSelectedEntity
472 void idEditEntities::RemoveSelectedEntity( idEntity *ent ) {
473 if ( selectedEntities.Find( ent ) ) {
474 selectedEntities.Remove( ent );
480 idEditEntities::ClearSelectedEntities
483 void idEditEntities::ClearSelectedEntities() {
486 count = selectedEntities.Num();
487 for ( i = 0; i < count; i++ ) {
488 selectedEntities[i]->fl.selected = false;
490 selectedEntities.Clear();
496 idEditEntities::EntityIsSelectable
499 bool idEditEntities::EntityIsSelectable( idEntity *ent, idVec4 *color, idStr *text ) {
500 for ( int i = 0; i < selectableEntityClasses.Num(); i++ ) {
501 if ( ent->GetType() == selectableEntityClasses[i].typeInfo ) {
503 *text = selectableEntityClasses[i].textKey;
506 if ( ent->fl.selected ) {
511 *color = colorYellow;
529 idEditEntities::DisplayEntities
532 void idEditEntities::DisplayEntities( void ) {
535 if ( !gameLocal.GetLocalPlayer() ) {
539 selectableEntityClasses.Clear();
540 selectedTypeInfo_t sit;
542 switch( g_editEntityMode.GetInteger() ) {
544 sit.typeInfo = &idLight::Type;
545 sit.textKey = "texture";
546 selectableEntityClasses.Append( sit );
549 sit.typeInfo = &idSound::Type;
550 sit.textKey = "s_shader";
551 selectableEntityClasses.Append( sit );
552 sit.typeInfo = &idLight::Type;
553 sit.textKey = "texture";
554 selectableEntityClasses.Append( sit );
557 sit.typeInfo = &idAFEntity_Base::Type;
558 sit.textKey = "articulatedFigure";
559 selectableEntityClasses.Append( sit );
562 sit.typeInfo = &idFuncEmitter::Type;
563 sit.textKey = "model";
564 selectableEntityClasses.Append( sit );
567 sit.typeInfo = &idAI::Type;
568 sit.textKey = "name";
569 selectableEntityClasses.Append( sit );
572 sit.typeInfo = &idEntity::Type;
573 sit.textKey = "name";
574 selectableEntityClasses.Append( sit );
577 sit.typeInfo = &idEntity::Type;
578 sit.textKey = "model";
579 selectableEntityClasses.Append( sit );
585 idBounds viewBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
586 idBounds viewTextBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
587 idMat3 axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3();
589 viewBounds.ExpandSelf( 512 );
590 viewTextBounds.ExpandSelf( 128 );
594 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
599 if ( !EntityIsSelectable( ent, &color, &textKey ) ) {
603 bool drawArrows = false;
604 if ( ent->GetType() == &idAFEntity_Base::Type ) {
605 if ( !static_cast<idAFEntity_Base *>(ent)->IsActiveAF() ) {
608 } else if ( ent->GetType() == &idSound::Type ) {
609 if ( ent->fl.selected ) {
612 const idSoundShader * ss = declManager->FindSound( ent->spawnArgs.GetString( textKey ) );
613 if ( ss->HasDefaultSound() || ss->base->GetState() == DS_DEFAULTED ) {
614 color.Set( 1.0f, 0.0f, 1.0f, 1.0f );
616 } else if ( ent->GetType() == &idFuncEmitter::Type ) {
617 if ( ent->fl.selected ) {
622 if ( !viewBounds.ContainsPoint( ent->GetPhysics()->GetOrigin() ) ) {
626 gameRenderWorld->DebugBounds( color, idBounds( ent->GetPhysics()->GetOrigin() ).Expand( 8 ) );
628 idVec3 start = ent->GetPhysics()->GetOrigin();
629 idVec3 end = start + idVec3( 1, 0, 0 ) * 20.0f;
630 gameRenderWorld->DebugArrow( colorWhite, start, end, 2 );
631 gameRenderWorld->DrawText( "x+", end + idVec3( 4, 0, 0 ), 0.15f, colorWhite, axis );
632 end = start + idVec3( 1, 0, 0 ) * -20.0f;
633 gameRenderWorld->DebugArrow( colorWhite, start, end, 2 );
634 gameRenderWorld->DrawText( "x-", end + idVec3( -4, 0, 0 ), 0.15f, colorWhite, axis );
635 end = start + idVec3( 0, 1, 0 ) * +20.0f;
636 gameRenderWorld->DebugArrow( colorGreen, start, end, 2 );
637 gameRenderWorld->DrawText( "y+", end + idVec3( 0, 4, 0 ), 0.15f, colorWhite, axis );
638 end = start + idVec3( 0, 1, 0 ) * -20.0f;
639 gameRenderWorld->DebugArrow( colorGreen, start, end, 2 );
640 gameRenderWorld->DrawText( "y-", end + idVec3( 0, -4, 0 ), 0.15f, colorWhite, axis );
641 end = start + idVec3( 0, 0, 1 ) * +20.0f;
642 gameRenderWorld->DebugArrow( colorBlue, start, end, 2 );
643 gameRenderWorld->DrawText( "z+", end + idVec3( 0, 0, 4 ), 0.15f, colorWhite, axis );
644 end = start + idVec3( 0, 0, 1 ) * -20.0f;
645 gameRenderWorld->DebugArrow( colorBlue, start, end, 2 );
646 gameRenderWorld->DrawText( "z-", end + idVec3( 0, 0, -4 ), 0.15f, colorWhite, axis );
649 if ( textKey.Length() ) {
650 const char *text = ent->spawnArgs.GetString( textKey );
651 if ( viewTextBounds.ContainsPoint( ent->GetPhysics()->GetOrigin() ) ) {
652 gameRenderWorld->DrawText( text, ent->GetPhysics()->GetOrigin() + idVec3(0, 0, 12), 0.25, colorWhite, axis, 1 );
660 ===============================================================================
664 ===============================================================================
667 idGameEdit gameEditLocal;
668 idGameEdit * gameEdit = &gameEditLocal;
673 idGameEdit::GetSelectedEntities
676 int idGameEdit::GetSelectedEntities( idEntity *list[], int max ) {
680 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
681 if ( ent->fl.selected ) {
693 idGameEdit::TriggerSelected
696 void idGameEdit::TriggerSelected() {
698 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
699 if ( ent->fl.selected ) {
700 ent->ProcessEvent( &EV_Activate, gameLocal.GetLocalPlayer() );
707 idGameEdit::ClearEntitySelection
710 void idGameEdit::ClearEntitySelection() {
713 for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
714 ent->fl.selected = false;
716 gameLocal.editEntities->ClearSelectedEntities();
721 idGameEdit::AddSelectedEntity
724 void idGameEdit::AddSelectedEntity( idEntity *ent ) {
726 gameLocal.editEntities->AddSelectedEntity( ent );
732 idGameEdit::FindEntityDefDict
735 const idDict *idGameEdit::FindEntityDefDict( const char *name, bool makeDefault ) const {
736 return gameLocal.FindEntityDefDict( name, makeDefault );
741 idGameEdit::SpawnEntityDef
744 void idGameEdit::SpawnEntityDef( const idDict &args, idEntity **ent ) {
745 gameLocal.SpawnEntityDef( args, ent );
750 idGameEdit::FindEntity
753 idEntity *idGameEdit::FindEntity( const char *name ) const {
754 return gameLocal.FindEntity( name );
759 idGameEdit::GetUniqueEntityName
761 generates a unique name for a given classname
764 const char *idGameEdit::GetUniqueEntityName( const char *classname ) const {
766 static char name[1024];
768 // can only have MAX_GENTITIES, so if we have a spot available, we're guaranteed to find one
769 for( id = 0; id < MAX_GENTITIES; id++ ) {
770 idStr::snPrintf( name, sizeof( name ), "%s_%d", classname, id );
771 if ( !gameLocal.FindEntity( name ) ) {
776 // id == MAX_GENTITIES + 1, which can't be in use if we get here
777 idStr::snPrintf( name, sizeof( name ), "%s_%d", classname, id );
783 idGameEdit::EntityGetOrigin
786 void idGameEdit::EntityGetOrigin( idEntity *ent, idVec3 &org ) const {
788 org = ent->GetPhysics()->GetOrigin();
794 idGameEdit::EntityGetAxis
797 void idGameEdit::EntityGetAxis( idEntity *ent, idMat3 &axis ) const {
799 axis = ent->GetPhysics()->GetAxis();
805 idGameEdit::EntitySetOrigin
808 void idGameEdit::EntitySetOrigin( idEntity *ent, const idVec3 &org ) {
810 ent->SetOrigin( org );
816 idGameEdit::EntitySetAxis
819 void idGameEdit::EntitySetAxis( idEntity *ent, const idMat3 &axis ) {
821 ent->SetAxis( axis );
827 idGameEdit::EntitySetColor
830 void idGameEdit::EntitySetColor( idEntity *ent, const idVec3 color ) {
832 ent->SetColor( color );
838 idGameEdit::EntityTranslate
841 void idGameEdit::EntityTranslate( idEntity *ent, const idVec3 &org ) {
843 ent->GetPhysics()->Translate( org );
849 idGameEdit::EntityGetSpawnArgs
852 const idDict *idGameEdit::EntityGetSpawnArgs( idEntity *ent ) const {
854 return &ent->spawnArgs;
861 idGameEdit::EntityUpdateChangeableSpawnArgs
864 void idGameEdit::EntityUpdateChangeableSpawnArgs( idEntity *ent, const idDict *dict ) {
866 ent->UpdateChangeableSpawnArgs( dict );
872 idGameEdit::EntityChangeSpawnArgs
875 void idGameEdit::EntityChangeSpawnArgs( idEntity *ent, const idDict *newArgs ) {
877 for ( int i = 0 ; i < newArgs->GetNumKeyVals () ; i ++ ) {
878 const idKeyValue *kv = newArgs->GetKeyVal( i );
880 if ( kv->GetValue().Length() > 0 ) {
881 ent->spawnArgs.Set ( kv->GetKey() ,kv->GetValue() );
883 ent->spawnArgs.Delete ( kv->GetKey() );
891 idGameEdit::EntityUpdateVisuals
894 void idGameEdit::EntityUpdateVisuals( idEntity *ent ) {
896 ent->UpdateVisuals();
902 idGameEdit::EntitySetModel
905 void idGameEdit::EntitySetModel( idEntity *ent, const char *val ) {
907 ent->spawnArgs.Set( "model", val );
908 ent->SetModel( val );
914 idGameEdit::EntityStopSound
917 void idGameEdit::EntityStopSound( idEntity *ent ) {
919 ent->StopSound( SND_CHANNEL_ANY, false );
925 idGameEdit::EntityDelete
928 void idGameEdit::EntityDelete( idEntity *ent ) {
934 idGameEdit::PlayerIsValid
937 bool idGameEdit::PlayerIsValid() const {
938 return ( gameLocal.GetLocalPlayer() != NULL );
943 idGameEdit::PlayerGetOrigin
946 void idGameEdit::PlayerGetOrigin( idVec3 &org ) const {
947 org = gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin();
952 idGameEdit::PlayerGetAxis
955 void idGameEdit::PlayerGetAxis( idMat3 &axis ) const {
956 axis = gameLocal.GetLocalPlayer()->GetPhysics()->GetAxis();
961 idGameEdit::PlayerGetViewAngles
964 void idGameEdit::PlayerGetViewAngles( idAngles &angles ) const {
965 angles = gameLocal.GetLocalPlayer()->viewAngles;
970 idGameEdit::PlayerGetEyePosition
973 void idGameEdit::PlayerGetEyePosition( idVec3 &org ) const {
974 org = gameLocal.GetLocalPlayer()->GetEyePosition();
980 idGameEdit::MapGetEntityDict
983 const idDict *idGameEdit::MapGetEntityDict( const char *name ) const {
984 idMapFile *mapFile = gameLocal.GetLevelMap();
985 if ( mapFile && name && *name ) {
986 idMapEntity *mapent = mapFile->FindEntity( name );
988 return &mapent->epairs;
999 void idGameEdit::MapSave( const char *path ) const {
1000 idMapFile *mapFile = gameLocal.GetLevelMap();
1002 mapFile->Write( (path) ? path : mapFile->GetName(), ".map");
1008 idGameEdit::MapSetEntityKeyVal
1011 void idGameEdit::MapSetEntityKeyVal( const char *name, const char *key, const char *val ) const {
1012 idMapFile *mapFile = gameLocal.GetLevelMap();
1013 if ( mapFile && name && *name ) {
1014 idMapEntity *mapent = mapFile->FindEntity( name );
1016 mapent->epairs.Set( key, val );
1023 idGameEdit::MapCopyDictToEntity
1026 void idGameEdit::MapCopyDictToEntity( const char *name, const idDict *dict ) const {
1027 idMapFile *mapFile = gameLocal.GetLevelMap();
1028 if ( mapFile && name && *name ) {
1029 idMapEntity *mapent = mapFile->FindEntity( name );
1031 for ( int i = 0; i < dict->GetNumKeyVals(); i++ ) {
1032 const idKeyValue *kv = dict->GetKeyVal( i );
1033 const char *key = kv->GetKey();
1034 const char *val = kv->GetValue();
1035 mapent->epairs.Set( key, val );
1045 idGameEdit::MapGetUniqueMatchingKeyVals
1048 int idGameEdit::MapGetUniqueMatchingKeyVals( const char *key, const char *list[], int max ) const {
1049 idMapFile *mapFile = gameLocal.GetLevelMap();
1052 for ( int i = 0; i < mapFile->GetNumEntities(); i++ ) {
1053 idMapEntity *ent = mapFile->GetEntity( i );
1055 const char *k = ent->epairs.GetString( key );
1056 if ( k && *k && count < max ) {
1067 idGameEdit::MapAddEntity
1070 void idGameEdit::MapAddEntity( const idDict *dict ) const {
1071 idMapFile *mapFile = gameLocal.GetLevelMap();
1073 idMapEntity *ent = new idMapEntity();
1074 ent->epairs = *dict;
1075 mapFile->AddEntity( ent );
1081 idGameEdit::MapRemoveEntity
1084 void idGameEdit::MapRemoveEntity( const char *name ) const {
1085 idMapFile *mapFile = gameLocal.GetLevelMap();
1087 idMapEntity *ent = mapFile->FindEntity( name );
1089 mapFile->RemoveEntity( ent );
1097 idGameEdit::MapGetEntitiesMatchignClassWithString
1100 int idGameEdit::MapGetEntitiesMatchingClassWithString( const char *classname, const char *match, const char *list[], const int max ) const {
1101 idMapFile *mapFile = gameLocal.GetLevelMap();
1104 int entCount = mapFile->GetNumEntities();
1105 for ( int i = 0 ; i < entCount; i++ ) {
1106 idMapEntity *ent = mapFile->GetEntity(i);
1108 idStr work = ent->epairs.GetString("classname");
1109 if ( work.Icmp( classname ) == 0 ) {
1110 if ( match && *match ) {
1111 work = ent->epairs.GetString( "soundgroup" );
1112 if ( count < max && work.Icmp( match ) == 0 ) {
1113 list[count++] = ent->epairs.GetString( "name" );
1115 } else if ( count < max ) {
1116 list[count++] = ent->epairs.GetString( "name" );
1128 idGameEdit::MapEntityTranslate
1131 void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const {
1132 idMapFile *mapFile = gameLocal.GetLevelMap();
1133 if ( mapFile && name && *name ) {
1134 idMapEntity *mapent = mapFile->FindEntity( name );
1137 mapent->epairs.GetVector( "origin", "", origin );
1139 mapent->epairs.SetVector( "origin", origin );