summaryrefslogtreecommitdiff
path: root/vgui2/dme_controls/dmepresetgroupeditorpanel.cpp
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 /vgui2/dme_controls/dmepresetgroupeditorpanel.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'vgui2/dme_controls/dmepresetgroupeditorpanel.cpp')
-rw-r--r--vgui2/dme_controls/dmepresetgroupeditorpanel.cpp2332
1 files changed, 2332 insertions, 0 deletions
diff --git a/vgui2/dme_controls/dmepresetgroupeditorpanel.cpp b/vgui2/dme_controls/dmepresetgroupeditorpanel.cpp
new file mode 100644
index 0000000..a2e9f34
--- /dev/null
+++ b/vgui2/dme_controls/dmepresetgroupeditorpanel.cpp
@@ -0,0 +1,2332 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "dme_controls/dmepresetgroupeditorpanel.h"
+#include "dme_controls/dmecontrols_utils.h"
+#include "movieobjects/dmeanimationset.h"
+#include "vgui_controls/ListPanel.h"
+#include "vgui_controls/PropertySheet.h"
+#include "vgui_controls/PropertyPage.h"
+#include "vgui_controls/Button.h"
+#include "vgui_controls/Menu.h"
+#include "vgui_controls/Splitter.h"
+#include "vgui_controls/MessageBox.h"
+#include "vgui_controls/ComboBox.h"
+#include "vgui_controls/InputDialog.h"
+#include "vgui_controls/TextEntry.h"
+#include "vgui/MouseCode.h"
+#include "vgui/IInput.h"
+#include "vgui/ISurface.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utldict.h"
+#include "dme_controls/presetpicker.h"
+#include "vgui_controls/FileOpenDialog.h"
+#include "tier2/fileutils.h"
+#include "tier1/utlbuffer.h"
+#include "dme_controls/inotifyui.h"
+#include "../game/shared/iscenetokenprocessor.h"
+#include "movieobjects/dmx_to_vcd.h"
+#include "studio.h"
+#include "phonemeconverter.h"
+
+// Forward declaration
+class CDmePresetGroupEditorPanel;
+
+
+//-----------------------------------------------------------------------------
+// Utility scope guards
+//-----------------------------------------------------------------------------
+DEFINE_SOURCE_UNDO_SCOPE_GUARD( PresetGroup, NOTIFY_SOURCE_PRESET_GROUP_EDITOR );
+DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( PresetGroup, NOTIFY_SOURCE_PRESET_GROUP_EDITOR );
+
+#define PRESET_FILE_FORMAT "preset"
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+// CDmePresetRemapPanel
+//
+// Implementation below because of scoping issues
+//
+//-----------------------------------------------------------------------------
+class CDmePresetRemapPanel : public vgui::Frame
+{
+ DECLARE_CLASS_SIMPLE( CDmePresetRemapPanel, vgui::Frame );
+
+public:
+ CDmePresetRemapPanel( vgui::Panel *pParent, const char *pTitle );
+ ~CDmePresetRemapPanel();
+
+ // Shows the modal dialog
+ void DoModal( CDmeAnimationSet *pAnimationSet, CDmePresetGroup *pDestGroup );
+
+ // Inherited from Frame
+ virtual void OnCommand( const char *pCommand );
+
+ virtual void OnKeyCodeTyped( KeyCode code );
+
+private:
+ MESSAGE_FUNC( OnTextChanged, "TextChanged" );
+ MESSAGE_FUNC( OnSelectPreset, "SelectPreset" );
+ MESSAGE_FUNC( OnRemovePreset, "RemovePreset" );
+ MESSAGE_FUNC_PARAMS( OnPresetPicked, "PresetPicked", params );
+ MESSAGE_FUNC_PARAMS( OnOpenContextMenu, "OpenContextMenu", kv );
+
+ // Refreshes the list of presets
+ void RefreshPresetList( );
+
+ // Applies changes to the preset remap
+ void ApplyChangesToPresetRemap();
+
+ // Cleans up the context menu
+ void CleanupContextMenu();
+
+ vgui::ListPanel *m_pPresetRemapList;
+ vgui::ComboBox *m_pSourcePresetGroup;
+ CDmeHandle< CDmePresetGroup > m_hSourceGroup;
+ CDmeHandle< CDmePresetGroup > m_hDestGroup;
+ vgui::DHANDLE< vgui::Menu > m_hContextMenu;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+static int __cdecl DestPresetNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString( "dest" );
+ const char *string2 = item2.kv->GetString( "dest" );
+ return Q_stricmp( string1, string2 );
+}
+
+static int __cdecl SrcPresetNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString( "src" );
+ const char *string2 = item2.kv->GetString( "src" );
+ return Q_stricmp( string1, string2 );
+}
+
+CDmePresetRemapPanel::CDmePresetRemapPanel( vgui::Panel *pParent, const char *pTitle ) :
+ BaseClass( pParent, "DmePresetRemapPanel" )
+{
+ m_pSourcePresetGroup = new vgui::ComboBox( this, "SourcePresetGroup", 8, true );
+ SetDeleteSelfOnClose( true );
+
+ m_pPresetRemapList = new vgui::ListPanel( this, "PresetRemapList" );
+ m_pPresetRemapList->AddColumnHeader( 0, "dest", "Dest Preset", 100, 0 );
+ m_pPresetRemapList->AddColumnHeader( 1, "src", "Source Preset", 100, 0 );
+ m_pPresetRemapList->SetSelectIndividualCells( false );
+ m_pPresetRemapList->SetMultiselectEnabled( true );
+ m_pPresetRemapList->SetEmptyListText( "No presets" );
+ m_pPresetRemapList->AddActionSignalTarget( this );
+ m_pPresetRemapList->SetSortFunc( 0, DestPresetNameSortFunc );
+ m_pPresetRemapList->SetSortFunc( 1, SrcPresetNameSortFunc );
+ m_pPresetRemapList->SetSortColumn( 0 );
+
+ SetBlockDragChaining( true );
+
+ LoadControlSettingsAndUserConfig( "resource/presetremappanel.res" );
+
+ SetTitle( pTitle, false );
+}
+
+CDmePresetRemapPanel::~CDmePresetRemapPanel()
+{
+ CleanupContextMenu();
+}
+
+
+//-----------------------------------------------------------------------------
+// Cleans up the context menu
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::CleanupContextMenu()
+{
+ if ( m_hContextMenu.Get() )
+ {
+ m_hContextMenu->MarkForDeletion();
+ m_hContextMenu = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Refreshes the list of presets
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::RefreshPresetList( )
+{
+ m_pPresetRemapList->RemoveAll();
+
+ CDmaElementArray< CDmePreset > *pPresetList = m_hDestGroup.Get() ? &m_hDestGroup->GetPresets() : NULL;
+ if ( !pPresetList )
+ return;
+
+ int nCount = pPresetList->Count();
+ if ( nCount == 0 )
+ return;
+
+ CDmePresetRemap *pRemap = m_hDestGroup->GetPresetRemap();
+ bool bUseRemap = ( pRemap && m_hSourceGroup.Get() && !Q_stricmp( pRemap->m_SourcePresetGroup, m_hSourceGroup->GetName() ) );
+
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmePreset *pPreset = pPresetList->Get(i);
+
+ const char *pName = pPreset->GetName();
+ if ( !pName || !pName[0] )
+ {
+ pName = "<no name>";
+ }
+
+ KeyValues *kv = new KeyValues( "node" );
+ kv->SetString( "dest", pName );
+ SetElementKeyValue( kv, "destPreset", pPreset );
+ if ( bUseRemap )
+ {
+ const char *pSource = pRemap->FindSourcePreset( pName );
+ CDmePreset *pSrcPreset = pSource ? m_hSourceGroup->FindPreset( pSource ) : NULL;
+ kv->SetString( "src", pSrcPreset ? pSrcPreset->GetName() : "" );
+ SetElementKeyValue( kv, "srcPreset", pSrcPreset );
+ }
+ else
+ {
+ kv->SetString( "src", "" );
+ SetElementKeyValue( kv, "srcPreset", NULL );
+ }
+
+ m_pPresetRemapList->AddItem( kv, 0, false, false );
+ }
+ m_pPresetRemapList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the preset picker when a preset is picked
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::OnPresetPicked( KeyValues *pParams )
+{
+ int nSelectedItemCount = m_pPresetRemapList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ CDmePreset *pPreset = GetElementKeyValue< CDmePreset >( pParams, "preset" );
+ int nItemID = m_pPresetRemapList->GetSelectedItem( 0 );
+ KeyValues *kv = m_pPresetRemapList->GetItem( nItemID );
+ kv->SetString( "src", pPreset ? pPreset->GetName() : "" );
+ SetElementKeyValue( kv, "srcPreset", pPreset );
+ m_pPresetRemapList->ApplyItemChanges( nItemID );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when double-clicking on a list entry
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::OnKeyCodeTyped( KeyCode code )
+{
+ if ( code == KEY_ENTER )
+ {
+ OnSelectPreset();
+ return;
+ }
+
+ if ( code == KEY_DELETE || code == KEY_BACKSPACE )
+ {
+ OnRemovePreset();
+ return;
+ }
+
+ BaseClass::OnKeyCodeTyped( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the context menu
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::OnSelectPreset()
+{
+ int nSelectedItemCount = m_pPresetRemapList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ CPresetPickerFrame *pPresetPicker = new CPresetPickerFrame( this, "Select Source Preset", false );
+ pPresetPicker->AddActionSignalTarget( this );
+ pPresetPicker->DoModal( m_hSourceGroup, false, NULL );
+}
+
+void CDmePresetRemapPanel::OnRemovePreset()
+{
+ int nSelectedItemCount = m_pPresetRemapList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ int nItemID = m_pPresetRemapList->GetSelectedItem( 0 );
+ KeyValues *kv = m_pPresetRemapList->GetItem( nItemID );
+ kv->SetString( "src", "" );
+ SetElementKeyValue( kv, "srcPreset", NULL );
+ m_pPresetRemapList->ApplyItemChanges( nItemID );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::OnOpenContextMenu( KeyValues *kv )
+{
+ CleanupContextMenu();
+
+ int nSelectedItemCount = m_pPresetRemapList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
+ m_hContextMenu->AddMenuItem( "#DmePresetRemapPanel_SelectPreset", new KeyValues( "SelectPreset" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetRemapPanel_RemovePreset", new KeyValues( "RemovePreset" ), this );
+
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the dest combo list changes
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::OnTextChanged()
+{
+ KeyValues *pCurrentGroup = m_pSourcePresetGroup->GetActiveItemUserData();
+ m_hSourceGroup = pCurrentGroup ? GetElementKeyValue<CDmePresetGroup>( pCurrentGroup, "presetGroup" ) : NULL;
+ RefreshPresetList();
+}
+
+
+void CDmePresetRemapPanel::DoModal( CDmeAnimationSet *pAnimationSet, CDmePresetGroup *pDestGroup )
+{
+ m_hDestGroup = pDestGroup;
+
+ m_pSourcePresetGroup->DeleteAllItems();
+
+ bool bSelected = false;
+
+ CDmePresetRemap* pRemap = m_hDestGroup->GetPresetRemap();
+
+ // Populate the combo box with preset group names
+ const CDmaElementArray< CDmePresetGroup > &presetGroupList = pAnimationSet->GetPresetGroups();
+ int nCount = presetGroupList.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmePresetGroup *pPresetGroup = presetGroupList[i];
+ if ( pPresetGroup == m_hDestGroup.Get() )
+ continue;
+
+ KeyValues *kv = new KeyValues( "entry" );
+ SetElementKeyValue( kv, "presetGroup", pPresetGroup );
+ int nItemID = m_pSourcePresetGroup->AddItem( pPresetGroup->GetName(), kv );
+ if ( !bSelected || ( pRemap && !Q_stricmp( pRemap->m_SourcePresetGroup, pPresetGroup->GetName() ) ) )
+ {
+ m_pSourcePresetGroup->ActivateItem( nItemID );
+ bSelected = true;
+ }
+ }
+
+ BaseClass::DoModal( );
+
+ m_pSourcePresetGroup->RequestFocus();
+}
+
+
+//-----------------------------------------------------------------------------
+// Applies changes to the preset remap
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::ApplyChangesToPresetRemap()
+{
+ int nTextLength = m_pSourcePresetGroup->GetTextLength() + 1;
+ char* pSourceName = (char*)_alloca( nTextLength * sizeof(char) );
+ m_pSourcePresetGroup->GetText( pSourceName, nTextLength );
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Change Preset Remap" );
+ CDmePresetRemap *pPresetRemap = m_hDestGroup->GetOrAddPresetRemap();
+ pPresetRemap->m_SourcePresetGroup = pSourceName;
+ pPresetRemap->RemoveAll();
+ for ( int nItemID = m_pPresetRemapList->FirstItem();
+ nItemID != m_pPresetRemapList->InvalidItemID();
+ nItemID = m_pPresetRemapList->NextItem( nItemID ) )
+ {
+ KeyValues* pKeyValues = m_pPresetRemapList->GetItem( nItemID );
+ CDmePreset *pSrcPreset = GetElementKeyValue< CDmePreset >( pKeyValues, "srcPreset" );
+ CDmePreset *pDestPreset = GetElementKeyValue< CDmePreset >( pKeyValues, "destPreset" );
+ if ( pSrcPreset && pDestPreset )
+ {
+ pPresetRemap->AddRemap( pSrcPreset->GetName(), pDestPreset->GetName() );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// command handler
+//-----------------------------------------------------------------------------
+void CDmePresetRemapPanel::OnCommand( const char *command )
+{
+ if ( !Q_stricmp( command, "Ok") )
+ {
+ ApplyChangesToPresetRemap();
+ CloseModal();
+ return;
+ }
+
+ if ( !Q_stricmp( command, "Cancel") )
+ {
+ CloseModal();
+ return;
+ }
+
+ BaseClass::OnCommand( command );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// CDmePresetGroupListPanel
+//
+// Implementation below because of scoping issues
+//
+//-----------------------------------------------------------------------------
+class CDmePresetGroupListPanel : public vgui::ListPanel
+{
+ DECLARE_CLASS_SIMPLE( CDmePresetGroupListPanel, vgui::ListPanel );
+
+public:
+ // constructor, destructor
+ CDmePresetGroupListPanel( vgui::Panel *pParent, const char *pName, CDmePresetGroupEditorPanel *pComboPanel );
+
+ virtual void OnCreateDragData( KeyValues *msg );
+ virtual bool IsDroppable( CUtlVector< KeyValues * >& msgList );
+ virtual void OnPanelDropped( CUtlVector< KeyValues * >& msgList );
+ virtual void OnKeyCodeTyped( vgui::KeyCode code );
+ virtual void OnMouseDoublePressed( vgui::MouseCode code );
+ virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels );
+
+private:
+ CDmePresetGroupEditorPanel *m_pPresetGroupPanel;
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// CDmePresetListPanel
+//
+// Implementation below because of scoping issues
+//
+//-----------------------------------------------------------------------------
+class CDmePresetListPanel : public vgui::ListPanel
+{
+ DECLARE_CLASS_SIMPLE( CDmePresetListPanel, vgui::ListPanel );
+
+public:
+ // constructor, destructor
+ CDmePresetListPanel( vgui::Panel *pParent, const char *pName, CDmePresetGroupEditorPanel *pComboPanel );
+
+ virtual void OnKeyCodeTyped( vgui::KeyCode code );
+ virtual void OnCreateDragData( KeyValues *msg );
+ virtual bool IsDroppable( CUtlVector< KeyValues * >& msgList );
+ virtual void OnPanelDropped( CUtlVector< KeyValues * >& msgList );
+ virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels );
+
+private:
+
+ CDmePresetGroupEditorPanel *m_pPresetGroupPanel;
+};
+
+
+//-----------------------------------------------------------------------------
+// Sort functions for list panel
+//-----------------------------------------------------------------------------
+static int __cdecl IndexSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
+{
+ int nIndex1 = item1.kv->GetInt("index");
+ int nIndex2 = item2.kv->GetInt("index");
+ return nIndex1 - nIndex2;
+}
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+CDmePresetGroupEditorPanel::CDmePresetGroupEditorPanel( vgui::Panel *pParent, const char *pName ) :
+ BaseClass( pParent, pName )
+{
+ m_pSplitter = new vgui::Splitter( this, "PresetGroupSplitter", vgui::SPLITTER_MODE_VERTICAL, 1 );
+ vgui::Panel *pSplitterLeftSide = m_pSplitter->GetChild( 0 );
+ vgui::Panel *pSplitterRightSide = m_pSplitter->GetChild( 1 );
+
+ m_pPresetGroupList = new CDmePresetGroupListPanel( pSplitterLeftSide, "PresetGroupList", this );
+ m_pPresetGroupList->AddColumnHeader( 0, "name", "Preset Group Name", 150, 0 );
+ m_pPresetGroupList->AddColumnHeader( 1, "visible", "Visible", 70, 0 );
+ m_pPresetGroupList->AddColumnHeader( 2, "shared", "Shared", 52, 0 );
+ m_pPresetGroupList->AddColumnHeader( 3, "readonly", "Read Only", 52, 0 );
+ m_pPresetGroupList->SetSelectIndividualCells( false );
+ m_pPresetGroupList->SetMultiselectEnabled( false );
+ m_pPresetGroupList->SetEmptyListText( "No preset groups" );
+ m_pPresetGroupList->AddActionSignalTarget( this );
+ m_pPresetGroupList->SetSortFunc( 0, IndexSortFunc );
+ m_pPresetGroupList->SetSortFunc( 1, NULL );
+ m_pPresetGroupList->SetColumnSortable( 1, false );
+ m_pPresetGroupList->SetSortFunc( 2, NULL );
+ m_pPresetGroupList->SetColumnSortable( 2, false );
+ m_pPresetGroupList->SetSortFunc( 3, NULL );
+ m_pPresetGroupList->SetColumnSortable( 3, false );
+ m_pPresetGroupList->SetDropEnabled( true );
+ m_pPresetGroupList->SetSortColumn( 0 );
+ m_pPresetGroupList->SetDragEnabled( true );
+ m_pPresetGroupList->SetDropEnabled( true );
+ m_pPresetGroupList->SetIgnoreDoubleClick( true );
+
+ m_pPresetList = new CDmePresetListPanel( pSplitterRightSide, "PresetList", this );
+ m_pPresetList->AddColumnHeader( 0, "name", "Preset Name", 150, 0 );
+ m_pPresetList->SetSelectIndividualCells( false );
+ m_pPresetList->SetEmptyListText( "No presets" );
+ m_pPresetList->AddActionSignalTarget( this );
+ m_pPresetList->SetSortFunc( 0, IndexSortFunc );
+ m_pPresetList->SetSortColumn( 0 );
+ m_pPresetList->SetDragEnabled( true );
+ m_pPresetList->SetDropEnabled( true );
+ m_pPresetList->SetIgnoreDoubleClick( true );
+
+ LoadControlSettingsAndUserConfig( "resource/dmepresetgroupeditorpanel.res" );
+
+ m_hFileOpenStateMachine = new vgui::FileOpenStateMachine( this, this );
+ m_hFileOpenStateMachine->AddActionSignalTarget( this );
+}
+
+
+CDmePresetGroupEditorPanel::~CDmePresetGroupEditorPanel()
+{
+ CleanupContextMenu();
+ SaveUserConfig();
+}
+
+
+//-----------------------------------------------------------------------------
+// Cleans up the context menu
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::CleanupContextMenu()
+{
+ if ( m_hContextMenu.Get() )
+ {
+ m_hContextMenu->MarkForDeletion();
+ m_hContextMenu = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the combination operator
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::SetAnimationSet( CDmeAnimationSet *pAnimationSet )
+{
+ m_hAnimationSet = pAnimationSet;
+ RefreshAnimationSet();
+}
+
+CDmeAnimationSet* CDmePresetGroupEditorPanel::GetAnimationSet()
+{
+ return m_hAnimationSet;
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds the preset group list for the animation set
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::RefreshAnimationSet()
+{
+ CDmePresetGroup *pSelectedPresetGroup = GetSelectedPresetGroup();
+
+ m_pPresetGroupList->RemoveAll();
+ if ( !m_hAnimationSet.Get() )
+ return;
+
+ const CDmaElementArray< CDmePresetGroup > &presetGroupList = m_hAnimationSet->GetPresetGroups();
+ int nCount = presetGroupList.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmePresetGroup *pPresetGroup = presetGroupList[i];
+ Assert( pPresetGroup );
+ if ( !pPresetGroup )
+ continue;
+
+ bool bIsVisible = pPresetGroup->m_bIsVisible;
+ KeyValues *kv = new KeyValues( "node", "name", pPresetGroup->GetName() );
+ kv->SetString( "visible", bIsVisible ? "Yes" : "No" );
+ kv->SetString( "shared", pPresetGroup->IsShared() ? "Yes" : "No" );
+ kv->SetString( "readonly", pPresetGroup->m_bIsReadOnly ? "Yes" : "No" );
+ SetElementKeyValue( kv, "presetGroup", pPresetGroup );
+ kv->SetColor( "cellcolor", pPresetGroup->m_bIsReadOnly ? Color( 255, 0, 0, 255 ) : Color( 255, 255, 255, 255 ) );
+ kv->SetInt( "index", i );
+ int nItemID = m_pPresetGroupList->AddItem( kv, 0, false, false );
+
+ if ( pSelectedPresetGroup == pPresetGroup )
+ {
+ m_pPresetGroupList->AddSelectedItem( nItemID );
+ }
+ }
+
+ m_pPresetGroupList->SortList();
+
+ RefreshPresetNames();
+}
+
+
+//-----------------------------------------------------------------------------
+// Tells any class that cares that the data in this thing has changed
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::NotifyDataChanged()
+{
+ PostActionSignal( new KeyValues( "PresetsChanged" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Refreshes the list of presets in the selected preset group
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::RefreshPresetNames()
+{
+ CDmePreset *pSelectedPreset = GetSelectedPreset();
+
+ m_pPresetList->RemoveAll();
+ if ( !m_hAnimationSet.Get() )
+ return;
+
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ const CDmaElementArray< CDmePreset > &presetList = pPresetGroup->GetPresets();
+ int nCount = presetList.Count( );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmePreset *pPreset = presetList[i];
+ KeyValues *kv = new KeyValues( "node", "name", pPreset->GetName() );
+ SetElementKeyValue( kv, "preset", pPreset );
+ kv->SetInt( "index", i );
+ int nItemID = m_pPresetList->AddItem( kv, 0, false, false );
+ if ( pSelectedPreset == pPreset )
+ {
+ m_pPresetList->AddSelectedItem( nItemID );
+ }
+ }
+
+ m_pPresetList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+CDmePreset* CDmePresetGroupEditorPanel::GetSelectedPreset()
+{
+ if ( !m_hAnimationSet.Get() )
+ return NULL;
+
+ int nSelectedPresetCount = m_pPresetList->GetSelectedItemsCount();
+ if ( nSelectedPresetCount != 1 )
+ return NULL;
+
+ int nItemID = m_pPresetList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pPresetList->GetItem( nItemID );
+
+ CDmePreset *pPreset = GetElementKeyValue< CDmePreset >( pKeyValues, "preset" );
+ return pPreset;
+}
+
+
+//-----------------------------------------------------------------------------
+// Selects a particular preset
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::SetSelectedPreset( CDmePreset* pPreset )
+{
+ m_pPresetList->ClearSelectedItems();
+ for ( int nItemID = m_pPresetList->FirstItem();
+ nItemID != m_pPresetList->InvalidItemID();
+ nItemID = m_pPresetList->NextItem( nItemID ) )
+ {
+ KeyValues* pKeyValues = m_pPresetList->GetItem( nItemID );
+ CDmePreset *pItemPreset = GetElementKeyValue< CDmePreset >( pKeyValues, "preset" );
+ if ( pItemPreset == pPreset )
+ {
+ m_pPresetList->AddSelectedItem( nItemID );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+CDmePresetGroup* CDmePresetGroupEditorPanel::GetSelectedPresetGroup()
+{
+ if ( !m_hAnimationSet.Get() )
+ return NULL;
+
+ int nSelectedItemCount = m_pPresetGroupList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return NULL;
+
+ int nItemID = m_pPresetGroupList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pPresetGroupList->GetItem( nItemID );
+ CDmePresetGroup *pPresetGroup = GetElementKeyValue<CDmePresetGroup>( pKeyValues, "presetGroup" );
+ return pPresetGroup;
+}
+
+
+//-----------------------------------------------------------------------------
+// Selects a particular preset group
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::SetSelectedPresetGroup( CDmePresetGroup* pPresetGroup )
+{
+ m_pPresetGroupList->ClearSelectedItems();
+ for ( int nItemID = m_pPresetGroupList->FirstItem();
+ nItemID != m_pPresetGroupList->InvalidItemID();
+ nItemID = m_pPresetGroupList->NextItem( nItemID ) )
+ {
+ KeyValues* pKeyValues = m_pPresetGroupList->GetItem( nItemID );
+ CDmePresetGroup *pItemPresetGroup = GetElementKeyValue< CDmePresetGroup >( pKeyValues, "presetGroup" );
+ if ( pItemPresetGroup == pPresetGroup )
+ {
+ m_pPresetGroupList->AddSelectedItem( nItemID );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// If it finds a duplicate preset name, reports an error message and returns it found one
+//-----------------------------------------------------------------------------
+bool CDmePresetGroupEditorPanel::HasDuplicatePresetName( const char *pPresetName, CDmePreset *pIgnorePreset )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return false;
+
+ CDmePreset *pMatch = pPresetGroup->FindPreset( pPresetName );
+ if ( pMatch && pMatch != pIgnorePreset )
+ {
+ vgui::MessageBox *pError = new vgui::MessageBox( "#DmePresetGroupEditor_DuplicatePresetNameTitle", "#DmePresetGroupEditor_DuplicatePresetNameText", this );
+ pError->DoModal();
+ return true;
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnInputCompleted after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::PerformAddPreset( const char *pNewPresetName )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ if ( HasDuplicatePresetName( pNewPresetName ) )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Add Preset" );
+ CDmePreset *pPreset = pPresetGroup->FindOrAddPreset( pNewPresetName );
+ sg.Release();
+
+ RefreshPresetNames();
+ SetSelectedPreset( pPreset );
+ NotifyDataChanged();
+
+ KeyValues *pKeyValues = new KeyValues( "AddNewPreset" );
+ SetElementKeyValue( pKeyValues, "preset", pPreset );
+ PostActionSignal( pKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnInputCompleted after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::PerformRenamePreset( const char *pNewPresetName )
+{
+ CDmePreset *pPreset = GetSelectedPreset();
+ if ( !pPreset )
+ return;
+
+ if ( HasDuplicatePresetName( pNewPresetName, pPreset ) )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Rename Preset" );
+ pPreset->SetName( pNewPresetName );
+ sg.Release();
+
+ RefreshPresetNames();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Add a preset
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnAddPreset()
+{
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Add Preset", "Enter name of new preset" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnAddPreset" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Rename a preset
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnRenamePreset()
+{
+ CDmePreset *pPreset = GetSelectedPreset();
+ if ( !pPreset )
+ return;
+
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Rename Preset", "Enter new name of preset" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnRenamePreset" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Remove a preset
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnRemovePreset()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CDmePreset *pPreset = GetSelectedPreset();
+ if ( !pPreset )
+ return;
+
+ int nItemID = m_pPresetList->GetSelectedItem( 0 );
+ int nCurrentRow = m_pPresetList->GetItemCurrentRow( nItemID );
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Remove Preset" );
+ pPresetGroup->RemovePreset( pPreset );
+ sg.Release();
+
+ RefreshPresetNames();
+ if ( nCurrentRow >= m_pPresetList->GetItemCount() )
+ {
+ --nCurrentRow;
+ }
+ if ( nCurrentRow >= 0 )
+ {
+ nItemID = m_pPresetList->GetItemIDFromRow( nCurrentRow );
+ m_pPresetList->ClearSelectedItems();
+ m_pPresetList->AddSelectedItem( nItemID );
+ }
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnMovePresetUp()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ CDmePreset *pPreset = GetSelectedPreset();
+ if ( !pPresetGroup || !pPreset )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Reorder Presets" );
+ pPresetGroup->MovePresetUp( pPreset );
+ sg.Release();
+
+ RefreshPresetNames();
+ SetSelectedPreset( pPreset );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnMovePresetDown()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ CDmePreset *pPreset = GetSelectedPreset();
+ if ( !pPresetGroup || !pPreset )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Reorder Presets" );
+ pPresetGroup->MovePresetDown( pPreset );
+ sg.Release();
+
+ RefreshPresetNames();
+ SetSelectedPreset( pPreset );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Drag/drop reordering of presets
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::MovePresetInFrontOf( CDmePreset *pDragPreset, CDmePreset *pDropPreset )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Reorder Presets" );
+ pPresetGroup->MovePresetInFrontOf( pDragPreset, pDropPreset );
+ sg.Release();
+
+ RefreshPresetNames();
+ SetSelectedPreset( pDragPreset );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Fileopen state machine
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnFileStateMachineFinished( KeyValues *pParams )
+{
+ KeyValues *pContextKeyValues = pParams->GetFirstTrueSubKey();
+ if ( Q_stricmp( pContextKeyValues->GetName(), "ImportPresets" ) )
+ return;
+
+ CDmElement *pRoot = GetElementKeyValue<CDmElement>( pContextKeyValues, "presets" );
+ if ( !pRoot )
+ return;
+
+ if ( pParams->GetInt( "completionState", 0 ) != 0 )
+ {
+ CPresetPickerFrame *pPresetPicker = new CPresetPickerFrame( this, "Select Preset(s) to Import" );
+ pPresetPicker->AddActionSignalTarget( this );
+ KeyValues *pContextKeyValuesImport = new KeyValues( "ImportPicked" );
+ SetElementKeyValue( pContextKeyValuesImport, "presets", pRoot );
+ pPresetPicker->DoModal( pRoot, true, pContextKeyValuesImport );
+ }
+ else
+ {
+ // Clean up the read-in file
+ CDisableUndoScopeGuard sg;
+ g_pDataModel->RemoveFileId( pRoot->GetFileId() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Finds a control index
+//-----------------------------------------------------------------------------
+struct ExportedControl_t
+{
+ CUtlString m_Name;
+ bool m_bIsStereo;
+ bool m_bIsMulti;
+ int m_nFirstIndex;
+};
+
+static int FindExportedControlIndex( const char *pControlName, CUtlVector< ExportedControl_t > &uniqueControls )
+{
+ int nCount = uniqueControls.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if ( !Q_stricmp( pControlName, uniqueControls[i].m_Name ) )
+ return i;
+ }
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds a unique list of controls found in the presets
+//-----------------------------------------------------------------------------
+static int BuildExportedControlList( CDmeAnimationSet *pAnimationSet, CDmePresetGroup *pPresetGroup, CUtlVector< ExportedControl_t > &uniqueControls )
+{
+ int nGlobalIndex = 0;
+ const CDmrElementArray< CDmePreset > &presets = pPresetGroup->GetPresets();
+ int nPresetCount = presets.Count();
+ for ( int iPreset = 0; iPreset < nPresetCount; ++iPreset )
+ {
+ CDmePreset *pPreset = presets[iPreset];
+ const CDmrElementArray< CDmElement > &controls = pPreset->GetControlValues();
+
+ int nControlCount = controls.Count();
+ for ( int i = 0; i < nControlCount; ++i )
+ {
+ const char *pControlName = controls[i]->GetName();
+ int nIndex = FindExportedControlIndex( pControlName, uniqueControls );
+ if ( nIndex >= 0 )
+ continue;
+ CDmAttribute *pValueAttribute = controls[i]->GetAttribute( "value" );
+ if ( !pValueAttribute || pValueAttribute->GetType() != AT_FLOAT )
+ continue;
+
+ CDmElement *pControl = pAnimationSet->FindControl( pControlName );
+ if ( !pControl )
+ continue;
+
+ int j = uniqueControls.AddToTail();
+ ExportedControl_t &control = uniqueControls[j];
+ control.m_Name = pControlName;
+ control.m_bIsStereo = pControl->GetValue<bool>( "combo" );
+ control.m_bIsMulti = pControl->GetValue<bool>( "multi" );
+ control.m_nFirstIndex = nGlobalIndex;
+ nGlobalIndex += 1 + control.m_bIsStereo + control.m_bIsMulti;
+ }
+ }
+ return nGlobalIndex;
+}
+
+
+//-----------------------------------------------------------------------------
+// Fileopen state machine
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ if ( bOpenFile )
+ {
+ pDialog->SetTitle( "Import Preset File", true );
+ }
+ else
+ {
+ pDialog->SetTitle( "Export Preset File", true );
+ }
+
+ char pPresetPath[MAX_PATH];
+ if ( !Q_stricmp( pFileFormat, PRESET_FILE_FORMAT ) )
+ {
+ GetModSubdirectory( "models", pPresetPath, sizeof(pPresetPath) );
+ pDialog->SetStartDirectoryContext( "preset_importexport", pPresetPath );
+ pDialog->AddFilter( "*.*", "All Files (*.*)", false );
+ pDialog->AddFilter( "*.pre", "Preset File (*.pre)", true, PRESET_FILE_FORMAT );
+ }
+ else if ( !Q_stricmp( pFileFormat, "vfe" ) )
+ {
+ GetModSubdirectory( "expressions", pPresetPath, sizeof(pPresetPath) );
+ pDialog->SetStartDirectoryContext( "preset_exportvfe", pPresetPath );
+ pDialog->AddFilter( "*.*", "All Files (*.*)", false );
+ pDialog->AddFilter( "*.vfe", "Expression File (*.vfe)", true, "vfe" );
+ }
+ else if ( !Q_stricmp( pFileFormat, "txt" ) )
+ {
+ GetModSubdirectory( "expressions", pPresetPath, sizeof(pPresetPath) );
+ pDialog->SetStartDirectoryContext( "preset_exportvfe", pPresetPath );
+ pDialog->AddFilter( "*.*", "All Files (*.*)", false );
+ pDialog->AddFilter( "*.txt", "Faceposer Expression File (*.txt)", true, "txt" );
+ }
+}
+
+bool CDmePresetGroupEditorPanel::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ CDmElement *pRoot;
+ CDisableUndoScopeGuard sgRestore;
+ DmFileId_t fileId = g_pDataModel->RestoreFromFile( pFileName, NULL, pFileFormat, &pRoot, CR_FORCE_COPY );
+ sgRestore.Release();
+
+ if ( fileId == DMFILEID_INVALID )
+ return false;
+
+ // When importing an entire group, we can do it all right here
+ if ( !Q_stricmp( pContextKeyValues->GetName(), "ImportPresetGroup" ) )
+ {
+ CDmePresetGroup *pPresetGroup = CastElement< CDmePresetGroup >( pRoot );
+ if ( !pPresetGroup )
+ return false;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Import Preset Group" );
+ pPresetGroup->SetFileId( m_hAnimationSet->GetFileId(), TD_DEEP );
+ m_hAnimationSet->GetPresetGroups( ).AddToTail( pPresetGroup );
+ sg.Release();
+
+ // Warn if we import a remap which doesn't exist
+ CDmePresetRemap *pPresetRemap = pPresetGroup->GetPresetRemap();
+ if ( pPresetRemap )
+ {
+ if ( m_hAnimationSet->FindPresetGroup( pPresetRemap->m_SourcePresetGroup ) == NULL )
+ {
+ char pBuf[512];
+ Q_snprintf( pBuf, sizeof(pBuf),
+ "Import contains a remap which refers to an unknown preset group \"%s\"!\n",
+ pPresetRemap->m_SourcePresetGroup.Get() );
+ vgui::MessageBox *pError = new vgui::MessageBox( "Bad source remap name!", pBuf, this );
+ pError->DoModal();
+ }
+ }
+
+ RefreshAnimationSet();
+ NotifyDataChanged();
+ return true;
+ }
+
+ CDmAttribute* pPresets = pRoot->GetAttribute( "presets", AT_ELEMENT_ARRAY );
+ if ( !pPresets )
+ return false;
+
+ SetElementKeyValue( pContextKeyValues, "presets", pRoot );
+ return true;
+}
+
+bool CDmePresetGroupEditorPanel::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ // Used when exporting an entire preset group
+ if ( !Q_stricmp( pContextKeyValues->GetName(), "ExportPresetGroup" ) )
+ {
+ CDmePresetGroup *pPresetGroup = GetElementKeyValue<CDmePresetGroup>( pContextKeyValues, "presetGroup" );
+ if ( !pPresetGroup )
+ return false;
+
+ bool bOk = g_pDataModel->SaveToFile( pFileName, NULL, g_pDataModel->GetDefaultEncoding( pFileFormat ), pFileFormat, pPresetGroup );
+ return bOk;
+ }
+
+ // Used when exporting an entire preset group
+ if ( !Q_stricmp( pContextKeyValues->GetName(), "ExportPresetGroupToVFE" ) )
+ {
+ CDmePresetGroup *pPresetGroup = GetElementKeyValue<CDmePresetGroup>( pContextKeyValues, "presetGroup" );
+ if ( !pPresetGroup )
+ return false;
+
+ bool bOk = pPresetGroup->ExportToVFE( pFileName, m_hAnimationSet );
+ return bOk;
+ }
+
+ // Used when exporting an entire preset group
+ if ( !Q_stricmp( pContextKeyValues->GetName(), "ExportPresetGroupToTXT" ) )
+ {
+ CDmePresetGroup *pPresetGroup = GetElementKeyValue<CDmePresetGroup>( pContextKeyValues, "presetGroup" );
+ if ( !pPresetGroup )
+ return false;
+
+ bool bOk = pPresetGroup->ExportToTXT( pFileName, m_hAnimationSet );
+ return bOk;
+ }
+
+ // Used when exporting a subset of a preset group
+ int nCount = pContextKeyValues->GetInt( "count" );
+ if ( nCount == 0 )
+ return true;
+
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ const char *pPresetGroupName = pPresetGroup ? pPresetGroup->GetName() : "root";
+
+ CDisableUndoScopeGuard sg;
+ CDmePresetGroup *pRoot = CreateElement< CDmePresetGroup >( pPresetGroupName, DMFILEID_INVALID );
+ CDmaElementArray< CDmePreset >& presets = pRoot->GetPresets( );
+
+ // Build list of selected presets
+ for ( int i = 0; i < nCount; ++i )
+ {
+ char pBuf[32];
+ Q_snprintf( pBuf, sizeof(pBuf), "%d", i );
+ CDmePreset *pPreset = GetElementKeyValue<CDmePreset>( pContextKeyValues, pBuf );
+ presets.AddToTail( pPreset );
+ }
+
+ bool bOk = g_pDataModel->SaveToFile( pFileName, NULL, g_pDataModel->GetDefaultEncoding( pFileFormat ), pFileFormat, pRoot );
+ g_pDataModel->DestroyElement( pRoot->GetHandle() );
+ return bOk;
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when preset picking is cancelled
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnPresetPickCancelled( KeyValues *pParams )
+{
+ KeyValues *pContextKeyValues = pParams->FindKey( "ImportPicked" );
+ if ( pContextKeyValues )
+ {
+ // Clean up the read-in file
+ CDisableUndoScopeGuard sg;
+ CDmElement *pRoot = GetElementKeyValue<CDmElement>( pContextKeyValues, "presets" );
+ g_pDataModel->RemoveFileId( pRoot->GetFileId() );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Actually imports the presets from a file
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::ImportPresets( const CUtlVector< CDmePreset * >& presets )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Import Presets" );
+
+ int nPresetCount = presets.Count();
+ for ( int i = 0; i < nPresetCount; ++i )
+ {
+ CDmePreset *pPreset = pPresetGroup->FindOrAddPreset( presets[i]->GetName() );
+ const CDmaElementArray< CDmElement > &srcValues = presets[i]->GetControlValues( );
+ CDmaElementArray< CDmElement > &values = pPreset->GetControlValues( );
+ values.RemoveAll();
+
+ int nValueCount = srcValues.Count();
+ for ( int j = 0; j < nValueCount; ++j )
+ {
+ CDmElement *pSrcControlValue = srcValues[j];
+ CDmElement *pControlValue = pSrcControlValue->Copy( );
+ pControlValue->SetFileId( pPresetGroup->GetFileId(), TD_DEEP );
+ values.AddToTail( pControlValue );
+ }
+ }
+
+ RefreshAnimationSet();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'export presets' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnPresetPicked( KeyValues *pParams )
+{
+ CUtlVector< CDmePreset * > presets;
+ int nCount = pParams->GetInt( "count" );
+ if ( nCount == 0 )
+ return;
+
+ // Build list of selected presets
+ for ( int i = 0; i < nCount; ++i )
+ {
+ char pBuf[32];
+ Q_snprintf( pBuf, sizeof(pBuf), "%d", i );
+ CDmePreset *pPreset = GetElementKeyValue<CDmePreset>( pParams, pBuf );
+ presets.AddToTail( pPreset );
+ }
+
+ if ( pParams->FindKey( "ExportPicked" ) )
+ {
+ KeyValues *pContextKeyValues = new KeyValues( "ExportPresets" );
+ pContextKeyValues->SetInt( "count", nCount );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ char pBuf[32];
+ Q_snprintf( pBuf, sizeof(pBuf), "%d", i );
+ SetElementKeyValue( pContextKeyValues, pBuf, presets[i] );
+ }
+
+ m_hFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, PRESET_FILE_FORMAT, vgui::FOSM_SHOW_PERFORCE_DIALOGS );
+ return;
+ }
+
+ KeyValues *pContextKeyValues = pParams->FindKey( "ImportPicked" );
+ if ( pContextKeyValues )
+ {
+ ImportPresets( presets );
+
+ // Clean up the read-in file
+ {
+ CDisableUndoScopeGuard sg;
+ CDmElement *pRoot = GetElementKeyValue<CDmElement>( pContextKeyValues, "presets" );
+ g_pDataModel->RemoveFileId( pRoot->GetFileId() );
+ return;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'export presets' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnExportPresets()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CPresetPickerFrame *pPresetPicker = new CPresetPickerFrame( this, "Select Preset(s) to Export" );
+ pPresetPicker->AddActionSignalTarget( this );
+ pPresetPicker->DoModal( pPresetGroup, true, new KeyValues( "ExportPicked" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'import presets' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnImportPresets()
+{
+ KeyValues *pContextKeyValues = new KeyValues( "ImportPresets" );
+ m_hFileOpenStateMachine->OpenFile( PRESET_FILE_FORMAT, pContextKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'export preset groups to VFE' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnExportPresetGroupToVFE()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "ExportPresetGroupToVFE" );
+ SetElementKeyValue( pContextKeyValues, "presetGroup", pPresetGroup );
+ m_hFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, "vfe", vgui::FOSM_SHOW_PERFORCE_DIALOGS );
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'export preset groups to TXT' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnExportPresetGroupToTXT()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "ExportPresetGroupToTXT" );
+ SetElementKeyValue( pContextKeyValues, "presetGroup", pPresetGroup );
+ m_hFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, "txt", vgui::FOSM_SHOW_PERFORCE_DIALOGS );
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'export preset groups' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnExportPresetGroups()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "ExportPresetGroup" );
+ SetElementKeyValue( pContextKeyValues, "presetGroup", pPresetGroup );
+ m_hFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, PRESET_FILE_FORMAT, vgui::FOSM_SHOW_PERFORCE_DIALOGS );
+}
+
+
+//-----------------------------------------------------------------------------
+// The 'import preset groups' context menu option
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnImportPresetGroups()
+{
+ KeyValues *pContextKeyValues = new KeyValues( "ImportPresetGroup" );
+ m_hFileOpenStateMachine->OpenFile( PRESET_FILE_FORMAT, pContextKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+// Preset remap editor
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnRemoveDefaultControls()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Remove Default Controls" );
+ CDmrElementArray< CDmePreset > presets = pPresetGroup->GetPresets();
+ int nPresetCount = presets.Count();
+ for ( int i = 0; i < nPresetCount; ++i )
+ {
+ CDmePreset *pPreset = presets[i];
+ CDmrElementArray< CDmElement > controls = pPreset->GetControlValues();
+ int nControlCount = controls.Count();
+ for ( int j = nControlCount; --j >= 0; )
+ {
+ CDmElement *pControlValue = controls[j];
+ CDmElement *pControl = m_hAnimationSet->FindControl( pControlValue->GetName() );
+ if ( !pControl )
+ {
+ controls.Remove( j );
+ continue;
+ }
+
+ bool bIsDefault = true;
+ if ( pControl->GetValue<float>( "defaultValue" ) != pControlValue->GetValue<float>( "value" ) )
+ {
+ bIsDefault = false;
+ }
+
+ bool bIsStereo = pControl->GetValue<bool>( "combo" );
+ if ( bIsStereo )
+ {
+ if ( pControl->GetValue<float>( "defaultBalance" ) != pControlValue->GetValue<float>( "balance" ) )
+ {
+ bIsDefault = false;
+ }
+ }
+
+ bool bIsMulti = pControl->GetValue<bool>( "multi" );
+ if ( bIsMulti )
+ {
+ if ( pControl->GetValue<float>( "defaultMultilevel" ) != pControlValue->GetValue<float>( "multilevel" ) )
+ {
+ bIsDefault = false;
+ }
+ }
+
+ if ( bIsDefault )
+ {
+ controls.Remove( j );
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Preset remap editor
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnEditPresetRemapping()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CDmePresetRemapPanel *pPresetRemapPanel = new CDmePresetRemapPanel( this, "Manage Preset Remapping" );
+ pPresetRemapPanel->DoModal( m_hAnimationSet, pPresetGroup );
+}
+
+
+//-----------------------------------------------------------------------------
+// Perform preset remap
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnRemapPresets()
+{
+ CDmePresetGroup *pDestPresetGroup = GetSelectedPresetGroup();
+ if ( !pDestPresetGroup || pDestPresetGroup->m_bIsReadOnly )
+ return;
+
+ CDmePresetRemap *pPresetRemap = pDestPresetGroup->GetPresetRemap();
+ if ( !pPresetRemap )
+ return;
+
+ CDmePresetGroup *pSourcePresetGroup = m_hAnimationSet->FindPresetGroup( pPresetRemap->m_SourcePresetGroup );
+ if ( !pSourcePresetGroup )
+ {
+ char pBuf[512];
+ Q_snprintf( pBuf, sizeof(pBuf), "Unable to find preset group name %s in animation set %s!\n",
+ pPresetRemap->m_SourcePresetGroup.Get(), m_hAnimationSet->GetName() );
+ vgui::MessageBox *pError = new vgui::MessageBox( "Bad source remap name!", pBuf, this );
+ pError->DoModal();
+ return;
+ }
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Remap Presets" );
+
+ int nCount = pPresetRemap->GetRemapCount();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ const char *pSourceName = pPresetRemap->GetRemapSource( i );
+ CDmePreset *pSourcePreset = pSourcePresetGroup->FindPreset( pSourceName );
+
+ const char *pDestName = pPresetRemap->GetRemapDest( i );
+ CDmePreset *pDestPreset = pDestPresetGroup->FindPreset( pDestName );
+
+ if ( !pSourcePreset || !pDestPreset )
+ continue;
+
+ pDestPreset->CopyControlValuesFrom( pSourcePreset );
+ }
+
+ sg.Release();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular preset
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnOpenPresetContextMenu( )
+{
+ if ( !m_hAnimationSet.Get() )
+ return;
+
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ CDmePreset *pPreset = GetSelectedPreset();
+
+ m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
+
+ // Can only export from read-only groups
+ if ( pPresetGroup->m_bIsReadOnly )
+ {
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ExportPresets", new KeyValues( "ExportPresets" ), this );
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+ return;
+ }
+
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_AddPreset", new KeyValues( "AddPreset" ), this );
+ if ( pPreset )
+ {
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_RenamePreset", new KeyValues( "RenamePreset" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_RemovePreset", new KeyValues( "RemovePreset" ), this );
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_MoveUp", new KeyValues( "MovePresetUp" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_MoveDown", new KeyValues( "MovePresetDown" ), this );
+ }
+
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ImportPresets", new KeyValues( "ImportPresets" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ExportPresets", new KeyValues( "ExportPresets" ), this );
+
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnOpenContextMenu( KeyValues *kv )
+{
+ CleanupContextMenu();
+ if ( !m_hAnimationSet.Get() )
+ return;
+
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pPresetList )
+ {
+ OnOpenPresetContextMenu();
+ return;
+ }
+
+ if ( pPanel != m_pPresetGroupList )
+ return;
+
+ m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_AddGroup", new KeyValues( "AddGroup" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_AddPhonemeGroup", new KeyValues( "AddPhonemeGroup" ), this );
+
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( pPresetGroup )
+ {
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_RenameGroup", new KeyValues( "RenameGroup" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_RemoveGroup", new KeyValues( "RemoveGroup" ), this );
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ToggleVisibility", new KeyValues( "ToggleGroupVisibility" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ToggleSharing", new KeyValues( "ToggleGroupSharing" ), this );
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_MoveUp", new KeyValues( "MoveGroupUp" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_MoveDown", new KeyValues( "MoveGroupDown" ), this );
+
+ CDmePresetRemap *pPresetRemap = pPresetGroup->GetPresetRemap();
+ bool bUseSeparator = !pPresetGroup->m_bIsReadOnly || pPresetRemap;
+ if ( bUseSeparator )
+ {
+ m_hContextMenu->AddSeparator();
+ }
+ if ( !pPresetGroup->m_bIsReadOnly )
+ {
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_RemoveDefaultControls", new KeyValues( "RemoveDefaultControls" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_EditPresetRemapping", new KeyValues( "EditPresetRemapping" ), this );
+ }
+ if ( pPresetRemap )
+ {
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_RemapPresets", new KeyValues( "RemapPresets" ), this );
+ }
+ }
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ImportPresets", new KeyValues( "ImportPresetGroups" ), this );
+ if ( pPresetGroup )
+ {
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ExportPresets", new KeyValues( "ExportPresetGroups" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ExportPresetsToFaceposer", new KeyValues( "ExportPresetGroupsToTXT" ), this );
+ m_hContextMenu->AddMenuItem( "#DmePresetGroupEditor_ExportPresetsToExpression", new KeyValues( "ExportPresetGroupsToVFE" ), this );
+ }
+
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnItemSelected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pPresetGroupList )
+ {
+ RefreshPresetNames();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnItemDeselected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pPresetGroupList )
+ {
+ RefreshPresetNames();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// If it finds a duplicate control name, reports an error message and returns it found one
+//-----------------------------------------------------------------------------
+bool CDmePresetGroupEditorPanel::HasDuplicateGroupName( const char *pGroupName, CDmePresetGroup *pIgnorePreset )
+{
+ if ( !m_hAnimationSet )
+ return false;
+
+ CDmePresetGroup *pMatch = m_hAnimationSet->FindPresetGroup( pGroupName );
+ if ( pMatch && pMatch != pIgnorePreset )
+ {
+ vgui::MessageBox *pError = new vgui::MessageBox( "#DmePresetGroupEditor_DuplicateNameTitle", "#DmePresetGroupEditor_DuplicateNameText", this );
+ pError->DoModal();
+ return true;
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnInputCompleted after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::PerformAddGroup( const char *pNewGroupName )
+{
+ if ( !m_hAnimationSet )
+ return;
+
+ if ( HasDuplicateGroupName( pNewGroupName ) )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Add Preset Group" );
+ CDmePresetGroup *pPresetGroup = m_hAnimationSet->FindOrAddPresetGroup( pNewGroupName );
+ sg.Release();
+
+ RefreshAnimationSet();
+ SetSelectedPresetGroup( pPresetGroup );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnInputCompleted after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::PerformAddPhonemeGroup( const char *pNewGroupName )
+{
+ if ( !m_hAnimationSet )
+ return;
+
+ if ( HasDuplicateGroupName( pNewGroupName ) )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Add Phoneme Preset Group" );
+ CDmePresetGroup *pPresetGroup = m_hAnimationSet->FindOrAddPresetGroup( pNewGroupName );
+
+ int nPhonemeCount = NumPhonemes();
+ for ( int i = 0; i < nPhonemeCount; ++i )
+ {
+ if ( !IsStandardPhoneme( i ) )
+ continue;
+
+ char pTempBuf[256];
+ const char *pPhonemeName = NameForPhonemeByIndex( i );
+ if ( !Q_stricmp( pPhonemeName, "<sil>" ) )
+ {
+ pPhonemeName = "silence";
+ }
+ Q_snprintf( pTempBuf, sizeof(pTempBuf), "p_%s", pPhonemeName );
+
+ pPresetGroup->FindOrAddPreset( pTempBuf );
+ }
+
+ sg.Release();
+
+ RefreshAnimationSet();
+ SetSelectedPresetGroup( pPresetGroup );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnInputCompleted after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::PerformRenameGroup( const char *pNewGroupName )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ if ( HasDuplicateGroupName( pNewGroupName, pPresetGroup ) )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Rename Preset Group" );
+ pPresetGroup->SetName( pNewGroupName );
+ sg.Release();
+
+ RefreshAnimationSet();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnGroupControls after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnInputCompleted( KeyValues *pKeyValues )
+{
+ const char *pName = pKeyValues->GetString( "text", NULL );
+ if ( !pName || !pName[0] )
+ return;
+
+ if ( pKeyValues->FindKey( "OnAddGroup" ) )
+ {
+ PerformAddGroup( pName );
+ return;
+ }
+
+ if ( pKeyValues->FindKey( "OnAddPhonemeGroup" ) )
+ {
+ PerformAddPhonemeGroup( pName );
+ return;
+ }
+
+ if ( pKeyValues->FindKey( "OnRenameGroup" ) )
+ {
+ PerformRenameGroup( pName );
+ return;
+ }
+
+ if ( pKeyValues->FindKey( "OnAddPreset" ) )
+ {
+ PerformAddPreset( pName );
+ return;
+ }
+
+ if ( pKeyValues->FindKey( "OnRenamePreset" ) )
+ {
+ PerformRenamePreset( pName );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Toggle group visibility
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::ToggleGroupVisibility( CDmePresetGroup *pPresetGroup )
+{
+ if ( pPresetGroup )
+ {
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Toggle Preset Group Visibility" );
+
+ pPresetGroup->m_bIsVisible = !pPresetGroup->m_bIsVisible;
+ }
+
+ RefreshAnimationSet();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Ungroup controls from each other
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnToggleGroupVisibility( )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ ToggleGroupVisibility( pPresetGroup );
+}
+
+
+//-----------------------------------------------------------------------------
+// Ungroup controls from each other
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnToggleGroupSharing( )
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( pPresetGroup )
+ {
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Toggle Preset Group Sharing" );
+
+ pPresetGroup->SetShared( !pPresetGroup->IsShared() );
+ }
+
+ RefreshAnimationSet();
+}
+
+
+//-----------------------------------------------------------------------------
+// Add a preset group
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnAddGroup()
+{
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Add Preset Group", "Enter name of new preset group" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnAddGroup" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Add a preset group
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnAddPhonemeGroup()
+{
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Add Phoneme Preset Group", "Enter name of new preset group", "phoneme" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnAddPhonemeGroup" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Rename a preset group
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnRenameGroup()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Rename Preset Group", "Enter new name of preset group" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnRenameGroup" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Remove a preset group
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnRemoveGroup()
+{
+ if ( !m_hAnimationSet.Get() )
+ return;
+
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ if ( !Q_stricmp( pPresetGroup->GetName(), "procedural" ) )
+ {
+ vgui::MessageBox *pError = new vgui::MessageBox( "#DmePresetGroupEditor_CannotRemovePresetGroupTitle", "#DmePresetGroupEditor_CannotRemovePresetGroupText", this );
+ pError->DoModal();
+ return;
+ }
+
+ int nItemID = m_pPresetGroupList->GetSelectedItem( 0 );
+ int nCurrentRow = m_pPresetGroupList->GetItemCurrentRow( nItemID );
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Remove Preset Group" );
+ m_hAnimationSet->RemovePresetGroup( pPresetGroup );
+ sg.Release();
+
+ RefreshAnimationSet();
+ if ( nCurrentRow >= m_pPresetGroupList->GetItemCount() )
+ {
+ --nCurrentRow;
+ }
+ if ( nCurrentRow >= 0 )
+ {
+ nItemID = m_pPresetGroupList->GetItemIDFromRow( nCurrentRow );
+ m_pPresetGroupList->ClearSelectedItems();
+ m_pPresetGroupList->AddSelectedItem( nItemID );
+ }
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnMoveGroupUp()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup || !m_hAnimationSet.Get() )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Reorder Preset Groups" );
+ m_hAnimationSet->MovePresetGroupUp( pPresetGroup );
+ sg.Release();
+
+ RefreshAnimationSet();
+ SetSelectedPresetGroup( pPresetGroup );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::OnMoveGroupDown()
+{
+ CDmePresetGroup *pPresetGroup = GetSelectedPresetGroup();
+ if ( !pPresetGroup || !m_hAnimationSet.Get() )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Reorder Preset Groups" );
+ m_hAnimationSet->MovePresetGroupDown( pPresetGroup );
+ sg.Release();
+
+ RefreshAnimationSet();
+ SetSelectedPresetGroup( pPresetGroup );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Drag/drop reordering of preset groups
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::MovePresetGroupInFrontOf( CDmePresetGroup *pDragGroup, CDmePresetGroup *pDropGroup )
+{
+ if ( !m_hAnimationSet.Get() )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Reorder Preset Groups" );
+ m_hAnimationSet->MovePresetGroupInFrontOf( pDragGroup, pDropGroup );
+ sg.Release();
+
+ RefreshAnimationSet();
+ SetSelectedPresetGroup( pDragGroup );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Drag/drop preset moving
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorPanel::MovePresetIntoGroup( CDmePreset *pPreset, CDmePresetGroup *pGroup )
+{
+ if ( !m_hAnimationSet.Get() || !pPreset || !pGroup )
+ return;
+
+ CPresetGroupUndoScopeGuard sg( NOTIFY_SETDIRTYFLAG, "Change Preset Group" );
+
+ m_hAnimationSet->RemovePreset( pPreset );
+ pGroup->GetPresets().AddToTail( pPreset );
+ sg.Release();
+
+ RefreshPresetNames();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// CDmePresetGroupListPanel
+//
+// Declaration above because of scoping issues
+//
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CDmePresetGroupListPanel::CDmePresetGroupListPanel( vgui::Panel *pParent, const char *pName, CDmePresetGroupEditorPanel *pComboPanel ) :
+ BaseClass( pParent, pName ), m_pPresetGroupPanel( pComboPanel )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Handle keypresses
+//-----------------------------------------------------------------------------
+void CDmePresetGroupListPanel::OnMouseDoublePressed( vgui::MouseCode code )
+{
+ if ( code == MOUSE_LEFT )
+ {
+ int x, y, row, column;
+ vgui::input()->GetCursorPos( x, y );
+ GetCellAtPos( x, y, row, column );
+ int itemId = GetItemIDFromRow( row );
+ KeyValues *pKeyValues = GetItem( itemId );
+ CDmePresetGroup *pPresetGroup = GetElementKeyValue< CDmePresetGroup >( pKeyValues, "presetGroup" );
+ m_pPresetGroupPanel->ToggleGroupVisibility( pPresetGroup );
+ return;
+ }
+
+ BaseClass::OnMouseDoublePressed( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Handle keypresses
+//-----------------------------------------------------------------------------
+void CDmePresetGroupListPanel::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ if ( code == KEY_DELETE || code == KEY_BACKSPACE )
+ {
+ m_pPresetGroupPanel->OnRemoveGroup();
+ return;
+ }
+
+ if ( vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT ) )
+ {
+ if ( code == KEY_UP )
+ {
+ m_pPresetGroupPanel->OnMoveGroupUp();
+ return;
+ }
+
+ if ( code == KEY_DOWN )
+ {
+ m_pPresetGroupPanel->OnMoveGroupDown();
+ return;
+ }
+ }
+
+ vgui::ListPanel::OnKeyCodeTyped( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmePresetGroupListPanel::OnCreateDragData( KeyValues *msg )
+{
+ CDmePresetGroup *pPresetGroup = m_pPresetGroupPanel->GetSelectedPresetGroup();
+ if ( !pPresetGroup )
+ return;
+
+ SetElementKeyValue( msg, "presetGroup", pPresetGroup );
+ msg->SetInt( "selfDroppable", 1 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+bool CDmePresetGroupListPanel::IsDroppable( CUtlVector< KeyValues * >& msgList )
+{
+ if ( msgList.Count() > 0 )
+ {
+ KeyValues *pData( msgList[ 0 ] );
+ if ( m_pPresetGroupPanel )
+ {
+ CDmePresetGroup *pPresetGroup = GetElementKeyValue< CDmePresetGroup >( pData, "presetGroup" );
+ if ( pPresetGroup )
+ return true;
+
+ CDmePreset *pPreset = GetElementKeyValue< CDmePreset >( pData, "preset" );
+ if ( pPreset )
+ {
+ // Can't drop presets onto read-only preset groups
+ int x, y, row, column;
+ vgui::input()->GetCursorPos( x, y );
+ GetCellAtPos( x, y, row, column );
+ KeyValues *pKeyValues = GetItem( row );
+ CDmePresetGroup *pDropGroup = pKeyValues ? GetElementKeyValue<CDmePresetGroup>( pKeyValues, "presetGroup" ) : NULL;
+
+ if ( pDropGroup && !pDropGroup->m_bIsReadOnly )
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmePresetGroupListPanel::OnPanelDropped( CUtlVector< KeyValues * >& msgList )
+{
+ if ( msgList.Count() == 0 )
+ return;
+
+ KeyValues *pData = msgList[ 0 ];
+ if ( !m_pPresetGroupPanel )
+ return;
+
+ // Discover the cell the panel is over
+ int x, y, row, column;
+ vgui::input()->GetCursorPos( x, y );
+ GetCellAtPos( x, y, row, column );
+ KeyValues *pKeyValues = GetItem( row );
+
+ CDmePresetGroup *pDragGroup = GetElementKeyValue<CDmePresetGroup>( pData, "presetGroup" );
+ if ( pDragGroup )
+ {
+ CDmePresetGroup *pDropGroup = pKeyValues ? GetElementKeyValue<CDmePresetGroup>( pKeyValues, "presetGroup" ) : NULL;
+ m_pPresetGroupPanel->MovePresetGroupInFrontOf( pDragGroup, pDropGroup );
+ return;
+ }
+
+ CDmePreset *pDragPreset = GetElementKeyValue<CDmePreset>( pData, "preset" );
+ if ( pDragPreset )
+ {
+ CDmePresetGroup *pDropGroup = pKeyValues ? GetElementKeyValue<CDmePresetGroup>( pKeyValues, "presetGroup" ) : NULL;
+ if ( pDropGroup )
+ {
+ m_pPresetGroupPanel->MovePresetIntoGroup( pDragPreset, pDropGroup );
+ }
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Mouse is now over a droppable panel
+//-----------------------------------------------------------------------------
+void CDmePresetGroupListPanel::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
+{
+ // Discover the cell the panel is over
+ int x, y, w, h, row, column;
+ vgui::input()->GetCursorPos( x, y );
+ GetCellAtPos( x, y, row, column );
+ GetCellBounds( row, 0, x, y, w, h );
+
+ int x2, y2, w2, h2;
+ GetCellBounds( row, 3, x2, y2, w2, h2 );
+ w = x2 + w2 - x;
+
+ LocalToScreen( x, y );
+
+ surface()->DrawSetColor( GetDropFrameColor() );
+
+ // Draw insertion point
+ surface()->DrawFilledRect( x, y, x + w, y + 2 );
+ surface()->DrawFilledRect( x, y + h - 2, x + w, y + h );
+ surface()->DrawFilledRect( x, y, x + 2, y + h );
+ surface()->DrawFilledRect( x + w - 2, y, x + w, y + h );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// CDmePresetListPanel
+//
+// Declaration above because of scoping issues
+//
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CDmePresetListPanel::CDmePresetListPanel( vgui::Panel *pParent, const char *pName, CDmePresetGroupEditorPanel *pComboPanel ) :
+ BaseClass( pParent, pName ), m_pPresetGroupPanel( pComboPanel )
+{
+}
+
+void CDmePresetListPanel::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ CDmePresetGroup *pPresetGroup = m_pPresetGroupPanel->GetSelectedPresetGroup();
+ if ( pPresetGroup && !pPresetGroup->m_bIsReadOnly )
+ {
+ if ( code == KEY_DELETE || code == KEY_BACKSPACE )
+ {
+ m_pPresetGroupPanel->OnRemovePreset();
+ return;
+ }
+
+ // Not sure how to handle 'edit' mode... the relevant stuff is private
+ if ( vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT ) )
+ {
+ if ( code == KEY_UP )
+ {
+ m_pPresetGroupPanel->OnMovePresetUp();
+ return;
+ }
+
+ if ( code == KEY_DOWN )
+ {
+ m_pPresetGroupPanel->OnMovePresetDown();
+ return;
+ }
+ }
+ }
+
+ vgui::ListPanel::OnKeyCodeTyped( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmePresetListPanel::OnCreateDragData( KeyValues *msg )
+{
+ CDmePresetGroup *pPresetGroup = m_pPresetGroupPanel->GetSelectedPresetGroup();
+ if ( pPresetGroup->m_bIsReadOnly )
+ return;
+
+ CDmePreset *pPreset = m_pPresetGroupPanel->GetSelectedPreset();
+ if ( !pPreset )
+ return;
+
+ SetElementKeyValue( msg, "preset", pPreset );
+ msg->SetInt( "selfDroppable", 1 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+bool CDmePresetListPanel::IsDroppable( CUtlVector< KeyValues * >& msgList )
+{
+ if ( msgList.Count() > 0 )
+ {
+ KeyValues *pData( msgList[ 0 ] );
+ if ( pData->GetPtr( "panel", NULL ) == this && m_pPresetGroupPanel )
+ {
+ CDmePreset *pPreset = GetElementKeyValue< CDmePreset >( pData, "preset" );
+ if ( pPreset )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmePresetListPanel::OnPanelDropped( CUtlVector< KeyValues * >& msgList )
+{
+ if ( msgList.Count() == 0 )
+ return;
+
+ KeyValues *pData = msgList[ 0 ];
+ if ( pData->GetPtr( "panel", NULL ) != this || !m_pPresetGroupPanel )
+ return;
+
+ // Discover the cell the panel is over
+ int x, y, row, column;
+ vgui::input()->GetCursorPos( x, y );
+ GetCellAtPos( x, y, row, column );
+
+ KeyValues *pKeyValues = GetItem( row );
+
+ CDmePreset *pDragPreset = GetElementKeyValue<CDmePreset>( pData, "preset" );
+ if ( pDragPreset )
+ {
+ CDmePreset *pDropPreset = pKeyValues ? GetElementKeyValue<CDmePreset>( pKeyValues, "preset" ) : NULL;
+ m_pPresetGroupPanel->MovePresetInFrontOf( pDragPreset, pDropPreset );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Mouse is now over a droppable panel
+//-----------------------------------------------------------------------------
+void CDmePresetListPanel::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
+{
+ // Discover the cell the panel is over
+ int x, y, w, h, row, column;
+ vgui::input()->GetCursorPos( x, y );
+ GetCellAtPos( x, y, row, column );
+ GetCellBounds( row, column, x, y, w, h );
+ LocalToScreen( x, y );
+
+ surface()->DrawSetColor( GetDropFrameColor() );
+
+ // Draw insertion point
+ surface()->DrawFilledRect( x, y, x + w, y + 2 );
+ surface()->DrawFilledRect( x, y + h - 2, x + w, y + h );
+ surface()->DrawFilledRect( x, y, x + 2, y + h );
+ surface()->DrawFilledRect( x + w - 2, y, x + w, y + h );
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Combination system editor frame
+//
+//-----------------------------------------------------------------------------
+CDmePresetGroupEditorFrame::CDmePresetGroupEditorFrame( vgui::Panel *pParent, const char *pTitle ) :
+ BaseClass( pParent, "DmePresetGroupEditorFrame" )
+{
+ SetDeleteSelfOnClose( true );
+ m_pEditor = new CDmePresetGroupEditorPanel( this, "DmePresetGroupEditorPanel" );
+ m_pEditor->AddActionSignalTarget( this );
+ m_pOkButton = new vgui::Button( this, "OkButton", "#VGui_OK", this, "Ok" );
+ SetBlockDragChaining( true );
+
+ LoadControlSettingsAndUserConfig( "resource/dmepresetgroupeditorframe.res" );
+
+ SetTitle( pTitle, false );
+ g_pDataModel->InstallNotificationCallback( this );
+}
+
+CDmePresetGroupEditorFrame::~CDmePresetGroupEditorFrame()
+{
+ g_pDataModel->RemoveNotificationCallback( this );
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the current scene + animation list
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorFrame::SetAnimationSet( CDmeAnimationSet *pComboSystem )
+{
+ m_pEditor->SetAnimationSet( pComboSystem );
+}
+
+
+//-----------------------------------------------------------------------------
+// On command
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorFrame::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "Ok" ) )
+ {
+ CloseModal();
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
+//-----------------------------------------------------------------------------
+// Inherited from IDmNotify
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorFrame::NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
+{
+ if ( !IsVisible() )
+ return;
+
+ if ( nNotifySource == NOTIFY_SOURCE_PRESET_GROUP_EDITOR )
+ return;
+
+ m_pEditor->RefreshAnimationSet();
+}
+
+
+//-----------------------------------------------------------------------------
+// Chains notification messages from the contained panel to external clients
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorFrame::OnPresetsChanged()
+{
+ PostActionSignal( new KeyValues( "PresetsChanged" ) );
+}
+
+void CDmePresetGroupEditorFrame::OnAddNewPreset( KeyValues *pKeyValues )
+{
+ PostActionSignal( pKeyValues->MakeCopy() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Various command handlers related to the Edit menu
+//-----------------------------------------------------------------------------
+void CDmePresetGroupEditorFrame::OnUndo()
+{
+ if ( g_pDataModel->CanUndo() )
+ {
+ CDisableUndoScopeGuard guard;
+ g_pDataModel->Undo();
+ }
+}
+
+void CDmePresetGroupEditorFrame::OnRedo()
+{
+ if ( g_pDataModel->CanRedo() )
+ {
+ CDisableUndoScopeGuard guard;
+ g_pDataModel->Redo();
+ }
+}