summaryrefslogtreecommitdiff
path: root/tools/commedit
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tools/commedit
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'tools/commedit')
-rw-r--r--tools/commedit/commedit.vpc64
-rw-r--r--tools/commedit/commeditdoc.cpp443
-rw-r--r--tools/commedit/commeditdoc.h92
-rw-r--r--tools/commedit/commedittool.cpp1284
-rw-r--r--tools/commedit/commedittool.h231
-rw-r--r--tools/commedit/commentarynodebrowserpanel.cpp283
-rw-r--r--tools/commedit/commentarynodebrowserpanel.h67
-rw-r--r--tools/commedit/commentarypropertiespanel.cpp458
-rw-r--r--tools/commedit/commentarypropertiespanel.h113
-rw-r--r--tools/commedit/dmecommentarynodeentity.cpp339
-rw-r--r--tools/commedit/dmecommentarynodeentity.h100
-rw-r--r--tools/commedit/entityreportpanel.cpp581
12 files changed, 4055 insertions, 0 deletions
diff --git a/tools/commedit/commedit.vpc b/tools/commedit/commedit.vpc
new file mode 100644
index 0000000..1545cb3
--- /dev/null
+++ b/tools/commedit/commedit.vpc
@@ -0,0 +1,64 @@
+//-----------------------------------------------------------------------------
+// COMMEDIT.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+
+$Macro SRCDIR "..\.."
+$Macro OUTBINDIR "$SRCDIR\..\game\bin\tools"
+
+$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
+
+$Configuration
+{
+ $Compiler
+ {
+ $AdditionalIncludeDirectories "$BASE,.\,..\common,$SRCDIR\game\shared"
+ $PreprocessorDefinitions "$BASE;COMMEDIT_EXPORTS"
+ }
+
+ $Linker
+ {
+ $AdditionalDependencies "$BASE Psapi.lib"
+ }
+}
+
+$Project "Commedit"
+{
+ $Folder "Source Files"
+ {
+ $File "commeditdoc.cpp"
+ $File "commedittool.cpp"
+ $File "commentarynodebrowserpanel.cpp"
+ $File "commentarypropertiespanel.cpp"
+ $File "dmecommentarynodeentity.cpp"
+ $File "$SRCDIR\public\interpolatortypes.cpp"
+ $File "$SRCDIR\public\registry.cpp"
+ $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
+ }
+
+ $Folder "Header Files"
+ {
+ $File "commeditdoc.h"
+ $File "commedittool.h"
+ $File "commentarynodebrowserpanel.h"
+ $File "commentarypropertiespanel.h"
+ $File "dmecommentarynodeentity.h"
+ $File "$SRCDIR\public\mathlib\mathlib.h"
+ }
+
+ $Folder "Link Libraries"
+ {
+ $Lib datamodel
+ $Lib dme_controls
+ $Lib dmserializers
+ $Lib mathlib
+ $Lib matsys_controls
+ $Lib movieobjects
+ $Lib sfmobjects
+ $Lib tier2
+ $Lib tier3
+ $Lib toolutils
+ $Lib vgui_controls
+ }
+}
diff --git a/tools/commedit/commeditdoc.cpp b/tools/commedit/commeditdoc.cpp
new file mode 100644
index 0000000..6ebd5fd
--- /dev/null
+++ b/tools/commedit/commeditdoc.cpp
@@ -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 );
+}
+
+
diff --git a/tools/commedit/commeditdoc.h b/tools/commedit/commeditdoc.h
new file mode 100644
index 0000000..0c51b62
--- /dev/null
+++ b/tools/commedit/commeditdoc.h
@@ -0,0 +1,92 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef COMMEDITDOC_H
+#define COMMEDITDOC_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "dme_controls/inotifyui.h"
+#include "datamodel/dmehandle.h"
+#include "datamodel/dmelement.h"
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class ICommEditDocCallback;
+class CCommEditDoc;
+class CDmeCommentaryNodeEntity;
+
+typedef CDmrElementArray<CDmeCommentaryNodeEntity> CDmrCommentaryNodeEntityList;
+
+
+//-----------------------------------------------------------------------------
+// Contains all editable state
+//-----------------------------------------------------------------------------
+class CCommEditDoc : public IDmNotify
+{
+public:
+ CCommEditDoc( ICommEditDocCallback *pCallback );
+ ~CCommEditDoc();
+
+ // Inherited from INotifyUI
+ virtual void NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags );
+
+ // Sets/Gets the file name
+ const char *GetTXTFileName();
+ void SetTXTFileName( const char *pFileName );
+
+ // Dirty bits (has it changed since the last time it was saved?)
+ void SetDirty( bool bDirty );
+ bool IsDirty() const;
+
+ // Saves/loads from file
+ bool LoadFromFile( const char *pFileName );
+ void SaveToFile( );
+
+ // Returns the root object
+ CDmElement *GetRootObject();
+
+ // Called when data changes (see INotifyUI for flags)
+ void OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags );
+
+ // Returns the entity list
+ CDmAttribute *GetEntityList();
+
+ // Adds a new info_target
+ void AddNewInfoTarget( void );
+ void AddNewInfoTarget( const Vector &vecOrigin, const QAngle &angAngles );
+
+ // Adds a new commentary node
+ void AddNewCommentaryNode( void );
+ void AddNewCommentaryNode( const Vector &vecOrigin, const QAngle &angAngles );
+
+ // Deletes a commentary node
+ void DeleteCommentaryNode( CDmElement *pNode );
+
+ // Returns the commentary node at the specified location
+ CDmeCommentaryNodeEntity *GetCommentaryNodeForLocation( Vector &vecOrigin, QAngle &angAbsAngles );
+
+ // 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 );
+
+private:
+ ICommEditDocCallback *m_pCallback;
+ CDmeHandle< CDmElement > m_hRoot;
+ char m_pTXTFileName[512];
+ bool m_bDirty;
+};
+
+
+#endif // COMMEDITDOC_H
diff --git a/tools/commedit/commedittool.cpp b/tools/commedit/commedittool.cpp
new file mode 100644
index 0000000..299d770
--- /dev/null
+++ b/tools/commedit/commedittool.cpp
@@ -0,0 +1,1284 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Core Movie Maker UI API
+//
+//=============================================================================
+
+#include "commedittool.h"
+#include "vgui_controls/Menu.h"
+#include "tier1/KeyValues.h"
+#include "vgui/IInput.h"
+#include "vgui/KeyCode.h"
+#include "vgui_controls/FileOpenDialog.h"
+#include "vgui_controls/PropertySheet.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 "commeditdoc.h"
+#include "commentarynodebrowserpanel.h"
+#include "commentarypropertiespanel.h"
+#include "dme_controls/AttributeStringChoicePanel.h"
+#include "tier2/fileutils.h"
+#include "tier3/tier3.h"
+#include "vgui/ivgui.h"
+#include "toolutils/ConsolePage.h"
+
+
+using namespace vgui;
+
+
+enum
+{
+ FILEOPEN_NEW_BSP,
+ FILEOPEN_EXISTING_TXT,
+};
+
+
+const char *GetVGuiControlsModuleName()
+{
+ return "CommEditTool";
+}
+
+//-----------------------------------------------------------------------------
+// Connect, disconnect
+//-----------------------------------------------------------------------------
+bool ConnectTools( CreateInterfaceFn factory )
+{
+ return (materials != NULL) && (g_pMatSystemSurface != NULL) && (g_pMDLCache != NULL) && (studiorender != NULL) && (g_pMaterialSystemHardwareConfig != NULL);
+}
+
+void DisconnectTools( )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Singleton
+//-----------------------------------------------------------------------------
+CCommEditTool *g_pCommEditTool = NULL;
+
+void CreateTools()
+{
+ g_pCommEditTool = new CCommEditTool();
+}
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CCommEditTool::CCommEditTool()
+{
+ m_bInNodeDropMode = false;
+ m_pMenuBar = NULL;
+ m_pDoc = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Init, shutdown
+//-----------------------------------------------------------------------------
+bool CCommEditTool::Init( )
+{
+ m_pDoc = NULL;
+ m_RecentFiles.LoadFromRegistry( GetRegistryName() );
+
+ // NOTE: This has to happen before BaseClass::Init
+ g_pVGuiLocalize->AddFile( "resource/toolcommedit_%language%.txt" );
+
+ if ( !BaseClass::Init( ) )
+ return false;
+
+ {
+ m_hPreviewNode = CreateElement<CDmeCommentaryNodeEntity>( "preview node", DMFILEID_INVALID );
+ m_hPreviewNode->SetValue( "classname", "point_commentary_node" );
+ m_hPreviewTarget = CreateElement<CDmeCommentaryNodeEntity>( "preview target", DMFILEID_INVALID );
+ m_hPreviewTarget->SetValue( "classname", "info_target" );
+ }
+
+ return true;
+}
+
+void CCommEditTool::Shutdown()
+{
+ m_RecentFiles.SaveToRegistry( GetRegistryName() );
+
+ g_pDataModel->DestroyElement( m_hPreviewNode );
+ g_pDataModel->DestroyElement( m_hPreviewTarget );
+
+ BaseClass::Shutdown();
+}
+
+
+//-----------------------------------------------------------------------------
+// returns the document
+//-----------------------------------------------------------------------------
+inline CCommEditDoc *CCommEditTool::GetDocument()
+{
+ return m_pDoc;
+}
+
+
+//-----------------------------------------------------------------------------
+// Tool activation/deactivation
+//-----------------------------------------------------------------------------
+void CCommEditTool::OnToolActivate()
+{
+ BaseClass::OnToolActivate();
+
+ enginetools->Command( "commentary 1\n" );
+}
+
+void CCommEditTool::OnToolDeactivate()
+{
+ BaseClass::OnToolDeactivate();
+
+ enginetools->Command( "commentary 0\n" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Enter mode where we preview dropping nodes
+//-----------------------------------------------------------------------------
+void CCommEditTool::EnterNodeDropMode()
+{
+ // Can only do it in editor mode
+ if ( IsGameInputEnabled() )
+ return;
+
+ m_bInNodeDropMode = true;
+ m_bDroppingCommentaryNodes = true;
+ SetMode( true, IsFullscreen() );
+ {
+ CDisableUndoScopeGuard guard;
+ m_hPreviewNode->DrawInEngine( true );
+ }
+ SetMiniViewportText( "Left Click To Place Commentary\nRight Click To Toggle Modes\nESC to exit" );
+ enginetools->Command( "noclip\n" );
+}
+
+void CCommEditTool::LeaveNodeDropMode()
+{
+ Assert( m_bInNodeDropMode );
+
+ m_bInNodeDropMode = false;
+ SetMode( false, IsFullscreen() );
+ {
+ CDisableUndoScopeGuard guard;
+ m_hPreviewNode->DrawInEngine( false );
+ m_hPreviewTarget->DrawInEngine( false );
+ }
+ SetMiniViewportText( NULL );
+ enginetools->Command( "noclip\n" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the position of the preview object
+//-----------------------------------------------------------------------------
+void CCommEditTool::GetPlacementInfo( Vector &vecOrigin, QAngle &angAngles )
+{
+ // Places the placement objects
+ float flFov;
+ clienttools->GetLocalPlayerEyePosition( vecOrigin, angAngles, flFov );
+
+ Vector vecForward;
+ AngleVectors( angAngles, &vecForward );
+ VectorMA( vecOrigin, 40.0f, vecForward, vecOrigin );
+
+ // Eliminate pitch
+ angAngles.x = 0.0f;
+}
+
+
+//-----------------------------------------------------------------------------
+// Place the preview object before rendering
+//-----------------------------------------------------------------------------
+void CCommEditTool::ClientPreRender()
+{
+ BaseClass::ClientPreRender();
+ if ( !m_bInNodeDropMode )
+ return;
+
+ // Places the placement objects
+ Vector vecOrigin;
+ QAngle angAngles;
+ GetPlacementInfo( vecOrigin, angAngles );
+
+ CDisableUndoScopeGuard guard;
+ m_hPreviewNode->SetRenderOrigin( vecOrigin );
+ m_hPreviewNode->SetRenderAngles( angAngles );
+
+ m_hPreviewTarget->SetRenderOrigin( vecOrigin );
+ m_hPreviewTarget->SetRenderAngles( angAngles );
+}
+
+
+//-----------------------------------------------------------------------------
+// Let tool override key events (ie ESC and ~)
+//-----------------------------------------------------------------------------
+bool CCommEditTool::TrapKey( ButtonCode_t key, bool down )
+{
+ // Don't hook keyboard if not topmost
+ if ( !IsActiveTool() )
+ return false; // didn't trap, continue processing
+
+ if ( !m_bInNodeDropMode )
+ {
+ if ( !IsGameInputEnabled() && !IsFullscreen() && ( key == KEY_BACKQUOTE ) && down )
+ {
+ BringConsoleToFront();
+ return true;
+ }
+ return BaseClass::TrapKey( key, down );
+ }
+
+ if ( !down )
+ return false;
+
+ if ( key == KEY_ESCAPE )
+ {
+ LeaveNodeDropMode();
+ return true; // trapping this key, stop processing
+ }
+
+ if ( key == MOUSE_LEFT )
+ {
+ Vector vecOrigin;
+ QAngle angAngles;
+ GetPlacementInfo( vecOrigin, angAngles );
+ if ( m_bDroppingCommentaryNodes )
+ {
+ m_pDoc->AddNewCommentaryNode( vecOrigin, angAngles );
+ }
+ else
+ {
+ m_pDoc->AddNewInfoTarget( vecOrigin, angAngles );
+ }
+ return true; // trapping this key, stop processing
+ }
+
+ if ( key == MOUSE_RIGHT )
+ {
+ m_bDroppingCommentaryNodes = !m_bDroppingCommentaryNodes;
+ if ( m_bDroppingCommentaryNodes )
+ {
+ SetMiniViewportText( "Left Click To Place Commentary\nRight Click To Toggle Modes\nESC to exit" );
+ }
+ else
+ {
+ SetMiniViewportText( "Left Click To Place Target\nRight Click To Toggle Modes\nESC to exit" );
+ }
+ CDisableUndoScopeGuard guard;
+ m_hPreviewNode->DrawInEngine( m_bDroppingCommentaryNodes );
+ m_hPreviewTarget->DrawInEngine( !m_bDroppingCommentaryNodes );
+ return true; // trapping this key, stop processing
+ }
+
+ return false; // didn't trap, continue processing
+}
+
+
+//-----------------------------------------------------------------------------
+// Used to hook DME VMF entities into the render lists
+//-----------------------------------------------------------------------------
+void CCommEditTool::DrawCommentaryNodeEntitiesInEngine( bool bDrawInEngine )
+{
+ if ( !m_pDoc )
+ return;
+
+ CDmrCommentaryNodeEntityList entities = m_pDoc->GetEntityList();
+ if ( !entities.IsValid() )
+ return;
+
+ CDisableUndoScopeGuard guard;
+ int nCount = entities.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmeCommentaryNodeEntity *pEntity = entities[i];
+ Assert( pEntity );
+ if ( pEntity )
+ {
+ pEntity->DrawInEngine( bDrawInEngine );
+ }
+ }
+}
+
+void CCommEditTool::ClientLevelInitPostEntity()
+{
+ BaseClass::ClientLevelInitPostEntity();
+ DrawCommentaryNodeEntitiesInEngine( true );
+
+ AttachAllEngineEntities();
+}
+
+void CCommEditTool::ClientLevelShutdownPreEntity()
+{
+ DrawCommentaryNodeEntitiesInEngine( false );
+ BaseClass::ClientLevelShutdownPreEntity();
+}
+
+
+//-----------------------------------------------------------------------------
+// Derived classes can implement this to get a new scheme to be applied to this tool
+//-----------------------------------------------------------------------------
+vgui::HScheme CCommEditTool::GetToolScheme()
+{
+ return vgui::scheme()->LoadSchemeFromFile( "Resource/BoxRocket.res", "BoxRocket" );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// The View menu
+//
+//-----------------------------------------------------------------------------
+class CCommEditViewMenuButton : public CToolMenuButton
+{
+ DECLARE_CLASS_SIMPLE( CCommEditViewMenuButton, CToolMenuButton );
+public:
+ CCommEditViewMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget );
+ virtual void OnShowMenu(vgui::Menu *menu);
+
+private:
+ CCommEditTool *m_pTool;
+};
+
+CCommEditViewMenuButton::CCommEditViewMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget )
+ : BaseClass( parent, panelName, text, pActionSignalTarget )
+{
+ m_pTool = parent;
+
+ AddCheckableMenuItem( "properties", "#CommEditProperties", new KeyValues( "OnToggleProperties" ), pActionSignalTarget );
+ AddCheckableMenuItem( "commentarynodebrowser", "#CommEditEntityReport", new KeyValues( "OnToggleEntityReport" ), pActionSignalTarget );
+ AddCheckableMenuItem( "console", "#BxConsole", new KeyValues( "ToggleConsole" ), pActionSignalTarget );
+
+ AddSeparator();
+
+ AddMenuItem( "defaultlayout", "#CommEditViewDefault", new KeyValues( "OnDefaultLayout" ), pActionSignalTarget );
+
+ SetMenu(m_pMenu);
+}
+
+void CCommEditViewMenuButton::OnShowMenu(vgui::Menu *menu)
+{
+ BaseClass::OnShowMenu( menu );
+
+ // Update the menu
+ int id;
+
+ CCommEditDoc *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( "commentarynodebrowser" );
+ m_pMenu->SetItemEnabled( id, true );
+
+ p = m_pTool->GetCommentaryNodeBrowser();
+ Assert( p );
+ m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false );
+
+ id = m_Items.Find( "console" );
+ m_pMenu->SetItemEnabled( id, true );
+
+ CConsolePage *console = m_pTool->GetConsole();
+ m_pMenu->SetMenuItemChecked( id, console->GetParent() );
+ }
+ else
+ {
+ id = m_Items.Find( "properties" );
+ m_pMenu->SetItemEnabled( id, false );
+ id = m_Items.Find( "commentarynodebrowser" );
+ m_pMenu->SetItemEnabled( id, false );
+ id = m_Items.Find( "console" );
+ m_pMenu->SetItemEnabled( id, false );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// The Tool menu
+//
+//-----------------------------------------------------------------------------
+class CCommEditToolMenuButton : public CToolMenuButton
+{
+ DECLARE_CLASS_SIMPLE( CCommEditToolMenuButton, CToolMenuButton );
+public:
+ CCommEditToolMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget );
+ virtual void OnShowMenu(vgui::Menu *menu);
+
+private:
+ CCommEditTool *m_pTool;
+};
+
+CCommEditToolMenuButton::CCommEditToolMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget )
+ : BaseClass( parent, panelName, text, pActionSignalTarget )
+{
+ m_pTool = parent;
+
+ AddMenuItem( "addnewnodes", "#CommEditAddNewNodes", new KeyValues( "AddNewNodes" ), pActionSignalTarget, NULL, "CommEditAddNewNodes" );
+
+ SetMenu(m_pMenu);
+}
+
+void CCommEditToolMenuButton::OnShowMenu(vgui::Menu *menu)
+{
+ BaseClass::OnShowMenu( menu );
+
+ // Update the menu
+ int id;
+
+ CCommEditDoc *pDoc = m_pTool->GetDocument();
+ id = m_Items.Find( "addnewnodes" );
+ m_pMenu->SetItemEnabled( id, pDoc != NULL );
+}
+
+
+//-----------------------------------------------------------------------------
+// Initializes the menu bar
+//-----------------------------------------------------------------------------
+vgui::MenuBar *CCommEditTool::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() );
+ CCommEditToolMenuButton *pToolButton = new CCommEditToolMenuButton( this, "CommEdit", "&CommEdit", GetActionTarget() );
+ CCommEditViewMenuButton *pViewButton = new CCommEditViewMenuButton( this, "View", "&View", GetActionTarget() );
+ CToolMenuButton *pSwitchButton = CreateToolSwitchMenuButton( m_pMenuBar, "Switcher", "&Tools", GetActionTarget() );
+
+ 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 CCommEditTool::UpdateMenuBar( )
+{
+ if ( !m_pDoc )
+ {
+ m_pMenuBar->SetFileName( "#CommEditNoFile" );
+ return;
+ }
+
+ const char *pTXTFile = m_pDoc->GetTXTFileName();
+ if ( !pTXTFile[0] )
+ {
+ m_pMenuBar->SetFileName( "#CommEditNoFile" );
+ return;
+ }
+
+ if ( m_pDoc->IsDirty() )
+ {
+ char sz[ 512 ];
+ Q_snprintf( sz, sizeof( sz ), "* %s", pTXTFile );
+ m_pMenuBar->SetFileName( sz );
+ }
+ else
+ {
+ m_pMenuBar->SetFileName( pTXTFile );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets at tool windows
+//-----------------------------------------------------------------------------
+CCommentaryPropertiesPanel *CCommEditTool::GetProperties()
+{
+ return m_hProperties.Get();
+}
+
+CCommentaryNodeBrowserPanel *CCommEditTool::GetCommentaryNodeBrowser()
+{
+ return m_hCommentaryNodeBrowser.Get();
+}
+
+CConsolePage *CCommEditTool::GetConsole()
+{
+ return m_hConsole;
+}
+
+
+//-----------------------------------------------------------------------------
+// Shows element properties
+//-----------------------------------------------------------------------------
+void CCommEditTool::ShowElementProperties( )
+{
+ if ( !m_pDoc )
+ return;
+
+ // It should already exist
+ Assert( m_hProperties.Get() );
+ if ( m_hProperties.Get() )
+ {
+ m_hProperties->SetObject( m_hCurrentEntity );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Destroys all tool windows
+//-----------------------------------------------------------------------------
+void CCommEditTool::ShowEntityInEntityProperties( CDmeCommentaryNodeEntity *pEntity )
+{
+ Assert( m_hProperties.Get() );
+ m_hCurrentEntity = pEntity;
+ m_hProperties->SetObject( m_hCurrentEntity );
+}
+
+
+//-----------------------------------------------------------------------------
+// Destroys all tool windows
+//-----------------------------------------------------------------------------
+void CCommEditTool::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 CCommEditTool::OnDefaultLayout()
+{
+ int y = m_pMenuBar->GetTall();
+
+ int usew, useh;
+ GetSize( usew, useh );
+
+ DestroyToolContainers();
+
+ Assert( ToolWindow::GetToolWindowCount() == 0 );
+
+ CCommentaryPropertiesPanel *properties = GetProperties();
+ CCommentaryNodeBrowserPanel *pEntityReport = GetCommentaryNodeBrowser();
+ CConsolePage *pConsole = GetConsole();
+
+ // Need three containers
+ ToolWindow *pPropertyWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, properties, "#CommEditProperties", false );
+ ToolWindow *pEntityReportWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pEntityReport, "#CommEditEntityReport", false );
+
+ ToolWindow *pMiniViewport = dynamic_cast< ToolWindow* >( GetMiniViewport() );
+ pMiniViewport->AddPage( pConsole, "#BxConsole", false );
+
+ int halfScreen = usew / 2;
+ int bottom = useh - y;
+ int sy = (bottom - y) / 2;
+ SetMiniViewportBounds( halfScreen, y, halfScreen, sy - y );
+ pEntityReportWindow->SetBounds( 0, y, halfScreen, bottom - y );
+ pPropertyWindow->SetBounds( halfScreen, sy, halfScreen, bottom - sy );
+}
+
+void CCommEditTool::OnToggleProperties()
+{
+ if ( m_hProperties.Get() )
+ {
+ ToggleToolWindow( m_hProperties.Get(), "#CommEditProperties" );
+ }
+}
+
+void CCommEditTool::OnToggleEntityReport()
+{
+ if ( m_hCommentaryNodeBrowser.Get() )
+ {
+ ToggleToolWindow( m_hCommentaryNodeBrowser.Get(), "#CommEditEntityReport" );
+ }
+}
+
+void CCommEditTool::OnToggleConsole()
+{
+ if ( m_hConsole.Get() )
+ {
+ ToggleToolWindow( m_hConsole.Get(), "#BxConsole" );
+ }
+}
+
+void CCommEditTool::BringConsoleToFront()
+{
+ CConsolePage *p = GetConsole();
+ Panel *pPage = p ? p->GetParent() : NULL;
+ if ( pPage == NULL )
+ {
+ OnToggleConsole();
+ }
+ else
+ {
+ ToolWindow *tw = dynamic_cast< ToolWindow * >( pPage->GetParent() );
+ if ( tw )
+ {
+ if ( tw->GetActivePage() != p )
+ {
+ tw->SetActivePage( p );
+ vgui::surface()->SetForegroundWindow( tw->GetVPanel() );
+ p->TextEntryRequestFocus();
+ }
+ else
+ {
+ PropertySheet *pSheet = tw->GetPropertySheet();
+ int nPageCount = pSheet->GetNumPages();
+ int i;
+ for ( i = 0; i < nPageCount; ++i )
+ {
+ if ( p == pSheet->GetPage(i) )
+ break;
+ }
+ i = ( i + 1 ) % nPageCount;
+ pSheet->SetActivePage( pSheet->GetPage(i) );
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Creates
+//-----------------------------------------------------------------------------
+void CCommEditTool::CreateTools( CCommEditDoc *doc )
+{
+ if ( !m_hProperties.Get() )
+ {
+ m_hProperties = new CCommentaryPropertiesPanel( m_pDoc, this );
+ }
+
+ if ( !m_hCommentaryNodeBrowser.Get() )
+ {
+ m_hCommentaryNodeBrowser = new CCommentaryNodeBrowserPanel( m_pDoc, this, "CommentaryNodeBrowserPanel" );
+ }
+
+ if ( !m_hConsole.Get() )
+ {
+ m_hConsole = new CConsolePage( NULL, false );
+ }
+
+ RegisterToolWindow( m_hProperties );
+ RegisterToolWindow( m_hCommentaryNodeBrowser );
+ RegisterToolWindow( m_hConsole );
+}
+
+
+//-----------------------------------------------------------------------------
+// Initializes the tools
+//-----------------------------------------------------------------------------
+void CCommEditTool::InitTools()
+{
+ ShowElementProperties();
+
+ // FIXME: There are no tool windows here; how should this work?
+ // These panels are saved
+ windowposmgr->RegisterPanel( "properties", m_hProperties, false );
+ windowposmgr->RegisterPanel( "commentarynodebrowser", m_hCommentaryNodeBrowser, false );
+ windowposmgr->RegisterPanel( "Console", m_hConsole, false ); // No context menu
+
+ if ( !windowposmgr->LoadPositions( "cfg/commedit.txt", this, &m_ToolWindowFactory, "CommEdit" ) )
+ {
+ OnDefaultLayout();
+ }
+}
+
+
+void CCommEditTool::DestroyTools()
+{
+ m_hCurrentEntity = 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_hCommentaryNodeBrowser.Get() )
+ {
+ windowposmgr->UnregisterPanel( m_hCommentaryNodeBrowser.Get() );
+ delete m_hCommentaryNodeBrowser.Get();
+ m_hCommentaryNodeBrowser = NULL;
+ }
+
+ if ( m_hConsole.Get() )
+ {
+ windowposmgr->UnregisterPanel( m_hConsole.Get() );
+ delete m_hConsole.Get();
+ m_hConsole = NULL;
+ }
+}
+
+
+void CCommEditTool::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 CCommEditTool::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 *CCommEditTool::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 CCommEditTool::GetFileMenuItemsEnabled( )
+{
+ int nFlags = FILE_ALL;
+ if ( m_RecentFiles.IsEmpty() )
+ {
+ nFlags &= ~(FILE_RECENT | FILE_CLEAR_RECENT);
+ }
+ return nFlags;
+}
+
+void CCommEditTool::AddRecentFilesToMenu( vgui::Menu *pMenu )
+{
+ m_RecentFiles.AddToMenu( pMenu, GetActionTarget(), "OnRecent" );
+}
+
+bool CCommEditTool::GetPerforceFileName( char *pFileName, int nMaxLen )
+{
+ if ( !m_pDoc )
+ return false;
+
+ Q_strncpy( pFileName, m_pDoc->GetTXTFileName(), nMaxLen );
+ return pFileName[0] != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : -
+//-----------------------------------------------------------------------------
+void CCommEditTool::OnExit()
+{
+ windowposmgr->SavePositions( "cfg/commedit.txt", "CommEdit" );
+
+ enginetools->Command( "quit\n" );
+}
+
+//-----------------------------------------------------------------------------
+// Handle commands from the action menu and other menus
+//-----------------------------------------------------------------------------
+void CCommEditTool::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 *pSuffixTool = StringAfterPrefix( cmd, "OnTool" ) )
+ {
+ int idx = Q_atoi( pSuffixTool );
+ 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 CCommEditTool::OnNew()
+{
+ 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->GetTXTFileName();
+ }
+
+ // Bring up the file open dialog to choose a .bsp file
+ OpenFile( "bsp", pSaveFileName, "txt", nFlags );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the File->Open menu is selected
+//-----------------------------------------------------------------------------
+void CCommEditTool::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->GetTXTFileName();
+ }
+
+ OpenFile( "txt", pSaveFileName, "txt", nFlags );
+}
+
+bool CCommEditTool::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 CCommEditTool::Save()
+{
+ if ( m_pDoc )
+ {
+ SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS );
+ }
+}
+
+void CCommEditTool::OnSaveAs()
+{
+ if ( m_pDoc )
+ {
+ SaveFile( NULL, "txt", FOSM_SHOW_PERFORCE_DIALOGS );
+ }
+}
+
+void CCommEditTool::OnRestartLevel()
+{
+ enginetools->Command( "restart" );
+ enginetools->Execute();
+
+ CDmrCommentaryNodeEntityList entities = m_pDoc->GetEntityList();
+ int nCount = entities.IsValid() ? entities.Count() : 0;
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmeCommentaryNodeEntity *pEntity = entities[i];
+ Assert( pEntity );
+ pEntity->MarkDirty( false );
+ }
+}
+
+void CCommEditTool::SaveAndTest()
+{
+ if ( m_pDoc && m_pDoc->IsDirty() )
+ {
+ SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS,
+ new KeyValues( "RestartLevel" ) );
+ }
+ else
+ {
+ OnRestartLevel();
+ }
+}
+
+bool CCommEditTool::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ if ( !m_pDoc )
+ return false;
+
+ m_pDoc->SetTXTFileName( pFileName );
+ m_pDoc->SaveToFile( );
+
+ m_RecentFiles.Add( pFileName, pFileFormat );
+ m_RecentFiles.SaveToRegistry( GetRegistryName() );
+ UpdateMenuBar();
+ return true;
+}
+
+void CCommEditTool::OnClose()
+{
+ if ( m_pDoc && m_pDoc->IsDirty() )
+ {
+ SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY,
+ new KeyValues( "OnClose" ) );
+ return;
+ }
+
+ OnCloseNoSave();
+}
+
+void CCommEditTool::OnCloseNoSave()
+{
+ DestroyTools();
+
+ if ( m_pDoc )
+ {
+ CAppNotifyScopeGuard sg( "CCommEditTool::OnCloseNoSave", 0 );
+
+ delete m_pDoc;
+ m_pDoc = NULL;
+
+ if ( m_hProperties )
+ {
+ m_hProperties->SetObject( NULL );
+ }
+ }
+
+ UpdateMenuBar( );
+}
+
+void CCommEditTool::CenterView( CDmeCommentaryNodeEntity *pEntity )
+{
+ EntitySearchResult pPlayer = clienttools->GetLocalPlayer();
+
+ Vector vecOrigin = pEntity->GetRenderOrigin();
+ QAngle angles = pEntity->GetRenderAngles();
+
+ Vector vecForward, vecUp, vecRight;
+ AngleVectors( angles, &vecForward, &vecRight, &vecUp );
+ VectorMA( vecOrigin, 40.0f, vecForward, vecOrigin );
+ vecForward *= -1.0f;
+ VectorAngles( vecForward, vecUp, angles );
+
+ servertools->SnapPlayerToPosition( vecOrigin, angles, ( IClientEntity* )pPlayer );
+}
+
+
+void CCommEditTool::OnMarkNotDirty()
+{
+ if ( m_pDoc )
+ {
+ m_pDoc->SetDirty( false );
+ }
+}
+
+void CCommEditTool::AttachAllEngineEntities()
+{
+ if ( !clienttools || !m_pDoc )
+ return;
+
+ for ( EntitySearchResult sr = clienttools->FirstEntity(); sr != NULL; sr = clienttools->NextEntity( sr ) )
+ {
+ if ( !sr )
+ continue;
+
+ HTOOLHANDLE handle = clienttools->AttachToEntity( sr );
+
+ const char *pClassName = clienttools->GetClassname( handle );
+ if ( Q_strcmp( pClassName, "class C_PointCommentaryNode" ) == 0 )
+ {
+ Vector vecOrigin = clienttools->GetAbsOrigin( handle );
+ QAngle angAngles = clienttools->GetAbsAngles( handle );
+
+ // Find the associated commentary node entry in our doc
+ CDmeCommentaryNodeEntity *pNode = m_pDoc->GetCommentaryNodeForLocation( vecOrigin, angAngles );
+ if ( pNode )
+ {
+ pNode->AttachToEngineEntity( handle );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Show the save document query dialog
+//-----------------------------------------------------------------------------
+void CCommEditTool::OpenSpecificFile( const char *pFileName )
+{
+ int nFlags = 0;
+ const char *pSaveFileName = NULL;
+ if ( m_pDoc )
+ {
+ // File is already open
+ if ( !Q_stricmp( m_pDoc->GetTXTFileName(), pFileName ) )
+ return;
+
+ if ( m_pDoc->IsDirty() )
+ {
+ nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
+ pSaveFileName = m_pDoc->GetTXTFileName();
+ }
+ else
+ {
+ OnCloseNoSave();
+ }
+ }
+
+ OpenFile( pFileName, "txt", pSaveFileName, "txt", nFlags );
+}
+
+void CCommEditTool::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 CCommEditTool::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(), "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 CCommEditTool::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ char pStartingDir[ MAX_PATH ];
+
+ GetModSubdirectory( "maps", pStartingDir, sizeof(pStartingDir) );
+
+ if ( !Q_stricmp( pFileFormat, "bsp" ) )
+ {
+ // Open a bsp file to create a new commentary file
+ pDialog->SetTitle( "Choose BSP File", true );
+ pDialog->SetStartDirectoryContext( "commedit_bsp_session", pStartingDir );
+ pDialog->AddFilter( "*.bsp", "Valve BSP File (*.bsp)", true );
+ }
+ else
+ {
+ // Open existing commentary text files
+ pDialog->SetTitle( "Choose Valve Commentary File", true );
+ pDialog->SetStartDirectoryContext( "commedit_txt_session", pStartingDir );
+ pDialog->AddFilter( "*.txt", "Valve Commentary File (*.txt)", true );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Can we quit?
+//-----------------------------------------------------------------------------
+bool CCommEditTool::CanQuit()
+{
+ if ( m_pDoc && m_pDoc->IsDirty() )
+ {
+ // Show Save changes Yes/No/Cancel and re-quit if hit yes/no
+ SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY,
+ new KeyValues( "OnQuit" ) );
+ return false;
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Various command handlers related to the Edit menu
+//-----------------------------------------------------------------------------
+void CCommEditTool::OnUndo()
+{
+ CDisableUndoScopeGuard guard;
+ g_pDataModel->Undo();
+}
+
+void CCommEditTool::OnRedo()
+{
+ CDisableUndoScopeGuard guard;
+ g_pDataModel->Redo();
+}
+
+void CCommEditTool::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 );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// CommEdit menu items
+//-----------------------------------------------------------------------------
+void CCommEditTool::OnAddNewNodes()
+{
+ if ( !m_pDoc )
+ return;
+
+ EnterNodeDropMode();
+}
+
+
+//-----------------------------------------------------------------------------
+// Background
+//-----------------------------------------------------------------------------
+const char *CCommEditTool::GetLogoTextureName()
+{
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Inherited from ICommEditDocCallback
+//-----------------------------------------------------------------------------
+void CCommEditTool::OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
+{
+ if ( GetCommentaryNodeBrowser() )
+ {
+ GetCommentaryNodeBrowser()->UpdateEntityList();
+ }
+
+ UpdateMenuBar();
+
+ /*
+ if ( bRefreshUI && m_hProperties.Get() )
+ {
+ m_hProperties->Refresh();
+ }
+ */
+}
+
+
+//-----------------------------------------------------------------------------
+// Loads up a new document
+//-----------------------------------------------------------------------------
+bool CCommEditTool::LoadDocument( const char *pDocName )
+{
+ Assert( !m_pDoc );
+
+ DestroyTools();
+
+ m_pDoc = new CCommEditDoc( 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 );
+ InitTools();
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Create the entities that are in our TXT file
+//-----------------------------------------------------------------------------
+const char* CCommEditTool::GetEntityData( const char *pActualEntityData )
+{
+// if ( !m_pDoc )
+ return pActualEntityData;
+
+// return m_pDoc->GenerateEntityData( pActualEntityData );
+}
diff --git a/tools/commedit/commedittool.h b/tools/commedit/commedittool.h
new file mode 100644
index 0000000..7a5af7e
--- /dev/null
+++ b/tools/commedit/commedittool.h
@@ -0,0 +1,231 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: CommEdit tool; main UI smarts class
+//
+//=============================================================================
+
+#ifndef COMMEDITTOOL_H
+#define COMMEDITTOOL_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 "dmecommentarynodeentity.h"
+#include "toolframework/ienginetool.h"
+#include "toolutils/enginetools_int.h"
+#include "toolutils/savewindowpositions.h"
+#include "toolutils/toolwindowfactory.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class CDmElement;
+class CConsolePage;
+class CCommEditDoc;
+class CCommentaryPropertiesPanel;
+class CCommentaryNodeBrowserPanel;
+
+namespace vgui
+{
+ class Panel;
+}
+
+
+//-----------------------------------------------------------------------------
+// Allows the doc to call back into the CommEdit editor tool
+//-----------------------------------------------------------------------------
+abstract_class ICommEditDocCallback
+{
+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 ICommEditTool
+{
+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;
+
+ // Shows a particular entity in the entity properties dialog
+ virtual void ShowEntityInEntityProperties( CDmeCommentaryNodeEntity *pEntity ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Implementation of the CommEdit tool
+//-----------------------------------------------------------------------------
+class CCommEditTool : public CBaseToolSystem, public IFileMenuCallbacks, public ICommEditDocCallback, public ICommEditTool
+{
+ DECLARE_CLASS_SIMPLE( CCommEditTool, CBaseToolSystem );
+
+public:
+ CCommEditTool();
+
+ // Inherited from IToolSystem
+ virtual const char *GetToolName() { return "Commentary Editor"; }
+ virtual bool Init( );
+ virtual void Shutdown();
+ virtual bool CanQuit();
+ virtual void OnToolActivate();
+ virtual void OnToolDeactivate();
+ virtual const char* GetEntityData( const char *pActualEntityData );
+ virtual void DrawCommentaryNodeEntitiesInEngine( bool bDrawInEngine );
+ virtual void ClientLevelInitPostEntity();
+ virtual void ClientLevelShutdownPreEntity();
+ virtual bool TrapKey( ButtonCode_t key, bool down );
+ virtual void ClientPreRender();
+
+ // Inherited from IFileMenuCallbacks
+ virtual int GetFileMenuItemsEnabled( );
+ virtual void AddRecentFilesToMenu( vgui::Menu *menu );
+ virtual bool GetPerforceFileName( char *pFileName, int nMaxLen );
+
+ // Inherited from ICommEditDocCallback
+ virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags );
+ virtual vgui::Panel *GetRootPanel() { return this; }
+ virtual void ShowEntityInEntityProperties( CDmeCommentaryNodeEntity *pEntity );
+
+ // 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 "CommEditTool"; }
+ virtual const char *GetBindingsContextFile() { return "cfg/CommEdit.kb"; }
+ virtual vgui::MenuBar *CreateMenuBar( CBaseToolSystem *pParent );
+
+ MESSAGE_FUNC( Save, "OnSave" );
+ void SaveAndTest();
+ void CenterView( CDmeCommentaryNodeEntity* pEntity );
+
+ // Enter mode where we preview dropping nodes
+ void EnterNodeDropMode();
+ void LeaveNodeDropMode();
+
+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" );
+
+ // Commands related to the edit menu
+ void OnDescribeUndo();
+
+ // Methods related to the CommEdit menu
+ MESSAGE_FUNC( OnAddNewNodes, "AddNewNodes" );
+
+ // Methods related to the view menu
+ MESSAGE_FUNC( OnToggleProperties, "OnToggleProperties" );
+ MESSAGE_FUNC( OnToggleEntityReport, "OnToggleEntityReport" );
+ MESSAGE_FUNC( OnToggleConsole, "ToggleConsole" );
+
+ 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( CommEditAddNewNodes, KEY_A, vgui::MODIFIER_CONTROL, OnAddNewNodes, "#CommEditAddNewNodesHelp", 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 );
+
+ void AttachAllEngineEntities();
+
+ // returns the document
+ CCommEditDoc *GetDocument();
+
+ // Gets at tool windows
+ CCommentaryPropertiesPanel *GetProperties();
+ CCommentaryNodeBrowserPanel *GetCommentaryNodeBrowser();
+ CConsolePage *GetConsole();
+
+ CDmeHandle< CDmeCommentaryNodeEntity > GetCurrentEntity( void ) { return m_hCurrentEntity; }
+
+private:
+ // Loads up a new document
+ bool LoadDocument( const char *pDocName );
+
+ // Updates the menu bar based on the current file
+ void UpdateMenuBar( );
+
+ // Shows element properties
+ void ShowElementProperties( );
+
+ virtual const char *GetLogoTextureName();
+
+ // Creates, destroys tools
+ void CreateTools( CCommEditDoc *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();
+
+ // Gets the position of the preview object
+ void GetPlacementInfo( Vector &vecOrigin, QAngle &angles );
+
+ // Brings the console to front
+ void BringConsoleToFront();
+
+private:
+ // Document
+ CCommEditDoc *m_pDoc;
+
+ // The menu bar
+ CToolFileMenuBar *m_pMenuBar;
+
+ // Element properties for editing material
+ vgui::DHANDLE< CCommentaryPropertiesPanel > m_hProperties;
+
+ // The entity report
+ vgui::DHANDLE< CCommentaryNodeBrowserPanel > m_hCommentaryNodeBrowser;
+
+ // The console
+ vgui::DHANDLE< CConsolePage > m_hConsole;
+
+ // The currently viewed entity
+ CDmeHandle< CDmeCommentaryNodeEntity > m_hCurrentEntity;
+
+ // Separate undo context for the act busy tool
+ bool m_bInNodeDropMode;
+ bool m_bDroppingCommentaryNodes;
+ CDmeHandle< CDmeCommentaryNodeEntity > m_hPreviewNode;
+ CDmeHandle< CDmeCommentaryNodeEntity > m_hPreviewTarget;
+ CToolWindowFactory< ToolWindow > m_ToolWindowFactory;
+};
+
+extern CCommEditTool *g_pCommEditTool;
+
+#endif // COMMEDITTOOL_H
diff --git a/tools/commedit/commentarynodebrowserpanel.cpp b/tools/commedit/commentarynodebrowserpanel.cpp
new file mode 100644
index 0000000..aa76156
--- /dev/null
+++ b/tools/commedit/commentarynodebrowserpanel.cpp
@@ -0,0 +1,283 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Singleton dialog that generates and presents the entity report.
+//
+//===========================================================================//
+
+#include "CommentaryNodeBrowserPanel.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utlbuffer.h"
+#include "iregistry.h"
+#include "vgui/ivgui.h"
+#include "vgui_controls/listpanel.h"
+#include "vgui_controls/textentry.h"
+#include "vgui_controls/checkbutton.h"
+#include "vgui_controls/combobox.h"
+#include "vgui_controls/radiobutton.h"
+#include "vgui_controls/messagebox.h"
+#include "commeditdoc.h"
+#include "commedittool.h"
+#include "datamodel/dmelement.h"
+#include "vgui/keycode.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+
+
+//-----------------------------------------------------------------------------
+// Sort by target name
+//-----------------------------------------------------------------------------
+static int __cdecl TargetNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("targetname");
+ const char *string2 = item2.kv->GetString("targetname");
+ int nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ string1 = item1.kv->GetString("classname");
+ string2 = item2.kv->GetString("classname");
+ return Q_stricmp( string1, string2 );
+}
+
+//-----------------------------------------------------------------------------
+// Sort by class name
+//-----------------------------------------------------------------------------
+static int __cdecl ClassNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("classname");
+ const char *string2 = item2.kv->GetString("classname");
+ int nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ string1 = item1.kv->GetString("targetname");
+ string2 = item2.kv->GetString("targetname");
+ return Q_stricmp( string1, string2 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CCommentaryNodeBrowserPanel::CCommentaryNodeBrowserPanel( CCommEditDoc *pDoc, vgui::Panel* pParent, const char *pName )
+ : BaseClass( pParent, pName ), m_pDoc( pDoc )
+{
+ SetPaintBackgroundEnabled( true );
+
+ m_pEntities = new vgui::ListPanel( this, "Entities" );
+ m_pEntities->AddColumnHeader( 0, "targetname", "Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW );
+ m_pEntities->AddColumnHeader( 1, "classname", "Class Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW );
+ m_pEntities->SetColumnSortable( 0, true );
+ m_pEntities->SetColumnSortable( 1, true );
+ m_pEntities->SetEmptyListText( "No Entities" );
+ // m_pEntities->SetDragEnabled( true );
+ m_pEntities->AddActionSignalTarget( this );
+ m_pEntities->SetSortFunc( 0, TargetNameSortFunc );
+ m_pEntities->SetSortFunc( 1, ClassNameSortFunc );
+ m_pEntities->SetSortColumn( 0 );
+
+ LoadControlSettingsAndUserConfig( "resource/commentarynodebrowserpanel.res" );
+
+ UpdateEntityList();
+}
+
+CCommentaryNodeBrowserPanel::~CCommentaryNodeBrowserPanel()
+{
+ SaveUserConfig();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Shows the most recent selected object in properties window
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::OnProperties( )
+{
+ if ( m_pEntities->GetSelectedItemsCount() == 0 )
+ {
+ g_pCommEditTool->ShowEntityInEntityProperties( NULL );
+ return;
+ }
+
+ int iSel = m_pEntities->GetSelectedItem( 0 );
+ KeyValues *kv = m_pEntities->GetItem( iSel );
+ CDmeCommentaryNodeEntity *pEntity = CastElement< CDmeCommentaryNodeEntity >( (CDmElement *)kv->GetPtr( "entity" ) );
+ g_pCommEditTool->ShowEntityInEntityProperties( pEntity );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Deletes the marked objects.
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::OnDeleteEntities(void)
+{
+ int iSel = m_pEntities->GetSelectedItem( 0 );
+
+ {
+ // This is undoable
+ CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Entities", "Delete Entities" );
+
+ //
+ // Build a list of objects to delete.
+ //
+ int nCount = m_pEntities->GetSelectedItemsCount();
+ for (int i = 0; i < nCount; i++)
+ {
+ int nItemID = m_pEntities->GetSelectedItem(i);
+ KeyValues *kv = m_pEntities->GetItem( nItemID );
+ CDmElement *pEntity = (CDmElement *)kv->GetPtr( "entity" );
+ if ( pEntity )
+ {
+ m_pDoc->DeleteCommentaryNode( pEntity );
+ }
+ }
+ }
+
+ // Update the list box selection.
+ if (iSel >= m_pEntities->GetItemCount())
+ {
+ iSel = m_pEntities->GetItemCount() - 1;
+ }
+ m_pEntities->SetSingleSelectedItem( iSel );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ if ( code == KEY_DELETE )
+ {
+ OnDeleteEntities();
+ }
+ else
+ {
+ BaseClass::OnKeyCodeTyped( code );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::OnItemSelected( void )
+{
+ OnProperties();
+}
+
+
+//-----------------------------------------------------------------------------
+// Select a particular node
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::SelectNode( CDmeCommentaryNodeEntity *pNode )
+{
+ m_pEntities->ClearSelectedItems();
+ for ( int nItemID = m_pEntities->FirstItem(); nItemID != m_pEntities->InvalidItemID(); nItemID = m_pEntities->NextItem( nItemID ) )
+ {
+ KeyValues *kv = m_pEntities->GetItem( nItemID );
+ CDmElement *pEntity = (CDmElement *)kv->GetPtr( "entity" );
+ if ( pEntity == pNode )
+ {
+ m_pEntities->AddSelectedItem( nItemID );
+ break;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when buttons are clicked
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "delete" ) )
+ {
+ // Confirm we want to do it
+ MessageBox *pConfirm = new MessageBox( "#CommEditDeleteObjects", "#CommEditDeleteObjectsMsg", g_pCommEditTool->GetRootPanel() );
+ pConfirm->AddActionSignalTarget( this );
+ pConfirm->SetOKButtonText( "Yes" );
+ pConfirm->SetCommand( new KeyValues( "DeleteEntities" ) );
+ pConfirm->SetCancelButtonVisible( true );
+ pConfirm->SetCancelButtonText( "No" );
+ pConfirm->DoModal();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "Save" ) )
+ {
+ g_pCommEditTool->Save();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "CenterView" ) )
+ {
+ if ( m_pEntities->GetSelectedItemsCount() == 1 )
+ {
+ int iSel = m_pEntities->GetSelectedItem( 0 );
+ KeyValues *kv = m_pEntities->GetItem( iSel );
+ CDmeCommentaryNodeEntity *pEntity = CastElement< CDmeCommentaryNodeEntity >( (CDmElement *)kv->GetPtr( "entity" ) );
+ g_pCommEditTool->CenterView( pEntity );
+ }
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "SaveAndTest" ) )
+ {
+ g_pCommEditTool->SaveAndTest();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "DropNodes" ) )
+ {
+ g_pCommEditTool->EnterNodeDropMode();
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCommentaryNodeBrowserPanel::UpdateEntityList(void)
+{
+ m_pEntities->RemoveAll();
+
+ CDmrCommentaryNodeEntityList entityList( m_pDoc->GetEntityList() );
+ if ( !entityList.IsValid() )
+ return;
+
+ int nCount = entityList.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmElement *pEntity = entityList[i];
+ Assert( pEntity );
+ if ( !pEntity )
+ continue;
+
+ const char *pClassName = pEntity->GetValueString( "classname" );
+ if ( !pClassName || !pClassName[0] )
+ {
+ pClassName = "<no class>";
+ }
+
+ KeyValues *kv = new KeyValues( "node" );
+ kv->SetString( "classname", pClassName );
+ kv->SetPtr( "entity", pEntity );
+
+ const char *pTargetname = pEntity->GetValueString( "targetname" );
+ if ( !pTargetname || !pTargetname[0] )
+ {
+ pTargetname = "<no targetname>";
+ }
+ kv->SetString( "targetname", pTargetname );
+
+ m_pEntities->AddItem( kv, 0, false, false );
+ }
+ m_pEntities->SortList();
+}
+
diff --git a/tools/commedit/commentarynodebrowserpanel.h b/tools/commedit/commentarynodebrowserpanel.h
new file mode 100644
index 0000000..38a7de1
--- /dev/null
+++ b/tools/commedit/commentarynodebrowserpanel.h
@@ -0,0 +1,67 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef COMMENTARYNODEBROWSERPANEL_H
+#define COMMENTARYNODEBROWSERPANEL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vgui_controls/editablepanel.h"
+#include "tier1/utlstring.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class CCommEditDoc;
+class CDmeCommentaryNodeEntity;
+namespace vgui
+{
+ class ComboBox;
+ class Button;
+ class TextEntry;
+ class ListPanel;
+ class CheckButton;
+ class RadioButton;
+}
+
+
+//-----------------------------------------------------------------------------
+// Panel that shows all entities in the level
+//-----------------------------------------------------------------------------
+class CCommentaryNodeBrowserPanel : public vgui::EditablePanel
+{
+ DECLARE_CLASS_SIMPLE( CCommentaryNodeBrowserPanel, vgui::EditablePanel );
+
+public:
+ CCommentaryNodeBrowserPanel( CCommEditDoc *pDoc, vgui::Panel* pParent, const char *pName ); // standard constructor
+ virtual ~CCommentaryNodeBrowserPanel();
+
+// Inherited from Panel
+ virtual void OnCommand( const char *pCommand );
+ virtual void OnKeyCodeTyped( vgui::KeyCode code );
+
+ // Methods related to updating the listpanel
+ void UpdateEntityList();
+
+ // Select a particular node
+ void SelectNode( CDmeCommentaryNodeEntity *pNode );
+
+private:
+ // Messages handled
+ MESSAGE_FUNC( OnDeleteEntities, "DeleteEntities" );
+ MESSAGE_FUNC( OnItemSelected, "ItemSelected" );
+
+ // Shows the most recent selected object in properties window
+ void OnProperties();
+
+ CCommEditDoc *m_pDoc;
+ vgui::ListPanel *m_pEntities;
+};
+
+
+#endif // COMMENTARYNODEBROWSERPANEL_H
diff --git a/tools/commedit/commentarypropertiespanel.cpp b/tools/commedit/commentarypropertiespanel.cpp
new file mode 100644
index 0000000..e875bb0
--- /dev/null
+++ b/tools/commedit/commentarypropertiespanel.cpp
@@ -0,0 +1,458 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Singleton dialog that generates and presents the entity report.
+//
+//===========================================================================//
+
+#include "CommentaryPropertiesPanel.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utlbuffer.h"
+#include "iregistry.h"
+#include "vgui/ivgui.h"
+#include "vgui_controls/listpanel.h"
+#include "vgui_controls/textentry.h"
+#include "vgui_controls/checkbutton.h"
+#include "vgui_controls/combobox.h"
+#include "vgui_controls/radiobutton.h"
+#include "vgui_controls/messagebox.h"
+#include "vgui_controls/scrollbar.h"
+#include "vgui_controls/scrollableeditablepanel.h"
+#include "commeditdoc.h"
+#include "commedittool.h"
+#include "datamodel/dmelement.h"
+#include "dmecommentarynodeentity.h"
+#include "dme_controls/soundpicker.h"
+#include "dme_controls/soundrecordpanel.h"
+#include "matsys_controls/picker.h"
+#include "vgui_controls/fileopendialog.h"
+#include "filesystem.h"
+#include "tier2/fileutils.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CCommentaryPropertiesPanel::CCommentaryPropertiesPanel( CCommEditDoc *pDoc, vgui::Panel* pParent )
+ : BaseClass( pParent, "CommentaryPropertiesPanel" ), m_pDoc( pDoc )
+{
+ SetPaintBackgroundEnabled( true );
+ SetKeyBoardInputEnabled( true );
+
+ m_pCommentaryNode = new vgui::EditablePanel( (vgui::Panel*)NULL, "CommentaryNode" );
+
+ m_pNodeName = new vgui::TextEntry( m_pCommentaryNode, "CommentaryNodeName" );
+ m_pNodeName->AddActionSignalTarget( this );
+
+ m_pSoundFilePicker = new vgui::Button( m_pCommentaryNode, "AudioFilePickerButton", "", this, "PickSound" );
+
+ m_pSoundFileName = new vgui::TextEntry( m_pCommentaryNode, "AudioFileName" );
+ m_pSoundFileName->AddActionSignalTarget( this );
+
+ m_pRecordSound = new vgui::Button( m_pCommentaryNode, "RecordAudioButton", "", this, "Record" );
+
+ m_pSpeakerName = new vgui::TextEntry( m_pCommentaryNode, "Speaker" );
+ m_pSpeakerName->AddActionSignalTarget( this );
+
+ m_pSynopsis = new vgui::TextEntry( m_pCommentaryNode, "Synopsis" );
+ m_pSynopsis->AddActionSignalTarget( this );
+
+ m_pViewPositionPicker = new vgui::Button( m_pCommentaryNode, "ViewPositionPickerButton", "", this, "PickViewPosition" );
+ m_pViewTargetPicker = new vgui::Button( m_pCommentaryNode, "ViewTargetPickerButton", "", this, "PickViewTarget" );
+
+ m_pViewPosition = new vgui::TextEntry( m_pCommentaryNode, "ViewPosition" );
+ m_pViewPosition->AddActionSignalTarget( this );
+
+ m_pViewTarget = new vgui::TextEntry( m_pCommentaryNode, "ViewTarget" );
+ m_pViewTarget->AddActionSignalTarget( this );
+
+ m_pPreventMovement = new vgui::CheckButton( m_pCommentaryNode, "PreventMovement", "" );
+ m_pPreventMovement->SetCommand( "PreventMovementClicked" );
+ m_pPreventMovement->AddActionSignalTarget( this );
+
+ m_pStartCommands = new vgui::TextEntry( m_pCommentaryNode, "StartCommands" );
+ m_pStartCommands->AddActionSignalTarget( this );
+
+ m_pEndCommands = new vgui::TextEntry( m_pCommentaryNode, "EndCommands" );
+ m_pEndCommands->AddActionSignalTarget( this );
+
+ m_pPosition[0] = new vgui::TextEntry( m_pCommentaryNode, "PositionX" );
+ m_pPosition[0]->AddActionSignalTarget( this );
+ m_pPosition[1] = new vgui::TextEntry( m_pCommentaryNode, "PositionY" );
+ m_pPosition[1]->AddActionSignalTarget( this );
+ m_pPosition[2] = new vgui::TextEntry( m_pCommentaryNode, "PositionZ" );
+ m_pPosition[2]->AddActionSignalTarget( this );
+
+ m_pOrientation[0] = new vgui::TextEntry( m_pCommentaryNode, "Pitch" );
+ m_pOrientation[0]->AddActionSignalTarget( this );
+ m_pOrientation[1] = new vgui::TextEntry( m_pCommentaryNode, "Yaw" );
+ m_pOrientation[1]->AddActionSignalTarget( this );
+ m_pOrientation[2] = new vgui::TextEntry( m_pCommentaryNode, "Roll" );
+ m_pOrientation[2]->AddActionSignalTarget( this );
+
+ m_pCommentaryNode->LoadControlSettings( "resource/commentarypropertiessubpanel_node.res" );
+
+ m_pInfoTarget = new vgui::EditablePanel( (vgui::Panel*)NULL, "InfoTarget" );
+
+ m_pTargetName = new vgui::TextEntry( m_pInfoTarget, "TargetName" );
+ m_pTargetName->AddActionSignalTarget( this );
+
+ m_pTargetPosition[0] = new vgui::TextEntry( m_pInfoTarget, "PositionX" );
+ m_pTargetPosition[0]->AddActionSignalTarget( this );
+ m_pTargetPosition[1] = new vgui::TextEntry( m_pInfoTarget, "PositionY" );
+ m_pTargetPosition[1]->AddActionSignalTarget( this );
+ m_pTargetPosition[2] = new vgui::TextEntry( m_pInfoTarget, "PositionZ" );
+ m_pTargetPosition[2]->AddActionSignalTarget( this );
+
+ m_pTargetOrientation[0] = new vgui::TextEntry( m_pInfoTarget, "Pitch" );
+ m_pTargetOrientation[0]->AddActionSignalTarget( this );
+ m_pTargetOrientation[1] = new vgui::TextEntry( m_pInfoTarget, "Yaw" );
+ m_pTargetOrientation[1]->AddActionSignalTarget( this );
+ m_pTargetOrientation[2] = new vgui::TextEntry( m_pInfoTarget, "Roll" );
+ m_pTargetOrientation[2]->AddActionSignalTarget( this );
+
+ m_pInfoTarget->LoadControlSettings( "resource/commentarypropertiessubpanel_target.res" );
+
+ m_pCommentaryNodeScroll = new vgui::ScrollableEditablePanel( this, m_pCommentaryNode, "CommentaryNodeScroll" );
+ m_pInfoTargetScroll = new vgui::ScrollableEditablePanel( this, m_pInfoTarget, "InfoTargetScroll" );
+
+ LoadControlSettings( "resource/commentarypropertiespanel.res" );
+
+ m_pCommentaryNodeScroll->SetVisible( false );
+ m_pInfoTargetScroll->SetVisible( false );
+}
+
+
+//-----------------------------------------------------------------------------
+// Text to attribute...
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::TextEntryToAttribute( vgui::TextEntry *pEntry, const char *pAttributeName )
+{
+ int nLen = pEntry->GetTextLength();
+ char *pBuf = (char*)_alloca( nLen+1 );
+ pEntry->GetText( pBuf, nLen+1 );
+ m_hEntity->SetValue( pAttributeName, pBuf );
+}
+
+void CCommentaryPropertiesPanel::TextEntriesToVector( vgui::TextEntry *pEntry[3], const char *pAttributeName )
+{
+ Vector vec;
+ for ( int i = 0; i < 3; ++i )
+ {
+ int nLen = pEntry[i]->GetTextLength();
+ char *pBuf = (char*)_alloca( nLen+1 );
+ pEntry[i]->GetText( pBuf, nLen+1 );
+ vec[i] = atof( pBuf );
+ }
+ m_hEntity->SetValue( pAttributeName, vec );
+ clienttools->MarkClientRenderableDirty( m_hEntity );
+}
+
+
+//-----------------------------------------------------------------------------
+// Updates entity state when text fields change
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::UpdateCommentaryNode()
+{
+ if ( !m_hEntity.Get() )
+ return;
+
+ CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Commentary Node Change", "Commentary Node Change" );
+ TextEntryToAttribute( m_pNodeName, "targetname" );
+ TextEntryToAttribute( m_pStartCommands, "precommands" );
+ TextEntryToAttribute( m_pEndCommands, "postcommands" );
+ TextEntryToAttribute( m_pViewPosition, "viewposition" );
+ TextEntryToAttribute( m_pViewTarget, "viewtarget" );
+ TextEntryToAttribute( m_pSynopsis, "synopsis" );
+ TextEntryToAttribute( m_pSpeakerName, "speakers" );
+ TextEntryToAttribute( m_pSoundFileName, "commentaryfile" );
+ TextEntriesToVector( m_pPosition, "origin" );
+ TextEntriesToVector( m_pOrientation, "angles" );
+ m_hEntity->SetValue<int>( "prevent_movement", m_pPreventMovement->IsSelected() ? 1 : 0 );
+ m_hEntity->MarkDirty();
+}
+
+void CCommentaryPropertiesPanel::UpdateInfoTarget()
+{
+ if ( !m_hEntity.Get() )
+ return;
+
+ CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Info Target Change", "Info Target Change" );
+ TextEntryToAttribute( m_pTargetName, "targetname" );
+ TextEntriesToVector( m_pTargetPosition, "origin" );
+ TextEntriesToVector( m_pTargetOrientation, "angles" );
+ m_hEntity->MarkDirty();
+}
+
+
+//-----------------------------------------------------------------------------
+// Populates the commentary node fields
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::PopulateCommentaryNodeFields()
+{
+ if ( !m_hEntity.Get() )
+ return;
+
+ m_pNodeName->SetText( m_hEntity->GetTargetName() );
+ m_pStartCommands->SetText( m_hEntity->GetValueString( "precommands" ) );
+ m_pEndCommands->SetText( m_hEntity->GetValueString( "postcommands" ) );
+ m_pViewPosition->SetText( m_hEntity->GetValueString( "viewposition" ) );
+ m_pViewTarget->SetText( m_hEntity->GetValueString( "viewtarget" ) );
+ m_pSynopsis->SetText( m_hEntity->GetValueString( "synopsis" ) );
+ m_pSpeakerName->SetText( m_hEntity->GetValueString( "speakers" ) );
+ m_pSoundFileName->SetText( m_hEntity->GetValueString( "commentaryfile" ) );
+
+ Vector vecPosition = m_hEntity->GetRenderOrigin();
+ QAngle vecAngles = m_hEntity->GetRenderAngles();
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ char pTemp[512];
+ Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
+ m_pPosition[i]->SetText( pTemp );
+
+ Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
+ m_pOrientation[i]->SetText( pTemp );
+ }
+
+ m_pPreventMovement->SetSelected( m_hEntity->GetValue<int>( "prevent_movement" ) != 0 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Populates the info_target fields
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::PopulateInfoTargetFields()
+{
+ if ( !m_hEntity.Get() )
+ return;
+
+ m_pTargetName->SetText( m_hEntity->GetTargetName() );
+
+ Vector vecPosition = m_hEntity->GetRenderOrigin();
+ QAngle vecAngles = m_hEntity->GetRenderAngles();
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ char pTemp[512];
+ Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
+ m_pTargetPosition[i]->SetText( pTemp );
+
+ Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
+ m_pTargetOrientation[i]->SetText( pTemp );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the object to look at
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::SetObject( CDmeCommentaryNodeEntity *pEntity )
+{
+ m_hEntity = pEntity;
+ m_pCommentaryNodeScroll->SetVisible( false );
+ m_pInfoTargetScroll->SetVisible( false );
+
+ if ( pEntity )
+ {
+ if ( !Q_stricmp( pEntity->GetClassName(), "info_target" ) )
+ {
+ PopulateInfoTargetFields();
+ m_pInfoTargetScroll->SetVisible( true );
+ m_pTargetName->RequestFocus();
+ return;
+ }
+
+ if ( !Q_stricmp( pEntity->GetClassName(), "point_commentary_node" ) )
+ {
+ PopulateCommentaryNodeFields();
+ m_pCommentaryNodeScroll->SetVisible( true );
+ m_pNodeName->RequestFocus();
+ return;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when text is changed
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::OnTextChanged( KeyValues *pParams )
+{
+ vgui::Panel *pPanel = (vgui::Panel*)pParams->GetPtr( "panel" );
+ if ( pPanel->GetParent() == m_pCommentaryNode )
+ {
+ UpdateCommentaryNode();
+ return;
+ }
+
+ if ( pPanel->GetParent() == m_pInfoTarget )
+ {
+ UpdateInfoTarget();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the audio picker has picked something
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::OnSoundSelected( KeyValues *pParams )
+{
+ const char *pAssetName = pParams->GetString( "wav" );
+ m_pSoundFileName->SetText( pAssetName );
+ UpdateCommentaryNode();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the audio picker button is selected
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::PickSound()
+{
+ CSoundPickerFrame *pSoundPickerDialog = new CSoundPickerFrame( g_pCommEditTool->GetRootPanel(), "Select commentary audio file", CSoundPicker::PICK_WAVFILES );
+ pSoundPickerDialog->AddActionSignalTarget( this );
+ pSoundPickerDialog->DoModal( CSoundPicker::PICK_NONE, NULL );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the string picker has picked something
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::OnPicked( KeyValues *pParams )
+{
+ const char *pInfoTargetName = pParams->GetString( "choice" );
+ KeyValues *pContextKeyValues = pParams->FindKey( "context" );
+ vgui::TextEntry *pTextEntry = (vgui::TextEntry *)pContextKeyValues->GetPtr( "widget" );
+ pTextEntry->SetText( pInfoTargetName );
+ UpdateCommentaryNode();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the audio picker button is selected
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::PickInfoTarget( vgui::TextEntry *pControl )
+{
+ CDmrCommentaryNodeEntityList entities( m_pDoc->GetEntityList() );
+ int nCount = entities.Count();
+ PickerList_t vec( 0, nCount+1 );
+ int j = vec.AddToTail( );
+ vec[j].m_pChoiceString = "<no target>";
+ vec[j].m_pChoiceValue = "";
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmeCommentaryNodeEntity *pNode = entities[ i ];
+ const char *pTargetName = pNode->GetTargetName();
+ if ( !pTargetName || !pTargetName[0] )
+ continue;
+
+ if ( !Q_stricmp( pNode->GetClassName(), "info_target" ) )
+ {
+ j = vec.AddToTail( );
+ vec[j].m_pChoiceString = pTargetName;
+ vec[j].m_pChoiceValue = pTargetName;
+ }
+ }
+
+ CPickerFrame *pInfoTargetPickerDialog = new CPickerFrame( g_pCommEditTool->GetRootPanel(), "Select Target", "InfoTarget", NULL );
+ KeyValues *pContextKeyValues = new KeyValues( "context" );
+ pContextKeyValues->SetPtr( "widget", pControl );
+ pInfoTargetPickerDialog->AddActionSignalTarget( this );
+ pInfoTargetPickerDialog->DoModal( vec, pContextKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a sound is successfully recorded
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::OnSoundRecorded( KeyValues *pKeyValues )
+{
+ const char *pFileName = pKeyValues->GetString( "relativepath" );
+ m_pSoundFileName->SetText( pFileName );
+ UpdateCommentaryNode();
+}
+
+
+//-----------------------------------------------------------------------------
+// Used to open a particular file in perforce, and deal with all the lovely dialogs
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::OnFileSelected( KeyValues *pKeyValues )
+{
+ const char *pFileName = pKeyValues->GetString( "fullpath" );
+ if ( g_pFileSystem->FileExists( pFileName ) )
+ {
+ char pBuf[1024];
+ Q_snprintf( pBuf, sizeof(pBuf), "File %s already exists!\nRecording audio will not overwrite existing files.", pFileName );
+ vgui::MessageBox *pMessageBox = new vgui::MessageBox( "File already Exists!\n", pBuf, g_pCommEditTool );
+ pMessageBox->DoModal( );
+ return;
+ }
+
+ CSoundRecordPanel *pSoundRecordPanel = new CSoundRecordPanel( g_pCommEditTool->GetRootPanel(), "Record Commentary" );
+ pSoundRecordPanel->AddActionSignalTarget( this );
+ pSoundRecordPanel->DoModal( pFileName );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when sound recording is requested
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::RecordSound( )
+{
+ char pStartingDir[ MAX_PATH ];
+ GetModSubdirectory( "sound", pStartingDir, sizeof(pStartingDir) );
+
+ vgui::FileOpenDialog *pDialog = new vgui::FileOpenDialog( this, "Save As", false );
+ pDialog->SetTitle( "Enter New Audio File", true );
+ pDialog->SetStartDirectoryContext( "commedit_audio_record", pStartingDir );
+ pDialog->AddFilter( "*.wav", "Audio File (*.wav)", true );
+ pDialog->SetDeleteSelfOnClose( true );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when buttons are clicked
+//-----------------------------------------------------------------------------
+void CCommentaryPropertiesPanel::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "PickSound" ) )
+ {
+ PickSound();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "Record" ) )
+ {
+ RecordSound();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "PickViewPosition" ) )
+ {
+ PickInfoTarget( m_pViewPosition );
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "PickViewTarget" ) )
+ {
+ PickInfoTarget( m_pViewTarget );
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "PreventMovementClicked" ) )
+ {
+ UpdateCommentaryNode();
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
diff --git a/tools/commedit/commentarypropertiespanel.h b/tools/commedit/commentarypropertiespanel.h
new file mode 100644
index 0000000..35e27e5
--- /dev/null
+++ b/tools/commedit/commentarypropertiespanel.h
@@ -0,0 +1,113 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef COMMENTARYPROPERTIESPANEL_H
+#define COMMENTARYPROPERTIESPANEL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vgui_controls/editablepanel.h"
+#include "tier1/utlstring.h"
+#include "datamodel/dmehandle.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class CCommEditDoc;
+class CDmeCommentaryNodeEntity;
+
+namespace vgui
+{
+ class ComboBox;
+ class Button;
+ class TextEntry;
+ class ListPanel;
+ class CheckButton;
+ class RadioButton;
+}
+
+
+//-----------------------------------------------------------------------------
+// Panel that shows all entities in the level
+//-----------------------------------------------------------------------------
+class CCommentaryPropertiesPanel : public vgui::EditablePanel
+{
+ DECLARE_CLASS_SIMPLE( CCommentaryPropertiesPanel, vgui::EditablePanel );
+
+public:
+ CCommentaryPropertiesPanel( CCommEditDoc *pDoc, vgui::Panel* pParent ); // standard constructor
+
+ // Inherited from Panel
+ virtual void OnCommand( const char *pCommand );
+
+ // Sets the object to look at
+ void SetObject( CDmeCommentaryNodeEntity *pEntity );
+
+private:
+ // Populates the commentary node fields
+ void PopulateCommentaryNodeFields();
+
+ // Populates the info_target fields
+ void PopulateInfoTargetFields();
+
+ // Text to attribute...
+ void TextEntryToAttribute( vgui::TextEntry *pEntry, const char *pAttributeName );
+ void TextEntriesToVector( vgui::TextEntry *pEntry[3], const char *pAttributeName );
+
+ // Updates entity state when text fields change
+ void UpdateCommentaryNode();
+ void UpdateInfoTarget();
+
+ // Called when the audio picker button is selected
+ void PickSound();
+
+ // Called when sound recording is requested
+ void RecordSound( );
+
+ // Called when the audio picker button is selected
+ void PickInfoTarget( vgui::TextEntry *pControl );
+
+ // Messages handled
+ MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv );
+ MESSAGE_FUNC_PARAMS( OnSoundSelected, "SoundSelected", kv );
+ MESSAGE_FUNC_PARAMS( OnPicked, "Picked", kv );
+ MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", kv );
+ MESSAGE_FUNC_PARAMS( OnSoundRecorded, "SoundRecorded", kv );
+
+ CCommEditDoc *m_pDoc;
+
+ vgui::EditablePanel *m_pCommentaryNodeScroll;
+ vgui::EditablePanel *m_pInfoTargetScroll;
+ vgui::EditablePanel *m_pCommentaryNode;
+ vgui::EditablePanel *m_pInfoTarget;
+
+ vgui::TextEntry *m_pNodeName;
+ vgui::Button *m_pSoundFilePicker;
+ vgui::TextEntry *m_pSoundFileName;
+ vgui::Button *m_pRecordSound;
+ vgui::TextEntry *m_pSpeakerName;
+ vgui::TextEntry *m_pSynopsis;
+ vgui::TextEntry *m_pViewPosition;
+ vgui::Button *m_pViewPositionPicker;
+ vgui::TextEntry *m_pViewTarget;
+ vgui::Button *m_pViewTargetPicker;
+ vgui::TextEntry *m_pStartCommands;
+ vgui::TextEntry *m_pEndCommands;
+ vgui::CheckButton *m_pPreventMovement;
+ vgui::TextEntry *m_pPosition[3];
+ vgui::TextEntry *m_pOrientation[3];
+
+ vgui::TextEntry *m_pTargetName;
+ vgui::TextEntry *m_pTargetPosition[3];
+ vgui::TextEntry *m_pTargetOrientation[3];
+
+ CDmeHandle< CDmeCommentaryNodeEntity > m_hEntity;
+};
+
+
+#endif // COMMENTARYPROPERTIESPANEL_H
diff --git a/tools/commedit/dmecommentarynodeentity.cpp b/tools/commedit/dmecommentarynodeentity.cpp
new file mode 100644
index 0000000..06ae859
--- /dev/null
+++ b/tools/commedit/dmecommentarynodeentity.cpp
@@ -0,0 +1,339 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "dmecommentarynodeentity.h"
+#include "datamodel/dmelementfactoryhelper.h"
+#include "toolframework/itoolentity.h"
+#include "materialsystem/imesh.h"
+#include "materialsystem/imaterial.h"
+#include "materialsystem/imaterialsystem.h"
+#include "engine/iclientleafsystem.h"
+#include "toolutils/enginetools_int.h"
+#include "commedittool.h"
+#include "KeyValues.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+#define SPHERE_RADIUS 16
+
+//-----------------------------------------------------------------------------
+// Expose this class to the scene database
+//-----------------------------------------------------------------------------
+IMPLEMENT_ELEMENT_FACTORY( DmeCommentaryNodeEntity, CDmeCommentaryNodeEntity );
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::OnConstruction()
+{
+ m_ClassName.InitAndSet( this, "classname", false, FATTRIB_HAS_CALLBACK );
+ m_TargetName.Init( this, "targetname" );
+ m_bIsPlaceholder.InitAndSet( this, "_placeholder", false, FATTRIB_DONTSAVE );
+ m_vecLocalOrigin.Init( this, "origin" );
+ m_vecLocalAngles.Init( this, "angles" );
+
+ // Used to make sure these aren't saved if they aren't changed
+ m_TargetName.GetAttribute()->AddFlag( FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK );
+ m_vecLocalAngles.GetAttribute()->AddFlag( FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK );
+
+ m_bInfoTarget = false;
+ m_bIsDirty = false;
+ m_hEngineEntity = HTOOLHANDLE_INVALID;
+
+ KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetString( "$basetexture", "editor/info_target" );
+ pVMTKeyValues->SetInt( "$nocull", 1 );
+ pVMTKeyValues->SetInt( "$vertexcolor", 1 );
+ pVMTKeyValues->SetInt( "$vertexalpha", 1 );
+ pVMTKeyValues->SetInt( "$no_fullbright", 1 );
+ pVMTKeyValues->SetInt( "$translucent", 1 );
+ m_InfoTargetSprite.Init( "__commentary_info_target", pVMTKeyValues );
+
+ pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetInt( "$nocull", 1 );
+ pVMTKeyValues->SetString( "$color", "{255 0 0}" );
+ pVMTKeyValues->SetInt( "$vertexalpha", 1 );
+ pVMTKeyValues->SetInt( "$no_fullbright", 1 );
+ pVMTKeyValues->SetInt( "$additive", 1 );
+ m_SelectedInfoTarget.Init( "__selected_commentary_info_target", pVMTKeyValues );
+}
+
+void CDmeCommentaryNodeEntity::OnDestruction()
+{
+ // Unhook it from the engine
+ AttachToEngineEntity( HTOOLHANDLE_INVALID );
+ m_SelectedInfoTarget.Shutdown();
+ m_InfoTargetSprite.Shutdown();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called whem attributes change
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::OnAttributeChanged( CDmAttribute *pAttribute )
+{
+ BaseClass::OnAttributeChanged( pAttribute );
+
+ // Once these have changed, then save them out, and don't bother calling back
+ if ( pAttribute == m_TargetName.GetAttribute() ||
+ pAttribute == m_vecLocalAngles.GetAttribute() )
+ {
+ pAttribute->RemoveFlag( FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK );
+ return;
+ }
+
+ if ( pAttribute == m_ClassName.GetAttribute() )
+ {
+ m_bInfoTarget = !Q_strncmp( m_ClassName, "info_target", 11 );
+ if ( !Q_stricmp( m_ClassName, "point_commentary_node" ) )
+ {
+ SetModelName( "models/extras/info_speech.mdl" );
+ GetMDL()->m_flPlaybackRate = 0.0f;
+ }
+ else
+ {
+ SetModelName( NULL );
+ }
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the entity ID
+//-----------------------------------------------------------------------------
+int CDmeCommentaryNodeEntity::GetEntityId() const
+{
+ return atoi( GetName() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Mark the entity as being dirty
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::MarkDirty( bool bDirty )
+{
+ m_bIsDirty = bDirty;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is the renderable transparent?
+//-----------------------------------------------------------------------------
+bool CDmeCommentaryNodeEntity::IsTransparent( void )
+{
+ return m_bIsDirty || m_bInfoTarget || BaseClass::IsTransparent();
+}
+
+
+//-----------------------------------------------------------------------------
+// Entity Key iteration
+//-----------------------------------------------------------------------------
+bool CDmeCommentaryNodeEntity::IsEntityKey( CDmAttribute *pEntityKey )
+{
+ return pEntityKey->IsFlagSet( FATTRIB_USERDEFINED );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CDmAttribute *CDmeCommentaryNodeEntity::FirstEntityKey()
+{
+ for ( CDmAttribute *pAttribute = FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
+ {
+ if ( IsEntityKey( pAttribute ) )
+ return pAttribute;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CDmAttribute *CDmeCommentaryNodeEntity::NextEntityKey( CDmAttribute *pEntityKey )
+{
+ if ( !pEntityKey )
+ return NULL;
+
+ for ( CDmAttribute *pAttribute = pEntityKey->NextAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
+ {
+ if ( IsEntityKey( pAttribute ) )
+ return pAttribute;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Attach/detach from an engine entity with the same editor index
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::AttachToEngineEntity( HTOOLHANDLE hToolHandle )
+{
+ if ( m_hEngineEntity != HTOOLHANDLE_INVALID )
+ {
+ clienttools->SetEnabled( m_hEngineEntity, true );
+ }
+ m_hEngineEntity = hToolHandle;
+ if ( m_hEngineEntity != HTOOLHANDLE_INVALID )
+ {
+ clienttools->SetEnabled( m_hEngineEntity, false );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Position and bounds for the model
+//-----------------------------------------------------------------------------
+const Vector &CDmeCommentaryNodeEntity::GetRenderOrigin( void )
+{
+ return m_vecLocalOrigin;
+}
+
+const QAngle &CDmeCommentaryNodeEntity::GetRenderAngles( void )
+{
+ return *(QAngle*)(&m_vecLocalAngles.Get());
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws the helper for the entity
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::DrawSprite( IMaterial *pMaterial )
+{
+ float t = 0.5f * sin( Plat_FloatTime() * M_PI / 1.0f ) + 0.5f;
+
+ CMatRenderContextPtr pRenderContext( materials );
+ pRenderContext->Bind( pMaterial );
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+
+ CMeshBuilder meshBuilder;
+ meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 4, 4 );
+
+ unsigned char nBaseR = 255;
+ unsigned char nBaseG = 255;
+ unsigned char nBaseB = 255;
+ unsigned char nAlpha = m_bIsDirty ? (unsigned char)(255 * t) : 255;
+
+ meshBuilder.Position3f( -SPHERE_RADIUS, -SPHERE_RADIUS, 0.0f );
+ meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
+ meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Position3f( SPHERE_RADIUS, -SPHERE_RADIUS, 0.0f );
+ meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
+ meshBuilder.TexCoord2f( 0, 1.0f, 1.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Position3f( SPHERE_RADIUS, SPHERE_RADIUS, 0.0f );
+ meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
+ meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Position3f( -SPHERE_RADIUS, SPHERE_RADIUS, 0.0f );
+ meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
+ meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.FastIndex( 0 );
+ meshBuilder.FastIndex( 1 );
+ meshBuilder.FastIndex( 3 );
+ meshBuilder.FastIndex( 2 );
+
+ meshBuilder.End();
+ pMesh->Draw();
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws the helper for the entity
+//-----------------------------------------------------------------------------
+int CDmeCommentaryNodeEntity::DrawModel( int flags )
+{
+ bool bSelected = ( g_pCommEditTool->GetCurrentEntity().Get() == this );
+ if ( !m_bInfoTarget )
+ {
+ // If we have a visible engine entity, we don't need to draw it here
+ // info targets always draw though, because they have no visible model.
+ CDisableUndoScopeGuard guard;
+ float t = 0.5f * sin( Plat_FloatTime() * M_PI / 1.0f ) + 0.5f;
+ unsigned char nAlpha = m_bIsDirty ? (unsigned char)(255 * t) : 255;
+ if ( bSelected )
+ {
+ GetMDL()->m_Color.SetColor( 255, 64, 64, nAlpha );
+ }
+ else
+ {
+ GetMDL()->m_Color.SetColor( 255, 255, 255, nAlpha );
+ }
+ return BaseClass::DrawModel( flags );
+ }
+
+ Assert( IsDrawingInEngine() );
+
+ CMatRenderContextPtr pRenderContext( materials );
+ matrix3x4_t mat;
+ VMatrix worldToCamera, cameraToWorld;
+ pRenderContext->GetMatrix( MATERIAL_VIEW, &worldToCamera );
+ MatrixInverseTR( worldToCamera, cameraToWorld );
+ MatrixCopy( cameraToWorld.As3x4(), mat );
+ MatrixSetColumn( m_vecLocalOrigin, 3, mat );
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadMatrix( mat );
+
+ pRenderContext->FogMode( MATERIAL_FOG_NONE );
+ pRenderContext->SetNumBoneWeights( 0 );
+ pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
+
+ DrawSprite( m_InfoTargetSprite );
+ if ( bSelected )
+ {
+ DrawSprite( m_SelectedInfoTarget );
+ }
+
+ pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PopMatrix();
+
+ return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Position and bounds for the model
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::GetRenderBounds( Vector& mins, Vector& maxs )
+{
+ if ( !m_bInfoTarget )
+ {
+ BaseClass::GetRenderBounds( mins, maxs );
+ return;
+ }
+
+ mins.Init( -SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS );
+ maxs.Init( SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS );
+}
+
+
+//-----------------------------------------------------------------------------
+// Update renderable position
+//-----------------------------------------------------------------------------
+void CDmeCommentaryNodeEntity::SetRenderOrigin( const Vector &vecOrigin )
+{
+ m_vecLocalOrigin = vecOrigin;
+ clienttools->MarkClientRenderableDirty( this );
+}
+
+void CDmeCommentaryNodeEntity::SetRenderAngles( const QAngle &angles )
+{
+ m_vecLocalAngles = *(Vector*)&angles;
+ clienttools->MarkClientRenderableDirty( this );
+}
+
+
diff --git a/tools/commedit/dmecommentarynodeentity.h b/tools/commedit/dmecommentarynodeentity.h
new file mode 100644
index 0000000..00c7aac
--- /dev/null
+++ b/tools/commedit/dmecommentarynodeentity.h
@@ -0,0 +1,100 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Represents an entity in a VMF
+//
+//=============================================================================
+
+#ifndef DMEVMFENTITY_H
+#define DMEVMFENTITY_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "toolutils/dmemdlrenderable.h"
+#include "datamodel/dmelement.h"
+#include "toolframework/itoolentity.h"
+#include "materialsystem/MaterialSystemUtil.h"
+
+
+//-----------------------------------------------------------------------------
+// Represents an editable entity; draws its helpers
+//-----------------------------------------------------------------------------
+class CDmeCommentaryNodeEntity : public CDmeMdlRenderable<CDmElement>
+{
+ DEFINE_ELEMENT( CDmeCommentaryNodeEntity, CDmeMdlRenderable<CDmElement> );
+
+public:
+ // Inherited from CDmElement
+ virtual void OnAttributeChanged( CDmAttribute *pAttribute );
+
+public:
+ // Inherited from DmeRenderable
+ virtual const Vector &GetRenderOrigin( void );
+ virtual const QAngle &GetRenderAngles( void );
+ virtual int DrawModel( int flags );
+ virtual void GetRenderBounds( Vector& mins, Vector& maxs );
+ virtual bool IsTransparent( void );
+
+public:
+ int GetEntityId() const;
+
+ const char *GetClassName() const;
+ const char *GetTargetName() const;
+
+ bool IsPlaceholder() const;
+
+ // Entity Key iteration
+ CDmAttribute *FirstEntityKey();
+ CDmAttribute *NextEntityKey( CDmAttribute *pEntityKey );
+
+ // Attach/detach from an engine entity with the same editor index
+ void AttachToEngineEntity( HTOOLHANDLE hToolHandle );
+
+ void SetRenderOrigin( const Vector &vecOrigin );
+ void SetRenderAngles( const QAngle &angles );
+
+ void MarkDirty( bool bDirty = true );
+
+private:
+ bool IsEntityKey( CDmAttribute *pEntityKey );
+
+ // Draws the helper for the entity
+ void DrawSprite( IMaterial *pMaterial );
+
+ CDmaVar<Vector> m_vecLocalOrigin;
+ CDmaVar<Vector> m_vecLocalAngles;
+
+ CDmaString m_ClassName;
+ CDmaString m_TargetName;
+ CDmaVar<bool> m_bIsPlaceholder;
+
+ bool m_bInfoTarget;
+ bool m_bIsDirty;
+
+ // The entity it's connected to in the engine
+ HTOOLHANDLE m_hEngineEntity;
+
+ CMaterialReference m_SelectedInfoTarget;
+ CMaterialReference m_InfoTargetSprite;
+};
+
+
+//-----------------------------------------------------------------------------
+// Inline methods
+//-----------------------------------------------------------------------------
+inline const char *CDmeCommentaryNodeEntity::GetClassName() const
+{
+ return m_ClassName;
+}
+
+inline const char *CDmeCommentaryNodeEntity::GetTargetName() const
+{
+ return m_TargetName;
+}
+
+inline bool CDmeCommentaryNodeEntity::IsPlaceholder() const
+{
+ return m_bIsPlaceholder;
+}
+
+#endif // DMEVMFENTITY_H
diff --git a/tools/commedit/entityreportpanel.cpp b/tools/commedit/entityreportpanel.cpp
new file mode 100644
index 0000000..0ea1032
--- /dev/null
+++ b/tools/commedit/entityreportpanel.cpp
@@ -0,0 +1,581 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Singleton dialog that generates and presents the entity report.
+//
+//===========================================================================//
+
+#include "EntityReportPanel.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utlbuffer.h"
+#include "iregistry.h"
+#include "vgui/ivgui.h"
+#include "vgui_controls/listpanel.h"
+#include "vgui_controls/textentry.h"
+#include "vgui_controls/checkbutton.h"
+#include "vgui_controls/combobox.h"
+#include "vgui_controls/radiobutton.h"
+#include "vgui_controls/messagebox.h"
+#include "commeditdoc.h"
+#include "commedittool.h"
+#include "datamodel/dmelement.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+
+
+//-----------------------------------------------------------------------------
+// Sort by target name
+//-----------------------------------------------------------------------------
+static int __cdecl TargetNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("targetname");
+ const char *string2 = item2.kv->GetString("targetname");
+ int nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ string1 = item1.kv->GetString("classname");
+ string2 = item2.kv->GetString("classname");
+ return Q_stricmp( string1, string2 );
+}
+
+//-----------------------------------------------------------------------------
+// Sort by class name
+//-----------------------------------------------------------------------------
+static int __cdecl ClassNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("classname");
+ const char *string2 = item2.kv->GetString("classname");
+ int nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ string1 = item1.kv->GetString("targetname");
+ string2 = item2.kv->GetString("targetname");
+ return Q_stricmp( string1, string2 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CEntityReportPanel::CEntityReportPanel( CCommEditDoc *pDoc, vgui::Panel* pParent, const char *pName )
+ : BaseClass( pParent, pName ), m_pDoc( pDoc )
+{
+ m_bSuppressEntityListUpdate = false;
+ m_iFilterByType = FILTER_SHOW_EVERYTHING;
+ m_bFilterByKeyvalue = false;
+ m_bFilterByClass = false;
+ m_bFilterByHidden = false;
+ m_bFilterByKeyvalue = false;
+ m_bExact = false;
+ m_bFilterTextChanged = false;
+
+ SetPaintBackgroundEnabled( true );
+
+ m_pEntities = new vgui::ListPanel( this, "Entities" );
+ m_pEntities->AddColumnHeader( 0, "targetname", "Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW );
+ m_pEntities->AddColumnHeader( 1, "classname", "Class Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW );
+ m_pEntities->SetColumnSortable( 0, true );
+ m_pEntities->SetColumnSortable( 1, true );
+ m_pEntities->SetEmptyListText( "No Entities" );
+ // m_pEntities->SetDragEnabled( true );
+ m_pEntities->AddActionSignalTarget( this );
+ m_pEntities->SetSortFunc( 0, TargetNameSortFunc );
+ m_pEntities->SetSortFunc( 1, ClassNameSortFunc );
+ m_pEntities->SetSortColumn( 0 );
+
+ // Filtering checkboxes
+ m_pFilterByClass = new vgui::CheckButton( this, "ClassnameCheck", "" );
+ m_pFilterByClass->AddActionSignalTarget( this );
+ m_pFilterByKeyvalue = new vgui::CheckButton( this, "KeyvalueCheck", "" );
+ m_pFilterByKeyvalue->AddActionSignalTarget( this );
+ m_pFilterByHidden = new vgui::CheckButton( this, "HiddenCheck", "" );
+ m_pFilterByHidden->AddActionSignalTarget( this );
+ m_pExact = new vgui::CheckButton( this, "ExactCheck", "" );
+ m_pExact->AddActionSignalTarget( this );
+
+ // Filtering text entries
+ m_pFilterKey = new vgui::TextEntry( this, "KeyTextEntry" );
+ m_pFilterValue = new vgui::TextEntry( this, "ValueTextEntry" );
+
+ // Classname combobox
+ m_pFilterClass = new vgui::ComboBox( this, "ClassNameComboBox", 16, true );
+
+ // Filter by type radio buttons
+ m_pFilterEverything = new vgui::RadioButton( this, "EverythingRadio", "" );
+ m_pFilterPointEntities = new vgui::RadioButton( this, "PointRadio", "" );
+ m_pFilterBrushModels = new vgui::RadioButton( this, "BrushRadio", "" );
+
+ LoadControlSettings( "resource/entityreportpanel.res" );
+
+ ReadSettingsFromRegistry();
+
+ // Used for updating filter while changing text
+ ivgui()->AddTickSignal( GetVPanel(), 300 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Reads settings from registry
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::ReadSettingsFromRegistry()
+{
+ m_bSuppressEntityListUpdate = true;
+
+ const char *pKeyBase = g_pCommEditTool->GetRegistryName();
+ m_pFilterByKeyvalue->SetSelected( registry->ReadInt(pKeyBase, "FilterByKeyvalue", 0) );
+ m_pFilterByClass->SetSelected( registry->ReadInt(pKeyBase, "FilterByClass", 0) );
+ m_pFilterByHidden->SetSelected( registry->ReadInt(pKeyBase, "FilterByHidden", 1) );
+ m_pExact->SetSelected( registry->ReadInt(pKeyBase, "Exact", 0) );
+
+ m_iFilterByType = (FilterType_t)registry->ReadInt(pKeyBase, "FilterByType", FILTER_SHOW_EVERYTHING);
+ m_pFilterEverything->SetSelected( m_iFilterByType == FILTER_SHOW_EVERYTHING );
+ m_pFilterPointEntities->SetSelected( m_iFilterByType == FILTER_SHOW_POINT_ENTITIES );
+ m_pFilterBrushModels->SetSelected( m_iFilterByType == FILTER_SHOW_BRUSH_ENTITIES );
+
+ // Gotta call change functions manually since SetText doesn't post an action signal
+ const char *pValue = registry->ReadString( pKeyBase, "FilterClass", "" );
+ m_pFilterClass->SetText( pValue );
+ OnChangeFilterclass( pValue );
+
+ pValue = registry->ReadString( pKeyBase, "FilterKey", "" );
+ m_pFilterKey->SetText( pValue );
+ OnChangeFilterkey( pValue );
+
+ pValue = registry->ReadString( pKeyBase, "FilterValue", "" );
+ m_pFilterValue->SetText( pValue );
+ OnChangeFiltervalue( pValue );
+
+ m_bSuppressEntityListUpdate = false;
+ UpdateEntityList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Writes settings to registry
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::SaveSettingsToRegistry()
+{
+ const char *pKeyBase = g_pCommEditTool->GetRegistryName();
+ registry->WriteInt(pKeyBase, "FilterByKeyvalue", m_bFilterByKeyvalue);
+ registry->WriteInt(pKeyBase, "FilterByClass", m_bFilterByClass);
+ registry->WriteInt(pKeyBase, "FilterByHidden", m_bFilterByHidden);
+ registry->WriteInt(pKeyBase, "FilterByType", m_iFilterByType);
+ registry->WriteInt(pKeyBase, "Exact", m_bExact);
+
+ registry->WriteString(pKeyBase, "FilterClass", m_szFilterClass);
+ registry->WriteString(pKeyBase, "FilterKey", m_szFilterKey);
+ registry->WriteString(pKeyBase, "FilterValue", m_szFilterValue);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Shows the most recent selected object in properties window
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnProperties(void)
+{
+ int iSel = m_pEntities->GetSelectedItem( 0 );
+ KeyValues *kv = m_pEntities->GetItem( iSel );
+ CDmElement *pEntity = (CDmElement *)kv->GetPtr( "entity" );
+ g_pCommEditTool->ShowEntityInEntityProperties( pEntity );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Deletes the marked objects.
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnDeleteEntities(void)
+{
+ // This is undoable
+ CUndoScopeGuard guard( g_pDataModel, "Delete Entities", "Delete Entities" );
+
+ int iSel = m_pEntities->GetSelectedItem( 0 );
+
+ //
+ // Build a list of objects to delete.
+ //
+ int nCount = m_pEntities->GetSelectedItemsCount();
+ for (int i = 0; i < nCount; i++)
+ {
+ int nItemID = m_pEntities->GetSelectedItem(i);
+ KeyValues *kv = m_pEntities->GetItem( nItemID );
+ CDmElement *pEntity = (CDmElement *)kv->GetPtr( "entity" );
+ if ( pEntity )
+ {
+ m_pDoc->DeleteCommentaryNode( pEntity );
+ }
+ }
+
+ UpdateEntityList();
+
+ // Update the list box selection.
+ if (iSel >= m_pEntities->GetItemCount())
+ {
+ iSel = m_pEntities->GetItemCount() - 1;
+ }
+ m_pEntities->SetSingleSelectedItem( iSel );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when buttons are clicked
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "delete" ) )
+ {
+ // Confirm we want to do it
+ MessageBox *pConfirm = new MessageBox( "#CommEditDeleteObjects", "#CommEditDeleteObjectsMsg", g_pCommEditTool->GetRootPanel() );
+ pConfirm->AddActionSignalTarget( this );
+ pConfirm->SetOKButtonText( "Yes" );
+ pConfirm->SetCommand( new KeyValues( "DeleteEntities" ) );
+ pConfirm->SetCancelButtonVisible( true );
+ pConfirm->SetCancelButtonText( "No" );
+ pConfirm->DoModal();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "ShowProperties" ) )
+ {
+ OnProperties();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Call this when our settings are dirty
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::MarkDirty( bool bFilterDirty )
+{
+ float flTime = Plat_FloatTime();
+ m_bRegistrySettingsChanged = true;
+ m_flRegistryTime = flTime;
+ if ( bFilterDirty && !m_bFilterTextChanged )
+ {
+ m_bFilterTextChanged = true;
+ m_flFilterTime = flTime;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods related to filtering
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnFilterByHidden( bool bState )
+{
+ m_bFilterByHidden = bState;
+ UpdateEntityList();
+ MarkDirty( false );
+}
+
+void CEntityReportPanel::OnFilterByKeyvalue( bool bState )
+{
+ m_bFilterByKeyvalue = bState;
+ UpdateEntityList();
+ MarkDirty( false );
+
+ m_pFilterKey->SetEnabled( bState );
+ m_pFilterValue->SetEnabled( bState );
+ m_pExact->SetEnabled( bState );
+}
+
+void CEntityReportPanel::OnFilterKeyValueExact( bool bState )
+{
+ m_bExact = bState;
+ UpdateEntityList();
+ MarkDirty( false );
+}
+
+void CEntityReportPanel::OnFilterByType( FilterType_t type )
+{
+ m_iFilterByType = type;
+ UpdateEntityList();
+ MarkDirty( false );
+}
+
+void CEntityReportPanel::OnFilterByClass( bool bState )
+{
+ m_bFilterByClass = bState;
+ UpdateEntityList();
+ MarkDirty( false );
+
+ m_pFilterClass->SetEnabled( bState );
+}
+
+void CEntityReportPanel::OnChangeFilterkey( const char *pText )
+{
+ m_szFilterKey = pText;
+ MarkDirty( true );
+}
+
+void CEntityReportPanel::OnChangeFiltervalue( const char *pText )
+{
+ m_szFilterValue = pText;
+ MarkDirty( true );
+}
+
+void CEntityReportPanel::OnChangeFilterclass( const char *pText )
+{
+ m_szFilterClass = pText;
+ MarkDirty( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Deals with all check buttons
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnTextChanged( KeyValues *kv )
+{
+ TextEntry *pPanel = (TextEntry*)kv->GetPtr( "panel", NULL );
+
+ int nLength = pPanel->GetTextLength();
+ char *pBuf = (char*)_alloca( nLength + 1 );
+ pPanel->GetText( pBuf, nLength+1 );
+
+ if ( pPanel == m_pFilterClass )
+ {
+ OnChangeFilterclass( pBuf );
+ return;
+ }
+ if ( pPanel == m_pFilterKey )
+ {
+ OnChangeFilterkey( pBuf );
+ return;
+ }
+ if ( pPanel == m_pFilterValue )
+ {
+ OnChangeFiltervalue( pBuf );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Deals with all check buttons
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnButtonToggled( KeyValues *kv )
+{
+ Panel *pPanel = (Panel*)kv->GetPtr( "panel", NULL );
+ bool bState = kv->GetInt( "state", 0 ) != 0;
+
+ if ( pPanel == m_pFilterByClass )
+ {
+ OnFilterByClass( bState );
+ return;
+ }
+ if ( pPanel == m_pFilterByKeyvalue )
+ {
+ OnFilterByKeyvalue( bState );
+ return;
+ }
+ if ( pPanel == m_pFilterByHidden )
+ {
+ OnFilterByHidden( bState );
+ return;
+ }
+ if ( pPanel == m_pExact )
+ {
+ OnFilterKeyValueExact( bState );
+ return;
+ }
+ if ( pPanel == m_pFilterEverything )
+ {
+ OnFilterByType( FILTER_SHOW_EVERYTHING );
+ return;
+ }
+ if ( pPanel == m_pFilterPointEntities )
+ {
+ OnFilterByType( FILTER_SHOW_POINT_ENTITIES );
+ return;
+ }
+ if ( pPanel == m_pFilterBrushModels )
+ {
+ OnFilterByType( FILTER_SHOW_BRUSH_ENTITIES );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// FIXME: Necessary because SetSelected doesn't cause a ButtonToggled message to trigger
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnCheckButtonChecked( KeyValues *kv )
+{
+ OnButtonToggled( kv );
+}
+
+void CEntityReportPanel::OnRadioButtonChecked( KeyValues *kv )
+{
+ OnButtonToggled( kv );
+}
+
+
+#if 0
+
+//-----------------------------------------------------------------------------
+// Purpose: Centers the 2D and 3D views on the selected entities.
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnGoto()
+{
+ MarkSelectedEntities();
+ m_pDoc->CenterViewsOnSelection();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::MarkSelectedEntities()
+{
+ m_pDoc->SelectObject(NULL, CMapDoc::scClear);
+
+ for(int i = 0; i < m_cEntities.GetCount(); i++)
+ {
+ if(!m_cEntities.GetSel(i))
+ continue;
+ CMapEntity *pEntity = (CMapEntity*) m_cEntities.GetItemDataPtr(i);
+ m_pDoc->SelectObject(pEntity, CMapDoc::scSelect);
+ }
+
+ m_pDoc->SelectObject(NULL, CMapDoc::scUpdateDisplay);
+}
+
+#endif
+
+void CEntityReportPanel::OnTick( )
+{
+ BaseClass::OnTick();
+
+ // check filters
+ float flTime = Plat_FloatTime();
+ if ( m_bFilterTextChanged )
+ {
+ if ( (flTime - m_flFilterTime) > 1e-3 )
+ {
+ m_bFilterTextChanged = false;
+ m_flFilterTime = flTime;
+ UpdateEntityList();
+ }
+ }
+ if ( m_bRegistrySettingsChanged )
+ {
+ if ( (flTime - m_flRegistryTime) > 1e-3 )
+ {
+ m_bRegistrySettingsChanged = false;
+ m_flRegistryTime = flTime;
+ SaveSettingsToRegistry();
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::UpdateEntityList(void)
+{
+ if ( m_bSuppressEntityListUpdate )
+ return;
+
+ m_bFilterTextChanged = false;
+
+ m_pEntities->RemoveAll();
+
+ CDmAttribute *pEntityList = m_pDoc->GetEntityList();
+ int nCount = pEntityList->Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmElement *pEntity = GetElement< CDmElement >( pEntityList->Get(i) );
+
+ const char *pClassName = pEntity->GetAttributeValueString( "classname" );
+ if ( !pClassName || !pClassName[0] )
+ {
+ pClassName = "<no class>";
+ }
+
+ KeyValues *kv = new KeyValues( "node" );
+ kv->SetString( "classname", pClassName );
+ kv->SetPtr( "entity", pEntity );
+
+ m_pEntities->AddItem( kv, 0, false, false );
+ }
+ m_pEntities->SortList();
+}
+
+
+#if 0
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::GenerateReport()
+{
+ POSITION p = pGD->Classes.GetHeadPosition();
+ CString str;
+ while(p)
+ {
+ GDclass *pc = pGD->Classes.GetNext(p);
+ if(!pc->IsBaseClass())
+ {
+ str = pc->GetName();
+ if(str != "worldspawn")
+ m_cFilterClass.AddString(str);
+ }
+ }
+
+ SetTimer(1, 500, NULL);
+
+ OnFilterbykeyvalue();
+ OnFilterbytype();
+ OnFilterbyclass();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnSelChangeEntityList()
+{
+ MarkSelectedEntities();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnDblClkEntityList()
+{
+ m_pDoc->CenterViewsOnSelection();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnOK()
+{
+ DestroyWindow();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnClose()
+{
+ DestroyWindow();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when our window is being destroyed.
+//-----------------------------------------------------------------------------
+void CEntityReportPanel::OnDestroy()
+{
+ SaveToIni();
+ s_pDlg = NULL;
+ delete this;
+}
+#endif \ No newline at end of file