mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,443 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "commeditdoc.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "toolutils/enginetools_int.h"
|
||||
#include "filesystem.h"
|
||||
#include "commedittool.h"
|
||||
#include "toolframework/ienginetool.h"
|
||||
#include "dmecommentarynodeentity.h"
|
||||
#include "datamodel/idatamodel.h"
|
||||
#include "toolutils/attributeelementchoicelist.h"
|
||||
#include "commentarynodebrowserpanel.h"
|
||||
#include "vgui_controls/messagebox.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CCommEditDoc::CCommEditDoc( ICommEditDocCallback *pCallback ) : m_pCallback( pCallback )
|
||||
{
|
||||
m_hRoot = NULL;
|
||||
m_pTXTFileName[0] = 0;
|
||||
m_bDirty = false;
|
||||
g_pDataModel->InstallNotificationCallback( this );
|
||||
}
|
||||
|
||||
CCommEditDoc::~CCommEditDoc()
|
||||
{
|
||||
g_pDataModel->RemoveNotificationCallback( this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inherited from INotifyUI
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
|
||||
{
|
||||
OnDataChanged( pReason, nNotifySource, nNotifyFlags );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the file name
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CCommEditDoc::GetTXTFileName()
|
||||
{
|
||||
return m_pTXTFileName;
|
||||
}
|
||||
|
||||
void CCommEditDoc::SetTXTFileName( const char *pFileName )
|
||||
{
|
||||
Q_strncpy( m_pTXTFileName, pFileName, sizeof( m_pTXTFileName ) );
|
||||
Q_FixSlashes( m_pTXTFileName );
|
||||
SetDirty( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dirty bits
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::SetDirty( bool bDirty )
|
||||
{
|
||||
m_bDirty = bDirty;
|
||||
}
|
||||
|
||||
bool CCommEditDoc::IsDirty() const
|
||||
{
|
||||
return m_bDirty;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handles creation of the right element for a keyvalue
|
||||
//-----------------------------------------------------------------------------
|
||||
class CElementForKeyValueCallback : public IElementForKeyValueCallback
|
||||
{
|
||||
public:
|
||||
const char *GetElementForKeyValue( const char *pszKeyName, int iNestingLevel )
|
||||
{
|
||||
if ( iNestingLevel == 1 && !Q_strncmp(pszKeyName, "entity", 6) )
|
||||
return "DmeCommentaryNodeEntity";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Saves/loads from file
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommEditDoc::LoadFromFile( const char *pFileName )
|
||||
{
|
||||
Assert( !m_hRoot.Get() );
|
||||
|
||||
CAppDisableUndoScopeGuard guard( "CCommEditDoc::LoadFromFile", 0 );
|
||||
SetDirty( false );
|
||||
|
||||
if ( !pFileName[0] )
|
||||
return false;
|
||||
|
||||
char mapname[ 256 ];
|
||||
|
||||
// Compute the map name
|
||||
const char *pMaps = Q_stristr( pFileName, "\\maps\\" );
|
||||
if ( !pMaps )
|
||||
return false;
|
||||
|
||||
// Build map name
|
||||
//int nNameLen = (int)( (size_t)pComm - (size_t)pMaps ) - 5;
|
||||
Q_StripExtension( pFileName, mapname, sizeof(mapname) );
|
||||
char *pszFileName = (char*)Q_UnqualifiedFileName(mapname);
|
||||
|
||||
// Set the txt file name.
|
||||
// If we loaded an existing commentary file, keep the same filename.
|
||||
// If we loaded a .bsp, change the name & the extension.
|
||||
if ( !V_stricmp( Q_GetFileExtension( pFileName ), "bsp" ) )
|
||||
{
|
||||
const char *pCommentaryAppend = "_commentary.txt";
|
||||
Q_StripExtension( pFileName, m_pTXTFileName, sizeof(m_pTXTFileName)- strlen(pCommentaryAppend) - 1 );
|
||||
Q_strcat( m_pTXTFileName, pCommentaryAppend, sizeof( m_pTXTFileName ) );
|
||||
|
||||
if ( g_pFileSystem->FileExists( m_pTXTFileName ) )
|
||||
{
|
||||
char pBuf[1024];
|
||||
Q_snprintf( pBuf, sizeof(pBuf), "File %s already exists!\n", m_pTXTFileName );
|
||||
m_pTXTFileName[0] = 0;
|
||||
vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Unable to overwrite file!\n", pBuf, g_pCommEditTool );
|
||||
pMessageBox->DoModal( );
|
||||
return false;
|
||||
}
|
||||
|
||||
DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( m_pTXTFileName );
|
||||
|
||||
m_hRoot = CreateElement<CDmElement>( "root", fileid );
|
||||
CDmrElementArray<> subkeys( m_hRoot->AddAttribute( "subkeys", AT_ELEMENT_ARRAY ) );
|
||||
CDmElement *pRoot2 = CreateElement<CDmElement>( "Entities", fileid );
|
||||
pRoot2->AddAttribute( "subkeys", AT_ELEMENT_ARRAY );
|
||||
subkeys.AddToTail( pRoot2 );
|
||||
g_pDataModel->SetFileRoot( fileid, m_hRoot );
|
||||
}
|
||||
else
|
||||
{
|
||||
char *pComm = Q_stristr( pszFileName, "_commentary" );
|
||||
if ( !pComm )
|
||||
{
|
||||
char pBuf[1024];
|
||||
Q_snprintf( pBuf, sizeof(pBuf), "File %s is not a commentary file!\nThe file name must end in _commentary.txt.\n", m_pTXTFileName );
|
||||
m_pTXTFileName[0] = 0;
|
||||
vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Bad file name!\n", pBuf, g_pCommEditTool );
|
||||
pMessageBox->DoModal( );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clip off the "_commentary" at the end of the filename
|
||||
*pComm = '\0';
|
||||
|
||||
// This is not undoable
|
||||
CDisableUndoScopeGuard guardFile;
|
||||
|
||||
CDmElement *pTXT = NULL;
|
||||
|
||||
CElementForKeyValueCallback KeyValuesCallback;
|
||||
g_pDataModel->SetKeyValuesElementCallback( &KeyValuesCallback );
|
||||
DmFileId_t fileid = g_pDataModel->RestoreFromFile( pFileName, NULL, "keyvalues", &pTXT );
|
||||
g_pDataModel->SetKeyValuesElementCallback( NULL );
|
||||
|
||||
if ( fileid == DMFILEID_INVALID )
|
||||
{
|
||||
m_pTXTFileName[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetTXTFileName( pFileName );
|
||||
m_hRoot = pTXT;
|
||||
}
|
||||
|
||||
guard.Release();
|
||||
SetDirty( false );
|
||||
|
||||
char cmd[ 256 ];
|
||||
Q_snprintf( cmd, sizeof( cmd ), "disconnect; map %s\n", pszFileName );
|
||||
enginetools->Command( cmd );
|
||||
enginetools->Execute( );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCommEditDoc::SaveToFile( )
|
||||
{
|
||||
if ( m_hRoot.Get() && m_pTXTFileName && m_pTXTFileName[0] )
|
||||
{
|
||||
g_pDataModel->SaveToFile( m_pTXTFileName, NULL, "keyvalues", "keyvalues", m_hRoot );
|
||||
}
|
||||
|
||||
SetDirty( false );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the root object
|
||||
//-----------------------------------------------------------------------------
|
||||
CDmElement *CCommEditDoc::GetRootObject()
|
||||
{
|
||||
return m_hRoot;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the entity list
|
||||
//-----------------------------------------------------------------------------
|
||||
CDmAttribute *CCommEditDoc::GetEntityList()
|
||||
{
|
||||
CDmrElementArray<> mainKeys( m_hRoot, "subkeys" );
|
||||
if ( !mainKeys.IsValid() || mainKeys.Count() == 0 )
|
||||
return NULL;
|
||||
CDmeHandle<CDmElement> hEntityList;
|
||||
hEntityList = mainKeys[ 0 ];
|
||||
return hEntityList ? hEntityList->GetAttribute( "subkeys", AT_ELEMENT_ARRAY ) : NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::AddNewInfoTarget( const Vector &vecOrigin, const QAngle &angAngles )
|
||||
{
|
||||
CDmrCommentaryNodeEntityList entities( GetEntityList() );
|
||||
if ( !entities.IsValid() )
|
||||
return;
|
||||
|
||||
CDmeCommentaryNodeEntity *pTarget;
|
||||
{
|
||||
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Add Info Target", "Add Info Target" );
|
||||
|
||||
pTarget = CreateElement<CDmeCommentaryNodeEntity>( "target", entities.GetOwner()->GetFileId() );
|
||||
pTarget->SetName( "entity" );
|
||||
pTarget->SetValue( "classname", "info_target" );
|
||||
pTarget->SetRenderOrigin( vecOrigin );
|
||||
pTarget->SetRenderAngles( angAngles );
|
||||
|
||||
entities.AddToTail( pTarget );
|
||||
pTarget->MarkDirty();
|
||||
pTarget->DrawInEngine( true );
|
||||
}
|
||||
|
||||
g_pCommEditTool->GetCommentaryNodeBrowser()->SelectNode( pTarget );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::AddNewInfoTarget( void )
|
||||
{
|
||||
Vector vecOrigin;
|
||||
QAngle angAngles;
|
||||
float flFov;
|
||||
clienttools->GetLocalPlayerEyePosition( vecOrigin, angAngles, flFov );
|
||||
AddNewInfoTarget( vecOrigin, vec3_angle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::AddNewCommentaryNode( const Vector &vecOrigin, const QAngle &angAngles )
|
||||
{
|
||||
CDmrCommentaryNodeEntityList entities = GetEntityList();
|
||||
|
||||
CDmeCommentaryNodeEntity *pNode;
|
||||
{
|
||||
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Add Commentary Node", "Add Commentary Node" );
|
||||
|
||||
pNode = CreateElement<CDmeCommentaryNodeEntity>( "node", entities.GetOwner()->GetFileId() );
|
||||
pNode->SetName( "entity" );
|
||||
pNode->SetValue( "classname", "point_commentary_node" );
|
||||
pNode->SetRenderOrigin( vecOrigin );
|
||||
pNode->SetRenderAngles( angAngles );
|
||||
pNode->SetValue<CUtlString>( "precommands", "" );
|
||||
pNode->SetValue<CUtlString>( "postcommands", "" );
|
||||
pNode->SetValue<CUtlString>( "commentaryfile", "" );
|
||||
pNode->SetValue<CUtlString>( "viewtarget", "" );
|
||||
pNode->SetValue<CUtlString>( "viewposition", "" );
|
||||
pNode->SetValue<int>( "prevent_movement", 0 );
|
||||
pNode->SetValue<CUtlString>( "speakers", "" );
|
||||
pNode->SetValue<CUtlString>( "synopsis", "" );
|
||||
|
||||
entities.AddToTail( pNode );
|
||||
pNode->MarkDirty();
|
||||
pNode->DrawInEngine( true );
|
||||
}
|
||||
|
||||
g_pCommEditTool->GetCommentaryNodeBrowser()->SelectNode( pNode );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::AddNewCommentaryNode( void )
|
||||
{
|
||||
Vector vecOrigin;
|
||||
QAngle angAngles;
|
||||
float flFov;
|
||||
clienttools->GetLocalPlayerEyePosition( vecOrigin, angAngles, flFov );
|
||||
AddNewCommentaryNode( vecOrigin, vec3_angle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deletes a commentary node
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCommEditDoc::DeleteCommentaryNode( CDmElement *pRemoveNode )
|
||||
{
|
||||
CDmrCommentaryNodeEntityList entities = GetEntityList();
|
||||
int nCount = entities.Count();
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
if ( pRemoveNode == entities[i] )
|
||||
{
|
||||
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Commentary Node", "Delete Commentary Node" );
|
||||
CDmeCommentaryNodeEntity *pNode = entities[ i ];
|
||||
pNode->DrawInEngine( false );
|
||||
entities.FastRemove( i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &vecOrigin -
|
||||
// &angAbsAngles -
|
||||
// Output : CDmeCommentaryNodeEntity
|
||||
//-----------------------------------------------------------------------------
|
||||
CDmeCommentaryNodeEntity *CCommEditDoc::GetCommentaryNodeForLocation( Vector &vecOrigin, QAngle &angAbsAngles )
|
||||
{
|
||||
CDmrCommentaryNodeEntityList entities = GetEntityList();
|
||||
int nCount = entities.Count();
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
CDmeCommentaryNodeEntity *pNode = entities[ i ];
|
||||
if ( !pNode )
|
||||
continue;
|
||||
|
||||
Vector &vecAngles = *(Vector*)(&pNode->GetRenderAngles());
|
||||
if ( pNode->GetRenderOrigin().DistTo( vecOrigin ) < 1e-3 && vecAngles.DistTo( *(Vector*)&angAbsAngles ) < 1e-1 )
|
||||
return pNode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populate string choice lists
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommEditDoc::GetStringChoiceList( const char *pChoiceListType, CDmElement *pElement,
|
||||
const char *pAttributeName, bool bArrayElement, StringChoiceList_t &list )
|
||||
{
|
||||
if ( !Q_stricmp( pChoiceListType, "info_targets" ) )
|
||||
{
|
||||
CDmrCommentaryNodeEntityList entities = GetEntityList();
|
||||
|
||||
StringChoice_t sChoice;
|
||||
sChoice.m_pValue = "";
|
||||
sChoice.m_pChoiceString = "";
|
||||
list.AddToTail( sChoice );
|
||||
|
||||
int nCount = entities.Count();
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
CDmeCommentaryNodeEntity *pNode = entities[ i ];
|
||||
if ( !pNode )
|
||||
continue;
|
||||
|
||||
if ( !V_stricmp( pNode->GetClassName(), "info_target" ) )
|
||||
{
|
||||
sChoice.m_pValue = pNode->GetTargetName();
|
||||
sChoice.m_pChoiceString = pNode->GetTargetName();
|
||||
list.AddToTail( sChoice );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populate element choice lists
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCommEditDoc::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, "info_targets" ) )
|
||||
{
|
||||
CDmrCommentaryNodeEntityList entities = GetEntityList();
|
||||
|
||||
bool bFound = false;
|
||||
int nCount = entities.Count();
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
CDmeCommentaryNodeEntity *pNode = entities[ i ];
|
||||
if ( pNode && !V_stricmp( pNode->GetClassName(), "info_target" ) )
|
||||
{
|
||||
bFound = true;
|
||||
ElementChoice_t sChoice;
|
||||
sChoice.m_pValue = pNode;
|
||||
sChoice.m_pChoiceString = pNode->GetTargetName();
|
||||
list.AddToTail( sChoice );
|
||||
}
|
||||
}
|
||||
return bFound;
|
||||
}
|
||||
|
||||
// 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 CCommEditDoc::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