1
This commit is contained in:
536
tools/pet/petdoc.cpp
Normal file
536
tools/pet/petdoc.cpp
Normal file
@ -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 );
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user