diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tools/pet | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'tools/pet')
| -rw-r--r-- | tools/pet/particlesystemdefinitionbrowser.cpp | 599 | ||||
| -rw-r--r-- | tools/pet/particlesystemdefinitionbrowser.h | 90 | ||||
| -rw-r--r-- | tools/pet/particlesystempropertiescontainer.cpp | 73 | ||||
| -rw-r--r-- | tools/pet/particlesystempropertiescontainer.h | 45 | ||||
| -rw-r--r-- | tools/pet/pet.vpc | 64 | ||||
| -rw-r--r-- | tools/pet/petdoc.cpp | 536 | ||||
| -rw-r--r-- | tools/pet/petdoc.h | 122 | ||||
| -rw-r--r-- | tools/pet/pettool.cpp | 1078 | ||||
| -rw-r--r-- | tools/pet/pettool.h | 209 |
9 files changed, 2816 insertions, 0 deletions
diff --git a/tools/pet/particlesystemdefinitionbrowser.cpp b/tools/pet/particlesystemdefinitionbrowser.cpp new file mode 100644 index 0000000..1924c30 --- /dev/null +++ b/tools/pet/particlesystemdefinitionbrowser.cpp @@ -0,0 +1,599 @@ +//========= Copyright 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 "filesystem.h" +#include "vgui_controls/FileOpenDialog.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + + +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_pParticleSystemsDefinitions = new vgui::ListPanel( this, "ParticleSystems" ); + m_pParticleSystemsDefinitions->AddColumnHeader( 0, "name", "Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW ); + m_pParticleSystemsDefinitions->SetColumnSortable( 0, true ); + m_pParticleSystemsDefinitions->SetEmptyListText( "No Particle System Definitions" ); + m_pParticleSystemsDefinitions->AddActionSignalTarget( this ); + m_pParticleSystemsDefinitions->SetSortFunc( 0, ParticleSystemNameSortFunc ); + m_pParticleSystemsDefinitions->SetSortColumn( 0 ); + + LoadControlSettingsAndUserConfig( "resource/particlesystemdefinitionbrowser.res" ); + + UpdateParticleSystemList(); +} + +CParticleSystemDefinitionBrowser::~CParticleSystemDefinitionBrowser() +{ + SaveUserConfig(); +} + + +//----------------------------------------------------------------------------- +// Gets the ith selected particle system +//----------------------------------------------------------------------------- +CDmeParticleSystemDefinition* CParticleSystemDefinitionBrowser::GetSelectedParticleSystem( int i ) +{ + int iSel = m_pParticleSystemsDefinitions->GetSelectedItem( i ); + KeyValues *kv = m_pParticleSystemsDefinitions->GetItem( iSel ); + return GetElementKeyValue< CDmeParticleSystemDefinition >( kv, "particleSystem" ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Deletes the marked objects. +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::DeleteParticleSystems() +{ + int iSel = m_pParticleSystemsDefinitions->GetSelectedItem( 0 ); + int nRow = m_pParticleSystemsDefinitions->GetItemCurrentRow( iSel ) - 1; + { + // This is undoable + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Particle Systems", "Delete Particle Systems" ); + + // + // Build a list of objects to delete. + // + CUtlVector< CDmeParticleSystemDefinition* > itemsToDelete; + int nCount = m_pParticleSystemsDefinitions->GetSelectedItemsCount(); + for (int i = 0; i < nCount; i++) + { + CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); + if ( pParticleSystem ) + { + itemsToDelete.AddToTail( pParticleSystem ); + } + } + + nCount = itemsToDelete.Count(); + for ( int i = 0; i < nCount; ++i ) + { + m_pDoc->DeleteParticleSystemDefinition( itemsToDelete[i] ); + } + } + + // Update the list box selection. + if ( m_pParticleSystemsDefinitions->GetItemCount() > 0 ) + { + if ( nRow < 0 ) + { + nRow = 0; + } + else if ( nRow >= m_pParticleSystemsDefinitions->GetItemCount() ) + { + nRow = m_pParticleSystemsDefinitions->GetItemCount() - 1; + } + + iSel = m_pParticleSystemsDefinitions->GetItemIDFromRow( nRow ); + m_pParticleSystemsDefinitions->SetSingleSelectedItem( iSel ); + } + else + { + m_pParticleSystemsDefinitions->ClearSelectedItems(); + } +} + +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::LoadKVSection( CDmeParticleSystemDefinition *pNew, KeyValues *pOverridesKv, ParticleFunctionType_t eType ) +{ + // Operator KV + KeyValues *pOperator = pOverridesKv->FindKey( GetParticleFunctionTypeName(eType), NULL ); + if ( !pOperator ) + return; + + // Function + FOR_EACH_TRUE_SUBKEY( pOperator, pFunctionBlock ) + { + int iFunction = pNew->FindFunction( eType, pFunctionBlock->GetName() ); + if ( iFunction >= 0 ) + { + CDmeParticleFunction *pDmeFunction = pNew->GetParticleFunction( eType, iFunction ); + // Elements + FOR_EACH_SUBKEY( pFunctionBlock, pAttributeItem ) + { + CDmAttribute *pAttribute = pDmeFunction->GetAttribute( pAttributeItem->GetName() ); + if ( !pAttribute ) + { + Warning( "Unable to Find Attribute [%s] in Function [%s] in Operator [%s] for Definition [%s]\n", pAttributeItem->GetName(), pFunctionBlock->GetName(), GetParticleFunctionTypeName(eType), pNew->GetName() ); + } + else + { + pAttribute->SetValueFromString( pAttributeItem->GetString() ); + } + } + } + else + { + Warning( "Function [%s] not found under Operator [%s] for Definition [%s]\n", pFunctionBlock->GetName(), GetParticleFunctionTypeName(eType), pNew->GetName() ); + } + } + +} + +//----------------------------------------------------------------------------- +// Given a KV, create, add and return an effect +//----------------------------------------------------------------------------- +CDmeParticleSystemDefinition* CParticleSystemDefinitionBrowser::CreateParticleFromKV( KeyValues *pKeyValue ) +{ + CDmeParticleSystemDefinition* pBaseParticleDef = NULL; + + // Get the Base Particle Effect Def + const char* pBaseParticleName = pKeyValue->GetString( "base_effect", "" ); + for ( int i = 0; i < m_pParticleSystemsDefinitions->GetItemCount(); ++i ) + { + KeyValues *kv = m_pParticleSystemsDefinitions->GetItem( i ); + if ( !V_strcmp( kv->GetString( "name", "" ), pBaseParticleName ) ) + { + // + pBaseParticleDef = GetElementKeyValue< CDmeParticleSystemDefinition >( kv, "particleSystem" ); + break; + } + } + + // Base Particle could not be found, end; + if ( !pBaseParticleDef ) + { + Warning( "Unable to to find base particle system [%s]", pBaseParticleName ); + return NULL; + } + + // Create a Copy of the Base Effect + const char *pszNewParticleName = pKeyValue->GetName(); + //CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Copy Particle System", "Copy Particle System" ); + CDmeParticleSystemDefinition *pNew = CastElement<CDmeParticleSystemDefinition>( pBaseParticleDef->Copy() ); + pNew->SetName( pszNewParticleName ); + + // Overrides + // + //"properties" + KeyValues *pProperties = pKeyValue->FindKey( "Properties", NULL ); + if ( pProperties ) + { + FOR_EACH_SUBKEY( pProperties, pProperty ) + { + CDmAttribute *pAttribute = pNew->GetAttribute( pProperty->GetName() ); + if ( !pAttribute ) + { + Warning( "Unable to Find Attribute [%s] in Function [%s]\n", pProperty->GetName(), "Properties" ); + } + else + { + pAttribute->SetValueFromString( pProperty->GetString() ); + } + } + } + + LoadKVSection( pNew, pKeyValue, FUNCTION_RENDERER ); + LoadKVSection( pNew, pKeyValue, FUNCTION_OPERATOR ); + LoadKVSection( pNew, pKeyValue, FUNCTION_INITIALIZER ); + LoadKVSection( pNew, pKeyValue, FUNCTION_EMITTER ); + LoadKVSection( pNew, pKeyValue, FUNCTION_FORCEGENERATOR ); + LoadKVSection( pNew, pKeyValue, FUNCTION_CONSTRAINT ); + + // Remove copied children + int iChildrenCount = pNew->GetParticleFunctionCount( FUNCTION_CHILDREN ); + for ( int i = iChildrenCount - 1; i >= 0; i-- ) + { + pNew->RemoveFunction( FUNCTION_CHILDREN, i ); + } + + // Search Children + KeyValues *pChildren = pKeyValue->FindKey( "Children", NULL ); + if ( pChildren ) + { + FOR_EACH_TRUE_SUBKEY( pChildren, pChild ) + { + // each Child is its own effect so we need to add it and return it + CDmeParticleSystemDefinition* pChildEffect = CreateParticleFromKV( pChild ); + if ( pChildEffect ) + { + pNew->AddChild( pChildEffect ); + } + } + } + + m_pDoc->ReplaceParticleSystemDefinition( pNew ); + m_pDoc->UpdateAllParticleSystems(); + return pNew; +} +//----------------------------------------------------------------------------- +// Create from KV +void CParticleSystemDefinitionBrowser::CreateParticleSystemsFromKV( const char *pFileName ) +{ + // + //const char * pFileName = "particles\\_weapon_prefab_override_kv.txt"; + + CUtlBuffer bufRawData; + bool bReadFileOK = g_pFullFileSystem->ReadFile( pFileName, "MOD", bufRawData ); + if ( !bReadFileOK ) + { + Warning( "Unable to Open KV file [%s]\n", pFileName ); + return; + } + + // Wrap it with a text buffer reader + CUtlBuffer bufText( bufRawData.Base(), bufRawData.TellPut(), CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER ); + + KeyValues *pBaseKeyValue = NULL; + pBaseKeyValue = new KeyValues( "CCreateParticlesFromKV" ); + + if ( !pBaseKeyValue->LoadFromBuffer( NULL, bufText ) ) + { + Warning( "Unable to Read KV file [%s]\n", pFileName ); + pBaseKeyValue->deleteThis(); + return; + } + + FOR_EACH_TRUE_SUBKEY( pBaseKeyValue, pKVOver ) + { + CreateParticleFromKV( pKVOver ); + } + +} +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::OnKeyCodeTyped( vgui::KeyCode code ) +{ + if ( code == KEY_DELETE ) + { + DeleteParticleSystems(); + } + else + { + BaseClass::OnKeyCodeTyped( code ); + } +} + +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::OnFileSelected(const char *fullpath) +{ + CreateParticleSystemsFromKV( fullpath ); +} +//----------------------------------------------------------------------------- +// Called when the selection changes +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::UpdateParticleSystemSelection() +{ + if ( m_pParticleSystemsDefinitions->GetSelectedItemsCount() == 1 ) + { + CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( 0 ); + g_pPetTool->SetCurrentParticleSystem( pParticleSystem, false ); + } + else + { + g_pPetTool->SetCurrentParticleSystem( NULL, false ); + } +} + + +//----------------------------------------------------------------------------- +// Item selection/deselection +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::OnItemSelected( void ) +{ + UpdateParticleSystemSelection(); +} + +void CParticleSystemDefinitionBrowser::OnItemDeselected( void ) +{ + UpdateParticleSystemSelection(); +} + + +//----------------------------------------------------------------------------- +// Select a particular node +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::SelectParticleSystem( CDmeParticleSystemDefinition *pFind ) +{ + m_pParticleSystemsDefinitions->ClearSelectedItems(); + for ( int nItemID = m_pParticleSystemsDefinitions->FirstItem(); nItemID != m_pParticleSystemsDefinitions->InvalidItemID(); nItemID = m_pParticleSystemsDefinitions->NextItem( nItemID ) ) + { + KeyValues *kv = m_pParticleSystemsDefinitions->GetItem( nItemID ); + CDmeParticleSystemDefinition *pParticleSystem = GetElementKeyValue<CDmeParticleSystemDefinition>( kv, "particleSystem" ); + if ( pParticleSystem == pFind ) + { + m_pParticleSystemsDefinitions->AddSelectedItem( nItemID ); + 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" ) ) + { + int nCount = m_pParticleSystemsDefinitions->GetSelectedItemsCount(); + if ( nCount ) + { + CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( 0 ); + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Copy Particle System", + "Copy Particle System" ); + CDmeParticleSystemDefinition * pNew = + CastElement<CDmeParticleSystemDefinition>( pParticleSystem->Copy( ) ); + pNew->SetName( pText ); + m_pDoc->AddNewParticleSystemDefinition( pNew, guard ); + } + } +} + + +//----------------------------------------------------------------------------- +// Copy to clipboard +//----------------------------------------------------------------------------- +void CParticleSystemDefinitionBrowser::CopyToClipboard( ) +{ + int nCount = m_pParticleSystemsDefinitions->GetSelectedItemsCount(); + + 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( "pcf", (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::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 ) + { + const char *pData = list[i]->GetString( "pcf" ); + if ( !pData ) + continue; + + int nLen = Q_strlen( pData ); + CUtlBuffer buf( pData, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY ); + + DmElementHandle_t hRoot; + if ( !g_pDataModel->Unserialize( buf, "keyvalues2", "pcf", NULL, "paste", CR_FORCE_COPY, hRoot ) ) + continue; + + CDmeParticleSystemDefinition *pDef = GetElement<CDmeParticleSystemDefinition>( hRoot ); + if ( !pDef ) + continue; + + ReplaceDef_r( guard, pDef ); + bRefreshAll = true; + } + + 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" ) ) + { + 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("copy") ); + return; + } + if ( !Q_stricmp( pCommand, "Create From KeyValue" ) ) + { + vgui::FileOpenDialog *pDialog = new vgui::FileOpenDialog( g_pPetTool->GetRootPanel(), "Select KV File", vgui::FOD_OPEN ); + pDialog->SetTitle( "Choose KeyValue File", true ); + pDialog->AddFilter( "*.txt", "KeyValue File (*.txt)", true ); + pDialog->AddActionSignalTarget( this ); + + char szParticlesDir[MAX_PATH]; + pDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "particles", "MOD", szParticlesDir, sizeof(szParticlesDir) ) ); + pDialog->DoModal( new KeyValues( "Create From KeyValue" ) ); + + 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(void) +{ + const CDmrParticleSystemList particleSystemList = m_pDoc->GetParticleSystemDefinitionList(); + if ( !particleSystemList.IsValid() ) + return; + + // Maintain selection if possible + CUtlVector< CUtlString > selectedItems; + int nCount = m_pParticleSystemsDefinitions->GetSelectedItemsCount(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeParticleSystemDefinition *pParticleSystem = GetSelectedParticleSystem( i ); + if ( pParticleSystem ) + { + selectedItems.AddToTail( pParticleSystem->GetName() ); + } + } + + m_pParticleSystemsDefinitions->RemoveAll(); + int nSelectedItemCount = selectedItems.Count(); + nCount = particleSystemList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeParticleSystemDefinition *pParticleSystem = particleSystemList[i]; + if ( !pParticleSystem ) + continue; + + const char *pName = pParticleSystem->GetName(); + if ( !pName || !pName[0] ) + { + pName = "<no name>"; + } + + KeyValues *kv = new KeyValues( "node" ); + kv->SetString( "name", pName ); + SetElementKeyValue( kv, "particleSystem", pParticleSystem ); + + int nItemID = m_pParticleSystemsDefinitions->AddItem( kv, 0, false, false ); + + for ( int j = 0; j < nSelectedItemCount; ++j ) + { + if ( Q_stricmp( selectedItems[j], pName ) ) + continue; + + m_pParticleSystemsDefinitions->AddSelectedItem( nItemID ); + selectedItems.FastRemove(j); + --nSelectedItemCount; + break; + } + } + m_pParticleSystemsDefinitions->SortList(); +} + diff --git a/tools/pet/particlesystemdefinitionbrowser.h b/tools/pet/particlesystemdefinitionbrowser.h new file mode 100644 index 0000000..725b2a1 --- /dev/null +++ b/tools/pet/particlesystemdefinitionbrowser.h @@ -0,0 +1,90 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#ifndef PARTICLESYSTEMDEFINITIONBROWSER_H +#define PARTICLESYSTEMDEFINITIONBROWSER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/editablepanel.h" +#include "tier1/utlstring.h" +#include "particles/particles.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CPetDoc; +class CDmeParticleSystemDefinition; +class CUndoScopeGuard; +namespace vgui +{ + class ComboBox; + class Button; + class TextEntry; + class ListPanel; + class CheckButton; + class RadioButton; +} + + +//----------------------------------------------------------------------------- +// Panel that shows all entities in the level +//----------------------------------------------------------------------------- +class CParticleSystemDefinitionBrowser : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( CParticleSystemDefinitionBrowser, vgui::EditablePanel ); + +public: + CParticleSystemDefinitionBrowser( CPetDoc *pDoc, vgui::Panel* pParent, const char *pName ); // standard constructor + virtual ~CParticleSystemDefinitionBrowser(); + + // Inherited from Panel + virtual void OnCommand( const char *pCommand ); + virtual void OnKeyCodeTyped( vgui::KeyCode code ); + MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath ); + // Methods related to updating the listpanel + void UpdateParticleSystemList(); + + // Select a particular node + void SelectParticleSystem( CDmeParticleSystemDefinition *pParticleSystem ); + + // Copy, paste. + void CopyToClipboard( ); + void PasteFromClipboard( ); + +private: + // Messages handled + MESSAGE_FUNC( OnItemDeselected, "ItemDeselected" ); + MESSAGE_FUNC( OnItemSelected, "ItemSelected" ); + MESSAGE_FUNC_PARAMS( OnInputCompleted, "InputCompleted", kv ); + + void ReplaceDef_r( CUndoScopeGuard& guard, CDmeParticleSystemDefinition *pDef ); + + // Gets the ith selected particle system + CDmeParticleSystemDefinition* GetSelectedParticleSystem( int i ); + + // Called when the selection changes + void UpdateParticleSystemSelection(); + + // Deletes selected particle systems + void DeleteParticleSystems(); + + // Create from KV + void LoadKVSection( CDmeParticleSystemDefinition *pNew, KeyValues *pOverridesKv, ParticleFunctionType_t eType ); + CDmeParticleSystemDefinition* CreateParticleFromKV( KeyValues *pKeyValue ); + void CreateParticleSystemsFromKV( const char *pFilepath ); + + // Shows the most recent selected object in properties window + void OnProperties(); + + CPetDoc *m_pDoc; + vgui::ListPanel *m_pParticleSystemsDefinitions; +}; + + +#endif // PARTICLESYSTEMDEFINITIONBROWSER_H diff --git a/tools/pet/particlesystempropertiescontainer.cpp b/tools/pet/particlesystempropertiescontainer.cpp new file mode 100644 index 0000000..58ee419 --- /dev/null +++ b/tools/pet/particlesystempropertiescontainer.cpp @@ -0,0 +1,73 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Dialog used to edit properties of a particle system definition +// +//===========================================================================// + +#include "ParticleSystemPropertiesContainer.h" +#include "petdoc.h" +#include "pettool.h" +#include "datamodel/dmelement.h" +#include "movieobjects/dmeparticlesystemdefinition.h" +#include "dme_controls/dmecontrols_utils.h" +#include "dme_controls/particlesystempanel.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +#pragma warning (disable:4355) +CParticleSystemPropertiesContainer::CParticleSystemPropertiesContainer( CPetDoc *pDoc, vgui::Panel* pParent ) : + BaseClass( this, pParent ), m_pDoc( pDoc ) +{ +} +#pragma warning (default:4355) + + +//----------------------------------------------------------------------------- +// Refreshes the list of raw controls +//----------------------------------------------------------------------------- +void CParticleSystemPropertiesContainer::GetKnownParticleDefinitions( CUtlVector< CDmeParticleSystemDefinition* > &definitions ) +{ + definitions.RemoveAll(); + + CDmrParticleSystemList particleSystemList = g_pPetTool->GetDocument()->GetParticleSystemDefinitionList(); + if ( !particleSystemList.IsValid() ) + return; + + int nCount = particleSystemList.Count(); + definitions.EnsureCapacity( nCount ); + for ( int i = 0; i < nCount; ++i ) + { + CDmeParticleSystemDefinition *pParticleSystem = particleSystemList[i]; + definitions.AddToTail( pParticleSystem ); + } +} + +//----------------------------------------------------------------------------- +// Called when the base class changes anything at all in the particle system +//----------------------------------------------------------------------------- +void CParticleSystemPropertiesContainer::OnParticleSystemModified() +{ + CAppNotifyScopeGuard sg( "CParticleSystemPropertiesContainer::OnParticleSystemModified", NOTIFY_SETDIRTYFLAG ); +} + + +//----------------------------------------------------------------------------- +// Called when the selected particle function changes +//----------------------------------------------------------------------------- +void CParticleSystemPropertiesContainer::OnParticleFunctionSelChanged( KeyValues *pParams ) +{ + if ( g_pPetTool->GetParticlePreview() ) + { + CDmeParticleFunction *pFunction = GetElementKeyValue<CDmeParticleFunction>( pParams, "function" ); + g_pPetTool->GetParticlePreview()->SetParticleFunction( pFunction ); + } +} + diff --git a/tools/pet/particlesystempropertiescontainer.h b/tools/pet/particlesystempropertiescontainer.h new file mode 100644 index 0000000..26ac3f8 --- /dev/null +++ b/tools/pet/particlesystempropertiescontainer.h @@ -0,0 +1,45 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Dialog used to edit properties of a particle system definition +// +//===========================================================================// + +#ifndef PARTICLESYSTEMPROPERTIESCONTAINER_H +#define PARTICLESYSTEMPROPERTIESCONTAINER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "dme_controls/particlesystempropertiespanel.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CPetDoc; + + +//----------------------------------------------------------------------------- +// Panel used to edit a particle system definition +//----------------------------------------------------------------------------- +class CParticleSystemPropertiesContainer : public CParticleSystemPropertiesPanel, public IParticleSystemPropertiesPanelQuery +{ + DECLARE_CLASS_SIMPLE( CParticleSystemPropertiesContainer, CParticleSystemPropertiesPanel ); + +public: + CParticleSystemPropertiesContainer( CPetDoc *pDoc, vgui::Panel* pParent ); // standard constructor + + // Inherited from IParticleSystemPropertiesPanelQuery + virtual void GetKnownParticleDefinitions( CUtlVector< CDmeParticleSystemDefinition* > &definitions ); + +private: + MESSAGE_FUNC_PARAMS( OnParticleFunctionSelChanged, "ParticleFunctionSelChanged", params ); + + // For inheriting classes to get notified without having to listen to messages + virtual void OnParticleSystemModified(); + + CPetDoc *m_pDoc; +}; + + +#endif // PARTICLESYSTEMPROPERTIESCONTAINER_H diff --git a/tools/pet/pet.vpc b/tools/pet/pet.vpc new file mode 100644 index 0000000..af3bd54 --- /dev/null +++ b/tools/pet/pet.vpc @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// PET.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin\tools" + +$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,.\,$SRCDIR\game\shared" + $PreprocessorDefinitions "$BASE;PET_EXPORTS" + } + + $Linker + { + $AdditionalDependencies "$BASE Psapi.lib" + } +} + +$Project "Pet" +{ + $Folder "Source Files" + { + $File "$SRCDIR\public\interpolatortypes.cpp" + $File "particlesystemdefinitionbrowser.cpp" + $File "particlesystempropertiescontainer.cpp" + $File "petdoc.cpp" + $File "pettool.cpp" + $File "$SRCDIR\public\registry.cpp" + $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp" + } + + $Folder "Header Files" + { + $File "$SRCDIR\public\mathlib\mathlib.h" + $File "particlesystemdefinitionbrowser.h" + $File "particlesystempropertiescontainer.h" + $File "petdoc.h" + $File "pettool.h" + } + + $Folder "Link Libraries" + { + $Lib datamodel + $Lib dme_controls + $Lib dmserializers + $Lib dmxloader + $Lib mathlib + $Lib matsys_controls + $Lib movieobjects + $Lib particles + $Lib sfmobjects + $Lib tier2 + $Lib tier3 + $Lib toolutils + $Lib vgui_controls + } +} diff --git a/tools/pet/petdoc.cpp b/tools/pet/petdoc.cpp new file mode 100644 index 0000000..707a77a --- /dev/null +++ b/tools/pet/petdoc.cpp @@ -0,0 +1,536 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "petdoc.h" +#include "tier1/KeyValues.h" +#include "tier1/utlbuffer.h" +#include "toolutils/enginetools_int.h" +#include "filesystem.h" +#include "pettool.h" +#include "toolframework/ienginetool.h" +#include "movieobjects/dmeparticlesystemdefinition.h" +#include "datamodel/idatamodel.h" +#include "toolutils/attributeelementchoicelist.h" +#include "particlesystemdefinitionbrowser.h" +#include "vgui_controls/messagebox.h" +#include "particles/particles.h" +#include "particlesystempropertiescontainer.h" +#include "dme_controls/particlesystempanel.h" +#include "dme_controls/dmecontrols.h" + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CPetDoc::CPetDoc( IPetDocCallback *pCallback ) : m_pCallback( pCallback ) +{ + m_hRoot = NULL; + m_pFileName[0] = 0; + m_bDirty = false; + g_pDataModel->InstallNotificationCallback( this ); + SetElementPropertiesChoices( this ); +} + +CPetDoc::~CPetDoc() +{ + if ( m_hRoot.Get() ) + { + g_pDataModel->RemoveFileId( m_hRoot->GetFileId() ); + m_hRoot = NULL; + } + g_pDataModel->RemoveNotificationCallback( this ); + SetElementPropertiesChoices( NULL ); +} + + +//----------------------------------------------------------------------------- +// Inherited from INotifyUI +//----------------------------------------------------------------------------- +void CPetDoc::NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) +{ + OnDataChanged( pReason, nNotifySource, nNotifyFlags ); +} + + +bool CPetDoc::GetIntChoiceList( const char *pChoiceListType, CDmElement *pElement, + const char *pAttributeName, bool bArrayElement, IntChoiceList_t &list ) +{ + if ( !Q_stricmp( pChoiceListType, "particlefield" ) ) + { + for ( int i = 0; i < MAX_PARTICLE_ATTRIBUTES; ++i ) + { + const char *pName = g_pParticleSystemMgr->GetParticleFieldName( i ); + if ( pName ) + { + int j = list.AddToTail(); + list[j].m_nValue = i; + list[j].m_pChoiceString = pName; + } + } + return true; + } + + if ( !Q_stricmp( pChoiceListType, "particlefield_scalar" ) ) + { + for ( int i = 0; i < MAX_PARTICLE_ATTRIBUTES; ++i ) + { + if ( ( ATTRIBUTES_WHICH_ARE_VEC3S_MASK & ( 1 << i ) ) != 0 ) + continue; + + const char *pName = g_pParticleSystemMgr->GetParticleFieldName( i ); + if ( pName ) + { + int j = list.AddToTail(); + list[j].m_nValue = i; + list[j].m_pChoiceString = pName; + } + } + return true; + } + + if ( !Q_stricmp( pChoiceListType, "particlefield_vector" ) ) + { + for ( int i = 0; i < MAX_PARTICLE_ATTRIBUTES; ++i ) + { + if ( ( ATTRIBUTES_WHICH_ARE_VEC3S_MASK & ( 1 << i ) ) == 0 ) + continue; + + const char *pName = g_pParticleSystemMgr->GetParticleFieldName( i ); + if ( pName ) + { + int j = list.AddToTail(); + list[j].m_nValue = i; + list[j].m_pChoiceString = pName; + } + } + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// Gets the file name +//----------------------------------------------------------------------------- +const char *CPetDoc::GetFileName() +{ + return m_pFileName; +} + +void CPetDoc::SetFileName( const char *pFileName ) +{ + Q_strncpy( m_pFileName, pFileName, sizeof( m_pFileName ) ); + Q_FixSlashes( m_pFileName ); + SetDirty( true ); +} + +//----------------------------------------------------------------------------- +// Dirty bits +//----------------------------------------------------------------------------- +void CPetDoc::SetDirty( bool bDirty ) +{ + m_bDirty = bDirty; +} + +bool CPetDoc::IsDirty() const +{ + return m_bDirty; +} + + +//----------------------------------------------------------------------------- +// Creates the root element +//----------------------------------------------------------------------------- +bool CPetDoc::CreateRootElement() +{ + Assert( !m_hRoot.Get() ); + + DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( GetFileName() ); + + // Create the main element + m_hRoot = g_pDataModel->CreateElement( "DmElement", GetFileName(), fileid ); + if ( m_hRoot == DMELEMENT_HANDLE_INVALID ) + return false; + + g_pDataModel->SetFileRoot( fileid, m_hRoot ); + + // We need to create an element array attribute storing particle system definitions + m_hRoot->AddAttribute( "particleSystemDefinitions", AT_ELEMENT_ARRAY ); + return true; +} + + +//----------------------------------------------------------------------------- +// Creates a new document +//----------------------------------------------------------------------------- +void CPetDoc::CreateNew() +{ + Assert( !m_hRoot.Get() ); + + // This is not undoable + CDisableUndoScopeGuard guard; + + Q_strncpy( m_pFileName, "untitled", sizeof( m_pFileName ) ); + + // Create the main element + if ( !CreateRootElement() ) + return; + + SetDirty( false ); +} + + +//----------------------------------------------------------------------------- +// Saves/loads from file +//----------------------------------------------------------------------------- +bool CPetDoc::LoadFromFile( const char *pFileName ) +{ + Assert( !m_hRoot.Get() ); + + CAppDisableUndoScopeGuard guard( "CPetDoc::LoadFromFile", NOTIFY_CHANGE_OTHER ); + SetDirty( false ); + + if ( !pFileName[0] ) + return false; + + Q_strncpy( m_pFileName, pFileName, sizeof( m_pFileName ) ); + + CDmElement *pRoot = NULL; + DmFileId_t fileid = g_pDataModel->RestoreFromFile( pFileName, NULL, NULL, &pRoot, CR_DELETE_OLD ); + + if ( fileid == DMFILEID_INVALID ) + { + m_pFileName[0] = 0; + return false; + } + + m_hRoot = pRoot; + + SetDirty( false ); + return true; +} + +void CPetDoc::SaveToFile( ) +{ + if ( m_hRoot.Get() && m_pFileName && m_pFileName[0] ) + { + g_pDataModel->SaveToFile( m_pFileName, NULL, "binary", PET_FILE_FORMAT, m_hRoot ); + } + + SetDirty( false ); +} + + +//----------------------------------------------------------------------------- +// Returns the root object +//----------------------------------------------------------------------------- +CDmElement *CPetDoc::GetRootObject() +{ + return m_hRoot; +} + + +//----------------------------------------------------------------------------- +// Returns the root object fileid +//----------------------------------------------------------------------------- +DmFileId_t CPetDoc::GetFileId() +{ + return m_hRoot.Get() ? m_hRoot->GetFileId() : DMFILEID_INVALID; +} + + +//----------------------------------------------------------------------------- +// Returns the particle system definition list +//----------------------------------------------------------------------------- +CDmAttribute *CPetDoc::GetParticleSystemDefinitionList() +{ + CDmrElementArray<> array( m_hRoot, "particleSystemDefinitions" ); + return array.GetAttribute(); +} + + +void CPetDoc::AddNewParticleSystemDefinition( CDmeParticleSystemDefinition *pNew, CUndoScopeGuard &Guard ) +{ + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + + particleSystemList.AddToTail( pNew ); + Guard.Release(); + + // Force a resolve to get the particle created + g_pDmElementFramework->Operate( true ); + g_pDmElementFramework->BeginEdit(); + + UpdateParticleDefinition( pNew ); +} + +//----------------------------------------------------------------------------- +// Adds a new particle system definition +//----------------------------------------------------------------------------- +CDmeParticleSystemDefinition* CPetDoc::AddNewParticleSystemDefinition( const char *pName ) +{ + if ( !pName || !pName[0] ) + { + pName = "New Particle System"; + } + + CDmeParticleSystemDefinition *pParticleSystem; + { + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Add Particle System", "Add Particle System" ); + + pParticleSystem = CreateElement<CDmeParticleSystemDefinition>( pName, GetFileId() ); + AddNewParticleSystemDefinition( pParticleSystem, guard ); + } + + return pParticleSystem; +} + + +//----------------------------------------------------------------------------- +// Refresh all particle definitions +//----------------------------------------------------------------------------- +void CPetDoc::UpdateAllParticleSystems( ) +{ + // Force a resolve to get the particle created + g_pDmElementFramework->Operate( true ); + g_pDmElementFramework->BeginEdit(); + + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + int nCount = particleSystemList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + UpdateParticleDefinition( particleSystemList[i] ); + } +} + + +//----------------------------------------------------------------------------- +// Deletes a particle system definition +//----------------------------------------------------------------------------- +void CPetDoc::DeleteParticleSystemDefinition( CDmeParticleSystemDefinition *pParticleSystem ) +{ + if ( !pParticleSystem ) + return; + + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + int nCount = particleSystemList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( pParticleSystem == particleSystemList[i] ) + { + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Particle System", "Delete Particle System" ); + particleSystemList.FastRemove( i ); + break; + } + } + + // Find all CDmeParticleChilds referring to this function + CUtlVector< CDmeParticleChild* > children; + FindAncestorsReferencingElement( pParticleSystem, children ); + int nChildCount = children.Count(); + for ( int i = 0; i < nChildCount; ++i ) + { + CDmeParticleChild *pChildReference = children[i]; + CDmeParticleSystemDefinition *pParent = FindReferringElement<CDmeParticleSystemDefinition>( pChildReference, "children" ); + if ( !pParent ) + continue; + + pParent->RemoveFunction( FUNCTION_CHILDREN, pChildReference ); + DestroyElement( pChildReference, TD_NONE ); + } + + DestroyElement( pParticleSystem, TD_DEEP ); +} + + +CDmeParticleSystemDefinition *CPetDoc::FindParticleSystemDefinition( const char *pName ) +{ + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + int nCount = particleSystemList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeParticleSystemDefinition* pParticleSystem = particleSystemList[i]; + if ( !Q_stricmp( pName, pParticleSystem->GetName() ) ) + return pParticleSystem; + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Deletes a particle system definition +//----------------------------------------------------------------------------- +void CPetDoc::ReplaceParticleSystemDefinition( CDmeParticleSystemDefinition *pParticleSystem ) +{ + if ( !pParticleSystem ) + return; + + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + int nCount = particleSystemList.Count(); + int nFoundIndex = -1; + for ( int i = 0; i < nCount; ++i ) + { + if ( !particleSystemList[i] ) + continue; + + if ( !Q_stricmp( particleSystemList[i]->GetName(), pParticleSystem->GetName() ) ) + { + nFoundIndex = i; + break; + } + } + + if ( nFoundIndex < 0 ) + { + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Replace Particle System", "Replace Particle System" ); + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + pParticleSystem->SetFileId( m_hRoot->GetFileId(), TD_ALL ); + particleSystemList.AddToTail( pParticleSystem ); + return; + } + + CDmeParticleSystemDefinition *pOldParticleSystem = particleSystemList[nFoundIndex]; + + // This can happen if we unserialized w/ replace + if ( pOldParticleSystem == pParticleSystem ) + return; + + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Replace Particle System", "Replace Particle System" ); + + particleSystemList.Set( nFoundIndex, pParticleSystem ); + pParticleSystem->SetFileId( m_hRoot->GetFileId(), TD_ALL ); + + // Find all CDmeParticleChilds referring to this function + CUtlVector< CDmeParticleChild* > children; + FindAncestorsReferencingElement( pOldParticleSystem, children ); + int nChildCount = children.Count(); + for ( int i = 0; i < nChildCount; ++i ) + { + CDmeParticleChild *pChildReference = children[i]; + pChildReference->m_Child = pParticleSystem; + } + + DestroyElement( pOldParticleSystem, TD_SHALLOW ); +} + + +//----------------------------------------------------------------------------- +// Does a particle system exist already? +//----------------------------------------------------------------------------- +bool CPetDoc::IsParticleSystemDefined( const char *pName ) +{ + return FindParticleSystemDefinition( pName ) != NULL; +} + + +//----------------------------------------------------------------------------- +// Updates a specific particle defintion +//----------------------------------------------------------------------------- +void CPetDoc::UpdateParticleDefinition( CDmeParticleSystemDefinition *pDef ) +{ + if ( !pDef ) + return; + + CUtlBuffer buf; + g_pDataModel->Serialize( buf, "binary", PET_FILE_FORMAT, pDef->GetHandle() ); + + // Tell the game about the new definitions + if ( clienttools ) + { + clienttools->ReloadParticleDefintions( GetFileName(), buf.Base(), buf.TellMaxPut() ); + } + if ( servertools ) + { + servertools->ReloadParticleDefintions( GetFileName(), buf.Base(), buf.TellMaxPut() ); + } + + // Let the other tools know + KeyValues *pMessage = new KeyValues( "ParticleSystemUpdated" ); + pMessage->SetPtr( "definitionBits", buf.Base() ); + pMessage->SetInt( "definitionSize", buf.TellMaxPut() ); + g_pPetTool->PostMessageToAllTools( pMessage ); + pMessage->deleteThis(); +} + + +//----------------------------------------------------------------------------- +// Populate string choice lists +//----------------------------------------------------------------------------- +bool CPetDoc::GetStringChoiceList( const char *pChoiceListType, CDmElement *pElement, + const char *pAttributeName, bool bArrayElement, StringChoiceList_t &list ) +{ + if ( !Q_stricmp( pChoiceListType, "particleSystemDefinitions" ) ) + { + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + + StringChoice_t sChoice; + sChoice.m_pValue = ""; + sChoice.m_pChoiceString = ""; + list.AddToTail( sChoice ); + + int nCount = particleSystemList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeParticleSystemDefinition *pParticleSystem = particleSystemList[ i ]; + + StringChoice_t sChoice; + sChoice.m_pValue = pParticleSystem->GetName(); + sChoice.m_pChoiceString = pParticleSystem->GetName(); + list.AddToTail( sChoice ); + } + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Populate element choice lists +//----------------------------------------------------------------------------- +bool CPetDoc::GetElementChoiceList( const char *pChoiceListType, CDmElement *pElement, + const char *pAttributeName, bool bArrayElement, ElementChoiceList_t &list ) +{ + if ( !Q_stricmp( pChoiceListType, "allelements" ) ) + { + AddElementsRecursively( m_hRoot, list ); + return true; + } + + if ( !Q_stricmp( pChoiceListType, "particleSystemDefinitions" ) ) + { + CDmrParticleSystemList particleSystemList( GetParticleSystemDefinitionList() ); + + int nCount = particleSystemList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeParticleSystemDefinition *pParticleSystem = particleSystemList[ i ]; + ElementChoice_t sChoice; + sChoice.m_pValue = pParticleSystem; + sChoice.m_pChoiceString = pParticleSystem->GetName(); + list.AddToTail( sChoice ); + } + return ( nCount > 0 ); + } + + // by default, try to treat the choice list type as a Dme element type + AddElementsRecursively( m_hRoot, list, pChoiceListType ); + + return list.Count() > 0; +} + + +//----------------------------------------------------------------------------- +// Called when data changes +//----------------------------------------------------------------------------- +void CPetDoc::OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) +{ + SetDirty( nNotifyFlags & NOTIFY_SETDIRTYFLAG ? true : false ); + m_pCallback->OnDocChanged( pReason, nNotifySource, nNotifyFlags ); +} + + diff --git a/tools/pet/petdoc.h b/tools/pet/petdoc.h new file mode 100644 index 0000000..d0f56c7 --- /dev/null +++ b/tools/pet/petdoc.h @@ -0,0 +1,122 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef PETDOC_H +#define PETDOC_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "dme_controls/inotifyui.h" +#include "datamodel/dmehandle.h" +#include "datamodel/dmelement.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class IPetDocCallback; +class CPetDoc; +class CDmeParticleSystemDefinition; + + +//----------------------------------------------------------------------------- +// The file format for particle system definitions +//----------------------------------------------------------------------------- +#define PET_FILE_FORMAT "pcf" + + +typedef CDmrElementArray<CDmeParticleSystemDefinition> CDmrParticleSystemList; + + +//----------------------------------------------------------------------------- +// Contains all editable state +//----------------------------------------------------------------------------- +class CPetDoc : public IDmNotify, CBaseElementPropertiesChoices +{ +public: + CPetDoc( IPetDocCallback *pCallback ); + ~CPetDoc(); + + // Inherited from INotifyUI + virtual void NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ); + virtual bool GetIntChoiceList( const char *pChoiceListType, CDmElement *pElement, + const char *pAttributeName, bool bArrayElement, IntChoiceList_t &list ); + + // Sets/Gets the file name + const char *GetFileName(); + void SetFileName( const char *pFileName ); + + // Dirty bits (has it changed since the last time it was saved?) + void SetDirty( bool bDirty ); + bool IsDirty() const; + + // Creates a new document + void CreateNew(); + + // Saves/loads from file + bool LoadFromFile( const char *pFileName ); + void SaveToFile( ); + + // Returns the root object + CDmElement *GetRootObject(); + + // Returns the root object fileid + DmFileId_t GetFileId(); + + // Called when data changes (see INotifyUI for flags) + void OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ); + + // Returns the particle system definition list + CDmAttribute *GetParticleSystemDefinitionList(); + + // add a new definition we've created + void AddNewParticleSystemDefinition( CDmeParticleSystemDefinition *pNew, + CUndoScopeGuard &Guard ); + + // Adds a new particle system definition + CDmeParticleSystemDefinition *AddNewParticleSystemDefinition( const char *pName ); + + // Deletes a particle system definition + void DeleteParticleSystemDefinition( CDmeParticleSystemDefinition *pParticleSystem ); + + // find particle system def by name + CDmeParticleSystemDefinition *FindParticleSystemDefinition( const char *pName ); + + // Replace any particle system with the same name as the passed-in definition + // with the passed-in definition + void ReplaceParticleSystemDefinition( CDmeParticleSystemDefinition *pParticleSystem ); + + // Does a particle system exist already? + bool IsParticleSystemDefined( const char *pName ); + + // For element choice lists. Return false if it's an unknown choice list type + virtual bool GetStringChoiceList( const char *pChoiceListType, CDmElement *pElement, + const char *pAttributeName, bool bArrayElement, StringChoiceList_t &list ); + virtual bool GetElementChoiceList( const char *pChoiceListType, CDmElement *pElement, + const char *pAttributeName, bool bArrayElement, ElementChoiceList_t &list ); + + // Updates a specific particle defintion + void UpdateParticleDefinition( CDmeParticleSystemDefinition *pDef ); + + // Update all particle definitions + void UpdateAllParticleSystems( ); + +private: + // Creates the root element + bool CreateRootElement(); + + IPetDocCallback *m_pCallback; + CDmeHandle< CDmElement > m_hRoot; + char m_pFileName[MAX_PATH]; + bool m_bDirty; +}; + + +#endif // PETDOC_H diff --git a/tools/pet/pettool.cpp b/tools/pet/pettool.cpp new file mode 100644 index 0000000..2eb83e5 --- /dev/null +++ b/tools/pet/pettool.cpp @@ -0,0 +1,1078 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Core Movie Maker UI API +// +//============================================================================= + +#include "pettool.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "vgui/IInput.h" +#include "vgui/KeyCode.h" +#include "vgui_controls/FileOpenDialog.h" +#include "filesystem.h" +#include "vgui/ilocalize.h" +#include "dme_controls/elementpropertiestree.h" +#include "tier0/icommandline.h" +#include "materialsystem/imaterialsystem.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "petdoc.h" +#include "particlesystemdefinitionbrowser.h" +#include "particlesystempropertiescontainer.h" +#include "dme_controls/AttributeStringChoicePanel.h" +#include "dme_controls/ParticleSystemPanel.h" +#include "datamodel/dmelementfactoryhelper.h" +#include "matsys_controls/picker.h" +#include "tier2/fileutils.h" +#include "tier3/tier3.h" +#include "particles/particles.h" +#include "dmserializers/idmserializers.h" +#include "dme_controls/dmepanel.h" +#include "vgui/ivgui.h" + +using namespace vgui; + + +//----------------------------------------------------------------------------- +// Methods needed by scenedatabase. They have to live here instead of toolutils +// because this is a DLL but toolutils is only a static library +//----------------------------------------------------------------------------- +USING_DMEPANEL_FACTORY( CParticleSystemPreviewPanel, DmeParticleSystemDefinition ); +USING_DMEPANEL_FACTORY( CParticleSystemDmePanel, DmeParticleSystemDefinition ); + + +const char *GetVGuiControlsModuleName() +{ + return "PetTool"; +} + +//----------------------------------------------------------------------------- +// Connect, disconnect +//----------------------------------------------------------------------------- +bool ConnectTools( CreateInterfaceFn factory ) +{ + // Attach to the dmserializers instance of the particle system + return (materials != NULL) && (g_pMatSystemSurface != NULL) && (g_pMDLCache != NULL) && (studiorender != NULL) && (g_pMaterialSystemHardwareConfig != NULL); +} + +void DisconnectTools( ) +{ +} + + +//----------------------------------------------------------------------------- +// Singleton +//----------------------------------------------------------------------------- +CPetTool *g_pPetTool = NULL; + +void CreateTools() +{ + g_pPetTool = new CPetTool(); +} + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CPetTool::CPetTool() +{ + m_pMenuBar = NULL; + m_pDoc = NULL; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CPetTool::Init( ) +{ + m_hCurrentParticleSystem = NULL; + m_pDoc = NULL; + m_RecentFiles.LoadFromRegistry( GetRegistryName() ); + + // NOTE: This has to happen before BaseClass::Init + g_pVGuiLocalize->AddFile( "resource/toolpet_%language%.txt" ); + + if ( !BaseClass::Init( ) ) + return false; + + CreateInterfaceFn factory; + enginetools->GetClientFactory( factory ); + IParticleSystemQuery *pQuery = (IParticleSystemQuery*)factory( PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION, NULL ); + g_pParticleSystemMgr->Init( pQuery ); + // tell particle mgr to add the default simulation + rendering ops + g_pParticleSystemMgr->AddBuiltinSimulationOperators(); + g_pParticleSystemMgr->AddBuiltinRenderingOperators(); + + // Create a directory for particles if it doesn't exist + char pStartingDir[ MAX_PATH ]; + GetModSubdirectory( "particles", pStartingDir, sizeof(pStartingDir) ); + g_pFullFileSystem->CreateDirHierarchy( pStartingDir ); + + return true; +} + +void CPetTool::Shutdown() +{ + m_RecentFiles.SaveToRegistry( GetRegistryName() ); + + BaseClass::Shutdown(); +} + + +//----------------------------------------------------------------------------- +// returns the document +//----------------------------------------------------------------------------- +CPetDoc *CPetTool::GetDocument() +{ + return m_pDoc; +} + + +//----------------------------------------------------------------------------- +// Tool activation/deactivation +//----------------------------------------------------------------------------- +void CPetTool::OnToolActivate() +{ + BaseClass::OnToolActivate(); +} + +void CPetTool::OnToolDeactivate() +{ + BaseClass::OnToolDeactivate(); +} + + +//----------------------------------------------------------------------------- +// Used to hook DME VMF entities into the render lists +//----------------------------------------------------------------------------- +void CPetTool::Think( bool finalTick ) +{ + BaseClass::Think( finalTick ); + + if ( IsActiveTool() ) + { + // Force resolve calls to happen + // FIXME: Shouldn't this not have to happen here? + CUtlVector< IDmeOperator* > operators; + g_pDmElementFramework->SetOperators( operators ); + g_pDmElementFramework->Operate( true ); + g_pDmElementFramework->BeginEdit(); + } +} + + +//----------------------------------------------------------------------------- +// Derived classes can implement this to get a new scheme to be applied to this tool +//----------------------------------------------------------------------------- +vgui::HScheme CPetTool::GetToolScheme() +{ + return vgui::scheme()->LoadSchemeFromFile( "Resource/BoxRocket.res", "BoxRocket" ); +} + + +//----------------------------------------------------------------------------- +// +// The View menu +// +//----------------------------------------------------------------------------- +class CPetViewMenuButton : public CToolMenuButton +{ + DECLARE_CLASS_SIMPLE( CPetViewMenuButton, CToolMenuButton ); +public: + CPetViewMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ); + virtual void OnShowMenu(vgui::Menu *menu); + +private: + CPetTool *m_pTool; +}; + +CPetViewMenuButton::CPetViewMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ) + : BaseClass( parent, panelName, text, pActionSignalTarget ) +{ + m_pTool = parent; + + AddCheckableMenuItem( "properties", "#PetProperties", new KeyValues( "OnToggleProperties" ), pActionSignalTarget ); + AddCheckableMenuItem( "browser", "#PetParticleSystemBrowser", new KeyValues( "OnToggleParticleSystemBrowser" ), pActionSignalTarget ); + AddCheckableMenuItem( "particlepreview", "#PetParticlePreview", new KeyValues( "OnToggleParticlePreview" ), pActionSignalTarget ); + + AddSeparator(); + + AddMenuItem( "defaultlayout", "#PetViewDefault", new KeyValues( "OnDefaultLayout" ), pActionSignalTarget ); + + SetMenu(m_pMenu); +} + +void CPetViewMenuButton::OnShowMenu(vgui::Menu *menu) +{ + BaseClass::OnShowMenu( menu ); + + // Update the menu + int id; + + CPetDoc *pDoc = m_pTool->GetDocument(); + if ( pDoc ) + { + id = m_Items.Find( "properties" ); + m_pMenu->SetItemEnabled( id, true ); + + Panel *p; + p = m_pTool->GetProperties(); + Assert( p ); + m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false ); + + id = m_Items.Find( "browser" ); + m_pMenu->SetItemEnabled( id, true ); + + p = m_pTool->GetParticleSystemDefinitionBrowser(); + Assert( p ); + m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false ); + + id = m_Items.Find( "particlepreview" ); + m_pMenu->SetItemEnabled( id, true ); + + p = m_pTool->GetParticlePreview(); + Assert( p ); + m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false ); + } + else + { + id = m_Items.Find( "properties" ); + m_pMenu->SetItemEnabled( id, false ); + id = m_Items.Find( "browser" ); + m_pMenu->SetItemEnabled( id, false ); + id = m_Items.Find( "particlepreview" ); + m_pMenu->SetItemEnabled( id, false ); + } +} + + +//----------------------------------------------------------------------------- +// +// The Tool menu +// +//----------------------------------------------------------------------------- +class CPetToolMenuButton : public CToolMenuButton +{ + DECLARE_CLASS_SIMPLE( CPetToolMenuButton, CToolMenuButton ); +public: + CPetToolMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ); + virtual void OnShowMenu(vgui::Menu *menu); + +private: + CPetTool *m_pTool; +}; + +CPetToolMenuButton::CPetToolMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ) + : BaseClass( parent, panelName, text, pActionSignalTarget ) +{ + m_pTool = parent; + + SetMenu(m_pMenu); +} + +void CPetToolMenuButton::OnShowMenu(vgui::Menu *menu) +{ + BaseClass::OnShowMenu( menu ); +} + + +//----------------------------------------------------------------------------- +// Initializes the menu bar +//----------------------------------------------------------------------------- +vgui::MenuBar *CPetTool::CreateMenuBar( CBaseToolSystem *pParent ) +{ + m_pMenuBar = new CToolFileMenuBar( pParent, "Main Menu Bar" ); + + // Sets info in the menu bar + char title[ 64 ]; + ComputeMenuBarTitle( title, sizeof( title ) ); + m_pMenuBar->SetInfo( title ); + m_pMenuBar->SetToolName( GetToolName() ); + + // Add menu buttons + CToolMenuButton *pFileButton = CreateToolFileMenuButton( m_pMenuBar, "File", "&File", GetActionTarget(), this ); + CToolMenuButton *pEditButton = CreateToolEditMenuButton( this, "Edit", "&Edit", GetActionTarget() ); + CPetToolMenuButton *pToolButton = new CPetToolMenuButton( this, "Pet", "&Pet", GetActionTarget() ); + CPetViewMenuButton *pViewButton = new CPetViewMenuButton( this, "View", "&View", GetActionTarget() ); + CToolMenuButton *pSwitchButton = CreateToolSwitchMenuButton( m_pMenuBar, "Switcher", "&Tools", GetActionTarget() ); + + pEditButton->AddMenuItem( "copy", "#BxEditCopy", new KeyValues( "OnCopy" ), GetActionTarget(), NULL, "edit_copy" ); + pEditButton->AddMenuItem( "paste", "#BxEditPaste", new KeyValues( "OnPaste" ), GetActionTarget(), NULL, "edit_paste" ); + + pEditButton->MoveMenuItem( pEditButton->FindMenuItem( "paste" ), pEditButton->FindMenuItem( "editkeybindings" ) ); + pEditButton->MoveMenuItem( pEditButton->FindMenuItem( "copy" ), pEditButton->FindMenuItem( "paste" ) ); + pEditButton->AddSeparatorAfterItem( "paste" ); + + m_pMenuBar->AddButton( pFileButton ); + m_pMenuBar->AddButton( pEditButton ); + m_pMenuBar->AddButton( pToolButton ); + m_pMenuBar->AddButton( pViewButton ); + m_pMenuBar->AddButton( pSwitchButton ); + + return m_pMenuBar; +} + + +//----------------------------------------------------------------------------- +// Updates the menu bar based on the current file +//----------------------------------------------------------------------------- +void CPetTool::UpdateMenuBar( ) +{ + if ( !m_pDoc ) + { + m_pMenuBar->SetFileName( "#PetNoFile" ); + return; + } + + const char *pFile = m_pDoc->GetFileName(); + if ( !pFile[0] ) + { + m_pMenuBar->SetFileName( "#PetNoFile" ); + return; + } + + if ( m_pDoc->IsDirty() ) + { + char sz[ 512 ]; + Q_snprintf( sz, sizeof( sz ), "* %s", pFile ); + m_pMenuBar->SetFileName( sz ); + } + else + { + m_pMenuBar->SetFileName( pFile ); + } +} + + +//----------------------------------------------------------------------------- +// Gets at tool windows +//----------------------------------------------------------------------------- +CParticleSystemPropertiesContainer *CPetTool::GetProperties() +{ + return m_hProperties.Get(); +} + +CParticleSystemDefinitionBrowser *CPetTool::GetParticleSystemDefinitionBrowser() +{ + return m_hParticleSystemDefinitionBrowser.Get(); +} + +CParticleSystemPreviewPanel *CPetTool::GetParticlePreview() +{ + return m_hParticlePreview.Get(); +} + + +//----------------------------------------------------------------------------- +// Copy/paste +//----------------------------------------------------------------------------- +void CPetTool::OnCopy() +{ + GetParticleSystemDefinitionBrowser()->CopyToClipboard(); +} + +void CPetTool::OnPaste() +{ + GetParticleSystemDefinitionBrowser()->PasteFromClipboard(); +} + + +//----------------------------------------------------------------------------- +// Sets/gets the current particle system +//----------------------------------------------------------------------------- +void CPetTool::SetCurrentParticleSystem( CDmeParticleSystemDefinition *pParticleSystem, bool bForceBrowserSelection ) +{ + if ( !m_pDoc ) + return; + + if ( m_hCurrentParticleSystem.Get() == pParticleSystem ) + return; + + m_hCurrentParticleSystem = pParticleSystem; + if ( bForceBrowserSelection && m_hParticleSystemDefinitionBrowser.Get() ) + { + m_hParticleSystemDefinitionBrowser->UpdateParticleSystemList(); + m_hParticleSystemDefinitionBrowser->SelectParticleSystem( pParticleSystem ); + } + if ( m_hParticlePreview.Get() ) + { + m_hParticlePreview->SetParticleSystem( pParticleSystem ); + } + if ( m_hProperties.Get() ) + { + m_hProperties->SetParticleSystem( m_hCurrentParticleSystem ); + } +} + +CDmeParticleSystemDefinition* CPetTool::GetCurrentParticleSystem( void ) +{ + return m_hCurrentParticleSystem; +} + + +//----------------------------------------------------------------------------- +// Destroys all tool windows +//----------------------------------------------------------------------------- +void CPetTool::DestroyToolContainers() +{ + int c = ToolWindow::GetToolWindowCount(); + for ( int i = c - 1; i >= 0 ; --i ) + { + ToolWindow *kill = ToolWindow::GetToolWindow( i ); + delete kill; + } +} + + +//----------------------------------------------------------------------------- +// Sets up the default layout +//----------------------------------------------------------------------------- +void CPetTool::OnDefaultLayout() +{ + int y = m_pMenuBar->GetTall(); + + int usew, useh; + GetSize( usew, useh ); + + DestroyToolContainers(); + + Assert( ToolWindow::GetToolWindowCount() == 0 ); + + CParticleSystemPropertiesContainer *pProperties = GetProperties(); + CParticleSystemDefinitionBrowser *pParticleSystemBrowser = GetParticleSystemDefinitionBrowser(); + CParticleSystemPreviewPanel *pPreviewer = GetParticlePreview(); + + // Need three containers + ToolWindow *pPropertyWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pProperties, "#PetProperties", false ); + ToolWindow *pBrowserWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pParticleSystemBrowser, "#PetParticleSystemBrowser", false ); + ToolWindow *pPreviewWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pPreviewer, "#PetPreviewer", false ); + + int halfScreen = usew / 2; + int bottom = useh - y; + int sy = (bottom - y) / 2; + SetMiniViewportBounds( halfScreen, y, halfScreen, sy - y ); + pPreviewWindow->SetBounds( halfScreen, sy, halfScreen, bottom - sy ); + pBrowserWindow->SetBounds( 0, y, halfScreen, sy - y ); + pPropertyWindow->SetBounds( 0, sy, halfScreen, bottom - sy ); +} + +void CPetTool::OnToggleProperties() +{ + if ( m_hProperties.Get() ) + { + ToggleToolWindow( m_hProperties.Get(), "#PetProperties" ); + } +} + +void CPetTool::OnToggleParticleSystemBrowser() +{ + if ( m_hParticleSystemDefinitionBrowser.Get() ) + { + ToggleToolWindow( m_hParticleSystemDefinitionBrowser.Get(), "#PetParticleSystemBrowser" ); + } +} + +void CPetTool::OnToggleParticlePreview() +{ + if ( m_hParticlePreview.Get() ) + { + ToggleToolWindow( m_hParticlePreview.Get(), "#PetPreviewer" ); + } +} + + +//----------------------------------------------------------------------------- +// Creates +//----------------------------------------------------------------------------- +void CPetTool::CreateTools( CPetDoc *doc ) +{ + if ( !m_hProperties.Get() ) + { + m_hProperties = new CParticleSystemPropertiesContainer( m_pDoc, this ); + } + + if ( !m_hParticleSystemDefinitionBrowser.Get() ) + { + m_hParticleSystemDefinitionBrowser = new CParticleSystemDefinitionBrowser( m_pDoc, this, "ParticleSystemDefinitionBrowser" ); + } + + if ( !m_hParticlePreview.Get() ) + { + m_hParticlePreview = new CParticleSystemPreviewPanel( NULL, "Particle System Preview" ); + } + RegisterToolWindow( m_hProperties ); + RegisterToolWindow( m_hParticleSystemDefinitionBrowser ); + RegisterToolWindow( m_hParticlePreview ); +} + + +//----------------------------------------------------------------------------- +// Initializes the tools +//----------------------------------------------------------------------------- +void CPetTool::InitTools() +{ + // FIXME: There are no tool windows here; how should this work? + // These panels are saved + windowposmgr->RegisterPanel( "properties", m_hProperties, false ); + windowposmgr->RegisterPanel( "particlesystemdefinitionbrowser", m_hParticleSystemDefinitionBrowser, false ); + windowposmgr->RegisterPanel( "previewpanel", m_hParticlePreview, false ); + + if ( !windowposmgr->LoadPositions( "cfg/pet.txt", this, &m_ToolWindowFactory, "Pet" ) ) + { + OnDefaultLayout(); + } +} + + +void CPetTool::DestroyTools() +{ + SetCurrentParticleSystem( NULL ); + + int c = ToolWindow::GetToolWindowCount(); + for ( int i = c - 1; i >= 0 ; --i ) + { + ToolWindow *kill = ToolWindow::GetToolWindow( i ); + delete kill; + } + + UnregisterAllToolWindows(); + + if ( m_hProperties.Get() ) + { + windowposmgr->UnregisterPanel( m_hProperties.Get() ); + delete m_hProperties.Get(); + m_hProperties = NULL; + } + + if ( m_hParticleSystemDefinitionBrowser.Get() ) + { + windowposmgr->UnregisterPanel( m_hParticleSystemDefinitionBrowser.Get() ); + delete m_hParticleSystemDefinitionBrowser.Get(); + m_hParticleSystemDefinitionBrowser = NULL; + } + + if ( m_hParticlePreview.Get() ) + { + windowposmgr->UnregisterPanel( m_hParticlePreview.Get() ); + delete m_hParticlePreview.Get(); + m_hParticlePreview = NULL; + } +} + + +void CPetTool::ShowToolWindow( Panel *tool, char const *toolName, bool visible ) +{ + Assert( tool ); + + if ( tool->GetParent() == NULL && visible ) + { + m_ToolWindowFactory.InstanceToolWindow( this, false, tool, toolName, false ); + } + else if ( !visible ) + { + ToolWindow *tw = dynamic_cast< ToolWindow * >( tool->GetParent()->GetParent() ); + Assert( tw ); + tw->RemovePage( tool ); + } +} + +void CPetTool::ToggleToolWindow( Panel *tool, char const *toolName ) +{ + Assert( tool ); + + if ( tool->GetParent() == NULL ) + { + ShowToolWindow( tool, toolName, true ); + } + else + { + ShowToolWindow( tool, toolName, false ); + } +} + + +//----------------------------------------------------------------------------- +// Creates the action menu +//----------------------------------------------------------------------------- +vgui::Menu *CPetTool::CreateActionMenu( vgui::Panel *pParent ) +{ + vgui::Menu *pActionMenu = new Menu( pParent, "ActionMenu" ); + pActionMenu->AddMenuItem( "#ToolHide", new KeyValues( "Command", "command", "HideActionMenu" ), GetActionTarget() ); + return pActionMenu; +} + + +//----------------------------------------------------------------------------- +// Inherited from IFileMenuCallbacks +//----------------------------------------------------------------------------- +int CPetTool::GetFileMenuItemsEnabled( ) +{ + int nFlags = FILE_ALL; + if ( m_RecentFiles.IsEmpty() ) + { + nFlags &= ~(FILE_RECENT | FILE_CLEAR_RECENT); + } + return nFlags; +} + +void CPetTool::AddRecentFilesToMenu( vgui::Menu *pMenu ) +{ + m_RecentFiles.AddToMenu( pMenu, GetActionTarget(), "OnRecent" ); +} + +bool CPetTool::GetPerforceFileName( char *pFileName, int nMaxLen ) +{ + if ( !m_pDoc ) + return false; + + Q_strncpy( pFileName, m_pDoc->GetFileName(), nMaxLen ); + return pFileName[0] != 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void CPetTool::OnExit() +{ + windowposmgr->SavePositions( "cfg/pet.txt", "Pet" ); + + enginetools->Command( "quit\n" ); +} + +//----------------------------------------------------------------------------- +// Handle commands from the action menu and other menus +//----------------------------------------------------------------------------- +void CPetTool::OnCommand( const char *cmd ) +{ + if ( !V_stricmp( cmd, "HideActionMenu" ) ) + { + if ( GetActionMenu() ) + { + GetActionMenu()->SetVisible( false ); + } + } + else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnRecent" ) ) + { + int idx = Q_atoi( pSuffix ); + OpenFileFromHistory( idx ); + } + else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnTool" ) ) + { + int idx = Q_atoi( pSuffix ); + enginetools->SwitchToTool( idx ); + } + else if ( !V_stricmp( cmd, "OnUndo" ) ) + { + OnUndo(); + } + else if ( !V_stricmp( cmd, "OnRedo" ) ) + { + OnRedo(); + } + else if ( !V_stricmp( cmd, "OnDescribeUndo" ) ) + { + OnDescribeUndo(); + } + else + { + BaseClass::OnCommand( cmd ); + } +} + + +//----------------------------------------------------------------------------- +// Command handlers +//----------------------------------------------------------------------------- +void CPetTool::PerformNew() +{ + OnCloseNoSave(); + NewDocument(); +} + +void CPetTool::OnNew() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, + new KeyValues( "OnNew" ) ); + return; + } + + PerformNew(); +} + + +//----------------------------------------------------------------------------- +// Called when the File->Open menu is selected +//----------------------------------------------------------------------------- +void CPetTool::OnOpen( ) +{ + int nFlags = 0; + const char *pSaveFileName = NULL; + if ( m_pDoc && m_pDoc->IsDirty() ) + { + nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY; + pSaveFileName = m_pDoc->GetFileName(); + } + + OpenFile( PET_FILE_FORMAT, pSaveFileName, PET_FILE_FORMAT, nFlags ); +} + +bool CPetTool::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) +{ + OnCloseNoSave(); + + if ( !LoadDocument( pFileName ) ) + return false; + + m_RecentFiles.Add( pFileName, pFileFormat ); + m_RecentFiles.SaveToRegistry( GetRegistryName() ); + UpdateMenuBar(); + return true; +} + +void CPetTool::Save() +{ + if ( m_pDoc ) + { + SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS ); + } +} + +void CPetTool::OnSaveAs() +{ + if ( m_pDoc ) + { + SaveFile( NULL, PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS ); + } +} + +void CPetTool::OnRestartLevel() +{ + enginetools->Command( "restart" ); + enginetools->Execute(); +} + +void CPetTool::SaveAndTest() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS, + new KeyValues( "RestartLevel" ) ); + } + else + { + OnRestartLevel(); + } +} + +bool CPetTool::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) +{ + if ( !m_pDoc ) + return true; + + m_pDoc->SetFileName( pFileName ); + m_pDoc->SaveToFile( ); + + m_RecentFiles.Add( pFileName, pFileFormat ); + m_RecentFiles.SaveToRegistry( GetRegistryName() ); + UpdateMenuBar(); + return true; +} + +void CPetTool::OnClose() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, + new KeyValues( "OnClose" ) ); + return; + } + + OnCloseNoSave(); +} + +void CPetTool::OnCloseNoSave() +{ + DestroyTools(); + + if ( m_pDoc ) + { + CAppNotifyScopeGuard sg( "CPetTool::OnCloseNoSave", NOTIFY_CHANGE_OTHER ); + + delete m_pDoc; + m_pDoc = NULL; + + if ( m_hProperties ) + { + m_hProperties->SetParticleSystem( NULL ); + } + } + + UpdateMenuBar( ); +} + +void CPetTool::OnMarkNotDirty() +{ + if ( m_pDoc ) + { + m_pDoc->SetDirty( false ); + } +} + + +//----------------------------------------------------------------------------- +// Open a specific file +//----------------------------------------------------------------------------- +void CPetTool::OpenSpecificFile( const char *pFileName ) +{ + int nFlags = 0; + const char *pSaveFileName = NULL; + if ( m_pDoc ) + { + // File is already open + if ( !Q_stricmp( m_pDoc->GetFileName(), pFileName ) ) + return; + + if ( m_pDoc->IsDirty() ) + { + nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY; + pSaveFileName = m_pDoc->GetFileName(); + } + else + { + OnCloseNoSave(); + } + } + + OpenFile( pFileName, PET_FILE_FORMAT, pSaveFileName, PET_FILE_FORMAT, nFlags ); +} + + +//----------------------------------------------------------------------------- +// Show the save document query dialog +//----------------------------------------------------------------------------- +void CPetTool::OpenFileFromHistory( int slot ) +{ + const char *pFileName = m_RecentFiles.GetFile( slot ); + if ( !pFileName ) + return; + OpenSpecificFile( pFileName ); +} + + +//----------------------------------------------------------------------------- +// Derived classes can implement this to get notified when files are saved/loaded +//----------------------------------------------------------------------------- +void CPetTool::OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues ) +{ + if ( bWroteFile ) + { + OnMarkNotDirty(); + } + + if ( !pContextKeyValues ) + return; + + if ( state != FileOpenStateMachine::SUCCESSFUL ) + return; + + if ( !Q_stricmp( pContextKeyValues->GetName(), "OnNew" ) ) + { + PerformNew(); + return; + } + + if ( !Q_stricmp( pContextKeyValues->GetName(), "OnClose" ) ) + { + OnCloseNoSave(); + return; + } + + if ( !Q_stricmp( pContextKeyValues->GetName(), "OnQuit" ) ) + { + OnCloseNoSave(); + vgui::ivgui()->PostMessage( GetVPanel(), new KeyValues( "OnExit" ), 0 ); + return; + } + + if ( !Q_stricmp( pContextKeyValues->GetName(), "RestartLevel" ) ) + { + OnRestartLevel(); + return; + } +} + + +//----------------------------------------------------------------------------- +// Show the File browser dialog +//----------------------------------------------------------------------------- +void CPetTool::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues ) +{ + char pStartingDir[ MAX_PATH ]; + + GetModSubdirectory( "particles", pStartingDir, sizeof(pStartingDir) ); + + // Open a bsp file to create a new commentary file + pDialog->SetTitle( "Choose Particle Configuration File", true ); + pDialog->SetStartDirectoryContext( "pet_session", pStartingDir ); + pDialog->AddFilter( "*.pcf", "Particle Configuration File (*.pcf)", true ); +} + + +//----------------------------------------------------------------------------- +// Can we quit? +//----------------------------------------------------------------------------- +bool CPetTool::CanQuit() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + // Show Save changes Yes/No/Cancel and re-quit if hit yes/no + SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, + new KeyValues( "OnQuit" ) ); + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Various command handlers related to the Edit menu +//----------------------------------------------------------------------------- +void CPetTool::OnUndo() +{ + CDisableUndoScopeGuard guard; + g_pDataModel->Undo(); +} + +void CPetTool::OnRedo() +{ + CDisableUndoScopeGuard guard; + g_pDataModel->Redo(); +} + +void CPetTool::OnDescribeUndo() +{ + CUtlVector< UndoInfo_t > list; + g_pDataModel->GetUndoInfo( list ); + + Msg( "%i operations in stack\n", list.Count() ); + + for ( int i = list.Count() - 1; i >= 0; --i ) + { + UndoInfo_t& entry = list[ i ]; + if ( entry.terminator ) + { + Msg( "[ '%s' ] - %i operations\n", entry.undo, entry.numoperations ); + } + + Msg( " +%s\n", entry.desc ); + } +} + + +//----------------------------------------------------------------------------- +// Background +//----------------------------------------------------------------------------- +const char *CPetTool::GetLogoTextureName() +{ + return NULL; +} + + +//----------------------------------------------------------------------------- +// Inherited from IPetDocCallback +//----------------------------------------------------------------------------- +void CPetTool::OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) +{ + CDmeParticleSystemDefinition *pParticleSystem = GetCurrentParticleSystem(); + if ( m_pDoc && GetParticlePreview() && pParticleSystem ) + { + m_pDoc->UpdateParticleDefinition( pParticleSystem ); + } + + if ( nNotifyFlags & NOTIFY_CHANGE_TOPOLOGICAL ) + { + if ( GetParticleSystemDefinitionBrowser() ) + { + GetParticleSystemDefinitionBrowser()->UpdateParticleSystemList(); + } + } + + bool bRefreshProperties = ( nNotifySource != NOTIFY_SOURCE_PROPERTIES_TREE ) && + ( ( nNotifyFlags & ( NOTIFY_CHANGE_TOPOLOGICAL | NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE ) ) != 0 ); + bool bRefreshPropertyValues = ( nNotifySource != NOTIFY_SOURCE_PROPERTIES_TREE ) && + ( nNotifyFlags & NOTIFY_CHANGE_ATTRIBUTE_VALUE ) != 0; + + if ( bRefreshProperties || bRefreshPropertyValues ) + { + if ( m_hProperties.Get() ) + { + m_hProperties->Refresh( !bRefreshProperties ); + } + } + + UpdateMenuBar(); +} + + +//----------------------------------------------------------------------------- +// Creates a new document +//----------------------------------------------------------------------------- +void CPetTool::NewDocument( ) +{ + Assert( !m_pDoc ); + + DestroyTools(); + + m_pDoc = new CPetDoc( this ); + m_pDoc->CreateNew( ); + + ShowMiniViewport( true ); + CreateTools( m_pDoc ); + UpdateMenuBar( ); + InitTools(); +} + + +//----------------------------------------------------------------------------- +// Loads up a new document +//----------------------------------------------------------------------------- +bool CPetTool::LoadDocument( const char *pDocName ) +{ + Assert( !m_pDoc ); + + DestroyTools(); + + m_pDoc = new CPetDoc( this ); + if ( !m_pDoc->LoadFromFile( pDocName ) ) + { + delete m_pDoc; + m_pDoc = NULL; + Warning( "Fatal error loading '%s'\n", pDocName ); + return false; + } + + ShowMiniViewport( true ); + + CreateTools( m_pDoc ); + UpdateMenuBar( ); + InitTools(); + + // Let the other tools know we've loaded + therefore modified particle systems + CUtlBuffer buf; + g_pDataModel->Serialize( buf, "binary", PET_FILE_FORMAT, m_pDoc->GetRootObject()->GetHandle() ); + + KeyValues *pMessage = new KeyValues( "ParticleSystemUpdated" ); + pMessage->SetPtr( "definitionBits", buf.Base() ); + pMessage->SetInt( "definitionSize", buf.TellMaxPut() ); + PostMessageToAllTools( pMessage ); + pMessage->deleteThis(); + return true; +} + + diff --git a/tools/pet/pettool.h b/tools/pet/pettool.h new file mode 100644 index 0000000..ba6395e --- /dev/null +++ b/tools/pet/pettool.h @@ -0,0 +1,209 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: P.E.T. (Particle Editing Tool); main UI smarts class +// +//============================================================================= + +#ifndef PETTOOL_H +#define PETTOOL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/platform.h" +#include "toolutils/basetoolsystem.h" +#include "toolutils/recentfilelist.h" +#include "toolutils/toolmenubar.h" +#include "toolutils/toolswitchmenubutton.h" +#include "toolutils/tooleditmenubutton.h" +#include "toolutils/toolfilemenubutton.h" +#include "toolutils/toolmenubutton.h" +#include "datamodel/dmelement.h" +#include "datamodel/dmehandle.h" +#include "toolframework/ienginetool.h" +#include "toolutils/enginetools_int.h" +#include "toolutils/savewindowpositions.h" +#include "toolutils/toolwindowfactory.h" +#include "movieobjects/dmeparticlesystemdefinition.h" +#include "particles/particles.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CDmElement; +class CPetDoc; +class CParticleSystemPropertiesContainer; +class CParticleSystemDefinitionBrowser; +class CParticleSystemPreviewPanel; +class CDmeParticleSystemDefinition; +enum ParticleFunctionType_t; + +namespace vgui +{ + class Panel; +} + + +//----------------------------------------------------------------------------- +// Allows the doc to call back into the CommEdit editor tool +//----------------------------------------------------------------------------- +abstract_class IPetDocCallback +{ +public: + // Called by the doc when the data changes + virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0; +}; + + +//----------------------------------------------------------------------------- +// Global methods of the commedit tool +//----------------------------------------------------------------------------- +abstract_class IPetTool +{ +public: + // Gets at the rool panel (for modal dialogs) + virtual vgui::Panel *GetRootPanel() = 0; + + // Gets the registry name (for saving settings) + virtual const char *GetRegistryName() = 0; +}; + +//----------------------------------------------------------------------------- +// Implementation of the CommEdit tool +//----------------------------------------------------------------------------- +class CPetTool : public CBaseToolSystem, public IFileMenuCallbacks, public IPetDocCallback, public IPetTool +{ + DECLARE_CLASS_SIMPLE( CPetTool, CBaseToolSystem ); + +public: + CPetTool(); + + // Inherited from IToolSystem + virtual const char *GetToolName() { return "Particle Editor"; } + virtual bool Init( ); + virtual void Shutdown(); + virtual bool CanQuit(); + virtual void OnToolActivate(); + virtual void OnToolDeactivate(); + virtual void Think( bool finalTick ); + + // Inherited from IFileMenuCallbacks + virtual int GetFileMenuItemsEnabled( ); + virtual void AddRecentFilesToMenu( vgui::Menu *menu ); + virtual bool GetPerforceFileName( char *pFileName, int nMaxLen ); + + // Inherited from IPetDocCallback + virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ); + virtual vgui::Panel *GetRootPanel() { return this; } + + // Inherited from CBaseToolSystem + virtual vgui::HScheme GetToolScheme(); + virtual vgui::Menu *CreateActionMenu( vgui::Panel *pParent ); + virtual void OnCommand( const char *cmd ); + virtual const char *GetRegistryName() { return "PetTool"; } + virtual const char *GetBindingsContextFile() { return "cfg/Pet.kb"; } + virtual vgui::MenuBar *CreateMenuBar( CBaseToolSystem *pParent ); + + MESSAGE_FUNC( Save, "OnSave" ); + void SaveAndTest(); + +public: + MESSAGE_FUNC( OnRestartLevel, "RestartLevel" ); + MESSAGE_FUNC( OnNew, "OnNew" ); + MESSAGE_FUNC( OnOpen, "OnOpen" ); + MESSAGE_FUNC( OnSaveAs, "OnSaveAs" ); + MESSAGE_FUNC( OnClose, "OnClose" ); + MESSAGE_FUNC( OnCloseNoSave, "OnCloseNoSave" ); + MESSAGE_FUNC( OnMarkNotDirty, "OnMarkNotDirty" ); + MESSAGE_FUNC( OnExit, "OnExit" ); + MESSAGE_FUNC( OnCopy, "OnCopy" ); + MESSAGE_FUNC( OnPaste, "OnPaste" ); + + // Commands related to the edit menu + void OnDescribeUndo(); + + // Methods related to the view menu + MESSAGE_FUNC( OnToggleProperties, "OnToggleProperties" ); + MESSAGE_FUNC( OnToggleParticleSystemBrowser, "OnToggleParticleSystemBrowser" ); + MESSAGE_FUNC( OnToggleParticlePreview, "OnToggleParticlePreview" ); + MESSAGE_FUNC( OnDefaultLayout, "OnDefaultLayout" ); + + // Keybindings + KEYBINDING_FUNC( undo, KEY_Z, vgui::MODIFIER_CONTROL, OnUndo, "#undo_help", 0 ); + KEYBINDING_FUNC( redo, KEY_Z, vgui::MODIFIER_CONTROL | vgui::MODIFIER_SHIFT, OnRedo, "#redo_help", 0 ); + KEYBINDING_FUNC_NODECLARE( edit_copy, KEY_C, vgui::MODIFIER_CONTROL, OnCopy, "#edit_copy_help", 0 ); + KEYBINDING_FUNC_NODECLARE( edit_paste, KEY_V, vgui::MODIFIER_CONTROL, OnPaste, "#edit_paste_help", 0 ); + + void PerformNew(); + void OpenFileFromHistory( int slot ); + void OpenSpecificFile( const char *pFileName ); + virtual void SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues ); + virtual bool OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ); + virtual bool OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ); + virtual void OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues ); + + // returns the document + CPetDoc *GetDocument(); + + // Gets at tool windows + CParticleSystemPropertiesContainer *GetProperties(); + CParticleSystemDefinitionBrowser *GetParticleSystemDefinitionBrowser(); + CParticleSystemPreviewPanel *GetParticlePreview(); + + void SetCurrentParticleSystem( CDmeParticleSystemDefinition *pParticleSystem, bool bForceBrowserSelection = true ); + CDmeParticleSystemDefinition* GetCurrentParticleSystem( void ); + +private: + // Creates a new document + void NewDocument( ); + + // Loads up a new document + bool LoadDocument( const char *pDocName ); + + // Updates the menu bar based on the current file + void UpdateMenuBar( ); + + virtual const char *GetLogoTextureName(); + + // Creates, destroys tools + void CreateTools( CPetDoc *doc ); + void DestroyTools(); + + // Initializes the tools + void InitTools(); + + // Shows, toggles tool windows + void ToggleToolWindow( Panel *tool, char const *toolName ); + void ShowToolWindow( Panel *tool, char const *toolName, bool visible ); + + // Kills all tool windows + void DestroyToolContainers(); + +private: + // Document + CPetDoc *m_pDoc; + + // The menu bar + CToolFileMenuBar *m_pMenuBar; + + // Element properties for editing material + vgui::DHANDLE< CParticleSystemPropertiesContainer > m_hProperties; + + // The entity report + vgui::DHANDLE< CParticleSystemDefinitionBrowser > m_hParticleSystemDefinitionBrowser; + + // Particle preview window + vgui::DHANDLE< CParticleSystemPreviewPanel > m_hParticlePreview; + + // The currently viewed entity + CDmeHandle< CDmeParticleSystemDefinition > m_hCurrentParticleSystem; + + // Separate undo context for the act busy tool + CToolWindowFactory< ToolWindow > m_ToolWindowFactory; +}; + +extern CPetTool *g_pPetTool; + +#endif // PETTOOL_H |