//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: Singleton dialog that generates and presents the entity report. // //===========================================================================// #include "particlesystemdefinitionbrowser.h" #include "tier1/keyvalues.h" #include "tier1/utlbuffer.h" #include "iregistry.h" #include "vgui/ivgui.h" #include "vgui_controls/listpanel.h" #include "vgui_controls/inputdialog.h" #include "vgui_controls/messagebox.h" #include "petdoc.h" #include "pettool.h" #include "datamodel/dmelement.h" #include "vgui/keycode.h" #include "dme_controls/dmecontrols_utils.h" #include "dme_controls/particlesystempanel.h" #include "matsys_controls/particlepicker.h" // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; //----------------------------------------------------------------------------- // Sort by particle system definition name //----------------------------------------------------------------------------- static int __cdecl ParticleSystemNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) { const char *string1 = item1.kv->GetString("name"); const char *string2 = item2.kv->GetString("name"); return Q_stricmp( string1, string2 ); } //----------------------------------------------------------------------------- // Constructor //----------------------------------------------------------------------------- CParticleSystemDefinitionBrowser::CParticleSystemDefinitionBrowser( CPetDoc *pDoc, vgui::Panel* pParent, const char *pName ) : BaseClass( pParent, pName ), m_pDoc( pDoc ) { SetKeyBoardInputEnabled( true ); SetPaintBackgroundEnabled( true ); m_pSystemGrid = new CParticleSnapshotGrid( this, "SnapshotGrid" ); m_pSystemGrid->AddActionSignalTarget(this); CBoxSizer *pBaseSizer = new CBoxSizer( ESLD_HORIZONTAL ); { CBoxSizer *pDefinitionSizer = new CBoxSizer( ESLD_VERTICAL ); pDefinitionSizer->AddPanel( new Label( this, "ParticleSystemsLabel", "Particle System Definitions:" ), SizerAddArgs_t() ); pDefinitionSizer->AddPanel( m_pSystemGrid, SizerAddArgs_t().Expand( 1.0f ) ); { CBoxSizer *pBottomRowSizer = new CBoxSizer( ESLD_HORIZONTAL ); pBottomRowSizer->AddPanel( new Button( this, "SaveButton", "Save", this, "save" ), SizerAddArgs_t() ); pBottomRowSizer->AddPanel( new Button( this, "SaveAndTestButton", "Save and Test", this, "SaveAndTest" ), SizerAddArgs_t() ); pDefinitionSizer->AddSizer( pBottomRowSizer, SizerAddArgs_t() ); } pBaseSizer->AddSizer( pDefinitionSizer, SizerAddArgs_t().Expand( 1.0f ) ); } { CBoxSizer *pButtonColSizer = new CBoxSizer( ESLD_VERTICAL ); m_pCreateButton = new Button( this, "CreateButton", "Create", this, "Create" ); pButtonColSizer->AddPanel( m_pCreateButton, SizerAddArgs_t() ); m_pDeleteButton = new Button( this, "DeleteButton", "Delete", this, "Delete" ); m_pDeleteButton->SetEnabled(false); pButtonColSizer->AddPanel( m_pDeleteButton, SizerAddArgs_t() ); m_pCopyButton = new Button( this, "CopyButton", "Duplicate", this, "Copy" ); m_pCopyButton->SetEnabled(false); pButtonColSizer->AddPanel( m_pCopyButton, SizerAddArgs_t() ); pBaseSizer->AddSizer( pButtonColSizer, SizerAddArgs_t() ); } SetSizer( pBaseSizer ); UpdateParticleSystemList(); } CParticleSystemDefinitionBrowser::~CParticleSystemDefinitionBrowser() { SaveUserConfig(); } //----------------------------------------------------------------------------- // Gets the ith selected particle system //----------------------------------------------------------------------------- CDmeParticleSystemDefinition* CParticleSystemDefinitionBrowser::GetSelectedParticleSystem( int i ) { if ( i < 0 || i >= m_pSystemGrid->GetSelectedSystemCount() ) return NULL; int iSel = m_pSystemGrid->GetSelectedSystemId(i); return m_pDoc->GetParticleSystem(iSel); } //----------------------------------------------------------------------------- // Purpose: Deletes the marked objects. //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::DeleteParticleSystems() { { // This is undoable CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG|NOTIFY_FLAG_PARTICLESYS_ADDED_OR_REMOVED, "Delete Particle Systems", "Delete Particle Systems" ); // // Build a list of objects to delete. // CUtlVector< CDmeParticleSystemDefinition* > itemsToDelete; int nCount = m_pSystemGrid->GetSelectedSystemCount(); for (int i = 0; i < nCount; i++) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); if ( pParticleSystem ) { itemsToDelete.AddToTail( pParticleSystem ); } } m_pSystemGrid->DeselectAll(); nCount = itemsToDelete.Count(); for ( int i = 0; i < nCount; ++i ) { m_pDoc->DeleteParticleSystemDefinition( itemsToDelete[i] ); } g_pPetTool->SetCurrentParticleSystem( NULL, true ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::OnKeyCodeTyped( vgui::KeyCode code ) { if ( code == KEY_DELETE ) { DeleteParticleSystems(); } else { BaseClass::OnKeyCodeTyped( code ); } } //----------------------------------------------------------------------------- // Called when the selection changes //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::UpdateParticleSystemSelection() { if ( m_pSystemGrid->GetSelectedSystemCount() == 1 ) { g_pPetTool->SetCurrentParticleSystem( m_pDoc->GetParticleSystem( m_pSystemGrid->GetSelectedSystemId(0) ), false ); } else { g_pPetTool->SetCurrentParticleSystem( NULL, false ); } } void CParticleSystemDefinitionBrowser::OnParticleSystemSelectionChanged( ) { UpdateParticleSystemSelection(); bool bAnySelected = ( m_pSystemGrid->GetSelectedSystemCount() > 0 ); m_pDeleteButton->SetEnabled( bAnySelected ); m_pCopyButton->SetEnabled( bAnySelected ); } //----------------------------------------------------------------------------- // Select a particular node //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::SelectParticleSystem( CDmeParticleSystemDefinition *pFind ) { for ( int i = 0; i < m_pDoc->GetParticleSystemCount(); ++i ) { if ( m_pDoc->GetParticleSystem(i) == pFind ) { m_pSystemGrid->SelectId( i, false, false ); break; } } } //----------------------------------------------------------------------------- // Called when buttons are clicked //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::OnInputCompleted( KeyValues *pKeyValues ) { const char *pText = pKeyValues->GetString( "text", NULL ); if ( m_pDoc->IsParticleSystemDefined( pText ) ) { char pBuf[1024]; Q_snprintf( pBuf, sizeof(pBuf), "Particle System \"%s\" already exists!\n", pText ); vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Duplicate Particle System Name!\n", pBuf, g_pPetTool->GetRootPanel() ); pMessageBox->DoModal( ); return; } if ( pKeyValues->FindKey( "create" ) ) { CDmeParticleSystemDefinition *pParticleSystem = m_pDoc->AddNewParticleSystemDefinition( pText ); g_pPetTool->SetCurrentParticleSystem( pParticleSystem ); } else if ( pKeyValues->FindKey( "copy_one" ) || pKeyValues->FindKey( "copy_many" ) ) { int nCount = m_pSystemGrid->GetSelectedSystemCount(); if ( nCount == 1 ) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( 0 ); CDmeParticleSystemDefinition * pNew = NULL; { CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG|NOTIFY_FLAG_PARTICLESYS_ADDED_OR_REMOVED, "Duplicate One Particle System", "Duplicate One Particle System" ); pNew = CastElement( pParticleSystem->Copy( ) ); pNew->SetName( pText ); m_pDoc->AddNewParticleSystemDefinition( pNew, guard ); } g_pPetTool->SetCurrentParticleSystem( pNew ); } else if ( nCount > 1 ) { CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG|NOTIFY_FLAG_PARTICLESYS_ADDED_OR_REMOVED, "Duplicate Multiple Particle Systems", "Duplicate Multiple Particle Systems" ); CUtlVector pNewSystems; for ( int i = 0; i < nCount; ++i ) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); CDmeParticleSystemDefinition *pNew = NULL; CUtlString newName = pParticleSystem->GetName(); newName += pText; pNew = CastElement( pParticleSystem->Copy( ) ); pNew->SetName( newName.Get() ); pNewSystems.AddToTail(pNew); } Assert( pNewSystems.Count() == nCount ); for ( int i = 0; i < nCount; ++i ) { m_pDoc->AddNewParticleSystemDefinition( pNewSystems[i], guard ); } g_pPetTool->SetCurrentParticleSystem( NULL ); } } } //----------------------------------------------------------------------------- // Copy to clipboard //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::OnCopy( ) { int nCount = m_pSystemGrid->GetSelectedSystemCount(); CUtlVector< KeyValues * > list; CUtlRBTree< CDmeParticleSystemDefinition* > defs( 0, 0, DefLessFunc( CDmeParticleSystemDefinition* ) ); for ( int i = 0; i < nCount; ++i ) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); if ( g_pDataModel->Serialize( buf, "keyvalues2", "pcf", pParticleSystem->GetHandle() ) ) { KeyValues *pData = new KeyValues( "Clipboard" ); pData->SetString( PARTICLE_CLIPBOARD_DEFINITION_STR, (char*)buf.Base() ); list.AddToTail( pData ); } } if ( list.Count() ) { g_pDataModel->SetClipboardData( list ); } } //----------------------------------------------------------------------------- // Paste from clipboard //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::ReplaceDef_r( CUndoScopeGuard& guard, CDmeParticleSystemDefinition *pDef ) { if ( !pDef ) return; m_pDoc->ReplaceParticleSystemDefinition( pDef ); int nChildCount = pDef->GetParticleFunctionCount( FUNCTION_CHILDREN ); for ( int i = 0; i < nChildCount; ++i ) { CDmeParticleChild *pChildFunction = static_cast< CDmeParticleChild* >( pDef->GetParticleFunction( FUNCTION_CHILDREN, i ) ); CDmeParticleSystemDefinition* pChild = pChildFunction->m_Child; ReplaceDef_r( guard, pChild ); } } void CParticleSystemDefinitionBrowser::PasteOperator( CUndoScopeGuard& guard, CDmeParticleFunction *pFunc ) { int nCount = m_pSystemGrid->GetSelectedSystemCount(); for ( int i = 0; i < nCount; ++i ) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); pParticleSystem->AddCopyOfOperator( pFunc ); } } void CParticleSystemDefinitionBrowser::PasteDefinitionBody( CUndoScopeGuard& guard, CDmeParticleSystemDefinition *pDef ) { int nCount = m_pSystemGrid->GetSelectedSystemCount(); for ( int i = 0; i < nCount; ++i ) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); pParticleSystem->OverrideAttributesFromOtherDefinition( pDef ); } } void CParticleSystemDefinitionBrowser::PasteFromClipboard( ) { // This is undoable CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Paste From Clipboard", "Paste From Clipboard" ); bool bRefreshAll = false; CUtlVector< KeyValues * > list; g_pDataModel->GetClipboardData( list ); int nItems = list.Count(); for ( int i = 0; i < nItems; ++i ) { CDmeParticleSystemDefinition *pDef = ReadParticleClassFromKV( list[i], PARTICLE_CLIPBOARD_DEFINITION_STR ); if ( pDef ) { ReplaceDef_r( guard, pDef ); bRefreshAll = true; continue; } CDmeParticleFunction *pFunc = ReadParticleClassFromKV( list[i], PARTICLE_CLIPBOARD_FUNCTIONS_STR ); if ( pFunc ) { PasteOperator( guard, pFunc ); bRefreshAll = true; continue; } pDef = ReadParticleClassFromKV( list[i], PARTICLE_CLIPBOARD_DEF_BODY_STR ); if ( pDef ) { PasteDefinitionBody( guard, pDef ); bRefreshAll = true; continue; } } guard.Release(); if ( bRefreshAll ) { m_pDoc->UpdateAllParticleSystems(); } } //----------------------------------------------------------------------------- // Called when buttons are clicked //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::OnCommand( const char *pCommand ) { if ( !Q_stricmp( pCommand, "create" ) ) { vgui::InputDialog *pInputDialog = new vgui::InputDialog( g_pPetTool->GetRootPanel(), "Enter Particle System Name", "Name:", "" ); pInputDialog->SetSmallCaption( true ); pInputDialog->SetMultiline( false ); pInputDialog->AddActionSignalTarget( this ); pInputDialog->DoModal( new KeyValues("create") ); return; } if ( !Q_stricmp( pCommand, "copy" ) ) { if ( m_pSystemGrid->GetSelectedSystemCount() == 1 ) { CUtlString newName = m_pSystemGrid->GetSystemName(m_pSystemGrid->GetSelectedSystemId(0)); newName += "_copy"; vgui::InputDialog *pInputDialog = new vgui::InputDialog( g_pPetTool->GetRootPanel(), "Enter Duplicate System Name", "Name:", newName.Get() ); pInputDialog->SetSmallCaption( true ); pInputDialog->SetMultiline( false ); pInputDialog->AddActionSignalTarget( this ); pInputDialog->DoModal( new KeyValues("copy_one") ); } else if ( m_pSystemGrid->GetSelectedSystemCount() > 1 ) { vgui::InputDialog *pInputDialog = new vgui::InputDialog( g_pPetTool->GetRootPanel(), "Enter Suffix for New Systems", "Suffix:", "_copy" ); pInputDialog->SetSmallCaption( true ); pInputDialog->SetMultiline( false ); pInputDialog->AddActionSignalTarget( this ); pInputDialog->DoModal( new KeyValues("copy_many") ); } return; } if ( !Q_stricmp( pCommand, "delete" ) ) { DeleteParticleSystems(); return; } if ( !Q_stricmp( pCommand, "Save" ) ) { g_pPetTool->Save(); return; } if ( !Q_stricmp( pCommand, "SaveAndTest" ) ) { g_pPetTool->SaveAndTest(); return; } BaseClass::OnCommand( pCommand ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystemDefinitionBrowser::UpdateParticleSystemList( bool bRetainSelection ) { ///////////////////////// // build a list of previously selected systems CUtlVector< CUtlString > selectedItems; if ( bRetainSelection ) { int nCount = m_pSystemGrid->GetSelectedSystemCount(); for ( int i = 0; i < nCount; ++i ) { CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); if ( pParticleSystem ) { selectedItems.AddToTail( pParticleSystem->GetName() ); } } } ///////////////////////// // now go nuts const CDmrParticleSystemList particleSystemList = m_pDoc->GetParticleSystemDefinitionList(); if ( !particleSystemList.IsValid() ) { m_pSystemGrid->SetParticleList( CUtlVector() ); return; } CUtlVector systemNames; CUtlVector selectionIndicies; ///////////////////////// // populate the new list for ( int i = 0; i < particleSystemList.Count(); ++i ) { CDmeParticleSystemDefinition *pParticleSystem = particleSystemList[i]; if ( !pParticleSystem ) continue; systemNames.AddToTail( pParticleSystem->GetName() ); // see if the system was previously selected for ( int s = 0; s < selectedItems.Count(); ++s ) { if( !V_strcmp(pParticleSystem->GetName(), selectedItems[s]) ) { selectionIndicies.AddToTail(i); } } } m_pSystemGrid->SetParticleList( systemNames ); ///////////////////////// // reselect any identified systems if ( bRetainSelection ) { for ( int i = 0; i < selectionIndicies.Count(); ++i ) { m_pSystemGrid->SelectId( selectionIndicies[i], true, false ); } } }