home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / GameEdit.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  46KB  |  1,961 lines

  1.         
  2. #include "../idlib/precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #include "Game_local.h"
  6. // RAVEN BEGIN
  7. // bdube: added
  8. #include "Effect.h"
  9. // nmckenzie:
  10. //#include "rvAI/AI.h"
  11. #include "ai/AI.h"
  12. #include "client/ClientEffect.h"
  13. // RAVEN END
  14.  
  15. /*
  16. ===============================================================================
  17.  
  18.     Ingame cursor.
  19.  
  20. ===============================================================================
  21. */
  22.  
  23. CLASS_DECLARATION( idEntity, idCursor3D )
  24. END_CLASS
  25.  
  26. /*
  27. ===============
  28. idCursor3D::idCursor3D
  29. ===============
  30. */
  31. idCursor3D::idCursor3D( void ) {
  32.     draggedPosition.Zero();
  33. }
  34.  
  35. /*
  36. ===============
  37. idCursor3D::~idCursor3D
  38. ===============
  39. */
  40. idCursor3D::~idCursor3D( void ) {
  41. }
  42.  
  43. /*
  44. ===============
  45. idCursor3D::Spawn
  46. ===============
  47. */
  48. void idCursor3D::Spawn( void ) {
  49. }
  50.  
  51. /*
  52. ===============
  53. idCursor3D::Present
  54. ===============
  55. */
  56. void idCursor3D::Present( void ) {
  57.     // don't present to the renderer if the entity hasn't changed
  58.     if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
  59.         return;
  60.     }
  61.     BecomeInactive( TH_UPDATEVISUALS );
  62.  
  63.     const idVec3 &origin = GetPhysics()->GetOrigin();
  64.     const idMat3 &axis = GetPhysics()->GetAxis();
  65.     gameRenderWorld->DebugArrow( colorYellow, origin + axis[1] * -5.0f + axis[2] * 5.0f, origin, 2 );
  66.     gameRenderWorld->DebugArrow( colorRed, origin, draggedPosition, 2 );
  67. }
  68.  
  69. /*
  70. ===============
  71. idCursor3D::Think
  72. ===============
  73. */
  74. void idCursor3D::Think( void ) {
  75.     if ( thinkFlags & TH_THINK ) {
  76.         drag.Evaluate( gameLocal.time );
  77.     }
  78.     Present();
  79. }
  80.  
  81.  
  82. /*
  83. ===============================================================================
  84.  
  85.     Allows entities to be dragged through the world with physics.
  86.  
  87. ===============================================================================
  88. */
  89.  
  90. #define MAX_DRAG_TRACE_DISTANCE            2048.0f
  91.  
  92. /*
  93. ==============
  94. idDragEntity::idDragEntity
  95. ==============
  96. */
  97. idDragEntity::idDragEntity( void ) {
  98.     cursor = NULL;
  99.     Clear();
  100. }
  101.  
  102. /*
  103. ==============
  104. idDragEntity::~idDragEntity
  105. ==============
  106. */
  107. idDragEntity::~idDragEntity( void ) {
  108.     StopDrag();
  109.     selected = NULL;
  110.     delete cursor;
  111.     cursor = NULL;
  112. }
  113.  
  114.  
  115. /*
  116. ==============
  117. idDragEntity::Clear
  118. ==============
  119. */
  120. void idDragEntity::Clear() {
  121.     dragEnt            = NULL;
  122.     joint            = INVALID_JOINT;
  123.     id                = 0;
  124.     localEntityPoint.Zero();
  125.     localPlayerPoint.Zero();
  126.     bodyName.Clear();
  127.     selected        = NULL;
  128. }
  129.  
  130. /*
  131. ==============
  132. idDragEntity::StopDrag
  133. ==============
  134. */
  135. void idDragEntity::StopDrag( void ) {
  136.     dragEnt = NULL;
  137.     if ( cursor ) {
  138.         cursor->BecomeInactive( TH_THINK );
  139.     }
  140. }
  141.  
  142. /*
  143. ==============
  144. idDragEntity::Update
  145. ==============
  146. */
  147. void idDragEntity::Update( idPlayer *player ) {
  148.     idVec3 viewPoint, origin;
  149.     idMat3 viewAxis, axis;
  150.     trace_t trace;
  151.     idEntity *newEnt;
  152.     idAngles angles;
  153.     jointHandle_t newJoint = INVALID_JOINT;
  154.     idStr newBodyName;
  155.  
  156.     player->GetViewPos( viewPoint, viewAxis );
  157.  
  158.     // if no entity selected for dragging
  159.     if ( !dragEnt.GetEntity() ) {
  160.  
  161.         if ( player->usercmd.buttons & BUTTON_ATTACK ) {
  162. // RAVEN BEGIN
  163. // ddynerman: multiple clip worlds
  164.             gameLocal.TracePoint( player, trace, viewPoint, viewPoint + viewAxis[0] * MAX_DRAG_TRACE_DISTANCE, (CONTENTS_SOLID|CONTENTS_RENDERMODEL|CONTENTS_BODY), player );
  165. // RAVEN END
  166.             if ( trace.fraction < 1.0f ) {
  167.  
  168.                 newEnt = gameLocal.entities[ trace.c.entityNum ];
  169.                 if ( newEnt ) {
  170.  
  171.                     if ( newEnt->GetBindMaster() ) {
  172.                         if ( newEnt->GetBindJoint() ) {
  173.                             trace.c.id = JOINT_HANDLE_TO_CLIPMODEL_ID( newEnt->GetBindJoint() );
  174.                         } else {
  175.                             trace.c.id = newEnt->GetBindBody();
  176.                         }
  177.                         newEnt = newEnt->GetBindMaster();
  178.                     }
  179.  
  180. // RAVEN BEGIN
  181. // jnewquist: Use accessor for static class type 
  182.                     if ( newEnt->IsType( idAFEntity_Base::GetClassType() ) && static_cast<idAFEntity_Base *>(newEnt)->IsActiveAF() ) {
  183. // RAVEN END
  184.                         idAFEntity_Base *af = static_cast<idAFEntity_Base *>(newEnt);
  185.  
  186.                         // joint being dragged
  187.                         newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
  188.                         // get the body id from the trace model id which might be a joint handle
  189.                         trace.c.id = af->BodyForClipModelId( trace.c.id );
  190.                         // get the name of the body being dragged
  191.                         newBodyName = af->GetAFPhysics()->GetBody( trace.c.id )->GetName();
  192.  
  193. // RAVEN BEGIN
  194. // jnewquist: Use accessor for static class type 
  195.                     } else if ( !newEnt->IsType( idWorldspawn::GetClassType() ) ) {
  196. // RAVEN END
  197.  
  198.                         if ( trace.c.id < 0 ) {
  199.                             newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
  200.                         } else {
  201.                             newJoint = INVALID_JOINT;
  202.                         }
  203.                         newBodyName = "";
  204.  
  205.                     } else {
  206.  
  207.                         newJoint = INVALID_JOINT;
  208.                         newEnt = NULL;
  209.                     }
  210.                 }
  211.                 if ( newEnt ) {
  212.                     dragEnt = newEnt;
  213.                     selected = newEnt;
  214.                     joint = newJoint;
  215.                     id = trace.c.id;
  216.                     bodyName = newBodyName;
  217.  
  218.                     if ( !cursor ) {
  219. // RAVEN BEGIN
  220. // jnewquist: Use accessor for static class type 
  221.                         cursor = ( idCursor3D * )gameLocal.SpawnEntityType( idCursor3D::GetClassType() );
  222. // RAVEN END
  223.                     }
  224.  
  225.                     idPhysics *phys = dragEnt.GetEntity()->GetPhysics();
  226.                     localPlayerPoint = ( trace.c.point - viewPoint ) * viewAxis.Transpose();
  227.                     origin = phys->GetOrigin( id );
  228.                     axis = phys->GetAxis( id );
  229.                     localEntityPoint = ( trace.c.point - origin ) * axis.Transpose();
  230.  
  231.                     cursor->drag.Init( g_dragDamping.GetFloat() );
  232.                     cursor->drag.SetPhysics( phys, id, localEntityPoint );
  233.                     cursor->Show();
  234.  
  235. // RAVEN BEGIN
  236. // jnewquist: Use accessor for static class type 
  237.                     if ( phys->IsType( idPhysics_AF::GetClassType() ) ||
  238.                             phys->IsType( idPhysics_RigidBody::GetClassType() ) ||
  239.                                 phys->IsType( idPhysics_Monster::GetClassType() ) ) {
  240. // RAVEN END
  241.                         cursor->BecomeActive( TH_THINK );
  242.                     }
  243.                 }
  244.             }
  245.         }
  246.     }
  247.  
  248.     // if there is an entity selected for dragging
  249.     idEntity *drag = dragEnt.GetEntity();
  250.     if ( drag ) {
  251.  
  252.         if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) {
  253.             StopDrag();
  254.             return;
  255.         }
  256.  
  257.         cursor->SetOrigin( viewPoint + localPlayerPoint * viewAxis );
  258.         cursor->SetAxis( viewAxis );
  259.  
  260.         cursor->drag.SetDragPosition( cursor->GetPhysics()->GetOrigin() );
  261.  
  262.         renderEntity_t *renderEntity = drag->GetRenderEntity();
  263.         idAnimator *dragAnimator = drag->GetAnimator();
  264.  
  265.         if ( joint != INVALID_JOINT && renderEntity && dragAnimator ) {
  266.             dragAnimator->GetJointTransform( joint, gameLocal.time, cursor->draggedPosition, axis );
  267.             cursor->draggedPosition = renderEntity->origin + cursor->draggedPosition * renderEntity->axis;
  268.             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 );
  269.         } else {
  270.             cursor->draggedPosition = cursor->GetPhysics()->GetOrigin();
  271.             gameRenderWorld->DrawText( va( "%s\n%s\n%s", drag->GetName(), drag->GetType()->classname, bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 );
  272.         }
  273.     }
  274.  
  275.     // if there is a selected entity
  276.     if ( selected.GetEntity() && g_dragShowSelection.GetBool() ) {
  277.         // draw the bbox of the selected entity
  278.         renderEntity_t *renderEntity = selected.GetEntity()->GetRenderEntity();
  279.         if ( renderEntity ) {
  280.             gameRenderWorld->DebugBox( colorYellow, idBox( renderEntity->bounds, renderEntity->origin, renderEntity->axis ) );
  281.         }
  282.     }
  283. }
  284.  
  285. /*
  286. ==============
  287. idDragEntity::SetSelected
  288. ==============
  289. */
  290. void idDragEntity::SetSelected( idEntity *ent ) {
  291.     selected = ent;
  292.     StopDrag();
  293. }
  294.  
  295. /*
  296. ==============
  297. idDragEntity::DeleteSelected
  298. ==============
  299. */
  300. void idDragEntity::DeleteSelected( void ) {
  301.     delete selected.GetEntity();
  302.     selected = NULL;
  303.     StopDrag();
  304. }
  305.  
  306. /*
  307. ==============
  308. idDragEntity::BindSelected
  309. ==============
  310. */
  311. void idDragEntity::BindSelected( void ) {
  312.     int num, largestNum;
  313.     idLexer lexer;
  314.     idToken type, bodyName;
  315.     idStr key, value, bindBodyName;
  316.     const idKeyValue *kv;
  317.     idAFEntity_Base *af;
  318.  
  319.     af = static_cast<idAFEntity_Base *>(dragEnt.GetEntity());
  320.  
  321. // RAVEN BEGIN
  322. // jnewquist: Use accessor for static class type 
  323.     if ( !af || !af->IsType( idAFEntity_Base::GetClassType() ) || !af->IsActiveAF() ) {
  324. // RAVEN END
  325.         return;
  326.     }
  327.  
  328.     bindBodyName = af->GetAFPhysics()->GetBody( id )->GetName();
  329.     largestNum = 1;
  330.  
  331.     // parse all the bind constraints
  332.     kv = af->spawnArgs.MatchPrefix( "bindConstraint ", NULL );
  333.     while ( kv ) {
  334.         key = kv->GetKey();
  335.         key.Strip( "bindConstraint " );
  336.         if ( sscanf( key, "bind%d", &num ) ) {
  337.             if ( num >= largestNum ) {
  338.                 largestNum = num + 1;
  339.             }
  340.         }
  341.  
  342.         lexer.LoadMemory( kv->GetValue(), kv->GetValue().Length(), kv->GetKey() );
  343.         lexer.ReadToken( &type );
  344.         lexer.ReadToken( &bodyName );
  345.         lexer.FreeSource();
  346.  
  347.         // if there already exists a bind constraint for this body
  348.         if ( bodyName.Icmp( bindBodyName ) == 0 ) {
  349.             // delete the bind constraint
  350.             af->spawnArgs.Delete( kv->GetKey() );
  351.             kv = NULL;
  352.         }
  353.  
  354.         kv = af->spawnArgs.MatchPrefix( "bindConstraint ", kv );
  355.     }
  356.  
  357.     sprintf( key, "bindConstraint bind%d", largestNum );
  358.     sprintf( value, "ballAndSocket %s %s", bindBodyName.c_str(), af->GetAnimator()->GetJointName( joint ) );
  359.  
  360.     af->spawnArgs.Set( key, value );
  361.     af->spawnArgs.Set( "bind", "worldspawn" );
  362.     af->Bind( gameLocal.world, true );
  363. }
  364.  
  365. /*
  366. ==============
  367. idDragEntity::UnbindSelected
  368. ==============
  369. */
  370. void idDragEntity::UnbindSelected( void ) {
  371.     const idKeyValue *kv;
  372.     idAFEntity_Base *af;
  373.  
  374.     af = static_cast<idAFEntity_Base *>(selected.GetEntity());
  375.  
  376. // RAVEN BEGIN
  377. // jnewquist: Use accessor for static class type 
  378.     if ( !af || !af->IsType( idAFEntity_Base::GetClassType() ) || !af->IsActiveAF() ) {
  379. // RAVEN END
  380.         return;
  381.     }
  382.  
  383.     // unbind the selected entity
  384.     af->Unbind();
  385.  
  386.     // delete all the bind constraints
  387.     kv = selected.GetEntity()->spawnArgs.MatchPrefix( "bindConstraint ", NULL );
  388.     while ( kv ) {
  389.         selected.GetEntity()->spawnArgs.Delete( kv->GetKey() );
  390.         kv = selected.GetEntity()->spawnArgs.MatchPrefix( "bindConstraint ", NULL );
  391.     }
  392.  
  393.     // delete any bind information
  394.     af->spawnArgs.Delete( "bind" );
  395.     af->spawnArgs.Delete( "bindToJoint" );
  396.     af->spawnArgs.Delete( "bindToBody" );
  397. }
  398.  
  399.  
  400. /*
  401. ===============================================================================
  402.  
  403.     Handles ingame entity editing.
  404.  
  405. ===============================================================================
  406. */
  407.  
  408. /*
  409. ==============
  410. idEditEntities::idEditEntities
  411. ==============
  412. */
  413. idEditEntities::idEditEntities( void ) {
  414.     selectableEntityClasses.Clear();
  415.     nextSelectTime = 0;
  416. }
  417.  
  418. // RAVEN BEGIN
  419. // bdube: made this special to edit entities
  420. /*
  421. =============
  422. idEditEntities::FindTraceEntity
  423. =============
  424. */
  425. idEntity* idEditEntities::FindTraceEntity( idVec3 start, idVec3 end, const idEntity *skip ) {
  426.     idEntity *ent;
  427.     idEntity *bestEnt;
  428.     float scale;
  429.     float bestScale;
  430.     idBounds b;
  431.  
  432.     bestEnt = NULL;
  433.     bestScale = 1.0f;
  434.     for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  435.         if ( ent != skip && EntityIsSelectable ( ent ) ) {
  436.             b = ent->GetPhysics()->GetAbsBounds().Expand( 16 );
  437.             if ( b.RayIntersection( start, end-start, scale ) ) {
  438.                 if ( scale >= 0.0f && scale < bestScale ) {
  439.                     bestEnt = ent;
  440.                     bestScale = scale;
  441.                 }
  442.             }
  443.         }
  444.     }
  445.  
  446.     return bestEnt;
  447. }
  448. // RAVEN END
  449.  
  450. /*
  451. =============
  452. idEditEntities::SelectEntity
  453. =============
  454. */
  455. bool idEditEntities::SelectEntity( const idVec3 &origin, const idVec3 &dir, const idEntity *skip ) {
  456.     idVec3        end;
  457.     idEntity    *ent;
  458.  
  459.     if ( !g_editEntityMode.GetInteger() || selectableEntityClasses.Num() == 0 ) {
  460.         return false;
  461.     }
  462.  
  463.     if ( gameLocal.time < nextSelectTime ) {
  464.         return true;
  465.     }
  466.     nextSelectTime = gameLocal.time + 300;
  467.  
  468.     end = origin + dir * 4096.0f;
  469.  
  470. // RAVEN BEGIN
  471. // bdube: more generic
  472.     ent = NULL;
  473.     for ( int i = 0; i < selectableEntityClasses.Num(); i++ ) {
  474.         ent = FindTraceEntity( origin, end, skip );
  475.         if ( ent ) {
  476.             break;
  477.         }
  478.     }
  479.     if ( !ent ) {
  480.         return false;
  481.     }
  482.     
  483.     ClearSelectedEntities();
  484.  
  485.     AddSelectedEntity( ent );
  486.     gameLocal.Printf( "entity #%d: %s '%s'\n", ent->entityNumber, ent->GetClassname(), ent->name.c_str() );
  487.  
  488.     if ( gameLocal.editors & EDITOR_ENTVIEW ) {
  489.         common->InitTool ( EDITOR_ENTVIEW, &ent->spawnArgs );
  490.     } else {
  491.         ent->ShowEditingDialog();
  492.     }
  493.  
  494.     return true;
  495. // RAVEN END
  496. }
  497.  
  498. /*
  499. =============
  500. idEditEntities::AddSelectedEntity
  501. =============
  502. */
  503. void idEditEntities::AddSelectedEntity(idEntity *ent) {
  504.     ent->fl.selected = true;
  505.     selectedEntities.AddUnique(ent);
  506. }
  507.  
  508. /*
  509. ==============
  510. idEditEntities::RemoveSelectedEntity
  511. ==============
  512. */
  513. void idEditEntities::RemoveSelectedEntity( idEntity *ent ) {
  514.     if ( selectedEntities.Find( ent ) ) {
  515.         selectedEntities.Remove( ent );
  516.     }
  517. }
  518.  
  519. /*
  520. =============
  521. idEditEntities::ClearSelectedEntities
  522. =============
  523. */
  524. void idEditEntities::ClearSelectedEntities() {
  525.     int i, count;
  526.  
  527.     count = selectedEntities.Num();
  528.     for ( i = 0; i < count; i++ ) {
  529.         selectedEntities[i]->fl.selected = false;
  530.     }
  531.     selectedEntities.Clear();
  532. }
  533.  
  534.  
  535. /*
  536. =============
  537. idEditEntities::EntityIsSelectable
  538. =============
  539. */
  540. bool idEditEntities::EntityIsSelectable( idEntity *ent, idVec4 *color, idStr *text ) {
  541. // RAVEN BEGIN
  542. // bdube: no matter what dont let the player or its entities be selectable
  543.     idPlayer* player;
  544.     if ( 0 != (player = gameLocal.GetLocalPlayer() )) {
  545.         if ( ent == player || ent == player->GetWeaponViewModel ( ) || ent == player->GetWeaponWorldModel ( ) ) {
  546.             return false;
  547.         }
  548.     }
  549.     for ( int i = 0; i < selectableEntityClasses.Num(); i++ ) {
  550.         if ( ent->IsType ( *selectableEntityClasses[i].typeInfo ) ) {        
  551. // RAVEN END
  552.             if ( text ) {
  553.                 *text = selectableEntityClasses[i].textKey;
  554.             }
  555.             if ( color ) {
  556.                 if ( ent->fl.selected ) {
  557.                     *color = colorRed;
  558.                 } else {
  559.                     switch( i ) {
  560.                     case 1 :
  561.                         *color = colorYellow;
  562.                         break;
  563.                     case 2 :
  564.                         *color = colorBlue;
  565.                         break;
  566.                     default:
  567.                         *color = colorGreen;
  568.                     }
  569.                 }
  570.             }
  571.             return true;
  572.         }
  573.     }
  574.     return false;
  575. }
  576.  
  577. /*
  578. =============
  579. idEditEntities::DisplayEntities
  580. =============
  581. */
  582. void idEditEntities::DisplayEntities( void ) {
  583.     idEntity *ent;
  584.  
  585.     if ( !gameLocal.GetLocalPlayer() ) {
  586.         return;
  587.     }
  588.  
  589.     selectableEntityClasses.Clear();
  590.     selectedTypeInfo_t sit;
  591.  
  592.     switch( g_editEntityMode.GetInteger() ) {
  593.         case 1:
  594. // RAVEN BEGIN
  595. // jnewquist: Use accessor for static class type 
  596.             sit.typeInfo = &idLight::GetClassType();
  597. // RAVEN END
  598.             sit.textKey = "texture";
  599.             selectableEntityClasses.Append( sit );
  600.             break;
  601.         case 2:
  602. // RAVEN BEGIN
  603. // jnewquist: Use accessor for static class type 
  604.             sit.typeInfo = &idSound::GetClassType();
  605. // scork: added secondary "name" field as well (Zack request)
  606.             sit.textKey = "s_shader|name";
  607.             selectableEntityClasses.Append( sit );
  608. // scork: Zack (reasonably enough) doesn't want the lights displayed when editing sounds
  609. //            sit.typeInfo = &idLight::GetClassType();
  610. //            sit.textKey = "texture";
  611. //            selectableEntityClasses.Append( sit );
  612. // RAVEN END
  613.             break;
  614.         case 3:
  615. // RAVEN BEGIN
  616. // jnewquist: Use accessor for static class type 
  617.             sit.typeInfo = &idAFEntity_Base::GetClassType();
  618. // RAVEN END
  619.             sit.textKey = "articulatedFigure";
  620.             selectableEntityClasses.Append( sit );
  621.             break;
  622.         case 4:
  623. // RAVEN BEGIN
  624. // jnewquist: Use accessor for static class type 
  625.             sit.typeInfo = &idFuncEmitter::GetClassType();
  626. // RAVEN END
  627.             sit.textKey = "model";
  628.             selectableEntityClasses.Append( sit );
  629.             break;
  630.         case 5:
  631. // RAVEN BEGIN
  632. // jnewquist: Use accessor for static class type 
  633.             sit.typeInfo = &idAI::GetClassType();
  634. // RAVEN END
  635.             sit.textKey = "name";
  636.             selectableEntityClasses.Append( sit );
  637.             break;
  638.         case 6:
  639. // RAVEN BEGIN
  640. // jnewquist: Use accessor for static class type 
  641.             sit.typeInfo = &idEntity::GetClassType();
  642. // RAVEN END
  643.             sit.textKey = "name";
  644.             selectableEntityClasses.Append( sit );
  645.             break;
  646.         case 7:
  647. // RAVEN BEGIN
  648. // jnewquist: Use accessor for static class type 
  649.             sit.typeInfo = &idEntity::GetClassType();
  650. // RAVEN END
  651.             sit.textKey = "model";
  652.             selectableEntityClasses.Append( sit );
  653.             break;
  654. // RAVEN BEGIN
  655. // bdube: added fx entities
  656.         case 8:
  657. // RAVEN BEGIN
  658. // jnewquist: Use accessor for static class type 
  659.             sit.typeInfo = &rvEffect::GetClassType();
  660. // RAVEN END
  661.             sit.textKey = "fx";
  662.             selectableEntityClasses.Append ( sit );
  663.             break;
  664. // RAVEN END                        
  665.         default:
  666.             return;
  667.     }
  668.  
  669.     idBounds viewBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
  670.     idBounds viewTextBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
  671.     idMat3 axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3();
  672.  
  673.     viewBounds.ExpandSelf( g_editEntityDistance.GetFloat() );
  674. // RAVEN BEGIN
  675. // scork: changed from 128 to 256 so we can see speaker ent descriptions before getting right up to them
  676. // rhummer: Added cvar to adjust the distance for the text too.
  677.     viewTextBounds.ExpandSelf( g_editEntityTextDistance.GetFloat() );
  678. // RAVEN END
  679.  
  680.     idStr textKey;
  681. // RAVEN BEGIN
  682. // scork: secondary field
  683.     idStr textKey2;
  684.     idStr strOutput;
  685. // RAVEN END
  686.  
  687.     for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  688.  
  689.         idVec4 color;
  690.  
  691.         textKey = "";
  692.         if ( !EntityIsSelectable( ent, &color, &textKey ) ) {
  693.             continue;
  694.         }
  695.  
  696. // RAVEN BEGIN
  697. // scork: handle optional secondary field
  698.         textKey2 = "";
  699.         int iIndex = textKey.Find('|');
  700.         if (iIndex >= 0)
  701.         {
  702.             textKey2 = textKey.Mid ( iIndex+1, textKey.Length()-(iIndex+1) );    // hmmm, they emulate 99% of MS CString but don't have a single-param Mid() func?
  703.             textKey  = textKey.Left( iIndex );
  704.         }
  705. // RAVEN END
  706.  
  707.  
  708.         bool drawArrows = false;
  709. // RAVEN BEGIN
  710. // bdube: added        
  711.         bool drawDirection = false;
  712. // RAVEN END
  713. // RAVEN BEGIN
  714. // jnewquist: Use accessor for static class type 
  715.         if ( ent->GetType() == &idAFEntity_Base::GetClassType() ) {
  716. // RAVEN END
  717.             if ( !static_cast<idAFEntity_Base *>(ent)->IsActiveAF() ) {
  718.                 continue;
  719.             }
  720. // RAVEN BEGIN
  721. // jnewquist: Use accessor for static class type 
  722.         } else if ( ent->GetType() == &idSound::GetClassType() ) {
  723. // RAVEN END
  724.             if ( ent->fl.selected ) 
  725.             {
  726.                 drawArrows = true;
  727.                 int iFlag = ent->GetRefSoundShaderFlags();
  728.                 iFlag |= SSF_HILITE;
  729.                 ent->SetRefSoundShaderFlags( iFlag );
  730.             }
  731.             else
  732.             {
  733.                 int iFlag = ent->GetRefSoundShaderFlags();
  734.                 iFlag &= ~SSF_HILITE;
  735.                 ent->SetRefSoundShaderFlags( iFlag );
  736.             }
  737.             ent->UpdateSound();
  738.             const idSoundShader * ss = declManager->FindSound( ent->spawnArgs.GetString( textKey ) );
  739.             if ( ss->HasDefaultSound() || ss->base->GetState() == DS_DEFAULTED ) {
  740.                 color.Set( 1.0f, 0.0f, 1.0f, 1.0f );
  741.             }
  742. // RAVEN BEGIN
  743. // bdube: added            
  744. // jnewquist: Use accessor for static class type 
  745.         } else if ( ent->GetType() == &rvEffect::GetClassType() ) {
  746.             drawDirection = true;
  747.             if ( ent->fl.selected ) {
  748.                 drawArrows = true;
  749.             }
  750.         } else if ( ent->GetType() == &idFuncEmitter::GetClassType() ) {
  751. // RAVEN END
  752.             if ( ent->fl.selected ) {
  753.                 drawArrows = true;
  754.             }
  755.         }
  756.  
  757.         if ( !viewBounds.ContainsPoint( ent->GetPhysics()->GetOrigin() ) ) {
  758.             continue;
  759.         }
  760.  
  761.         gameRenderWorld->DebugBounds( color, idBounds( ent->GetPhysics()->GetOrigin() ).Expand( 8 ) );
  762.         if ( drawArrows ) {
  763.             idVec3 start = ent->GetPhysics()->GetOrigin();
  764.             idVec3 end = start + idVec3( 1, 0, 0 ) * 20.0f;
  765.             gameRenderWorld->DebugArrow( colorWhite, start, end, 2 );
  766.             gameRenderWorld->DrawText( "x+", end + idVec3( 4, 0, 0 ), 0.15f, colorWhite, axis );
  767.             end = start + idVec3( 1, 0, 0 ) * -20.0f;
  768.             gameRenderWorld->DebugArrow( colorWhite, start, end, 2 );
  769.             gameRenderWorld->DrawText( "x-", end + idVec3( -4, 0, 0 ), 0.15f, colorWhite, axis );
  770.             end = start + idVec3( 0, 1, 0 ) * +20.0f;
  771.             gameRenderWorld->DebugArrow( colorGreen, start, end, 2 );
  772.             gameRenderWorld->DrawText( "y+", end + idVec3( 0, 4, 0 ), 0.15f, colorWhite, axis );
  773.             end = start + idVec3( 0, 1, 0 ) * -20.0f;
  774.             gameRenderWorld->DebugArrow( colorGreen, start, end, 2 );
  775.             gameRenderWorld->DrawText( "y-", end + idVec3( 0, -4, 0 ), 0.15f, colorWhite, axis );
  776.             end = start + idVec3( 0, 0, 1 ) * +20.0f;
  777.             gameRenderWorld->DebugArrow( colorBlue, start, end, 2 );
  778.             gameRenderWorld->DrawText( "z+", end + idVec3( 0, 0, 4 ), 0.15f, colorWhite, axis );
  779.             end = start + idVec3( 0, 0, 1 ) * -20.0f;
  780.             gameRenderWorld->DebugArrow( colorBlue, start, end, 2 );
  781.             gameRenderWorld->DrawText( "z-", end + idVec3( 0, 0, -4 ), 0.15f, colorWhite, axis );
  782.         }
  783.  
  784. // RAVEN BEGIN
  785. // bdube: added
  786.         if ( drawDirection ) {
  787.             idVec3 start = ent->GetPhysics()->GetOrigin ( );
  788.             idVec3 end   = start + ent->GetPhysics()->GetAxis()[0] * 35.0f;
  789.             gameRenderWorld->DebugArrow ( colorYellow, start, end, 6 );
  790.         }
  791. // RAVEN END
  792.  
  793.         if ( textKey.Length() ) {
  794. // RAVEN BEGIN
  795. // scork: handle optional secondary field, plus only call GetString when bounds are within view
  796.             if ( viewTextBounds.ContainsPoint( ent->GetPhysics()->GetOrigin() ) ) {
  797.                 strOutput = ent->spawnArgs.GetString( textKey );
  798.                 if (!textKey2.IsEmpty())
  799.                 {
  800.                     strOutput += " ( ";
  801.                     strOutput += ent->spawnArgs.GetString( textKey2 );
  802.                     strOutput += " )";
  803.                 }
  804.                 gameRenderWorld->DrawText( strOutput.c_str(), ent->GetPhysics()->GetOrigin() + idVec3(0, 0, 12), 0.25, colorWhite, axis, 1 );
  805.             }
  806. // RAVEN END
  807.         }
  808.     }
  809. }
  810.  
  811.  
  812. /*
  813. ===============================================================================
  814.  
  815.     idGameEdit
  816.  
  817. ===============================================================================
  818. */
  819.  
  820. idGameEdit            gameEditLocal;
  821. idGameEdit *        gameEdit = &gameEditLocal;
  822.  
  823.  
  824. /*
  825. =============
  826. idGameEdit::GetSelectedEntities
  827. =============
  828. */
  829. int idGameEdit::GetSelectedEntities( idEntity *list[], int max ) {
  830.     int num = 0;
  831.     idEntity *ent;
  832.  
  833.     for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  834.         if ( ent->fl.selected ) {
  835.             list[num++] = ent;
  836.             if ( num >= max ) {
  837.                 break;
  838.             }
  839.         }
  840.     }
  841.     return num;
  842. }
  843.  
  844. /*
  845. =============
  846. idGameEdit::TriggerSelected
  847. =============
  848. */
  849. void idGameEdit::TriggerSelected() {
  850.     idEntity *ent;
  851.     for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  852.         if ( ent->fl.selected ) {
  853.             ent->ProcessEvent( &EV_Activate, gameLocal.GetLocalPlayer() );
  854.         }
  855.     }
  856. }
  857.  
  858. /*
  859. ================
  860. idGameEdit::ClearEntitySelection
  861. ================
  862. */
  863. void idGameEdit::ClearEntitySelection() {
  864.     idEntity *ent;
  865.  
  866.     for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  867.         ent->fl.selected = false;
  868.     }
  869. // RAVEN BEGIN
  870. // bdube: fixed potential crash    
  871.     if ( gameLocal.editEntities ) {
  872.         gameLocal.editEntities->ClearSelectedEntities();
  873.     }
  874. // RAVEN END
  875. }
  876.  
  877. /*
  878. ================
  879. idGameEdit::AddSelectedEntity
  880. ================
  881. */
  882. void idGameEdit::AddSelectedEntity( idEntity *ent ) {
  883. // RAVEN BEGIN
  884. // mekberg: fixed crash
  885.     if ( ent && gameLocal.editEntities ) {
  886.         gameLocal.editEntities->AddSelectedEntity( ent );
  887.     }
  888. // RAVEN END
  889. }
  890.  
  891. /*
  892. ================
  893. idGameEdit::FindEntityDefDict
  894. ================
  895. */
  896. const idDict *idGameEdit::FindEntityDefDict( const char *name, bool makeDefault ) const {
  897.     return gameLocal.FindEntityDefDict( name, makeDefault );
  898. }
  899.  
  900. /*
  901. ================
  902. idGameEdit::SpawnEntityDef
  903. ================
  904. */
  905. void idGameEdit::SpawnEntityDef( const idDict &args, idEntity **ent ) {
  906.     gameLocal.SpawnEntityDef( args, ent );
  907. }
  908.  
  909. /*
  910. ================
  911. idGameEdit::FindEntity
  912. ================
  913. */
  914. idEntity *idGameEdit::FindEntity( const char *name ) const {
  915.     return gameLocal.FindEntity( name ); 
  916. }
  917.  
  918. /*
  919. =============
  920. idGameEdit::GetUniqueEntityName
  921.  
  922. generates a unique name for a given classname
  923. =============
  924. */
  925. const char *idGameEdit::GetUniqueEntityName( const char *classname ) const {
  926.     int            id;
  927.     static char    name[1024];
  928.  
  929.     // can only have MAX_GENTITIES, so if we have a spot available, we're guaranteed to find one
  930.     for( id = 0; id < MAX_GENTITIES; id++ ) {
  931.         idStr::snPrintf( name, sizeof( name ), "%s_%d", classname, id );
  932.         if ( !gameLocal.FindEntity( name ) ) {
  933.             return name;
  934.         }
  935.     }
  936.  
  937.     // id == MAX_GENTITIES + 1, which can't be in use if we get here
  938.     idStr::snPrintf( name, sizeof( name ), "%s_%d", classname, id );
  939.     return name;
  940. }
  941.  
  942. /*
  943. ================
  944. idGameEdit::EntityGetOrigin
  945. ================
  946. */
  947. void  idGameEdit::EntityGetOrigin( idEntity *ent, idVec3 &org ) const {
  948.     if ( ent ) {
  949.         org = ent->GetPhysics()->GetOrigin();
  950.     }
  951. }
  952.  
  953. /*
  954. ================
  955. idGameEdit::EntityGetAxis
  956. ================
  957. */
  958. void idGameEdit::EntityGetAxis( idEntity *ent, idMat3 &axis ) const {
  959.     if ( ent ) {
  960.         axis = ent->GetPhysics()->GetAxis();
  961.     }
  962. }
  963.  
  964. /*
  965. ================
  966. idGameEdit::EntitySetOrigin
  967. ================
  968. */
  969. void idGameEdit::EntitySetOrigin( idEntity *ent, const idVec3 &org ) {
  970.     if ( ent ) {
  971.         ent->SetOrigin( org );
  972.     }
  973. }
  974.  
  975. /*
  976. ================
  977. idGameEdit::EntitySetAxis
  978. ================
  979. */
  980. void idGameEdit::EntitySetAxis( idEntity *ent, const idMat3 &axis ) {
  981.     if ( ent ) {
  982.         ent->SetAxis( axis );
  983.     }
  984. }
  985.  
  986. /*
  987. ================
  988. idGameEdit::EntitySetColor
  989. ================
  990. */
  991. void idGameEdit::EntitySetColor( idEntity *ent, const idVec3 color ) {
  992.     if ( ent ) {
  993.         ent->SetColor( color );
  994.     }
  995. }
  996.  
  997. /*
  998. ================
  999. idGameEdit::EntityTranslate
  1000. ================
  1001. */
  1002. void idGameEdit::EntityTranslate( idEntity *ent, const idVec3 &org ) {
  1003.     if ( ent ) {
  1004.         ent->GetPhysics()->Translate( org );
  1005.     }
  1006. }
  1007.  
  1008. /*
  1009. ================
  1010. idGameEdit::EntityGetSpawnArgs
  1011. ================
  1012. */
  1013. // RAVEN BEGIN
  1014. // scork: const-qualified 'ent' so other things would compile
  1015. const idDict *idGameEdit::EntityGetSpawnArgs( const idEntity *ent ) const {
  1016. // RAVEN END
  1017.     if ( ent ) {
  1018.         return &ent->spawnArgs;
  1019.     }
  1020.     return NULL;
  1021. }
  1022.  
  1023. /*
  1024. ================
  1025. idGameEdit::EntityUpdateChangeableSpawnArgs
  1026. ================
  1027. */
  1028. void idGameEdit::EntityUpdateChangeableSpawnArgs( idEntity *ent, const idDict *dict ) {
  1029.     if ( ent ) {
  1030.         ent->UpdateChangeableSpawnArgs( dict );
  1031.     }
  1032. }
  1033.  
  1034. /*
  1035. ================
  1036. idGameEdit::EntityChangeSpawnArgs
  1037. ================
  1038. */
  1039. void idGameEdit::EntityChangeSpawnArgs( idEntity *ent, const idDict *newArgs ) {
  1040.     if ( ent ) {
  1041.         for ( int i = 0 ; i < newArgs->GetNumKeyVals () ; i ++ ) {
  1042.             const idKeyValue *kv = newArgs->GetKeyVal( i );
  1043.             
  1044.             if ( kv->GetValue().Length() > 0 ) {
  1045.                 ent->spawnArgs.Set ( kv->GetKey() ,kv->GetValue() );
  1046.             } else {
  1047.                 ent->spawnArgs.Delete ( kv->GetKey() );
  1048.             }
  1049.         }
  1050.     }
  1051. }
  1052.  
  1053. /*
  1054. ================
  1055. idGameEdit::EntityUpdateVisuals
  1056. ================
  1057. */
  1058. void idGameEdit::EntityUpdateVisuals( idEntity *ent ) {
  1059.     if ( ent ) {
  1060.         ent->UpdateVisuals();
  1061.     }
  1062. }
  1063.  
  1064. /*
  1065. ================
  1066. idGameEdit::EntitySetModel
  1067. ================
  1068. */
  1069. void idGameEdit::EntitySetModel( idEntity *ent, const char *val ) {
  1070.     if ( ent ) {
  1071.         ent->spawnArgs.Set( "model", val );
  1072.         ent->SetModel( val );
  1073.     }
  1074. }
  1075.  
  1076. /*
  1077. ================
  1078. idGameEdit::EntityStopSound
  1079. ================
  1080. */
  1081. void idGameEdit::EntityStopSound( idEntity *ent ) {
  1082.     if ( ent ) {
  1083.         ent->StopSound( SND_CHANNEL_ANY, false );
  1084.     }
  1085. }
  1086.  
  1087. /*
  1088. ================
  1089. idGameEdit::EntityDelete
  1090. ================
  1091. */
  1092. void idGameEdit::EntityDelete( idEntity *ent ) {
  1093.     delete ent;
  1094. }
  1095.  
  1096. // RAVEN BEGIN
  1097. // bdube: added
  1098. /*
  1099. ================
  1100. idGameEdit::EntityGetRenderEntity
  1101. ================
  1102. */
  1103. renderEntity_t* idGameEdit::EntityGetRenderEntity ( idEntity* ent ) {
  1104.     return ent->GetRenderEntity();
  1105. }
  1106.  
  1107. /*
  1108. ================
  1109. idGameEdit::EntityGetName
  1110. ================
  1111. */
  1112. const char* idGameEdit::EntityGetName ( idEntity* ent ) const {
  1113.     if ( !ent ) {
  1114.         return "";
  1115.     }
  1116.     return ent->GetName();
  1117. }
  1118.  
  1119. /*
  1120. ================
  1121. idGameEdit::EntityGetClassname
  1122. ================
  1123. */
  1124. const char* idGameEdit::EntityGetClassname ( idEntity* ent ) const {
  1125.     return ent->GetType()->classname;
  1126. }
  1127.  
  1128. /*
  1129. ================
  1130. idGameEdit::EntityIsDerivedFrom
  1131. ================
  1132. */
  1133. bool idGameEdit::EntityIsDerivedFrom ( idEntity* ent, const char* classname ) const {
  1134.     idTypeInfo* type;
  1135.     type = idClass::GetClass ( classname );
  1136.     if ( !type ) {
  1137.         return false;
  1138.     }
  1139.     
  1140.     return ent->IsType ( *type );
  1141. }
  1142.  
  1143. /*
  1144. ================
  1145. idGameEdit::EntityIsValid
  1146. ================
  1147. */
  1148. int idGameEdit::EntityToSafeId ( idEntity* ent ) const {
  1149.     if ( !ent ) {
  1150.         return 0;
  1151.     }
  1152.     return ( gameLocal.spawnIds[ent->entityNumber] << GENTITYNUM_BITS ) | ent->entityNumber;
  1153. }
  1154.  
  1155. /*
  1156. ================
  1157. idGameEdit::EntityFromSafeId
  1158. ================
  1159. */
  1160. idEntity *idGameEdit::EntityFromSafeId( int safeID ) const {
  1161.     int entityNum = safeID & ( ( 1 << GENTITYNUM_BITS ) - 1 );
  1162.     if ( ( gameLocal.spawnIds[ entityNum ] == ( safeID >> GENTITYNUM_BITS ) ) ) {
  1163.         return gameLocal.entities[ entityNum ];
  1164.     }
  1165.     return NULL;
  1166. }
  1167.  
  1168. /*
  1169. ================
  1170. idGameEdit::EntitySetSkin
  1171. ================
  1172. */
  1173. void idGameEdit::EntitySetSkin ( idEntity* ent, const char* temp ) const {
  1174.     ent->SetSkin ( declManager->FindSkin ( temp ) );
  1175. }
  1176.  
  1177. /*
  1178. ================
  1179. idGameEdit::EntityClearSkin
  1180. ================
  1181. */
  1182. void idGameEdit::EntityClearSkin ( idEntity* ent ) const {
  1183.     ent->ClearSkin ( );
  1184. }
  1185.  
  1186. /*
  1187. ================
  1188. idGameEdit::EntityClearSkin
  1189. ================
  1190. */
  1191. void idGameEdit::EntityShow ( idEntity* ent ) const {
  1192.     ent->Show ( );
  1193. }
  1194.  
  1195. /*
  1196. ================
  1197. idGameEdit::EntityClearSkin
  1198. ================
  1199. */
  1200. void idGameEdit::EntityHide ( idEntity* ent ) const {
  1201.     ent->Hide ( );
  1202. }
  1203.  
  1204. /*
  1205. ================
  1206. idGameEdit::EntityGetBounds
  1207. ================
  1208. */
  1209. void idGameEdit::EntityGetBounds ( idEntity* ent, idBounds &bounds ) const {
  1210.     bounds = ent->GetRenderEntity()->bounds;
  1211. }
  1212.  
  1213. /*
  1214. ================
  1215. idGameEdit::EntityPlayAnim
  1216. ================
  1217. */
  1218. int idGameEdit::EntityPlayAnim ( idEntity* ent, int animNum, int time, int blendtime ) {
  1219.     if ( !ent->GetAnimator ( ) ) {
  1220.         return 0;
  1221.     }
  1222.     ent->GetAnimator()->PlayAnim ( ANIMCHANNEL_ALL, animNum, time, blendtime );
  1223.     ent->GetAnimator()->ServiceAnims ( time, time );
  1224.     return ent->GetAnimator()->CurrentAnim( ANIMCHANNEL_ALL )->GetEndTime ( );
  1225. }
  1226.  
  1227. /*
  1228. ================
  1229. idGameEdit::EntitySetFrame
  1230. ================
  1231. */
  1232. void idGameEdit::EntitySetFrame ( idEntity* ent, int animNum, int frame, int time, int blendtime ) {
  1233.     idAnimator* animator;
  1234.         
  1235.     animator = ent->GetAnimator ( );    
  1236.     if ( !animator ) {
  1237.         return;
  1238.     }
  1239.  
  1240.     animator->ClearAllAnims ( time, time );
  1241.     
  1242.     // Move to the first frame of the animation
  1243. // RAVEN BEGIN
  1244.     frameBlend_t frameBlend = { 0, frame, frame, 1.0f, 0 };
  1245.     animator->SetFrame ( ANIMCHANNEL_ALL, animNum, frameBlend );
  1246. // RAVEN END
  1247.     animator->ForceUpdate ( );
  1248. }
  1249.  
  1250. /*
  1251. ================
  1252. idGameEdit::EntityGetDelta
  1253. ================
  1254. */
  1255. void idGameEdit::EntityGetDelta ( idEntity* ent, int fromTime, int toTime, idVec3& delta ) {
  1256.     ent->GetAnimator()->GetDelta ( fromTime, toTime, delta );
  1257. }
  1258.  
  1259. /*
  1260. ================
  1261. idGameEdit::EntityRemoveOriginOffset
  1262. ================
  1263. */
  1264. void idGameEdit::EntityRemoveOriginOffset ( idEntity* ent, bool remove ) {
  1265.     ent->GetAnimator()->RemoveOriginOffset ( remove );
  1266. }
  1267.  
  1268. /*
  1269. ================
  1270. idGameEdit::EntityStopAllEffects
  1271. ================
  1272. */
  1273. void idGameEdit::EntityStopAllEffects ( idEntity* ent ) {
  1274.     ent->StopAllEffects ( );
  1275.     ent->StopSound ( SND_CHANNEL_ANY, false );
  1276. }
  1277.  
  1278. // RAVEN BEGIN
  1279. // scork: some accessor functions for various utils
  1280. idEntity *idGameEdit::EntityGetNextTeamEntity( idEntity *pEnt ) const {
  1281.     return pEnt->GetNextTeamEntity();
  1282. }
  1283. void idGameEdit::GetPlayerInfo( idVec3 &v3Origin, idMat3 &mat3Axis, int PlayerNum, idAngles *deltaViewAngles ) const
  1284. {
  1285.     game->GetPlayerInfo( v3Origin, mat3Axis, PlayerNum, deltaViewAngles );
  1286. }
  1287.  
  1288. void idGameEdit::SetPlayerInfo( idVec3 &v3Origin, idMat3 &mat3Axis, int PlayerNum ) const
  1289. {
  1290.     game->SetPlayerInfo( v3Origin, mat3Axis, PlayerNum );
  1291. }
  1292. void idGameEdit::EntitySetName( idEntity* pEnt, const char *psName )
  1293. {
  1294.     pEnt->SetName( psName );
  1295. }
  1296. // RAVEN END
  1297.  
  1298. /*
  1299. ================
  1300. idGameEdit::LightSetParms
  1301. ================
  1302. */
  1303. void idGameEdit::LightSetParms ( idEntity* ent, int maxLevel, int currentLevel, float radius ) {    
  1304.     int         data;
  1305.     idLight* light;
  1306.     
  1307.     // Switch to a light entity
  1308.     light = dynamic_cast<idLight*>(ent);
  1309.     if ( !light )
  1310.     {
  1311.         return;
  1312.     }
  1313.  
  1314.     light->ProcessEvent ( &EV_Light_SetMaxLightLevel, maxLevel );
  1315.     light->ProcessEvent ( &EV_Light_SetCurrentLightLevel, (int)currentLevel );
  1316.  
  1317.     (*(float*)&data) = radius;
  1318.     light->ProcessEventArgPtr ( &EV_Light_SetRadius, &data );        
  1319.     
  1320.     light->SetLightLevel();
  1321. }
  1322. // RAVEN END
  1323.  
  1324. /*
  1325. ================
  1326. idGameEdit::PlayerIsValid
  1327. ================
  1328. */
  1329. bool idGameEdit::PlayerIsValid() const {
  1330.     return ( gameLocal.GetLocalPlayer() != NULL );
  1331. }
  1332.  
  1333. /*
  1334. ================
  1335. idGameEdit::PlayerGetOrigin
  1336. ================
  1337. */
  1338. void idGameEdit::PlayerGetOrigin( idVec3 &org ) const {
  1339.     org = gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin();
  1340. }
  1341.  
  1342. /*
  1343. ================
  1344. idGameEdit::PlayerGetAxis
  1345. ================
  1346. */
  1347. void idGameEdit::PlayerGetAxis( idMat3 &axis ) const {
  1348.     axis = gameLocal.GetLocalPlayer()->GetPhysics()->GetAxis();
  1349. }
  1350.  
  1351. /*
  1352. ================
  1353. idGameEdit::PlayerGetViewAngles
  1354. ================
  1355. */
  1356. void idGameEdit::PlayerGetViewAngles( idAngles &angles ) const {
  1357.     angles = gameLocal.GetLocalPlayer()->viewAngles;
  1358. }
  1359.  
  1360. /*
  1361. ================
  1362. idGameEdit::PlayerGetEyePosition
  1363. ================
  1364. */
  1365. void idGameEdit::PlayerGetEyePosition( idVec3 &org ) const {
  1366.     org = gameLocal.GetLocalPlayer()->GetEyePosition();
  1367. }
  1368.  
  1369.  
  1370. /*
  1371. ================
  1372. idGameEdit::MapGetEntityDict
  1373. ================
  1374. */
  1375. const idDict *idGameEdit::MapGetEntityDict( const char *name ) const {
  1376.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1377.     if ( mapFile && name && *name ) {
  1378.         idMapEntity *mapent = mapFile->FindEntity( name );
  1379.         if ( mapent ) {
  1380.             return &mapent->epairs;
  1381.         }
  1382.     }
  1383.     return NULL;
  1384. }
  1385.  
  1386. /*
  1387. ================
  1388. idGameEdit::MapSave
  1389. ================
  1390. */
  1391. void idGameEdit::MapSave( const char *path ) const {
  1392.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1393.     if (mapFile) {
  1394. // RAVEN BEGIN
  1395. // rjohnson: added entity export
  1396.         if (mapFile->HasExportEntities()) {
  1397.             mapFile->WriteExport( (path) ? path : mapFile->GetName() );
  1398.         } else {
  1399.             if ( path ) {
  1400.                 mapFile->Write( path, ".map");
  1401.             } else {
  1402.                 idStr osPath;
  1403.                 osPath = mapFile->GetName ( );
  1404.                 osPath.DefaultFileExtension ( ".map" );
  1405.                 idFile* file = fileSystem->OpenFileRead ( osPath );
  1406.                 if ( file ) {
  1407.                     osPath = file->GetFullPath ( );
  1408.                     fileSystem->CloseFile ( file );
  1409.                     mapFile->Write ( osPath, ".map", false );
  1410.                 } else {
  1411.                     mapFile->Write ( file->GetName(), ".map" );
  1412.                 }
  1413.             }                
  1414.         }
  1415. // RAVEN END
  1416.     }
  1417. }
  1418.  
  1419. // RAVEN BEGIN
  1420. // rjohnson: added entity export
  1421. bool idGameEdit::MapHasExportEntities( void ) const {
  1422.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1423.     if (mapFile) {
  1424.         return mapFile->HasExportEntities();
  1425.     }
  1426.     return false;
  1427. }
  1428. // scork: simple query function for the sound editor
  1429. // cdr: changed to also return the full string name of the map file (still compatable as a bool test)
  1430. const char* idGameEdit::MapLoaded( void ) const {
  1431.  
  1432.     const char *psMapName = gameLocal.GetMapName();
  1433.     if (psMapName && psMapName[0]) {
  1434.         return psMapName;
  1435.     }
  1436.     return 0;
  1437. }
  1438.  
  1439. // cdr: AASTactical
  1440. idAASFile* idGameEdit::GetAASFile( int i ) {
  1441.     if (gameLocal.GetAAS( i )) {
  1442.         return gameLocal.GetAAS( i )->GetFile();
  1443.     }
  1444.     return 0;
  1445. }
  1446. // RAVEN END
  1447.  
  1448. /*
  1449. ================
  1450. idGameEdit::MapSetEntityKeyVal
  1451. ================
  1452. */
  1453. void idGameEdit::MapSetEntityKeyVal( const char *name, const char *key, const char *val ) const {
  1454.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1455.     if ( mapFile && name && *name ) {
  1456.         idMapEntity *mapent = mapFile->FindEntity( name );
  1457.         if ( mapent ) {
  1458.             mapent->epairs.Set( key, val );
  1459.         }
  1460.     }
  1461. }
  1462.  
  1463. /*
  1464. ================
  1465. idGameEdit::MapCopyDictToEntity
  1466. ================
  1467. */
  1468. void idGameEdit::MapCopyDictToEntity( const char *name, const idDict *dict ) const {
  1469.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1470.     if ( mapFile && name && *name ) {
  1471.         idMapEntity *mapent = mapFile->FindEntity( name );
  1472.         if ( mapent ) {
  1473.             for ( int i = 0; i < dict->GetNumKeyVals(); i++ ) {
  1474.                 const idKeyValue *kv = dict->GetKeyVal( i );
  1475.                 const char *key = kv->GetKey();
  1476.                 const char *val = kv->GetValue();
  1477.                 mapent->epairs.Set( key, val );
  1478.             }
  1479.         }
  1480.     }
  1481. }
  1482.  
  1483.  
  1484.  
  1485. /*
  1486. ================
  1487. idGameEdit::MapGetUniqueMatchingKeyVals
  1488. ================
  1489. */
  1490. int idGameEdit::MapGetUniqueMatchingKeyVals( const char *key, const char *list[], int max ) const {
  1491.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1492.     int count = 0;
  1493.     if ( mapFile ) {
  1494.         for ( int i = 0; i < mapFile->GetNumEntities(); i++ ) {
  1495.             idMapEntity *ent = mapFile->GetEntity( i );
  1496.             if ( ent ) {
  1497.                 const char *k = ent->epairs.GetString( key );
  1498.                 if ( k && *k && count < max ) {
  1499.                     list[count++] = k;
  1500.                 }
  1501.             }
  1502.         }
  1503.     }
  1504.     return count;
  1505. }
  1506.  
  1507. /*
  1508. ================
  1509. idGameEdit::MapAddEntity
  1510. ================
  1511. */
  1512. void idGameEdit::MapAddEntity( const idDict *dict ) const {
  1513.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1514.     if ( mapFile ) {
  1515.         idMapEntity *ent = new idMapEntity();
  1516.         ent->epairs = *dict;
  1517.         mapFile->AddEntity( ent );
  1518.     }
  1519. }
  1520.  
  1521. /*
  1522. ================
  1523. idGameEdit::MapRemoveEntity
  1524. ================
  1525. */
  1526. void idGameEdit::MapRemoveEntity( const char *name ) const {
  1527.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1528.     if ( mapFile ) {
  1529.         idMapEntity *ent = mapFile->FindEntity( name );
  1530.         if ( ent ) {
  1531.             mapFile->RemoveEntity( ent );
  1532.         }
  1533.     }
  1534. }
  1535.  
  1536.  
  1537. /*
  1538. ================
  1539. idGameEdit::MapGetEntitiesMatchignClassWithString
  1540. ================
  1541. */
  1542. int idGameEdit::MapGetEntitiesMatchingClassWithString( const char *classname, const char *match, const char *list[], const int max ) const {
  1543.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1544.     int count = 0;
  1545.     if ( mapFile ) {
  1546.         int entCount = mapFile->GetNumEntities();
  1547.         for ( int i = 0 ; i < entCount; i++ ) {
  1548.             idMapEntity *ent = mapFile->GetEntity(i);
  1549.             if (ent) {
  1550.                 idStr work = ent->epairs.GetString("classname");
  1551.                 if ( work.Icmp( classname ) == 0 ) {
  1552.                     if ( match && *match ) { 
  1553.                         work = ent->epairs.GetString( "soundgroup" );
  1554.                         if ( count < max && work.Icmp( match ) == 0 ) {
  1555.                             list[count++] = ent->epairs.GetString( "name" );
  1556.                         }
  1557.                     } else if ( count < max ) {
  1558.                         list[count++] = ent->epairs.GetString( "name" );
  1559.                     }
  1560.                 }
  1561.             }
  1562.         }
  1563.     }
  1564.     return count;
  1565. }
  1566.  
  1567.  
  1568. /*
  1569. ================
  1570. idGameEdit::MapEntityTranslate
  1571. ================
  1572. */
  1573. void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const {
  1574.     idMapFile *mapFile = gameLocal.GetLevelMap();
  1575.     if ( mapFile && name && *name ) {
  1576.         idMapEntity *mapent = mapFile->FindEntity( name );
  1577.         if ( mapent ) {
  1578.             idVec3 origin;
  1579.             mapent->epairs.GetVector( "origin", "", origin );
  1580.             origin += v;
  1581.             mapent->epairs.SetVector( "origin", origin );
  1582.         }
  1583.     }
  1584. }
  1585.  
  1586. // RAVEN BEGIN
  1587. // bdube: new game edit stuff
  1588. /*
  1589. ================
  1590. idGameEdit::PlayerTraceFromEye
  1591. ================
  1592. */
  1593. bool idGameEdit::PlayerTraceFromEye ( trace_t &results, float length, int contentMask ) {
  1594.     idVec3        start;
  1595.     idVec3        end;
  1596.     idAngles    angles;
  1597.         
  1598.     PlayerGetEyePosition( start );
  1599.     PlayerGetEyePosition( end );
  1600.     PlayerGetViewAngles ( angles );
  1601.     
  1602.     end += angles.ToForward() * length;
  1603. // RAVEN BEGIN
  1604. // ddynerman: multiple clip worlds
  1605.     return gameLocal.TracePoint ( gameLocal.GetLocalPlayer(), results, start, end, contentMask, gameLocal.GetLocalPlayer() );
  1606. // RAVEN END
  1607. }
  1608.  
  1609. /*
  1610. ================
  1611. idGameEdit::EffectRefreshTemplate
  1612. ================
  1613. */
  1614. void idGameEdit::EffectRefreshTemplate ( const idDecl *effect ) const {
  1615.     rvClientEntity* cent;    
  1616.  
  1617.     // Restart all effects
  1618.     for ( cent = gameLocal.clientSpawnedEntities.Next(); cent; cent = cent->spawnNode.Next() ) {
  1619.         if ( cent->IsType ( rvClientEffect::GetClassType() ) ) {
  1620.             rvClientEffect* clientEffect;
  1621.             clientEffect = static_cast<rvClientEffect*>( cent );
  1622.             if ( clientEffect->GetEffectIndex ( ) == effect->Index() ) {
  1623.                 clientEffect->Restart ( );
  1624.             }
  1625.         }
  1626.     }
  1627. }
  1628.  
  1629. /*
  1630. ================
  1631. idGameEdit::GetGameTime
  1632. ================
  1633. */
  1634. int idGameEdit::GetGameTime ( int *previous ) const {
  1635.     if ( previous ) {
  1636.         *previous = gameLocal.previousTime;
  1637.     }
  1638.     
  1639.     return gameLocal.time;
  1640. }
  1641.  
  1642. /*
  1643. ================
  1644. idGameEdit::SetGameTime
  1645. ================
  1646. */
  1647. void idGameEdit::SetGameTime ( int time ) const {
  1648.     gameLocal.time = time;
  1649.     gameLocal.previousTime = time;
  1650. }
  1651.  
  1652. /*
  1653. ================
  1654. idGameEdit::TracePoint
  1655. ================
  1656. */
  1657. bool idGameEdit::TracePoint ( trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask ) const {
  1658. // RAVEN BEGIN
  1659. // ddynerman: multiple clip worlds
  1660.     return gameLocal.TracePoint( gameLocal.GetLocalPlayer(), results, start, end, contentMask, NULL );
  1661. // RAVEN END
  1662. }
  1663.  
  1664. /*
  1665. ================
  1666. idGameEdit::CacheDictionaryMedia
  1667. ================
  1668. */
  1669. void idGameEdit::CacheDictionaryMedia ( const idDict* dict ) const {
  1670.     gameLocal.CacheDictionaryMedia ( dict );
  1671. }
  1672.  
  1673. /*
  1674. ================
  1675. idGameEdit::SetCamera
  1676. ================
  1677. */
  1678. void idGameEdit::SetCamera ( idEntity* camera ) const {
  1679.     gameLocal.SetCamera ( dynamic_cast<idCamera*>(camera) );
  1680. }
  1681.  
  1682. /*
  1683. ================
  1684. idGameEdit::ScriptGetStatementLineNumber
  1685. ================
  1686. */
  1687. int idGameEdit::ScriptGetStatementLineNumber ( idProgram* program, int instructionPointer ) const {
  1688.     return program->GetStatement ( instructionPointer ).linenumber;
  1689. }
  1690.  
  1691. /*
  1692. ================
  1693. idGameEdit::ScriptGetStatementFileName
  1694. ================
  1695. */
  1696. const char* idGameEdit::ScriptGetStatementFileName ( idProgram* program, int instructionPointer ) const {
  1697.     return program->GetFilename ( program->GetStatement ( instructionPointer ).file );
  1698. }
  1699.  
  1700. /*
  1701. ================
  1702. idGameEdit::ScriptGetStatementOperator
  1703. ================
  1704. */
  1705. int idGameEdit::ScriptGetStatementOperator ( idProgram* program, int instructionPointer ) const {
  1706.     return program->GetStatement ( instructionPointer ).op;
  1707. }
  1708.  
  1709. /*
  1710. ================
  1711. idGameEdit::ScriptGetCurrentFunction
  1712. ================
  1713. */
  1714. void* idGameEdit::ScriptGetCurrentFunction ( idInterpreter* interpreter ) const {
  1715.     return (void*)interpreter->GetCurrentFunction ( );
  1716. }
  1717.  
  1718. /*
  1719. ================
  1720. idGameEdit::ScriptGetCurrentFunctionName
  1721. ================
  1722. */
  1723. const char* idGameEdit::ScriptGetCurrentFunctionName ( idInterpreter* interpreter ) const {
  1724.     if ( interpreter->GetCurrentFunction ( ) ) {
  1725.         return interpreter->GetCurrentFunction ( )->Name();
  1726.     }
  1727.     return "";
  1728. }
  1729.  
  1730. /*
  1731. ================
  1732. idGameEdit::ScriptGetStatementOperator
  1733. ================
  1734. */
  1735. int idGameEdit::ScriptGetCallstackDepth ( idInterpreter* interpreter ) const {
  1736.     return interpreter->GetCallstackDepth ( );
  1737. }
  1738.  
  1739. /*
  1740. ================
  1741. idGameEdit::ScriptGetCallstackFunction
  1742. ================
  1743. */
  1744. void* idGameEdit::ScriptGetCallstackFunction ( idInterpreter* interpreter, int depth ) const {
  1745.     return (void*)interpreter->GetCallstack ( )[depth].f;
  1746. }
  1747.  
  1748. /*
  1749. ================
  1750. idGameEdit::ScriptGetCallstackFunctionName
  1751. ================
  1752. */
  1753. const char* idGameEdit::ScriptGetCallstackFunctionName ( idInterpreter* interpreter, int depth ) const {
  1754.     return interpreter->GetCallstack()[depth].f->Name();
  1755. }
  1756.  
  1757. /*
  1758. ================
  1759. idGameEdit::ScriptGetCallstackStatement
  1760. ================
  1761. */
  1762. int idGameEdit::ScriptGetCallstackStatement ( idInterpreter* interpreter, int depth ) const {
  1763.     return interpreter->GetCallstack()[depth].s;
  1764. }
  1765.  
  1766. /*
  1767. ================
  1768. idGameEdit::ScriptIsReturnOperator
  1769. ================
  1770. */
  1771. bool idGameEdit::ScriptIsReturnOperator ( int op ) const {
  1772.     return op == OP_RETURN;
  1773. }
  1774.  
  1775. /*
  1776. ================
  1777. idGameEdit::ScriptGetRegisterValue
  1778. ================
  1779. */
  1780. const char* idGameEdit::ScriptGetRegisterValue ( idInterpreter* interpreter, const char* varname, int callstackDepth ) const {
  1781.     static char    value[4096];
  1782.     idStr        out;
  1783.     
  1784.     value[0] = '\0';
  1785.     if ( interpreter->GetRegisterValue ( varname, out, callstackDepth ) ) {    
  1786.         idStr::snPrintf ( value, 4095, out.c_str() );    
  1787.     }
  1788.     
  1789.     return value;
  1790. }
  1791.  
  1792. /*
  1793. ================
  1794. idGameEdit::ScriptGetThread
  1795. ================
  1796. */
  1797. idThread* idGameEdit::ScriptGetThread ( idInterpreter* interpreter ) const {
  1798.     return interpreter->GetThread();
  1799. }
  1800.  
  1801. /*
  1802. ================
  1803. idGameEdit::ThreadGetCount
  1804. ================
  1805. */
  1806. int idGameEdit::ThreadGetCount ( void ) {
  1807.     return idThread::GetThreads().Num();
  1808. }
  1809.  
  1810. /*
  1811. ================
  1812. idGameEdit::ThreadGetThread
  1813. ================
  1814. */
  1815. idThread* idGameEdit::ThreadGetThread ( int index ) {
  1816.     return idThread::GetThreads()[index];
  1817. }
  1818.  
  1819. /*
  1820. ================
  1821. idGameEdit::ThreadGetName
  1822. ================
  1823. */
  1824. const char* idGameEdit::ThreadGetName ( idThread* thread ) {
  1825.     return thread->GetThreadName ( );
  1826. }
  1827.  
  1828. /*
  1829. ================
  1830. idGameEdit::ThreadGetNumber
  1831. ================
  1832. */
  1833. int idGameEdit::ThreadGetNumber ( idThread* thread ) {
  1834.     return thread->GetThreadNum ( );
  1835. }
  1836.  
  1837. /*
  1838. ================
  1839. idGameEdit::ThreadGetState
  1840. ================
  1841. */
  1842. const char* idGameEdit::ThreadGetState ( idThread* thread ) {
  1843.     if ( thread->IsDying() ) {
  1844.         return "Dying";
  1845.     } else if ( thread->IsWaiting() ) {
  1846.         return "Waiting";
  1847.     } else if ( thread->IsDoneProcessing() ) {
  1848.         return "Stopped";
  1849.     }
  1850.     
  1851.     return "Running";
  1852. }
  1853.  
  1854. /*
  1855. ================
  1856. idGameEdit::GetClassDebugInfo
  1857. ================
  1858. */
  1859. void idGameEdit::GetClassDebugInfo ( const idEntity* entity, debugInfoProc_t proc, void* userdata ) {
  1860.     const_cast<idEntity *>( entity )->GetDebugInfo ( proc, userdata  );
  1861. }
  1862.  
  1863. /*
  1864. ================
  1865. idGameEdit::GetGameEntityRegisterTime
  1866. ================
  1867. */
  1868. int idGameEdit::GetGameEntityRegisterTime ( void ) const {
  1869.     return gameLocal.entityRegisterTime;
  1870. }
  1871.  
  1872. /*
  1873. ================
  1874. idGameEdit::GetFirstSpawnedEntity
  1875. ================
  1876. */
  1877. idEntity* idGameEdit::GetFirstSpawnedEntity ( void ) const {
  1878.     return gameLocal.spawnedEntities.Next();
  1879. }
  1880.  
  1881. /*
  1882. ================
  1883. idGameEdit::GetNextSpawnedEntity
  1884. ================
  1885. */
  1886. idEntity* idGameEdit::GetNextSpawnedEntity ( idEntity* from ) const {
  1887.     if ( !from ) {
  1888.         return NULL;
  1889.     }
  1890.     return from->spawnNode.Next();
  1891. }
  1892.  
  1893.  
  1894. // RAVEN END
  1895.  
  1896. // RAVEN BEGIN
  1897. // mekberg: access to animationlib functions for radiant
  1898. void idGameEdit::FlushUnusedAnims ( void ) {
  1899.  
  1900. // RAVEN BEGIN
  1901. // jsinger: animationLib changed to a pointer
  1902.     animationLib->FlushUnusedAnims();
  1903. // RAVEN END
  1904. }
  1905.  
  1906. /*
  1907. ===============================================================================
  1908.  
  1909.   rvModviewModel
  1910.  
  1911.   Actor model for modview
  1912.  
  1913. ===============================================================================
  1914. */
  1915.  
  1916. class rvModviewModel : public idActor {
  1917. public:
  1918.     CLASS_PROTOTYPE( rvModviewModel );
  1919.     
  1920.     rvModviewModel ( void );
  1921.         
  1922. private:
  1923.     
  1924.     void                    Event_Speak        ( const char* lipsync );
  1925. };
  1926.  
  1927. CLASS_DECLARATION( idActor, rvModviewModel )
  1928.     EVENT( AI_Speak,                rvModviewModel::Event_Speak )    
  1929. END_CLASS
  1930.  
  1931. /*
  1932. =====================
  1933. rvModviewModel::rvModviewModel
  1934. =====================
  1935. */
  1936. rvModviewModel::rvModviewModel ( void ) {
  1937. }
  1938.  
  1939. /*
  1940. =====================
  1941. rvModviewModel::Event_Speak
  1942. =====================
  1943. */
  1944. void rvModviewModel::Event_Speak ( const char* lipsync ) {
  1945.     assert( idStr::Icmpn( lipsync, "lipsync_", 7 ) == 0 );
  1946.     
  1947.     lipsync = spawnArgs.GetString ( lipsync );
  1948.     if ( !lipsync || !*lipsync ) {
  1949.         return;
  1950.     }
  1951.     
  1952.     if ( head ) {
  1953.         head->StartLipSyncing( lipsync );
  1954.     } else {
  1955.         StartSoundShader (declManager->FindSound ( lipsync ), SND_CHANNEL_VOICE, 0, false, NULL );
  1956.     }
  1957. }    
  1958.  
  1959. // RAVEN END
  1960.  
  1961.