Team Fortress 2 Source Code as on 22/4/2020
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.

458 lines
16 KiB

  1. //========= Copyright 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_pCommentaryNodeScroll = new vgui::ScrollableEditablePanel( this, m_pCommentaryNode, "CommentaryNodeScroll" );
  94. m_pInfoTargetScroll = new vgui::ScrollableEditablePanel( this, m_pInfoTarget, "InfoTargetScroll" );
  95. LoadControlSettings( "resource/commentarypropertiespanel.res" );
  96. m_pCommentaryNodeScroll->SetVisible( false );
  97. m_pInfoTargetScroll->SetVisible( false );
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Text to attribute...
  101. //-----------------------------------------------------------------------------
  102. void CCommentaryPropertiesPanel::TextEntryToAttribute( vgui::TextEntry *pEntry, const char *pAttributeName )
  103. {
  104. int nLen = pEntry->GetTextLength();
  105. char *pBuf = (char*)_alloca( nLen+1 );
  106. pEntry->GetText( pBuf, nLen+1 );
  107. m_hEntity->SetValue( pAttributeName, pBuf );
  108. }
  109. void CCommentaryPropertiesPanel::TextEntriesToVector( vgui::TextEntry *pEntry[3], const char *pAttributeName )
  110. {
  111. Vector vec;
  112. for ( int i = 0; i < 3; ++i )
  113. {
  114. int nLen = pEntry[i]->GetTextLength();
  115. char *pBuf = (char*)_alloca( nLen+1 );
  116. pEntry[i]->GetText( pBuf, nLen+1 );
  117. vec[i] = atof( pBuf );
  118. }
  119. m_hEntity->SetValue( pAttributeName, vec );
  120. clienttools->MarkClientRenderableDirty( m_hEntity );
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Updates entity state when text fields change
  124. //-----------------------------------------------------------------------------
  125. void CCommentaryPropertiesPanel::UpdateCommentaryNode()
  126. {
  127. if ( !m_hEntity.Get() )
  128. return;
  129. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Commentary Node Change", "Commentary Node Change" );
  130. TextEntryToAttribute( m_pNodeName, "targetname" );
  131. TextEntryToAttribute( m_pStartCommands, "precommands" );
  132. TextEntryToAttribute( m_pEndCommands, "postcommands" );
  133. TextEntryToAttribute( m_pViewPosition, "viewposition" );
  134. TextEntryToAttribute( m_pViewTarget, "viewtarget" );
  135. TextEntryToAttribute( m_pSynopsis, "synopsis" );
  136. TextEntryToAttribute( m_pSpeakerName, "speakers" );
  137. TextEntryToAttribute( m_pSoundFileName, "commentaryfile" );
  138. TextEntriesToVector( m_pPosition, "origin" );
  139. TextEntriesToVector( m_pOrientation, "angles" );
  140. m_hEntity->SetValue<int>( "prevent_movement", m_pPreventMovement->IsSelected() ? 1 : 0 );
  141. m_hEntity->MarkDirty();
  142. }
  143. void CCommentaryPropertiesPanel::UpdateInfoTarget()
  144. {
  145. if ( !m_hEntity.Get() )
  146. return;
  147. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Info Target Change", "Info Target Change" );
  148. TextEntryToAttribute( m_pTargetName, "targetname" );
  149. TextEntriesToVector( m_pTargetPosition, "origin" );
  150. TextEntriesToVector( m_pTargetOrientation, "angles" );
  151. m_hEntity->MarkDirty();
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Populates the commentary node fields
  155. //-----------------------------------------------------------------------------
  156. void CCommentaryPropertiesPanel::PopulateCommentaryNodeFields()
  157. {
  158. if ( !m_hEntity.Get() )
  159. return;
  160. m_pNodeName->SetText( m_hEntity->GetTargetName() );
  161. m_pStartCommands->SetText( m_hEntity->GetValueString( "precommands" ) );
  162. m_pEndCommands->SetText( m_hEntity->GetValueString( "postcommands" ) );
  163. m_pViewPosition->SetText( m_hEntity->GetValueString( "viewposition" ) );
  164. m_pViewTarget->SetText( m_hEntity->GetValueString( "viewtarget" ) );
  165. m_pSynopsis->SetText( m_hEntity->GetValueString( "synopsis" ) );
  166. m_pSpeakerName->SetText( m_hEntity->GetValueString( "speakers" ) );
  167. m_pSoundFileName->SetText( m_hEntity->GetValueString( "commentaryfile" ) );
  168. Vector vecPosition = m_hEntity->GetRenderOrigin();
  169. QAngle vecAngles = m_hEntity->GetRenderAngles();
  170. for ( int i = 0; i < 3; ++i )
  171. {
  172. char pTemp[512];
  173. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
  174. m_pPosition[i]->SetText( pTemp );
  175. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
  176. m_pOrientation[i]->SetText( pTemp );
  177. }
  178. m_pPreventMovement->SetSelected( m_hEntity->GetValue<int>( "prevent_movement" ) != 0 );
  179. }
  180. //-----------------------------------------------------------------------------
  181. // Populates the info_target fields
  182. //-----------------------------------------------------------------------------
  183. void CCommentaryPropertiesPanel::PopulateInfoTargetFields()
  184. {
  185. if ( !m_hEntity.Get() )
  186. return;
  187. m_pTargetName->SetText( m_hEntity->GetTargetName() );
  188. Vector vecPosition = m_hEntity->GetRenderOrigin();
  189. QAngle vecAngles = m_hEntity->GetRenderAngles();
  190. for ( int i = 0; i < 3; ++i )
  191. {
  192. char pTemp[512];
  193. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
  194. m_pTargetPosition[i]->SetText( pTemp );
  195. Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
  196. m_pTargetOrientation[i]->SetText( pTemp );
  197. }
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Sets the object to look at
  201. //-----------------------------------------------------------------------------
  202. void CCommentaryPropertiesPanel::SetObject( CDmeCommentaryNodeEntity *pEntity )
  203. {
  204. m_hEntity = pEntity;
  205. m_pCommentaryNodeScroll->SetVisible( false );
  206. m_pInfoTargetScroll->SetVisible( false );
  207. if ( pEntity )
  208. {
  209. if ( !Q_stricmp( pEntity->GetClassName(), "info_target" ) )
  210. {
  211. PopulateInfoTargetFields();
  212. m_pInfoTargetScroll->SetVisible( true );
  213. m_pTargetName->RequestFocus();
  214. return;
  215. }
  216. if ( !Q_stricmp( pEntity->GetClassName(), "point_commentary_node" ) )
  217. {
  218. PopulateCommentaryNodeFields();
  219. m_pCommentaryNodeScroll->SetVisible( true );
  220. m_pNodeName->RequestFocus();
  221. return;
  222. }
  223. }
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Called when text is changed
  227. //-----------------------------------------------------------------------------
  228. void CCommentaryPropertiesPanel::OnTextChanged( KeyValues *pParams )
  229. {
  230. vgui::Panel *pPanel = (vgui::Panel*)pParams->GetPtr( "panel" );
  231. if ( pPanel->GetParent() == m_pCommentaryNode )
  232. {
  233. UpdateCommentaryNode();
  234. return;
  235. }
  236. if ( pPanel->GetParent() == m_pInfoTarget )
  237. {
  238. UpdateInfoTarget();
  239. return;
  240. }
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Called when the audio picker has picked something
  244. //-----------------------------------------------------------------------------
  245. void CCommentaryPropertiesPanel::OnSoundSelected( KeyValues *pParams )
  246. {
  247. const char *pAssetName = pParams->GetString( "wav" );
  248. m_pSoundFileName->SetText( pAssetName );
  249. UpdateCommentaryNode();
  250. }
  251. //-----------------------------------------------------------------------------
  252. // Called when the audio picker button is selected
  253. //-----------------------------------------------------------------------------
  254. void CCommentaryPropertiesPanel::PickSound()
  255. {
  256. CSoundPickerFrame *pSoundPickerDialog = new CSoundPickerFrame( g_pCommEditTool->GetRootPanel(), "Select commentary audio file", CSoundPicker::PICK_WAVFILES );
  257. pSoundPickerDialog->AddActionSignalTarget( this );
  258. pSoundPickerDialog->DoModal( CSoundPicker::PICK_NONE, NULL );
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Called when the string picker has picked something
  262. //-----------------------------------------------------------------------------
  263. void CCommentaryPropertiesPanel::OnPicked( KeyValues *pParams )
  264. {
  265. const char *pInfoTargetName = pParams->GetString( "choice" );
  266. KeyValues *pContextKeyValues = pParams->FindKey( "context" );
  267. vgui::TextEntry *pTextEntry = (vgui::TextEntry *)pContextKeyValues->GetPtr( "widget" );
  268. pTextEntry->SetText( pInfoTargetName );
  269. UpdateCommentaryNode();
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Called when the audio picker button is selected
  273. //-----------------------------------------------------------------------------
  274. void CCommentaryPropertiesPanel::PickInfoTarget( vgui::TextEntry *pControl )
  275. {
  276. CDmrCommentaryNodeEntityList entities( m_pDoc->GetEntityList() );
  277. int nCount = entities.Count();
  278. PickerList_t vec( 0, nCount+1 );
  279. int j = vec.AddToTail( );
  280. vec[j].m_pChoiceString = "<no target>";
  281. vec[j].m_pChoiceValue = "";
  282. for ( int i = 0; i < nCount; ++i )
  283. {
  284. CDmeCommentaryNodeEntity *pNode = entities[ i ];
  285. const char *pTargetName = pNode->GetTargetName();
  286. if ( !pTargetName || !pTargetName[0] )
  287. continue;
  288. if ( !Q_stricmp( pNode->GetClassName(), "info_target" ) )
  289. {
  290. j = vec.AddToTail( );
  291. vec[j].m_pChoiceString = pTargetName;
  292. vec[j].m_pChoiceValue = pTargetName;
  293. }
  294. }
  295. CPickerFrame *pInfoTargetPickerDialog = new CPickerFrame( g_pCommEditTool->GetRootPanel(), "Select Target", "InfoTarget", NULL );
  296. KeyValues *pContextKeyValues = new KeyValues( "context" );
  297. pContextKeyValues->SetPtr( "widget", pControl );
  298. pInfoTargetPickerDialog->AddActionSignalTarget( this );
  299. pInfoTargetPickerDialog->DoModal( vec, pContextKeyValues );
  300. }
  301. //-----------------------------------------------------------------------------
  302. // Called when a sound is successfully recorded
  303. //-----------------------------------------------------------------------------
  304. void CCommentaryPropertiesPanel::OnSoundRecorded( KeyValues *pKeyValues )
  305. {
  306. const char *pFileName = pKeyValues->GetString( "relativepath" );
  307. m_pSoundFileName->SetText( pFileName );
  308. UpdateCommentaryNode();
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Used to open a particular file in perforce, and deal with all the lovely dialogs
  312. //-----------------------------------------------------------------------------
  313. void CCommentaryPropertiesPanel::OnFileSelected( KeyValues *pKeyValues )
  314. {
  315. const char *pFileName = pKeyValues->GetString( "fullpath" );
  316. if ( g_pFileSystem->FileExists( pFileName ) )
  317. {
  318. char pBuf[1024];
  319. Q_snprintf( pBuf, sizeof(pBuf), "File %s already exists!\nRecording audio will not overwrite existing files.", pFileName );
  320. vgui::MessageBox *pMessageBox = new vgui::MessageBox( "File already Exists!\n", pBuf, g_pCommEditTool );
  321. pMessageBox->DoModal( );
  322. return;
  323. }
  324. CSoundRecordPanel *pSoundRecordPanel = new CSoundRecordPanel( g_pCommEditTool->GetRootPanel(), "Record Commentary" );
  325. pSoundRecordPanel->AddActionSignalTarget( this );
  326. pSoundRecordPanel->DoModal( pFileName );
  327. }
  328. //-----------------------------------------------------------------------------
  329. // Called when sound recording is requested
  330. //-----------------------------------------------------------------------------
  331. void CCommentaryPropertiesPanel::RecordSound( )
  332. {
  333. char pStartingDir[ MAX_PATH ];
  334. GetModSubdirectory( "sound", pStartingDir, sizeof(pStartingDir) );
  335. vgui::FileOpenDialog *pDialog = new vgui::FileOpenDialog( this, "Save As", false );
  336. pDialog->SetTitle( "Enter New Audio File", true );
  337. pDialog->SetStartDirectoryContext( "commedit_audio_record", pStartingDir );
  338. pDialog->AddFilter( "*.wav", "Audio File (*.wav)", true );
  339. pDialog->SetDeleteSelfOnClose( true );
  340. pDialog->AddActionSignalTarget( this );
  341. pDialog->DoModal( true );
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Called when buttons are clicked
  345. //-----------------------------------------------------------------------------
  346. void CCommentaryPropertiesPanel::OnCommand( const char *pCommand )
  347. {
  348. if ( !Q_stricmp( pCommand, "PickSound" ) )
  349. {
  350. PickSound();
  351. return;
  352. }
  353. if ( !Q_stricmp( pCommand, "Record" ) )
  354. {
  355. RecordSound();
  356. return;
  357. }
  358. if ( !Q_stricmp( pCommand, "PickViewPosition" ) )
  359. {
  360. PickInfoTarget( m_pViewPosition );
  361. return;
  362. }
  363. if ( !Q_stricmp( pCommand, "PickViewTarget" ) )
  364. {
  365. PickInfoTarget( m_pViewTarget );
  366. return;
  367. }
  368. if ( !Q_stricmp( pCommand, "PreventMovementClicked" ) )
  369. {
  370. UpdateCommentaryNode();
  371. return;
  372. }
  373. BaseClass::OnCommand( pCommand );
  374. }