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.

488 lines
15 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dme_controls/DmeSourceDCCFilePanel.h"
  7. #include "dme_controls/DmePanel.h"
  8. #include "movieobjects/dmedccmakefile.h"
  9. #include "vgui_controls/TextEntry.h"
  10. #include "vgui_controls/ListPanel.h"
  11. #include "vgui_controls/Button.h"
  12. #include "vgui_controls/InputDialog.h"
  13. #include "vgui_controls/MessageBox.h"
  14. #include "vgui/keycode.h"
  15. #include "tier1/keyvalues.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. using namespace vgui;
  19. //-----------------------------------------------------------------------------
  20. //
  21. // Hook into the dme panel editor system
  22. //
  23. //-----------------------------------------------------------------------------
  24. IMPLEMENT_DMEPANEL_FACTORY( CDmeSourceDCCFilePanel, DmeSourceDCCFile, "DmeSourceDCCFileDefault", "Maya/XSI Source File Editor", true );
  25. //-----------------------------------------------------------------------------
  26. // Sort by MDL name
  27. //-----------------------------------------------------------------------------
  28. static int __cdecl DccObjectSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  29. {
  30. const char *string1 = item1.kv->GetString( "dccobject" );
  31. const char *string2 = item2.kv->GetString( "dccobject" );
  32. return Q_stricmp( string1, string2 );
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Purpose: Constructor, destructor
  36. //-----------------------------------------------------------------------------
  37. CDmeSourceDCCFilePanel::CDmeSourceDCCFilePanel( vgui::Panel *pParent, const char *pPanelName ) :
  38. BaseClass( pParent, pPanelName )
  39. {
  40. m_pRootDCCObjects = new vgui::ListPanel( this, "DCCObjectList" );
  41. m_pRootDCCObjects->AddColumnHeader( 0, "dccobject", "Maya/XSI Object Name", 100, 0 );
  42. m_pRootDCCObjects->AddActionSignalTarget( this );
  43. m_pRootDCCObjects->SetSortFunc( 0, DccObjectSortFunc );
  44. m_pRootDCCObjects->SetSortColumn( 0 );
  45. // m_pRootDCCObjects->SetSelectIndividualCells( true );
  46. m_pRootDCCObjects->SetEmptyListText("No sources");
  47. // m_pRootDCCObjects->SetDragEnabled( true );
  48. m_pDCCObjectBrowser = new vgui::Button( this, "DCCObjectBrowser", "...", this, "OnBrowseDCCObject" );
  49. m_pDCCObjectName = new vgui::TextEntry( this, "DCCObjectName" );
  50. m_pDCCObjectName->SendNewLine( true );
  51. m_pDCCObjectName->AddActionSignalTarget( this );
  52. m_pAddDCCObject = new vgui::Button( this, "AddDCCObjectButton", "Add", this, "OnAddDCCObject" );
  53. m_pRemoveDCCObject = new vgui::Button( this, "RemoveDCCObjectButton", "Remove", this, "OnRemoveDCCObject" );
  54. m_pApplyChanges = new vgui::Button( this, "ApplyChangesButton", "Apply", this, "OnApplyChanges" );
  55. // Load layout settings; has to happen before pinning occurs in code
  56. LoadControlSettings( "resource/DmeSourceDCCFilePanel.res" );
  57. }
  58. CDmeSourceDCCFilePanel::~CDmeSourceDCCFilePanel()
  59. {
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Marks the file as dirty (or not)
  63. //-----------------------------------------------------------------------------
  64. void CDmeSourceDCCFilePanel::SetDirty()
  65. {
  66. PostActionSignal( new KeyValues( "DmeElementChanged" ) );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Refresh the source list
  70. //-----------------------------------------------------------------------------
  71. void CDmeSourceDCCFilePanel::RefreshDCCObjectList( )
  72. {
  73. m_pRootDCCObjects->RemoveAll();
  74. if ( !m_hSourceDCCFile.Get() )
  75. return;
  76. int nCount = m_hSourceDCCFile->m_RootDCCObjects.Count();
  77. for ( int i = 0; i < nCount; ++i )
  78. {
  79. KeyValues *pItemKeys = new KeyValues( "node", "dccobject", m_hSourceDCCFile->m_RootDCCObjects.Get(i) );
  80. pItemKeys->SetInt( "dccObjectIndex", i );
  81. m_pRootDCCObjects->AddItem( pItemKeys, 0, false, false );
  82. }
  83. m_pRootDCCObjects->SortList();
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Resets the state
  87. //-----------------------------------------------------------------------------
  88. void CDmeSourceDCCFilePanel::SetDmeElement( CDmeSourceDCCFile *pSourceDCCFile )
  89. {
  90. m_hSourceDCCFile = pSourceDCCFile;
  91. bool bEnabled = ( pSourceDCCFile != NULL );
  92. m_pDCCObjectBrowser->SetEnabled( bEnabled );
  93. m_pAddDCCObject->SetEnabled( bEnabled );
  94. m_pRemoveDCCObject->SetEnabled( bEnabled );
  95. m_pApplyChanges->SetEnabled( bEnabled );
  96. if ( !bEnabled )
  97. {
  98. m_pRootDCCObjects->RemoveAll();
  99. m_pDCCObjectName->SetText( "" );
  100. return;
  101. }
  102. RefreshDCCObjectList();
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Called when a list panel's selection changes
  106. //-----------------------------------------------------------------------------
  107. void CDmeSourceDCCFilePanel::OnItemSelectionChanged( )
  108. {
  109. int nCount = m_pRootDCCObjects->GetSelectedItemsCount();
  110. bool bEnabled = ( nCount > 0 );
  111. bool bMultiselect = ( nCount > 1 );
  112. m_pDCCObjectBrowser->SetEnabled( bEnabled && !bMultiselect );
  113. m_pDCCObjectName->SetEnabled( bEnabled && !bMultiselect );
  114. m_pApplyChanges->SetEnabled( bEnabled && !bMultiselect );
  115. m_pRemoveDCCObject->SetEnabled( bEnabled );
  116. if ( !bEnabled || bMultiselect )
  117. {
  118. m_pDCCObjectName->SetText( "" );
  119. return;
  120. }
  121. int nItemID = m_pRootDCCObjects->GetSelectedItem( 0 );
  122. KeyValues *pKeyValues = m_pRootDCCObjects->GetItem( nItemID );
  123. m_pDCCObjectName->SetText( pKeyValues->GetString( "dccobject" ) );
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Called when a list panel's selection changes
  127. //-----------------------------------------------------------------------------
  128. void CDmeSourceDCCFilePanel::OnItemSelected( KeyValues *kv )
  129. {
  130. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  131. if ( pPanel == m_pRootDCCObjects )
  132. {
  133. OnItemSelectionChanged();
  134. return;
  135. }
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Called when a list panel's selection changes
  139. //-----------------------------------------------------------------------------
  140. void CDmeSourceDCCFilePanel::OnItemDeselected( KeyValues *kv )
  141. {
  142. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  143. if ( pPanel == m_pRootDCCObjects )
  144. {
  145. OnItemSelectionChanged();
  146. return;
  147. }
  148. }
  149. //-----------------------------------------------------------------------------
  150. // Called when return is hit in a text entry field
  151. //-----------------------------------------------------------------------------
  152. void CDmeSourceDCCFilePanel::OnTextNewLine( KeyValues *kv )
  153. {
  154. if ( !m_hSourceDCCFile.Get() )
  155. return;
  156. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  157. if ( pPanel == m_pDCCObjectName )
  158. {
  159. OnDCCObjectNameChanged();
  160. return;
  161. }
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Selects a particular DCC object
  165. //-----------------------------------------------------------------------------
  166. void CDmeSourceDCCFilePanel::SelectDCCObject( int nDCCObjectIndex )
  167. {
  168. if ( nDCCObjectIndex < 0 )
  169. {
  170. m_pRootDCCObjects->ClearSelectedItems();
  171. return;
  172. }
  173. int nItemID = m_pRootDCCObjects->FirstItem();
  174. for ( ; nItemID != m_pRootDCCObjects->InvalidItemID(); nItemID = m_pRootDCCObjects->NextItem( nItemID ) )
  175. {
  176. KeyValues *kv = m_pRootDCCObjects->GetItem( nItemID );
  177. if ( kv->GetInt( "dccObjectIndex", -1 ) != nDCCObjectIndex )
  178. continue;
  179. m_pRootDCCObjects->SetSingleSelectedItem( nItemID );
  180. break;
  181. }
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Called when we're browsing for a DCC object and one was selected
  185. //-----------------------------------------------------------------------------
  186. void CDmeSourceDCCFilePanel::OnDCCObjectAdded( const char *pDCCObjectName, KeyValues *pContextKeys )
  187. {
  188. if ( !m_hSourceDCCFile.Get() )
  189. return;
  190. if ( CheckForDuplicateNames( pDCCObjectName ) )
  191. return;
  192. int nIndex = -1;
  193. {
  194. CDisableUndoScopeGuard guard;
  195. nIndex = m_hSourceDCCFile->m_RootDCCObjects.AddToTail( pDCCObjectName );
  196. }
  197. SetDirty( );
  198. RefreshDCCObjectList( );
  199. SelectDCCObject( nIndex );
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Called when the file open dialog for browsing source files selects something
  203. //-----------------------------------------------------------------------------
  204. void CDmeSourceDCCFilePanel::OnInputCompleted( KeyValues *kv )
  205. {
  206. const char *pDCCObjectName = kv->GetString( "text", NULL );
  207. if ( !pDCCObjectName )
  208. return;
  209. KeyValues *pDialogKeys = kv->FindKey( "ChangeDCCObject" );
  210. if ( pDialogKeys )
  211. {
  212. m_pDCCObjectName->SetText( pDCCObjectName );
  213. OnDCCObjectNameChanged();
  214. return;
  215. }
  216. pDialogKeys = kv->FindKey( "AddDCCObject" );
  217. if ( pDialogKeys )
  218. {
  219. OnDCCObjectAdded( pDCCObjectName, pDialogKeys );
  220. return;
  221. }
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Shows the DCC object browser (once we have one)
  225. //-----------------------------------------------------------------------------
  226. void CDmeSourceDCCFilePanel::ShowDCCObjectBrowser( const char *pTitle, const char *pPrompt, KeyValues *pDialogKeys )
  227. {
  228. InputDialog *pInput = new InputDialog( this, pTitle, pPrompt );
  229. pInput->SetMultiline( false );
  230. pInput->DoModal( pDialogKeys );
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Called when the button to add a file is clicked
  234. //-----------------------------------------------------------------------------
  235. void CDmeSourceDCCFilePanel::OnAddDCCObject( )
  236. {
  237. if ( m_hSourceDCCFile.Get() )
  238. {
  239. KeyValues *pDialogKeys = new KeyValues( "AddDCCObject" );
  240. ShowDCCObjectBrowser( "Add DCC Object", "Enter DCC object name to add", pDialogKeys );
  241. }
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Called when the button to browse for a source file is clicked
  245. //-----------------------------------------------------------------------------
  246. void CDmeSourceDCCFilePanel::OnBrowseDCCObject( )
  247. {
  248. int nCount = m_pRootDCCObjects->GetSelectedItemsCount();
  249. if ( nCount == 0 || !m_hSourceDCCFile.Get() )
  250. return;
  251. int nItemID = m_pRootDCCObjects->GetSelectedItem( 0 );
  252. KeyValues *pKeyValues = m_pRootDCCObjects->GetItem( nItemID );
  253. int nDCCObjectIndex = pKeyValues->GetInt( "dccObjectIndex", -1 );
  254. KeyValues *pDialogKeys = new KeyValues( "ChangeDCCObject", "dccObjectIndex", nDCCObjectIndex );
  255. ShowDCCObjectBrowser( "Edit Maya/XSI Object", "Enter new name of Maya/XSI object", pDialogKeys );
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Called when the source file name changes
  259. //-----------------------------------------------------------------------------
  260. bool CDmeSourceDCCFilePanel::CheckForDuplicateNames( const char *pDCCObjectName, int nDCCObjectSkipIndex )
  261. {
  262. // Look for the existence of this source already
  263. if ( pDCCObjectName[0] )
  264. {
  265. int nCount = m_hSourceDCCFile->m_RootDCCObjects.Count();
  266. for ( int i = 0; i < nCount; ++i )
  267. {
  268. if ( i == nDCCObjectSkipIndex )
  269. continue;
  270. if ( !Q_stricmp( pDCCObjectName, m_hSourceDCCFile->m_RootDCCObjects[i] ) )
  271. {
  272. vgui::MessageBox *pError = new vgui::MessageBox( "#DmeSourceDCCFile_DuplicateSourceTitle", "#DmeSourceDCCFile_DuplicateSourceText", GetParent() );
  273. pError->DoModal();
  274. return true;
  275. }
  276. }
  277. }
  278. return false;
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Called when the source file name changes
  282. //-----------------------------------------------------------------------------
  283. void CDmeSourceDCCFilePanel::OnDCCObjectNameChanged()
  284. {
  285. int nCount = m_pRootDCCObjects->GetSelectedItemsCount();
  286. if ( nCount == 0 || !m_hSourceDCCFile.Get() )
  287. return;
  288. int nItemID = m_pRootDCCObjects->GetSelectedItem( 0 );
  289. KeyValues *pKeyValues = m_pRootDCCObjects->GetItem( nItemID );
  290. int nDCCObjectIndex = pKeyValues->GetInt( "dccObjectIndex", -1 );
  291. if ( nDCCObjectIndex < 0 )
  292. return;
  293. char pDCCObjectName[MAX_PATH];
  294. m_pDCCObjectName->GetText( pDCCObjectName, sizeof(pDCCObjectName) );
  295. if ( CheckForDuplicateNames( pDCCObjectName, nDCCObjectIndex ) )
  296. return;
  297. {
  298. CDisableUndoScopeGuard guard;
  299. m_hSourceDCCFile->m_RootDCCObjects.Set( nDCCObjectIndex, pDCCObjectName );
  300. }
  301. pKeyValues->SetString( "dccobject", pDCCObjectName );
  302. m_pRootDCCObjects->ApplyItemChanges( nItemID );
  303. m_pRootDCCObjects->SortList();
  304. SetDirty( );
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Used for sorting below
  308. //-----------------------------------------------------------------------------
  309. static int IntCompare( const void *pSrc1, const void *pSrc2 )
  310. {
  311. int i1 = *(int*)pSrc1;
  312. int i2 = *(int*)pSrc2;
  313. return i1 - i2;
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Called when the button to remove a DCC object is clicked
  317. //-----------------------------------------------------------------------------
  318. void CDmeSourceDCCFilePanel::OnRemoveDCCObject( )
  319. {
  320. int nCount = m_pRootDCCObjects->GetSelectedItemsCount();
  321. if ( nCount == 0 || !m_hSourceDCCFile.Get() )
  322. return;
  323. int nSelectedCount = 0;
  324. int *pDCCObjectIndex = (int*)alloca( nCount*sizeof(int) );
  325. for ( int i = 0; i < nCount; ++i )
  326. {
  327. int nItemID = m_pRootDCCObjects->GetSelectedItem( i );
  328. KeyValues *pKeyValues = m_pRootDCCObjects->GetItem( nItemID );
  329. int nDCCObjectIndex = pKeyValues->GetInt( "dccObjectIndex", -1 );
  330. if ( nDCCObjectIndex < 0 )
  331. continue;
  332. pDCCObjectIndex[nSelectedCount++] = nDCCObjectIndex;
  333. }
  334. if ( nSelectedCount == 0 )
  335. return;
  336. // Sort the object indices so we can remove them all
  337. qsort( pDCCObjectIndex, nSelectedCount, sizeof(int), IntCompare );
  338. // Update the selection to be reasonable after deletion
  339. int nItemID = m_pRootDCCObjects->GetSelectedItem( 0 );
  340. int nRow = m_pRootDCCObjects->GetItemCurrentRow( nItemID );
  341. Assert( nRow >= 0 );
  342. {
  343. CDisableUndoScopeGuard guard;
  344. // Because we sorted it above, removes will occur properly
  345. for ( int i = nSelectedCount; --i >= 0; )
  346. {
  347. m_hSourceDCCFile->m_RootDCCObjects.Remove( pDCCObjectIndex[i] );
  348. }
  349. SetDirty( );
  350. }
  351. RefreshDCCObjectList();
  352. int nVisibleRowCount = m_pRootDCCObjects->GetItemCount();
  353. if ( nVisibleRowCount == 0 )
  354. return;
  355. if ( nRow >= nVisibleRowCount )
  356. {
  357. nRow = nVisibleRowCount - 1;
  358. }
  359. int nNewItemID = m_pRootDCCObjects->GetItemIDFromRow( nRow );
  360. m_pRootDCCObjects->SetSingleSelectedItem( nNewItemID );
  361. }
  362. //-----------------------------------------------------------------------------
  363. // Called when a key is typed
  364. //-----------------------------------------------------------------------------
  365. void CDmeSourceDCCFilePanel::OnKeyCodeTyped( vgui::KeyCode code )
  366. {
  367. if ( code == KEY_DELETE )
  368. {
  369. OnRemoveDCCObject();
  370. return;
  371. }
  372. BaseClass::OnKeyCodeTyped( code );
  373. }
  374. //-----------------------------------------------------------------------------
  375. // Command handler
  376. //-----------------------------------------------------------------------------
  377. void CDmeSourceDCCFilePanel::OnCommand( const char *pCommand )
  378. {
  379. if ( !Q_stricmp( pCommand, "OnBrowseDCCObject" ) )
  380. {
  381. OnBrowseDCCObject();
  382. return;
  383. }
  384. if ( !Q_stricmp( pCommand, "OnAddDCCObject" ) )
  385. {
  386. OnAddDCCObject();
  387. return;
  388. }
  389. if ( !Q_stricmp( pCommand, "OnRemoveDCCObject" ) )
  390. {
  391. OnRemoveDCCObject();
  392. return;
  393. }
  394. if ( !Q_stricmp( pCommand, "OnApplyChanges" ) )
  395. {
  396. OnDCCObjectNameChanged();
  397. return;
  398. }
  399. BaseClass::OnCommand( pCommand );
  400. }