Counter Strike : Global Offensive Source Code
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.

530 lines
19 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Singleton dialog that generates and presents the entity report.
  4. //
  5. //===========================================================================//
  6. #include "CommentaryPropertiesPanel.h"
  7. #include "tier1/keyvalues.h"
  8. #include "tier1/utlbuffer.h"
  9. #include "iregistry.h"
  10. #include "vgui/ivgui.h"
  11. #include "vgui_controls/listpanel.h"
  12. #include "vgui_controls/textentry.h"
  13. #include "vgui_controls/checkbutton.h"
  14. #include "vgui_controls/combobox.h"
  15. #include "vgui_controls/radiobutton.h"
  16. #include "vgui_controls/messagebox.h"
  17. #include "vgui_controls/scrollbar.h"
  18. #include "vgui_controls/scrollableeditablepanel.h"
  19. #include "commeditdoc.h"
  20. #include "commedittool.h"
  21. #include "datamodel/dmelement.h"
  22. #include "dmecommentarynodeentity.h"
  23. #include "dme_controls/soundpicker.h"
  24. #include "dme_controls/soundrecordpanel.h"
  25. #include "matsys_controls/picker.h"
  26. #include "vgui_controls/fileopendialog.h"
  27. #include "filesystem.h"
  28. #include "tier2/fileutils.h"
  29. // memdbgon must be the last include file in a .cpp file!!!
  30. #include <tier0/memdbgon.h>
  31. using namespace vgui;
  32. //-----------------------------------------------------------------------------
  33. // Constructor
  34. //-----------------------------------------------------------------------------
  35. CCommentaryPropertiesPanel::CCommentaryPropertiesPanel( CCommEditDoc *pDoc, vgui::Panel* pParent )
  36. : BaseClass( pParent, "CommentaryPropertiesPanel" ), m_pDoc( pDoc )
  37. {
  38. SetPaintBackgroundEnabled( true );
  39. SetKeyBoardInputEnabled( true );
  40. m_pCommentaryNode = new vgui::EditablePanel( (vgui::Panel*)NULL, "CommentaryNode" );
  41. m_pNodeName = new vgui::TextEntry( m_pCommentaryNode, "CommentaryNodeName" );
  42. m_pNodeName->AddActionSignalTarget( this );
  43. m_pSoundFilePicker = new vgui::Button( m_pCommentaryNode, "AudioFilePickerButton", "", this, "PickSound" );
  44. m_pSoundFileName = new vgui::TextEntry( m_pCommentaryNode, "AudioFileName" );
  45. m_pSoundFileName->AddActionSignalTarget( this );
  46. m_pRecordSound = new vgui::Button( m_pCommentaryNode, "RecordAudioButton", "", this, "Record" );
  47. m_pSpeakerName = new vgui::TextEntry( m_pCommentaryNode, "Speaker" );
  48. m_pSpeakerName->AddActionSignalTarget( this );
  49. m_pSynopsis = new vgui::TextEntry( m_pCommentaryNode, "Synopsis" );
  50. m_pSynopsis->AddActionSignalTarget( this );
  51. m_pViewPositionPicker = new vgui::Button( m_pCommentaryNode, "ViewPositionPickerButton", "", this, "PickViewPosition" );
  52. m_pViewTargetPicker = new vgui::Button( m_pCommentaryNode, "ViewTargetPickerButton", "", this, "PickViewTarget" );
  53. m_pViewPosition = new vgui::TextEntry( m_pCommentaryNode, "ViewPosition" );
  54. m_pViewPosition->AddActionSignalTarget( this );
  55. m_pViewTarget = new vgui::TextEntry( m_pCommentaryNode, "ViewTarget" );
  56. m_pViewTarget->AddActionSignalTarget( this );
  57. m_pPreventMovement = new vgui::CheckButton( m_pCommentaryNode, "PreventMovement", "" );
  58. m_pPreventMovement->SetCommand( "PreventMovementClicked" );
  59. m_pPreventMovement->AddActionSignalTarget( this );
  60. m_pStartCommands = new vgui::TextEntry( m_pCommentaryNode, "StartCommands" );
  61. m_pStartCommands->AddActionSignalTarget( this );
  62. m_pEndCommands = new vgui::TextEntry( m_pCommentaryNode, "EndCommands" );
  63. m_pEndCommands->AddActionSignalTarget( this );
  64. m_pPosition[0] = new vgui::TextEntry( m_pCommentaryNode, "PositionX" );
  65. m_pPosition[0]->AddActionSignalTarget( this );
  66. m_pPosition[1] = new vgui::TextEntry( m_pCommentaryNode, "PositionY" );
  67. m_pPosition[1]->AddActionSignalTarget( this );
  68. m_pPosition[2] = new vgui::TextEntry( m_pCommentaryNode, "PositionZ" );
  69. m_pPosition[2]->AddActionSignalTarget( this );
  70. m_pOrientation[0] = new vgui::TextEntry( m_pCommentaryNode, "Pitch" );
  71. m_pOrientation[0]->AddActionSignalTarget( this );
  72. m_pOrientation[1] = new vgui::TextEntry( m_pCommentaryNode, "Yaw" );
  73. m_pOrientation[1]->AddActionSignalTarget( this );
  74. m_pOrientation[2] = new vgui::TextEntry( m_pCommentaryNode, "Roll" );
  75. m_pOrientation[2]->AddActionSignalTarget( this );
  76. m_pCommentaryNode->LoadControlSettings( "resource/commentarypropertiessubpanel_node.res" );
  77. m_pInfoTarget = new vgui::EditablePanel( (vgui::Panel*)NULL, "InfoTarget" );
  78. m_pTargetName = new vgui::TextEntry( m_pInfoTarget, "TargetName" );
  79. m_pTargetName->AddActionSignalTarget( this );
  80. m_pTargetPosition[0] = new vgui::TextEntry( m_pInfoTarget, "PositionX" );
  81. m_pTargetPosition[0]->AddActionSignalTarget( this );
  82. m_pTargetPosition[1] = new vgui::TextEntry( m_pInfoTarget, "PositionY" );
  83. m_pTargetPosition[1]->AddActionSignalTarget( this );
  84. m_pTargetPosition[2] = new vgui::TextEntry( m_pInfoTarget, "PositionZ" );
  85. m_pTargetPosition[2]->AddActionSignalTarget( this );
  86. m_pTargetOrientation[0] = new vgui::TextEntry( m_pInfoTarget, "Pitch" );
  87. m_pTargetOrientation[0]->AddActionSignalTarget( this );
  88. m_pTargetOrientation[1] = new vgui::TextEntry( m_pInfoTarget, "Yaw" );
  89. m_pTargetOrientation[1]->AddActionSignalTarget( this );
  90. m_pTargetOrientation[2] = new vgui::TextEntry( m_pInfoTarget, "Roll" );
  91. m_pTargetOrientation[2]->AddActionSignalTarget( this );
  92. m_pInfoTarget->LoadControlSettings( "resource/commentarypropertiessubpanel_target.res" );
  93. m_pInfoRemarkable = new vgui::EditablePanel( (vgui::Panel*)NULL, "InfoRemarkable" );
  94. m_pInfoRemarkableName = new vgui::TextEntry( m_pInfoRemarkable, "RemarkableName" );
  95. m_pInfoRemarkableName->AddActionSignalTarget( this );
  96. m_pRemarkablePosition[0] = new vgui::TextEntry( m_pInfoRemarkable, "PositionX" );
  97. m_pRemarkablePosition[0]->AddActionSignalTarget( this );
  98. m_pRemarkablePosition[1] = new vgui::TextEntry( m_pInfoRemarkable, "PositionY" );
  99. m_pRemarkablePosition[1]->AddActionSignalTarget( this );
  100. m_pRemarkablePosition[2] = new vgui::TextEntry( m_pInfoRemarkable, "PositionZ" );
  101. m_pRemarkablePosition[2]->AddActionSignalTarget( this );
  102. m_pInfoRemarkableSubject = new vgui::TextEntry( m_pInfoRemarkable, "RemarkableSubject" );
  103. m_pInfoRemarkableSubject->AddActionSignalTarget( this );
  104. m_pInfoRemarkable->LoadControlSettings( "resource/commentarypropertiessubpanel_remarkable.res" );
  105. m_pCommentaryNodeScroll = new vgui::ScrollableEditablePanel( this, m_pCommentaryNode, "CommentaryNodeScroll" );
  106. m_pInfoTargetScroll = new vgui::ScrollableEditablePanel( this, m_pInfoTarget, "InfoTargetScroll" );
  107. m_pInfoRemarkableScroll = new vgui::ScrollableEditablePanel( this, m_pInfoRemarkable, "InfoRemarkableScroll" );
  108. LoadControlSettings( "resource/commentarypropertiespanel.res" );
  109. m_pCommentaryNodeScroll->SetVisible( false );
  110. m_pInfoTargetScroll->SetVisible( false );
  111. m_pInfoRemarkableScroll->SetVisible( false );
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Text to attribute...
  115. //-----------------------------------------------------------------------------
  116. void CCommentaryPropertiesPanel::TextEntryToAttribute( vgui::TextEntry *pEntry, const char *pAttributeName )
  117. {
  118. int nLen = pEntry->GetTextLength();
  119. char *pBuf = (char*)_alloca( nLen+1 );
  120. pEntry->GetText( pBuf, nLen+1 );
  121. m_hEntity->SetValue( pAttributeName, pBuf );
  122. }
  123. void CCommentaryPropertiesPanel::TextEntriesToVector( vgui::TextEntry *pEntry[3], const char *pAttributeName )
  124. {
  125. CUtlVectorFixedGrowable< char, 256 > buf;
  126. Vector vec;
  127. for ( int i = 0; i < 3; ++i )
  128. {
  129. int nLen = pEntry[i]->GetTextLength();
  130. buf.EnsureCount( nLen + 1 );
  131. pEntry[i]->GetText( buf.Base(), nLen+1 );
  132. vec[i] = atof( buf.Base() );
  133. }
  134. m_hEntity->SetValue( pAttributeName, vec );
  135. clienttools->MarkClientRenderableDirty( m_hEntity );
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Updates entity state when text fields change
  139. //-----------------------------------------------------------------------------
  140. void CCommentaryPropertiesPanel::UpdateCommentaryNode()
  141. {
  142. if ( !m_hEntity.Get() )
  143. return;
  144. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Commentary Node Change", "Commentary Node Change" );
  145. TextEntryToAttribute( m_pNodeName, "targetname" );
  146. TextEntryToAttribute( m_pStartCommands, "precommands" );
  147. TextEntryToAttribute( m_pEndCommands, "postcommands" );
  148. TextEntryToAttribute( m_pViewPosition, "viewposition" );
  149. TextEntryToAttribute( m_pViewTarget, "viewtarget" );
  150. TextEntryToAttribute( m_pSynopsis, "synopsis" );
  151. TextEntryToAttribute( m_pSpeakerName, "speakers" );
  152. TextEntryToAttribute( m_pSoundFileName, "commentaryfile" );
  153. TextEntriesToVector( m_pPosition, "origin" );
  154. TextEntriesToVector( m_pOrientation, "angles" );
  155. m_hEntity->SetValue<int>( "prevent_movement", m_pPreventMovement->IsSelected() ? 1 : 0 );
  156. m_hEntity->MarkDirty();
  157. }
  158. void CCommentaryPropertiesPanel::UpdateInfoTarget()
  159. {
  160. if ( !m_hEntity.Get() )
  161. return;
  162. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Info Target Change", "Info Target Change" );
  163. TextEntryToAttribute( m_pTargetName, "targetname" );
  164. TextEntriesToVector( m_pTargetPosition, "origin" );
  165. TextEntriesToVector( m_pTargetOrientation, "angles" );
  166. m_hEntity->MarkDirty();
  167. }
  168. void CCommentaryPropertiesPanel::UpdateInfoRemarkable()
  169. {
  170. if ( !m_hEntity.Get() )
  171. return;
  172. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Info Remarkable Change", "Info Remarkable Change" );
  173. TextEntryToAttribute( m_pInfoRemarkableName, "targetname" );
  174. TextEntryToAttribute( m_pInfoRemarkableSubject, "contextsubject" );
  175. TextEntriesToVector( m_pRemarkablePosition, "origin" );
  176. m_hEntity->MarkDirty();
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Populates the commentary node fields
  180. //-----------------------------------------------------------------------------
  181. void CCommentaryPropertiesPanel::PopulateCommentaryNodeFields()
  182. {
  183. if ( !m_hEntity.Get() )
  184. return;
  185. m_pNodeName->SetText( m_hEntity->GetTargetName() );
  186. m_pStartCommands->SetText( m_hEntity->GetValueString( "precommands" ) );
  187. m_pEndCommands->SetText( m_hEntity->GetValueString( "postcommands" ) );
  188. m_pViewPosition->SetText( m_hEntity->GetValueString( "viewposition" ) );
  189. m_pViewTarget->SetText( m_hEntity->GetValueString( "viewtarget" ) );
  190. m_pSynopsis->SetText( m_hEntity->GetValueString( "synopsis" ) );
  191. m_pSpeakerName->SetText( m_hEntity->GetValueString( "speakers" ) );
  192. m_pSoundFileName->SetText( m_hEntity->GetValueString( "commentaryfile" ) );
  193. Vector vecPosition = m_hEntity->GetRenderOrigin();
  194. QAngle vecAngles = m_hEntity->GetRenderAngles();
  195. for ( int i = 0; i < 3; ++i )
  196. {
  197. char pTemp[512];
  198. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
  199. m_pPosition[i]->SetText( pTemp );
  200. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
  201. m_pOrientation[i]->SetText( pTemp );
  202. }
  203. m_pPreventMovement->SetSelected( m_hEntity->GetValue<int>( "prevent_movement" ) != 0 );
  204. }
  205. //-----------------------------------------------------------------------------
  206. // Populates the info_target fields
  207. //-----------------------------------------------------------------------------
  208. void CCommentaryPropertiesPanel::PopulateInfoTargetFields()
  209. {
  210. if ( !m_hEntity.Get() )
  211. return;
  212. m_pTargetName->SetText( m_hEntity->GetTargetName() );
  213. Vector vecPosition = m_hEntity->GetRenderOrigin();
  214. QAngle vecAngles = m_hEntity->GetRenderAngles();
  215. for ( int i = 0; i < 3; ++i )
  216. {
  217. char pTemp[512];
  218. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
  219. m_pTargetPosition[i]->SetText( pTemp );
  220. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
  221. m_pTargetOrientation[i]->SetText( pTemp );
  222. }
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Populates the info_target fields
  226. //-----------------------------------------------------------------------------
  227. void CCommentaryPropertiesPanel::PopulateInfoRemarkableFields()
  228. {
  229. if ( !m_hEntity.Get() )
  230. return;
  231. m_pInfoRemarkableName->SetText( m_hEntity->GetTargetName() );
  232. Vector vecPosition = m_hEntity->GetRenderOrigin();
  233. QAngle vecAngles = m_hEntity->GetRenderAngles();
  234. for ( int i = 0; i < 3; ++i )
  235. {
  236. char pTemp[512];
  237. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
  238. m_pRemarkablePosition[i]->SetText( pTemp );
  239. }
  240. m_pInfoRemarkableSubject->SetText( m_hEntity->GetValueString( "contextsubject" ) );
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Sets the object to look at
  244. //-----------------------------------------------------------------------------
  245. void CCommentaryPropertiesPanel::SetObject( CDmeCommentaryNodeEntity *pEntity )
  246. {
  247. m_hEntity = pEntity;
  248. m_pCommentaryNodeScroll->SetVisible( false );
  249. m_pInfoTargetScroll->SetVisible( false );
  250. m_pInfoRemarkableScroll->SetVisible( false );
  251. if ( pEntity )
  252. {
  253. if ( !Q_stricmp( pEntity->GetClassName(), "info_target" ) )
  254. {
  255. PopulateInfoTargetFields();
  256. m_pInfoTargetScroll->SetVisible( true );
  257. m_pTargetName->RequestFocus();
  258. return;
  259. }
  260. if ( !Q_stricmp( pEntity->GetClassName(), "info_remarkable" ) )
  261. {
  262. PopulateInfoRemarkableFields();
  263. m_pInfoRemarkableScroll->SetVisible( true );
  264. m_pInfoRemarkableName->RequestFocus();
  265. return;
  266. }
  267. if ( !Q_stricmp( pEntity->GetClassName(), "point_commentary_node" ) )
  268. {
  269. PopulateCommentaryNodeFields();
  270. m_pCommentaryNodeScroll->SetVisible( true );
  271. m_pNodeName->RequestFocus();
  272. return;
  273. }
  274. }
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Called when text is changed
  278. //-----------------------------------------------------------------------------
  279. void CCommentaryPropertiesPanel::OnTextChanged( KeyValues *pParams )
  280. {
  281. vgui::Panel *pPanel = (vgui::Panel*)pParams->GetPtr( "panel" );
  282. if ( pPanel->GetParent() == m_pCommentaryNode )
  283. {
  284. UpdateCommentaryNode();
  285. return;
  286. }
  287. if ( pPanel->GetParent() == m_pInfoTarget )
  288. {
  289. UpdateInfoTarget();
  290. return;
  291. }
  292. if ( pPanel->GetParent() == m_pInfoRemarkable )
  293. {
  294. UpdateInfoRemarkable();
  295. return;
  296. }
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Called when the audio picker has picked something
  300. //-----------------------------------------------------------------------------
  301. void CCommentaryPropertiesPanel::OnSoundSelected( KeyValues *pParams )
  302. {
  303. const char *pAssetName = pParams->GetString( "wav" );
  304. m_pSoundFileName->SetText( pAssetName );
  305. UpdateCommentaryNode();
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Called when the audio picker button is selected
  309. //-----------------------------------------------------------------------------
  310. void CCommentaryPropertiesPanel::PickSound()
  311. {
  312. CSoundPickerFrame *pSoundPickerDialog = new CSoundPickerFrame( g_pCommEditTool->GetRootPanel(), "Select commentary audio file", CSoundPicker::PICK_WAVFILES );
  313. pSoundPickerDialog->AddActionSignalTarget( this );
  314. pSoundPickerDialog->DoModal( CSoundPicker::PICK_NONE, NULL );
  315. }
  316. //-----------------------------------------------------------------------------
  317. // Called when the string picker has picked something
  318. //-----------------------------------------------------------------------------
  319. void CCommentaryPropertiesPanel::OnPicked( KeyValues *pParams )
  320. {
  321. const char *pInfoTargetName = pParams->GetString( "choice" );
  322. KeyValues *pContextKeyValues = pParams->FindKey( "context" );
  323. vgui::TextEntry *pTextEntry = (vgui::TextEntry *)pContextKeyValues->GetPtr( "widget" );
  324. pTextEntry->SetText( pInfoTargetName );
  325. UpdateCommentaryNode();
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Called when the audio picker button is selected
  329. //-----------------------------------------------------------------------------
  330. void CCommentaryPropertiesPanel::PickInfoTarget( vgui::TextEntry *pControl )
  331. {
  332. CDmrCommentaryNodeEntityList entities( m_pDoc->GetEntityList() );
  333. int nCount = entities.Count();
  334. PickerList_t vec( 0, nCount+1 );
  335. int j = vec.AddToTail( );
  336. vec[j].m_pChoiceString = "<no target>";
  337. vec[j].m_pChoiceValue = "";
  338. for ( int i = 0; i < nCount; ++i )
  339. {
  340. CDmeCommentaryNodeEntity *pNode = entities[ i ];
  341. const char *pTargetName = pNode->GetTargetName();
  342. if ( !pTargetName || !pTargetName[0] )
  343. continue;
  344. if ( !Q_stricmp( pNode->GetClassName(), "info_target" ) )
  345. {
  346. j = vec.AddToTail( );
  347. vec[j].m_pChoiceString = pTargetName;
  348. vec[j].m_pChoiceValue = pTargetName;
  349. }
  350. }
  351. CPickerFrame *pInfoTargetPickerDialog = new CPickerFrame( g_pCommEditTool->GetRootPanel(), "Select Target", "InfoTarget", NULL );
  352. KeyValues *pContextKeyValues = new KeyValues( "context" );
  353. pContextKeyValues->SetPtr( "widget", pControl );
  354. pInfoTargetPickerDialog->AddActionSignalTarget( this );
  355. pInfoTargetPickerDialog->DoModal( vec, pContextKeyValues );
  356. }
  357. //-----------------------------------------------------------------------------
  358. // Called when a sound is successfully recorded
  359. //-----------------------------------------------------------------------------
  360. void CCommentaryPropertiesPanel::OnSoundRecorded( KeyValues *pKeyValues )
  361. {
  362. const char *pFileName = pKeyValues->GetString( "relativepath" );
  363. m_pSoundFileName->SetText( pFileName );
  364. UpdateCommentaryNode();
  365. }
  366. //-----------------------------------------------------------------------------
  367. // Used to open a particular file in perforce, and deal with all the lovely dialogs
  368. //-----------------------------------------------------------------------------
  369. void CCommentaryPropertiesPanel::OnFileSelected( KeyValues *pKeyValues )
  370. {
  371. const char *pFileName = pKeyValues->GetString( "fullpath" );
  372. if ( g_pFileSystem->FileExists( pFileName ) )
  373. {
  374. char pBuf[1024];
  375. Q_snprintf( pBuf, sizeof(pBuf), "File %s already exists!\nRecording audio will not overwrite existing files.", pFileName );
  376. vgui::MessageBox *pMessageBox = new vgui::MessageBox( "File already Exists!\n", pBuf, g_pCommEditTool );
  377. pMessageBox->DoModal( );
  378. return;
  379. }
  380. CSoundRecordPanel *pSoundRecordPanel = new CSoundRecordPanel( g_pCommEditTool->GetRootPanel(), "Record Commentary" );
  381. pSoundRecordPanel->AddActionSignalTarget( this );
  382. pSoundRecordPanel->DoModal( pFileName );
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Called when sound recording is requested
  386. //-----------------------------------------------------------------------------
  387. void CCommentaryPropertiesPanel::RecordSound( )
  388. {
  389. char pStartingDir[ MAX_PATH ];
  390. GetModSubdirectory( "sound", pStartingDir, sizeof(pStartingDir) );
  391. vgui::FileOpenDialog *pDialog = new vgui::FileOpenDialog( this, "Save As", false );
  392. pDialog->SetTitle( "Enter New Audio File", true );
  393. pDialog->SetStartDirectoryContext( "commedit_audio_record", pStartingDir );
  394. pDialog->AddFilter( "*.wav", "Audio File (*.wav)", true );
  395. pDialog->AddActionSignalTarget( this );
  396. pDialog->DoModal( true );
  397. }
  398. //-----------------------------------------------------------------------------
  399. // Called when buttons are clicked
  400. //-----------------------------------------------------------------------------
  401. void CCommentaryPropertiesPanel::OnCommand( const char *pCommand )
  402. {
  403. if ( !Q_stricmp( pCommand, "PickSound" ) )
  404. {
  405. PickSound();
  406. return;
  407. }
  408. if ( !Q_stricmp( pCommand, "Record" ) )
  409. {
  410. RecordSound();
  411. return;
  412. }
  413. if ( !Q_stricmp( pCommand, "PickViewPosition" ) )
  414. {
  415. PickInfoTarget( m_pViewPosition );
  416. return;
  417. }
  418. if ( !Q_stricmp( pCommand, "PickViewTarget" ) )
  419. {
  420. PickInfoTarget( m_pViewTarget );
  421. return;
  422. }
  423. if ( !Q_stricmp( pCommand, "PreventMovementClicked" ) )
  424. {
  425. UpdateCommentaryNode();
  426. return;
  427. }
  428. BaseClass::OnCommand( pCommand );
  429. }