summaryrefslogtreecommitdiff
path: root/vgui2/dme_controls/dmecombinationsystemeditorpanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vgui2/dme_controls/dmecombinationsystemeditorpanel.cpp')
-rw-r--r--vgui2/dme_controls/dmecombinationsystemeditorpanel.cpp2150
1 files changed, 2150 insertions, 0 deletions
diff --git a/vgui2/dme_controls/dmecombinationsystemeditorpanel.cpp b/vgui2/dme_controls/dmecombinationsystemeditorpanel.cpp
new file mode 100644
index 0000000..5d6efaf
--- /dev/null
+++ b/vgui2/dme_controls/dmecombinationsystemeditorpanel.cpp
@@ -0,0 +1,2150 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "dme_controls/dmecombinationsystemeditorpanel.h"
+#include "dme_controls/dmepanel.h"
+#include "dme_controls/elementpropertiestree.h"
+#include "dme_controls/dmecontrols_utils.h"
+#include "movieobjects/dmecombinationoperator.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/InputDialog.h"
+#include "vgui_controls/TextEntry.h"
+#include "vgui_controls/FileOpenDialog.h"
+#include "vgui_controls/perforcefilelistframe.h"
+#include "vgui/MouseCode.h"
+#include "vgui/IInput.h"
+#include "tier1/KeyValues.h"
+#include "tier2/fileutils.h"
+
+
+//-----------------------------------------------------------------------------
+//
+// Hook into the dme panel editor system
+//
+//-----------------------------------------------------------------------------
+IMPLEMENT_DMEPANEL_FACTORY( CDmeCombinationSystemEditorPanel, DmeCombinationOperator, "DmeCombinationOperatorEditor", "Combination Operator Editor", true );
+
+
+// Forward declaration
+class CDmeCombinationControlsPanel;
+
+
+//-----------------------------------------------------------------------------
+// Import combination rules from this operator
+//-----------------------------------------------------------------------------
+static void ImportCombinationControls( CDmeCombinationOperator *pDestComboOp, CDmeCombinationOperator *pSrcComboOp, COperationFileListFrame *pStatusFrame )
+{
+ pDestComboOp->RemoveAllControls();
+
+ // Iterate through all controls in the imported operator.
+ // For each control that contains at least 1 raw controls
+ // that also exist in this combination op, create a control here also.
+ int nCount = pSrcComboOp->GetControlCount();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ const char *pControlName = pSrcComboOp->GetControlName( i );
+
+ int nRawControls = pSrcComboOp->GetRawControlCount( i );
+ int nMatchCount = 0;
+ bool *pFoundMatch = (bool*)_alloca( nRawControls * sizeof(bool) );
+ for ( int j = 0; j < nRawControls; ++j )
+ {
+ const char *pRawControl = pSrcComboOp->GetRawControlName( i, j );
+ pFoundMatch[j] = pDestComboOp->DoesTargetContainDeltaState( pRawControl );
+ nMatchCount += pFoundMatch[j];
+ }
+
+ // No match? Don't import
+ if ( nMatchCount == 0 )
+ {
+ pStatusFrame->AddOperation( pControlName, "No raw controls found!" );
+ continue;
+ }
+
+ bool bPartialMatch = ( nMatchCount != nRawControls );
+ pStatusFrame->AddOperation( pControlName, bPartialMatch ? "Partial rule match" : "Successful" );
+
+ // Found a match! Let's create the control and potentially raw control
+ bool bIsStereo = pSrcComboOp->IsStereoControl( i );
+ bool bIsEyelid = pSrcComboOp->IsEyelidControl( i );
+ ControlIndex_t index = pDestComboOp->FindOrCreateControl( pControlName, bIsStereo );
+ pDestComboOp->SetEyelidControl( index, bIsEyelid );
+ for ( int j = 0; j < nRawControls; ++j )
+ {
+ if ( pFoundMatch[j] )
+ {
+ const char *pRawControl = pSrcComboOp->GetRawControlName( i, j );
+ float flWrinkleScale = pSrcComboOp->GetRawControlWrinkleScale( i, j );
+
+ pDestComboOp->AddRawControl( index, pRawControl );
+ pDestComboOp->SetWrinkleScale( index, pRawControl, flWrinkleScale );
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Import dominance rules from this operator
+//-----------------------------------------------------------------------------
+static void ImportDominationRules( CDmeCombinationOperator *pDestComboOp, CDmeCombinationOperator *pSrcComboOp, COperationFileListFrame *pStatusFrame )
+{
+ pDestComboOp->RemoveAllDominationRules();
+
+ // Now deal with dominance rules
+ int nRuleCount = pSrcComboOp->DominationRuleCount();
+ for ( int i = 0; i < nRuleCount; ++i )
+ {
+ bool bMismatch = false;
+
+ // Only add dominance rule if *all* raw controls are present
+ CDmeCombinationDominationRule *pSrcRule = pSrcComboOp->GetDominationRule( i );
+ int nDominatorCount = pSrcRule->DominatorCount();
+ for ( int j = 0; j < nDominatorCount; ++j )
+ {
+ const char *pDominatorName = pSrcRule->GetDominator( j );
+ if ( !pDestComboOp->HasRawControl( pDominatorName ) )
+ {
+ bMismatch = true;
+ pStatusFrame->AddOperation( pDominatorName, "Missing raw control for dominance rule" );
+ break;
+ }
+ }
+
+ int nSuppressedCount = pSrcRule->SuppressedCount();
+ for ( int j = 0; j < nSuppressedCount; ++j )
+ {
+ const char *pSuppressedName = pSrcRule->GetSuppressed( j );
+ if ( !pDestComboOp->HasRawControl( pSuppressedName ) )
+ {
+ bMismatch = true;
+ pStatusFrame->AddOperation( pSuppressedName, "Missing raw control for dominance rule" );
+ break;
+ }
+ }
+
+ if ( bMismatch )
+ continue;
+
+ pDestComboOp->AddDominationRule( pSrcRule );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for browsing source files selects something
+//-----------------------------------------------------------------------------
+static bool ImportCombinationData( vgui::Panel* pParent, CDmeCombinationOperator *pDestComboOp, KeyValues *kv )
+{
+ const char *pFileName = kv->GetString( "fullpath", NULL );
+ if ( !pFileName )
+ return false;
+
+ CDmElement *pRoot;
+
+ {
+ CDisableUndoScopeGuard sg;
+ g_pDataModel->RestoreFromFile( pFileName, NULL, NULL, &pRoot, CR_FORCE_COPY );
+ }
+
+ if ( !pRoot )
+ return false;
+
+ // Try to find a combination system in the file
+ CDmeCombinationOperator *pComboOp = CastElement<CDmeCombinationOperator>( pRoot );
+ if ( !pComboOp )
+ {
+ pComboOp = pRoot->GetValueElement< CDmeCombinationOperator >( "combinationOperator" );
+ }
+
+ if ( pComboOp )
+ {
+ // Actually rename the files, build an error dialog if necessary
+ COperationFileListFrame *pStatusFrame = new COperationFileListFrame( pParent,
+ "Import Status", "Status", false, true );
+ pStatusFrame->SetOperationColumnHeaderText( "Control Name" );
+
+ CUndoScopeGuard sg( "Import Combination Rules" );
+ if ( kv->FindKey( "ImportControls" ) )
+ {
+ ImportCombinationControls( pDestComboOp, pComboOp, pStatusFrame );
+ }
+ ImportDominationRules( pDestComboOp, pComboOp, pStatusFrame );
+ sg.Release();
+
+ pStatusFrame->DoModal();
+ }
+
+ CDisableUndoScopeGuard sg;
+ g_pDataModel->UnloadFile( pRoot->GetFileId() );
+ sg.Release();
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// CDmeInputControlListPanel
+//
+// Implementation below because of scoping issues
+//
+//
+//-----------------------------------------------------------------------------
+class CDmeInputControlListPanel : public vgui::ListPanel
+{
+ DECLARE_CLASS_SIMPLE( CDmeInputControlListPanel, vgui::ListPanel );
+
+public:
+ // constructor, destructor
+ CDmeInputControlListPanel( vgui::Panel *pParent, const char *pName, CDmeCombinationControlsPanel *pComboPanel );
+
+ virtual void OnCreateDragData( KeyValues *msg );
+ virtual bool IsDroppable( CUtlVector< KeyValues * >& msgList );
+ virtual void OnPanelDropped( CUtlVector< KeyValues * >& msgList );
+ virtual void OnKeyCodeTyped( vgui::KeyCode code );
+
+private:
+ CDmeCombinationControlsPanel *m_pComboPanel;
+};
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// CDmeRawControlListPanel
+//
+// Implementation below because of scoping issues
+//
+//
+//-----------------------------------------------------------------------------
+class CDmeRawControlListPanel : public vgui::ListPanel
+{
+ DECLARE_CLASS_SIMPLE( CDmeRawControlListPanel, vgui::ListPanel );
+
+public:
+ // constructor, destructor
+ CDmeRawControlListPanel( vgui::Panel *pParent, const char *pName, CDmeCombinationControlsPanel *pComboPanel );
+
+ virtual void OnKeyCodeTyped( vgui::KeyCode code );
+ virtual void OnMouseDoublePressed( vgui::MouseCode code );
+
+private:
+ MESSAGE_FUNC( OnNewWrinkleText, "TextNewLine" );
+
+ CDmeCombinationControlsPanel *m_pComboPanel;
+ vgui::TextEntry *m_pWrinkleEdit;
+ bool m_bIsWrinkle;
+};
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// Slider panel
+//
+//
+//-----------------------------------------------------------------------------
+class CDmeCombinationControlsPanel : public vgui::EditablePanel
+{
+ DECLARE_CLASS_SIMPLE( CDmeCombinationControlsPanel, vgui::EditablePanel );
+
+public:
+ // constructor, destructor
+ CDmeCombinationControlsPanel( vgui::Panel *pParent, const char *pName );
+ virtual ~CDmeCombinationControlsPanel();
+
+ void SetCombinationOperator( CDmeCombinationOperator *pOp );
+ CDmeCombinationOperator* GetCombinationOperator();
+ void RefreshCombinationOperator();
+ void NotifyDataChanged();
+
+ const char *GetSelectedControlName();
+ void MoveControlInFrontOf( const char *pDragControl, const char *pDropControl );
+
+ void SetRawControlWrinkleValue( float flWrinkleValue );
+
+ int GetSelectedInputControlItemId();
+ void SelectedInputControlByItemId( int );
+
+ MESSAGE_FUNC( OnMoveUpInputControl, "MoveUpInputControl" );
+ MESSAGE_FUNC( OnMoveDownInputControl, "MoveDownInputControl" );
+ MESSAGE_FUNC( OnMoveUp, "MoveUp" );
+ MESSAGE_FUNC( OnMoveDown, "MoveDown" );
+
+private:
+ MESSAGE_FUNC_PARAMS( OnOpenContextMenu, "OpenContextMenu", kv );
+ MESSAGE_FUNC_PARAMS( OnInputCompleted, "InputCompleted", kv );
+ MESSAGE_FUNC( OnGroupControls, "GroupControls" );
+ MESSAGE_FUNC( OnUngroupControls, "UngroupControls" );
+ MESSAGE_FUNC( OnRenameControl, "RenameControl" );
+ MESSAGE_FUNC( OnImportCombination, "ImportCombination" );
+ MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", kv );
+ MESSAGE_FUNC( OnToggleStereoControl, "ToggleStereoControl" );
+ MESSAGE_FUNC( OnToggleEyelidControl, "ToggleEyelidControl" );
+ MESSAGE_FUNC( OnToggleWrinkleType, "ToggleWrinkleType" );
+ MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", kv );
+ MESSAGE_FUNC_PARAMS( OnItemDeselected, "ItemDeselected", kv );
+
+ // Cleans up the context menu
+ void CleanupContextMenu();
+
+ // Builds a list of selected control + raw control names, returns true if any control is stereo
+ void BuildSelectedControlLists( bool bOnlyGroupedControls, CUtlVector< CUtlString >& controlNames, CUtlVector< CUtlString >& rawControlNames, bool *pbStereo = NULL, bool *pbEyelid = NULL );
+
+ // If it finds a duplicate control name, reports an error message and returns it found one
+ bool HasDuplicateControlName( const char *pControlName, CUtlVector< CUtlString >& retiredControlNames );
+
+ // Refreshes the list of raw controls
+ void RefreshRawControlNames();
+
+ // Called by OnGroupControls and OnRenameControl after we get a new group name
+ void PerformGroupControls( const char *pGroupedControlName );
+
+ // Called by OnGroupControls after we get a new group name
+ void PerformRenameControl( const char *pNewControlName );
+
+ // Called to open a context-sensitive menu for a particular menu item
+ void OnOpenRawControlsContextMenu( );
+
+ // Called to open a context-sensitive menu for a particular menu item
+ const char* GetSelectedRawControl( ControlIndex_t &nControlIndex );
+
+ CDmeHandle< CDmeCombinationOperator > m_hCombinationOperator;
+ vgui::Splitter *m_pSplitter;
+ CDmeInputControlListPanel *m_pControlList;
+ CDmeRawControlListPanel *m_pRawControlList;
+ vgui::DHANDLE< vgui::Menu > m_hContextMenu;
+};
+
+
+//-----------------------------------------------------------------------------
+// Sort functions for list panel
+//-----------------------------------------------------------------------------
+static int __cdecl ControlNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("name");
+ const char *string2 = item2.kv->GetString("name");
+ return Q_stricmp( string1, string2 );
+}
+
+static int __cdecl PeakSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
+{
+ float flPeak1 = item1.kv->GetFloat("peak");
+ float flPeak2 = item2.kv->GetFloat("peak");
+ if ( flPeak1 < flPeak2 )
+ return -1;
+ if ( flPeak1 > flPeak2 )
+ return 1;
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+CDmeCombinationControlsPanel::CDmeCombinationControlsPanel( vgui::Panel *pParent, const char *pName ) :
+ BaseClass( pParent, pName )
+{
+ m_pSplitter = new vgui::Splitter( this, "ControlsSplitter", vgui::SPLITTER_MODE_VERTICAL, 1 );
+ vgui::Panel *pSplitterLeftSide = m_pSplitter->GetChild( 0 );
+ vgui::Panel *pSplitterRightSide = m_pSplitter->GetChild( 1 );
+
+ m_pControlList = new CDmeInputControlListPanel( pSplitterLeftSide, "ControlList", this );
+ m_pControlList->AddColumnHeader( 0, "name", "Control Name", 150, 0 );
+ m_pControlList->AddColumnHeader( 1, "stereo", "Stereo", 70, 0 );
+ m_pControlList->AddColumnHeader( 2, "eyelid", "Eyelid", 70, 0 );
+ m_pControlList->AddColumnHeader( 3, "default", "Default", 52, 0 );
+ m_pControlList->SetSelectIndividualCells( false );
+ m_pControlList->SetMultiselectEnabled( true );
+ m_pControlList->SetEmptyListText( "No controls" );
+ m_pControlList->AddActionSignalTarget( this );
+ m_pControlList->SetSortFunc( 0, NULL );
+ m_pControlList->SetColumnSortable( 0, false );
+ m_pControlList->SetSortFunc( 1, NULL );
+ m_pControlList->SetColumnSortable( 1, false );
+ m_pControlList->SetSortFunc( 2, NULL );
+ m_pControlList->SetColumnSortable( 2, false );
+ m_pControlList->SetSortFunc( 3, NULL );
+ m_pControlList->SetColumnSortable( 3, false );
+ m_pControlList->SetDragEnabled( true );
+ m_pControlList->SetDragEnabled( true );
+ m_pControlList->SetDropEnabled( true );
+
+ m_pRawControlList = new CDmeRawControlListPanel( pSplitterRightSide, "RawControlList", this );
+ m_pRawControlList->AddColumnHeader( 0, "name", "Raw Control Name", 150, 0 );
+ m_pRawControlList->AddColumnHeader( 1, "peak", "Peak", 52, 0 );
+ m_pRawControlList->AddColumnHeader( 2, "wrinkletype", "Wrinkle Type", 100, 0 );
+ m_pRawControlList->AddColumnHeader( 3, "wrinkle", "Wrinkle Amount", 100, 0 );
+ m_pRawControlList->SetSelectIndividualCells( false );
+ m_pRawControlList->SetEmptyListText( "No raw controls" );
+ m_pRawControlList->AddActionSignalTarget( this );
+ m_pRawControlList->SetSortFunc( 0, ControlNameSortFunc );
+ m_pRawControlList->SetSortFunc( 1, PeakSortFunc );
+ m_pRawControlList->SetSortFunc( 2, NULL );
+ m_pRawControlList->SetColumnSortable( 2, false );
+ m_pRawControlList->SetSortFunc( 3, NULL );
+ m_pRawControlList->SetColumnSortable( 3, false );
+ m_pRawControlList->SetSortColumn( 1 );
+}
+
+
+CDmeCombinationControlsPanel::~CDmeCombinationControlsPanel()
+{
+ CleanupContextMenu();
+ SaveUserConfig();
+}
+
+
+//-----------------------------------------------------------------------------
+// Cleans up the context menu
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::CleanupContextMenu()
+{
+ if ( m_hContextMenu.Get() )
+ {
+ m_hContextMenu->MarkForDeletion();
+ m_hContextMenu = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the combination operator
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::SetCombinationOperator( CDmeCombinationOperator *pOp )
+{
+ if ( pOp != m_hCombinationOperator.Get() )
+ {
+ m_hCombinationOperator = pOp;
+ RefreshCombinationOperator();
+ }
+}
+
+CDmeCombinationOperator* CDmeCombinationControlsPanel::GetCombinationOperator()
+{
+ return m_hCombinationOperator;
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds the control list for the combination operator
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::RefreshCombinationOperator()
+{
+ const CUtlString controlName = GetSelectedControlName();
+
+ m_pControlList->RemoveAll();
+ if ( !m_hCombinationOperator.Get() )
+ return;
+
+ int nCount = m_hCombinationOperator->GetControlCount();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ bool bIsMultiControl = m_hCombinationOperator->GetRawControlCount(i) > 1;
+ float flDefault = m_hCombinationOperator->GetRawControlCount(i) == 2 ? 0.5f : 0.0f;
+ const char *pName = m_hCombinationOperator->GetControlName( i );
+ KeyValues *kv = new KeyValues( "node", "name", pName );
+ kv->SetString( "stereo", m_hCombinationOperator->IsStereoControl(i) ? "On" : "Off" );
+ kv->SetString( "eyelid", m_hCombinationOperator->IsEyelidControl(i) ? "On" : "Off" );
+ kv->SetFloat( "default", flDefault );
+ kv->SetColor( "cellcolor", bIsMultiControl ? Color( 192, 192, 0, 255 ) : Color( 255, 255, 255, 255 ) );
+ const int nItemId = m_pControlList->AddItem( kv, 0, false, false );
+
+ if ( !Q_strcmp( controlName.Get(), pName ) )
+ {
+ m_pControlList->SetSingleSelectedItem( nItemId );
+ }
+ }
+
+ RefreshRawControlNames();
+}
+
+
+//-----------------------------------------------------------------------------
+// Tells any class that cares that the data in this thing has changed
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::NotifyDataChanged()
+{
+ PostActionSignal( new KeyValues( "DmeElementChanged", "DmeCombinationControlsPanel", 1 ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Refreshes the list of raw controls
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::RefreshRawControlNames()
+{
+ m_pRawControlList->RemoveAll();
+ if ( !m_hCombinationOperator.Get() )
+ return;
+
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ int nItemID = m_pControlList->GetSelectedItem( 0 );
+
+ KeyValues *pKeyValues = m_pControlList->GetItem( nItemID );
+ const char *pControlName = pKeyValues->GetString( "name" );
+ ControlIndex_t nControlIndex = m_hCombinationOperator->FindControlIndex( pControlName );
+ if ( nControlIndex < 0 )
+ return;
+
+ int nCount = m_hCombinationOperator->GetRawControlCount( nControlIndex );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ KeyValues *kv = new KeyValues( "node", "name", m_hCombinationOperator->GetRawControlName( nControlIndex, i ) );
+ switch( nCount )
+ {
+ case 0:
+ case 1:
+ kv->SetFloat( "peak", 1.0f );
+ break;
+
+ case 2:
+ kv->SetFloat( "peak", i == 0 ? 0.0f : 1.0f );
+ break;
+
+ default:
+ kv->SetFloat( "peak", (float)i / (nCount - 1) );
+ break;
+ }
+
+ float flWrinkleScale = m_hCombinationOperator->GetRawControlWrinkleScale( nControlIndex, i );
+ kv->SetString( "wrinkletype", ( flWrinkleScale < 0.0f ) ? "Compress" : "Stretch" );
+ kv->SetFloat( "wrinkle", fabs( flWrinkleScale ) );
+ m_pRawControlList->AddItem( kv, 0, false, false );
+ }
+
+ m_pRawControlList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+const char* CDmeCombinationControlsPanel::GetSelectedRawControl( ControlIndex_t &nControlIndex )
+{
+ if ( !m_hCombinationOperator.Get() )
+ return NULL;
+
+ nControlIndex = -1;
+
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return NULL;
+
+ int nSelectedRawItemCount = m_pRawControlList->GetSelectedItemsCount();
+ if ( nSelectedRawItemCount != 1 )
+ return NULL;
+
+ int nItemID = m_pControlList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pControlList->GetItem( nItemID );
+ const char *pControlName = pKeyValues->GetString( "name" );
+ nControlIndex = m_hCombinationOperator->FindControlIndex( pControlName );
+
+ nItemID = m_pRawControlList->GetSelectedItem( 0 );
+ pKeyValues = m_pRawControlList->GetItem( nItemID );
+ return pKeyValues->GetString( "name" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+const char *CDmeCombinationControlsPanel::GetSelectedControlName()
+{
+ if ( !m_hCombinationOperator.Get() )
+ return NULL;
+
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return NULL;
+
+ const int nItemId = m_pControlList->GetSelectedItem( 0 );
+ if ( !m_pControlList->IsValidItemID( nItemId ) )
+ return NULL;
+
+ KeyValues *pKeyValues = m_pControlList->GetItem( nItemId );
+ if ( !pKeyValues )
+ return NULL;
+
+ return pKeyValues->GetString( "name" );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+int CDmeCombinationControlsPanel::GetSelectedInputControlItemId()
+{
+ return m_pControlList->GetSelectedItem( 0 );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::SelectedInputControlByItemId( int nItemId )
+{
+ m_pControlList->SetSingleSelectedItem( nItemId );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnMoveUp()
+{
+ ControlIndex_t nControlIndex;
+ const char *pRawControlName = GetSelectedRawControl( nControlIndex );
+ if ( !pRawControlName )
+ return;
+
+ m_hCombinationOperator->MoveRawControlUp( nControlIndex, pRawControlName );
+ RefreshRawControlNames();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnMoveDown()
+{
+ ControlIndex_t nControlIndex;
+ const char *pRawControlName = GetSelectedRawControl( nControlIndex );
+ if ( !pRawControlName )
+ return;
+
+ m_hCombinationOperator->MoveRawControlDown( nControlIndex, pRawControlName );
+ RefreshRawControlNames();
+
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnMoveUpInputControl()
+{
+ const char *pControlName = GetSelectedControlName();
+ if ( !pControlName )
+ return;
+
+ m_hCombinationOperator->MoveControlUp( pControlName );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnMoveDownInputControl()
+{
+ const char *pControlName = GetSelectedControlName();
+ if ( !pControlName )
+ return;
+
+ m_hCombinationOperator->MoveControlDown( pControlName );
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::MoveControlInFrontOf(
+ const char *pDragControl,
+ const char *pDropControl )
+{
+ m_hCombinationOperator->MoveControlBefore( pDragControl, pDropControl );
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Toggles the wrinkle type
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnToggleWrinkleType()
+{
+ ControlIndex_t nControlIndex;
+ const char *pRawControlName = GetSelectedRawControl( nControlIndex );
+ if ( !pRawControlName )
+ return;
+
+ float flWrinkleScale = m_hCombinationOperator->GetRawControlWrinkleScale( nControlIndex, pRawControlName );
+ m_hCombinationOperator->SetWrinkleScale( nControlIndex, pRawControlName, -flWrinkleScale );
+ RefreshRawControlNames();
+ m_hCombinationOperator->GenerateWrinkleDeltas();
+}
+
+
+void CDmeCombinationControlsPanel::SetRawControlWrinkleValue( float flWrinkleValue )
+{
+ ControlIndex_t nControlIndex;
+ const char *pRawControlName = GetSelectedRawControl( nControlIndex );
+ if ( !pRawControlName )
+ return;
+
+ m_hCombinationOperator->SetWrinkleScale( nControlIndex, pRawControlName, flWrinkleValue );
+ RefreshRawControlNames();
+ m_hCombinationOperator->GenerateWrinkleDeltas();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnOpenRawControlsContextMenu( )
+{
+ if ( !m_hCombinationOperator.Get() )
+ return;
+
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ int nSelectedRawItemCount = m_pRawControlList->GetSelectedItemsCount();
+ if ( nSelectedRawItemCount != 1 )
+ return;
+
+ m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_MoveUp", new KeyValues( "MoveUp" ), this );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_MoveDown", new KeyValues( "MoveDown" ), this );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_ToggleWrinkleType", new KeyValues( "ToggleWrinkleType" ), this );
+
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnOpenContextMenu( KeyValues *kv )
+{
+ CleanupContextMenu();
+ if ( !m_hCombinationOperator.Get() )
+ return;
+
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pRawControlList )
+ {
+ OnOpenRawControlsContextMenu();
+ return;
+ }
+
+ if ( pPanel != m_pControlList )
+ return;
+
+ bool bGroupedControls = false;
+ bool bStereoControls = false;
+ bool bEyelidControls = false;
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ for ( int i = 0; i < nSelectedItemCount; ++i )
+ {
+ int nItemID = m_pControlList->GetSelectedItem( i );
+
+ KeyValues *pKeyValues = m_pControlList->GetItem( nItemID );
+ const char *pControlName = pKeyValues->GetString( "name" );
+ ControlIndex_t nControlIndex = m_hCombinationOperator->FindControlIndex( pControlName );
+ if ( nControlIndex < 0 )
+ continue;
+
+ if ( m_hCombinationOperator->GetRawControlCount( nControlIndex ) > 1 )
+ {
+ bGroupedControls = true;
+ }
+
+ if ( m_hCombinationOperator->IsStereoControl( nControlIndex ) )
+ {
+ bStereoControls = true;
+ }
+
+ if ( m_hCombinationOperator->IsEyelidControl( nControlIndex ) )
+ {
+ bEyelidControls = true;
+ }
+ }
+
+ m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
+
+ if ( nSelectedItemCount > 1 )
+ {
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_GroupControls", new KeyValues( "GroupControls" ), this );
+ }
+
+ if ( bGroupedControls )
+ {
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_UngroupControls", new KeyValues( "UngroupControls" ), this );
+ }
+
+ if ( nSelectedItemCount >= 1 )
+ {
+ int nMenuItemID = m_hContextMenu->AddCheckableMenuItem( "#DmeCombinationSystemEditor_StereoControl", new KeyValues( "ToggleStereoControl" ), this );
+ m_hContextMenu->SetMenuItemChecked( nMenuItemID, bStereoControls );
+ }
+
+ if ( nSelectedItemCount >= 1 )
+ {
+ int nMenuItemID = m_hContextMenu->AddCheckableMenuItem( "#DmeCombinationSystemEditor_EyelidControl", new KeyValues( "ToggleEyelidControl" ), this );
+ m_hContextMenu->SetMenuItemChecked( nMenuItemID, bEyelidControls );
+ }
+
+ if ( nSelectedItemCount == 1 )
+ {
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_RenameControl", new KeyValues( "RenameControl" ), this );
+ }
+
+ if ( nSelectedItemCount >= 1 )
+ {
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_MoveUp", new KeyValues( "MoveUpInputControl" ), this );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_MoveDown", new KeyValues( "MoveDownInputControl" ), this );
+ }
+
+ if ( nSelectedItemCount >= 1 || bGroupedControls )
+ {
+ m_hContextMenu->AddSeparator();
+ }
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_Import", new KeyValues( "ImportCombination" ), this );
+
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnItemSelected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pControlList )
+ {
+ RefreshRawControlNames();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnItemDeselected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pControlList )
+ {
+ RefreshRawControlNames();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds a list of selected control + raw control names, returns true if any control is stereo
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::BuildSelectedControlLists(
+ bool bOnlyGroupedControls,
+ CUtlVector< CUtlString >& controlNames, CUtlVector< CUtlString >& rawControlNames,
+ bool *pbStereo, bool *pbEyelid )
+{
+ bool bIsStereo = false;
+ bool bIsEyelid = false;
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ for ( int i = 0; i < nSelectedItemCount; ++i )
+ {
+ int nItemID = m_pControlList->GetSelectedItem( i );
+
+ KeyValues *pKeyValues = m_pControlList->GetItem( nItemID );
+ const char *pControlName = pKeyValues->GetString( "name" );
+ ControlIndex_t nControlIndex = m_hCombinationOperator->FindControlIndex( pControlName );
+ if ( nControlIndex < 0 )
+ continue;
+
+ int nRawControlCount = m_hCombinationOperator->GetRawControlCount( nControlIndex );
+ if ( bOnlyGroupedControls && ( nRawControlCount <= 1 ) )
+ continue;
+
+ if ( m_hCombinationOperator->IsStereoControl( nControlIndex ) )
+ {
+ bIsStereo = true;
+ }
+
+ if ( m_hCombinationOperator->IsEyelidControl( nControlIndex ) )
+ {
+ bIsEyelid = true;
+ }
+
+ controlNames.AddToTail( pControlName );
+ for ( int j = 0; j < nRawControlCount; ++j )
+ {
+ rawControlNames.AddToTail( m_hCombinationOperator->GetRawControlName( nControlIndex, j ) );
+ }
+ }
+
+ if ( pbStereo )
+ {
+ *pbStereo = bIsStereo;
+ }
+
+ if ( pbEyelid )
+ {
+ *pbEyelid = bIsEyelid;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// If it finds a duplicate control name, reports an error message and returns it found one
+//-----------------------------------------------------------------------------
+bool CDmeCombinationControlsPanel::HasDuplicateControlName( const char *pControlName, CUtlVector< CUtlString >& retiredControlNames )
+{
+ int i;
+ int nRetiredControlNameCount = retiredControlNames.Count();
+ for ( i = 0; i < nRetiredControlNameCount; ++i )
+ {
+ if ( !Q_stricmp( retiredControlNames[i], pControlName ) )
+ break;
+ }
+ if ( i == nRetiredControlNameCount )
+ {
+ // no match
+ if ( m_hCombinationOperator->FindControlIndex( pControlName ) >= 0 )
+ {
+ vgui::MessageBox *pError = new vgui::MessageBox( "#DmeCombinationSystemEditor_DuplicateNameTitle", "#DmeCombinationSystemEditor_DuplicateNameText", this );
+ pError->DoModal();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnGroupControls and OnRenameControl after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::PerformGroupControls( const char *pGroupedControlName )
+{
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount <= 1 )
+ return;
+
+ // Build lists of selected controls + raw controls
+ CUtlVector< CUtlString > controlNames;
+ CUtlVector< CUtlString > rawControlNames;
+ bool bIsStereo = false;
+ bool bIsEyelid = false;
+ BuildSelectedControlLists( false, controlNames, rawControlNames, &bIsStereo, &bIsEyelid );
+
+ // NOTE: It's illegal to use a grouped control name which already exists
+ // assuming it's not in the list of grouped control names we're going to group together
+ if ( HasDuplicateControlName( pGroupedControlName, controlNames ) )
+ return;
+
+ // Delete old controls
+ int nRetiredControlNameCount = controlNames.Count();
+ for ( int i = 0; i < nRetiredControlNameCount; ++i )
+ {
+ m_hCombinationOperator->RemoveControl( controlNames[i] );
+ }
+
+ // Create new control
+ ControlIndex_t nNewControl = m_hCombinationOperator->FindOrCreateControl( pGroupedControlName, bIsStereo );
+ m_hCombinationOperator->SetEyelidControl( nNewControl, bIsEyelid );
+ int nGroupedControlCount = rawControlNames.Count();
+ for ( int i = 0; i < nGroupedControlCount; ++i )
+ {
+ m_hCombinationOperator->AddRawControl( nNewControl, rawControlNames[i] );
+ }
+
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnGroupControls after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::PerformRenameControl( const char *pNewControlName )
+{
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ int nItemID = m_pControlList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pControlList->GetItem( nItemID );
+ const char *pControlName = pKeyValues->GetString( "name" );
+ ControlIndex_t nControlIndex = m_hCombinationOperator->FindControlIndex( pControlName );
+ if ( nControlIndex < 0 )
+ return;
+
+ // NOTE: It's illegal to use a grouped control name which already exists
+ // assuming it's not in the list of grouped control names we're going to group together
+ ControlIndex_t nFoundIndex = m_hCombinationOperator->FindControlIndex( pNewControlName );
+ if ( nFoundIndex >= 0 && nFoundIndex != nControlIndex )
+ return;
+
+ m_hCombinationOperator->SetControlName( nControlIndex, pNewControlName );
+
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by OnGroupControls after we get a new group name
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnInputCompleted( KeyValues *pKeyValues )
+{
+ const char *pControlName = pKeyValues->GetString( "text", NULL );
+ if ( !pControlName || !pControlName[0] )
+ return;
+
+ if ( pKeyValues->FindKey( "OnGroupControls" ) )
+ {
+ PerformGroupControls( pControlName );
+ return;
+ }
+
+ if ( pKeyValues->FindKey( "OnRenameControl" ) )
+ {
+ PerformRenameControl( pControlName );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Group controls together
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnGroupControls( )
+{
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Group Controls", "Enter name of grouped control" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnGroupControls" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Ungroup controls from each other
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnUngroupControls( )
+{
+ // Build lists of selected controls + raw controls
+ CUtlVector< CUtlString > controlNames;
+ CUtlVector< CUtlString > rawControlNames;
+ bool bIsStereo = false;
+ bool bIsEyelid = false;
+ BuildSelectedControlLists( true, controlNames, rawControlNames, &bIsStereo, &bIsEyelid );
+
+ // NOTE: It's illegal to use a grouped control name which already exists
+ // assuming it's not in the list of grouped control names we're going to group together
+ int nRawControlCount = rawControlNames.Count();
+ for ( int i = 0; i < nRawControlCount; ++i )
+ {
+ if ( HasDuplicateControlName( rawControlNames[i], controlNames ) )
+ return;
+ }
+
+ // Delete old controls
+ int nRetiredControlNameCount = controlNames.Count();
+ for ( int i = 0; i < nRetiredControlNameCount; ++i )
+ {
+ m_hCombinationOperator->RemoveControl( controlNames[i] );
+ }
+
+ // Create new control (this will also create raw controls with the same name)
+ int nGroupedControlCount = rawControlNames.Count();
+ for ( int i = 0; i < nGroupedControlCount; ++i )
+ {
+ const int nControlIndex = m_hCombinationOperator->FindOrCreateControl( rawControlNames[i], bIsStereo, true );
+ m_hCombinationOperator->SetEyelidControl( nControlIndex, bIsEyelid );
+ }
+
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Ungroup controls from each other
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnToggleStereoControl( )
+{
+ // Build lists of selected controls + raw controls
+ // Yeah, this isn't super efficient, but this UI is not going to be super-polished
+ CUtlVector< CUtlString > controlNames;
+ CUtlVector< CUtlString > rawControlNames;
+
+ bool bIsStereo = false;
+ BuildSelectedControlLists( false, controlNames, rawControlNames, &bIsStereo );
+
+ int nControlCount = controlNames.Count();
+ for ( int i = 0; i < nControlCount; ++i )
+ {
+ ControlIndex_t nControlIndex = m_hCombinationOperator->FindControlIndex( controlNames[i] );
+ m_hCombinationOperator->SetStereoControl( nControlIndex, !bIsStereo );
+ }
+
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Toggle Eyelid-Ness
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnToggleEyelidControl()
+{
+ // Build lists of selected controls + raw controls
+ // Yeah, this isn't super efficient, but this UI is not going to be super-polished
+ CUtlVector< CUtlString > controlNames;
+ CUtlVector< CUtlString > rawControlNames;
+
+ bool bIsEyelid = false;
+ BuildSelectedControlLists( false, controlNames, rawControlNames, NULL, &bIsEyelid );
+
+ int nControlCount = controlNames.Count();
+ for ( int i = 0; i < nControlCount; ++i )
+ {
+ ControlIndex_t nControlIndex = m_hCombinationOperator->FindControlIndex( controlNames[i] );
+ m_hCombinationOperator->SetEyelidControl( nControlIndex, !bIsEyelid );
+ }
+
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Rename a control
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnRenameControl()
+{
+ int nSelectedItemCount = m_pControlList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return;
+
+ vgui::InputDialog *pInput = new vgui::InputDialog( this, "Rename Control", "Enter new name of control" );
+ pInput->SetMultiline( false );
+ pInput->DoModal( new KeyValues( "OnRenameControl" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for browsing source files selects something
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnFileSelected( KeyValues *kv )
+{
+ if ( ImportCombinationData( this, m_hCombinationOperator, kv ) )
+ {
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Import combination controls + domination rules
+//-----------------------------------------------------------------------------
+void CDmeCombinationControlsPanel::OnImportCombination()
+{
+ char pStartingDir[MAX_PATH];
+ GetModContentSubdirectory( "models", pStartingDir, sizeof(pStartingDir) );
+
+ vgui::FileOpenDialog *pDialog = new vgui::FileOpenDialog( this, "Select File to Import", true, new KeyValues( "ImportControls" ) );
+ pDialog->SetStartDirectoryContext( "combination_system_import", pStartingDir );
+ pDialog->AddFilter( "*.dmx", "Exported model file (*.dmx)", true );
+ pDialog->SetDeleteSelfOnClose( true );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal( false );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// CDmeInputControlListPanel
+//
+// Declaration above because of scoping issues
+//
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CDmeInputControlListPanel::CDmeInputControlListPanel( vgui::Panel *pParent, const char *pName, CDmeCombinationControlsPanel *pComboPanel ) :
+ BaseClass( pParent, pName ), m_pComboPanel( pComboPanel )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmeInputControlListPanel::OnCreateDragData( KeyValues *msg )
+{
+ const char *const pControlName = m_pComboPanel->GetSelectedControlName();
+ if ( pControlName )
+ {
+ msg->SetString( "inputControl", pControlName );
+ msg->SetInt( "selfDroppable", 1 );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+bool CDmeInputControlListPanel::IsDroppable( CUtlVector< KeyValues * >& msgList )
+{
+ if ( msgList.Count() > 0 )
+ {
+ KeyValues *pData( msgList[ 0 ] );
+ if ( pData->GetPtr( "panel", NULL ) == this && m_pComboPanel )
+ {
+ if ( pData->GetString( "inputControl" ) && pData->GetInt( "selfDroppable" ) )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CDmeInputControlListPanel::OnPanelDropped( CUtlVector< KeyValues * >& msgList )
+{
+ if ( msgList.Count() > 0 )
+ {
+ KeyValues *pData( msgList[ 0 ] );
+ if ( pData->GetPtr( "panel", NULL ) == this && m_pComboPanel )
+ {
+ const char *const pDragControl( pData->GetString( "inputControl" ) );
+ if ( pDragControl )
+ {
+ int x;
+ int y;
+
+ vgui::input()->GetCursorPos( x, y );
+
+ int row;
+ int column;
+ GetCellAtPos( x, y, row, column );
+
+ KeyValues *pKeyValues = GetItem( GetItemIDFromRow( row ) );
+ if ( pKeyValues )
+ {
+ const char *pDropControl = pKeyValues->GetString( "name" );
+ if ( pDropControl )
+ {
+ m_pComboPanel->MoveControlInFrontOf( pDragControl, pDropControl );
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void CDmeInputControlListPanel::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ // 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 )
+ {
+ const int nItemId = m_pComboPanel->GetSelectedInputControlItemId();
+ m_pComboPanel->OnMoveUpInputControl();
+ vgui::ListPanel::OnKeyCodeTyped( code );
+ m_pComboPanel->SelectedInputControlByItemId( nItemId );
+ return;
+ }
+ else if ( code == KEY_DOWN )
+ {
+ const int nItemId = m_pComboPanel->GetSelectedInputControlItemId();
+ m_pComboPanel->OnMoveDownInputControl();
+ vgui::ListPanel::OnKeyCodeTyped( code );
+ m_pComboPanel->SelectedInputControlByItemId( nItemId );
+ return;
+ }
+ }
+
+ vgui::ListPanel::OnKeyCodeTyped( code );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//
+// CDmeRawControlListPanel
+//
+// Declaration above because of scoping issues
+//
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CDmeRawControlListPanel::CDmeRawControlListPanel( vgui::Panel *pParent, const char *pName, CDmeCombinationControlsPanel *pComboPanel ) :
+ BaseClass( pParent, pName ), m_pComboPanel( pComboPanel )
+{
+ m_pWrinkleEdit = new vgui::TextEntry( this, "WrinkleEdit" );
+ m_pWrinkleEdit->SetVisible( false );
+ m_pWrinkleEdit->AddActionSignalTarget( this );
+ m_pWrinkleEdit->SetAllowNumericInputOnly( true );
+}
+
+void CDmeRawControlListPanel::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ // 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_pComboPanel->OnMoveUp();
+ }
+ else if ( code == KEY_DOWN )
+ {
+ m_pComboPanel->OnMoveDown();
+ }
+ }
+
+ vgui::ListPanel::OnKeyCodeTyped( code );
+}
+
+void CDmeRawControlListPanel::OnMouseDoublePressed( vgui::MouseCode code )
+{
+ if ( code != MOUSE_LEFT )
+ {
+ BaseClass::OnMouseDoublePressed( code );
+ return;
+ }
+
+ int nNumSelected = GetSelectedItemsCount();
+ if ( IsInEditMode() || nNumSelected != 1 )
+ return;
+
+ m_pWrinkleEdit->SetVisible( true );
+ m_pWrinkleEdit->SendNewLine( true );
+
+ // Always edit column 3, which contains the wrinkle amount
+ int nEditingItem = GetSelectedItem( 0 );
+ KeyValues *pKeyValues = GetItem( nEditingItem );
+ float flWrinkleValue = pKeyValues->GetFloat( "wrinkle" );
+
+ m_bIsWrinkle = !Q_stricmp( pKeyValues->GetString( "wrinkletype" ), "Wrinkle" );
+
+ char buf[64];
+ Q_snprintf( buf, sizeof(buf), "%f", flWrinkleValue );
+ m_pWrinkleEdit->SetText( buf );
+
+ EnterEditMode( nEditingItem, 3, m_pWrinkleEdit );
+}
+
+void CDmeRawControlListPanel::OnNewWrinkleText()
+{
+ LeaveEditMode();
+
+ char szEditText[MAX_PATH];
+ m_pWrinkleEdit->GetText( szEditText, MAX_PATH );
+ m_pWrinkleEdit->SetVisible( false );
+
+ float flWrinkleScale = atof( szEditText );
+ if ( m_bIsWrinkle )
+ {
+ flWrinkleScale = -flWrinkleScale;
+ }
+ m_pComboPanel->SetRawControlWrinkleValue( flWrinkleScale );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Multiselect for raw controls
+//
+//-----------------------------------------------------------------------------
+class CRawControlPickerFrame : public vgui::Frame
+{
+ DECLARE_CLASS_SIMPLE( CRawControlPickerFrame, vgui::Frame );
+
+public:
+ CRawControlPickerFrame( vgui::Panel *pParent, const char *pTitle );
+ ~CRawControlPickerFrame();
+
+ // Sets the current scene + animation list
+ void DoModal( CDmeCombinationOperator *pCombinationOperator, CDmeCombinationDominationRule *pRule, bool bSuppressed, KeyValues *pContextKeyValues );
+
+ // Inherited from Frame
+ virtual void OnCommand( const char *pCommand );
+
+private:
+ // Refreshes the list of raw controls
+ void RefreshRawControlNames( CDmeCombinationOperator *pCombinationOperator, CDmeCombinationDominationRule *pRule, bool bSuppressed );
+ void CleanUpMessage();
+
+ vgui::ListPanel *m_pRawControlList;
+ vgui::Button *m_pOpenButton;
+ vgui::Button *m_pCancelButton;
+ KeyValues *m_pContextKeyValues;
+};
+
+CRawControlPickerFrame::CRawControlPickerFrame( vgui::Panel *pParent, const char *pTitle ) :
+ BaseClass( pParent, "RawControlPickerFrame" )
+{
+ SetDeleteSelfOnClose( true );
+ m_pContextKeyValues = NULL;
+
+ m_pRawControlList = new vgui::ListPanel( this, "RawControlList" );
+ m_pRawControlList->AddColumnHeader( 0, "name", "Raw Control Name", 52, 0 );
+ m_pRawControlList->SetSelectIndividualCells( false );
+ m_pRawControlList->SetEmptyListText( "No raw controls" );
+ m_pRawControlList->AddActionSignalTarget( this );
+ m_pRawControlList->SetSortFunc( 0, ControlNameSortFunc );
+ m_pRawControlList->SetSortColumn( 0 );
+
+ m_pOpenButton = new vgui::Button( this, "OkButton", "#MessageBox_OK", this, "Ok" );
+ m_pCancelButton = new vgui::Button( this, "CancelButton", "#MessageBox_Cancel", this, "Cancel" );
+ SetBlockDragChaining( true );
+
+ LoadControlSettingsAndUserConfig( "resource/dmecombinationsystemeditor_rawcontrolpickerframe.res" );
+
+ SetTitle( pTitle, false );
+}
+
+CRawControlPickerFrame::~CRawControlPickerFrame()
+{
+ CleanUpMessage();
+}
+
+
+//-----------------------------------------------------------------------------
+// Refreshes the list of raw controls
+//-----------------------------------------------------------------------------
+void CRawControlPickerFrame::RefreshRawControlNames( CDmeCombinationOperator *pCombinationOperator, CDmeCombinationDominationRule *pRule, bool bChooseSuppressed )
+{
+ m_pRawControlList->RemoveAll();
+ if ( !pCombinationOperator )
+ return;
+
+ int nCount = pCombinationOperator->GetRawControlCount( );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ const char *pRawControl = pCombinationOperator->GetRawControlName( i );
+
+ // Hide controls that are in the other part of the rule
+ bool bIsDominator = pRule->HasDominatorControl( pRawControl );
+ bool bIsSuppressed = pRule->HasSuppressedControl( pRawControl );
+ Assert( !bIsDominator || !bIsSuppressed );
+ if ( ( bChooseSuppressed && bIsDominator ) || ( !bChooseSuppressed && bIsSuppressed ) )
+ continue;
+
+ KeyValues *kv = new KeyValues( "node", "name", pCombinationOperator->GetRawControlName( i ) );
+ int nItemID = m_pRawControlList->AddItem( kv, 0, false, false );
+ if ( ( bChooseSuppressed && bIsSuppressed ) || ( !bChooseSuppressed && bIsDominator ) )
+ {
+ m_pRawControlList->AddSelectedItem( nItemID );
+ }
+ }
+
+ m_pRawControlList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Deletes the message
+//-----------------------------------------------------------------------------
+void CRawControlPickerFrame::CleanUpMessage()
+{
+ if ( m_pContextKeyValues )
+ {
+ m_pContextKeyValues->deleteThis();
+ m_pContextKeyValues = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the current scene + animation list
+//-----------------------------------------------------------------------------
+void CRawControlPickerFrame::DoModal( CDmeCombinationOperator *pCombinationOperator,
+ CDmeCombinationDominationRule *pRule, bool bSuppressed, KeyValues *pContextKeyValues )
+{
+ CleanUpMessage();
+ RefreshRawControlNames( pCombinationOperator, pRule, bSuppressed );
+ m_pContextKeyValues = pContextKeyValues;
+ BaseClass::DoModal();
+}
+
+
+//-----------------------------------------------------------------------------
+// On command
+//-----------------------------------------------------------------------------
+void CRawControlPickerFrame::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "Ok" ) )
+ {
+ KeyValues *pActionKeys = new KeyValues( "RawControlPicked" );
+ KeyValues *pControlList = pActionKeys->FindKey( "rawControls", true );
+
+ int nSelectedItemCount = m_pRawControlList->GetSelectedItemsCount();
+ for ( int i = 0; i < nSelectedItemCount; ++i )
+ {
+ int nItemID = m_pRawControlList->GetSelectedItem( i );
+ KeyValues *pKeyValues = m_pRawControlList->GetItem( nItemID );
+ const char *pControlName = pKeyValues->GetString( "name" );
+
+ pControlList->SetString( pControlName, pControlName );
+ }
+
+ if ( m_pContextKeyValues )
+ {
+ pActionKeys->AddSubKey( m_pContextKeyValues );
+
+ // This prevents them from being deleted later
+ m_pContextKeyValues = NULL;
+ }
+
+ PostActionSignal( pActionKeys );
+ CloseModal();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "Cancel" ) )
+ {
+ CloseModal();
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
+//-----------------------------------------------------------------------------
+// Domination rules panel
+//-----------------------------------------------------------------------------
+class CDmeCombinationDominationRulesPanel : public vgui::EditablePanel
+{
+ DECLARE_CLASS_SIMPLE( CDmeCombinationDominationRulesPanel, vgui::EditablePanel );
+
+public:
+ // constructor, destructor
+ CDmeCombinationDominationRulesPanel( vgui::Panel *pParent, const char *pName );
+ virtual ~CDmeCombinationDominationRulesPanel();
+
+ void SetCombinationOperator( CDmeCombinationOperator *pOp );
+ void RefreshCombinationOperator();
+ void NotifyDataChanged();
+
+private:
+ MESSAGE_FUNC_PARAMS( OnOpenContextMenu, "OpenContextMenu", kv );
+ MESSAGE_FUNC_PARAMS( OnRawControlPicked, "RawControlPicked", kv );
+ MESSAGE_FUNC( OnAddDominationRule, "AddDominationRule" );
+ MESSAGE_FUNC( OnRemoveDominationRule, "RemoveDominationRule" );
+ MESSAGE_FUNC( OnDuplicateSuppressed, "DuplicateSuppressed" );
+ MESSAGE_FUNC( OnDuplicateDominators, "DuplicateDominators" );
+ MESSAGE_FUNC( OnSelectDominators, "SelectDominators" );
+ MESSAGE_FUNC( OnSelectSuppressed, "SelectSuppressed" );
+ MESSAGE_FUNC( OnMoveUp, "MoveUp" );
+ MESSAGE_FUNC( OnMoveDown, "MoveDown" );
+ MESSAGE_FUNC( OnImportDominationRules, "ImportDominationRules" );
+ MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", kv );
+
+ // Cleans up the context menu
+ void CleanupContextMenu();
+
+ // Selects a particular domination rule
+ void SelectRule( CDmeCombinationDominationRule* pRule );
+
+ // Returns the currently selected rule
+ CDmeCombinationDominationRule* GetSelectedRule( );
+
+ CDmeHandle< CDmeCombinationOperator > m_hCombinationOperator;
+ vgui::ListPanel *m_pDominationRulesList;
+ vgui::DHANDLE< vgui::Menu > m_hContextMenu;
+};
+
+
+static int __cdecl DominatorNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
+{
+ int i1 = item1.kv->GetInt("index");
+ int i2 = item2.kv->GetInt("index");
+ return i1 - i2;
+}
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+CDmeCombinationDominationRulesPanel::CDmeCombinationDominationRulesPanel( vgui::Panel *pParent, const char *pName ) :
+ BaseClass( pParent, pName )
+{
+ m_pDominationRulesList = new vgui::ListPanel( this, "DominationRulesList" );
+ m_pDominationRulesList->AddColumnHeader( 0, "suppressed", "Suppress", 100, 0 );
+ m_pDominationRulesList->AddColumnHeader( 1, "dominator", "Dominate", 100, 0 );
+ m_pDominationRulesList->AddActionSignalTarget( this );
+ m_pDominationRulesList->SetSortFunc( 0, DominatorNameSortFunc );
+ m_pDominationRulesList->SetSortFunc( 1, DominatorNameSortFunc );
+ m_pDominationRulesList->SetSortColumn( 0 );
+ m_pDominationRulesList->SetEmptyListText("No domination rules.");
+ m_pDominationRulesList->SetMultiselectEnabled( false );
+}
+
+CDmeCombinationDominationRulesPanel::~CDmeCombinationDominationRulesPanel()
+{
+ CleanupContextMenu();
+ SaveUserConfig();
+}
+
+
+//-----------------------------------------------------------------------------
+// Cleans up the context menu
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::CleanupContextMenu()
+{
+ if ( m_hContextMenu.Get() )
+ {
+ m_hContextMenu->MarkForDeletion();
+ m_hContextMenu = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the combination operator
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::SetCombinationOperator( CDmeCombinationOperator *pOp )
+{
+ if ( pOp != m_hCombinationOperator.Get() )
+ {
+ m_hCombinationOperator = pOp;
+ RefreshCombinationOperator();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Basic sort function, for use in qsort
+//-----------------------------------------------------------------------------
+static int __cdecl ControlNameSortFunc(const void *elem1, const void *elem2)
+{
+ const char *pItem1 = *((const char **) elem1);
+ const char *pItem2 = *((const char **) elem2);
+ return Q_stricmp( pItem1, pItem2 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds the list of animations
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::RefreshCombinationOperator()
+{
+ m_pDominationRulesList->RemoveAll();
+ if ( !m_hCombinationOperator.Get() )
+ return;
+
+ char pTemp[1024];
+ int nCount = m_hCombinationOperator->DominationRuleCount();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ CDmeCombinationDominationRule *pRule = m_hCombinationOperator->GetDominationRule( i );
+
+ KeyValues *pItemKeys = new KeyValues( "node" );
+
+ int nLen = 0;
+ int nControlCount = pRule->DominatorCount();
+ pTemp[0] = 0;
+ const char **ppStrings = (const char**)_alloca( nControlCount * sizeof(const char*) );
+ for ( int j = 0; j < nControlCount; ++j )
+ {
+ ppStrings[j] = pRule->GetDominator(j);
+ }
+ qsort( ppStrings, (size_t)nControlCount, (size_t)sizeof(char*), ControlNameSortFunc );
+ for ( int j = 0; j < nControlCount; ++j )
+ {
+ nLen += Q_snprintf( &pTemp[nLen], sizeof(pTemp) - nLen, "%s ", ppStrings[j] );
+ }
+
+ pItemKeys->SetString( "dominator", pTemp );
+
+ nLen = 0;
+ nControlCount = pRule->SuppressedCount();
+ pTemp[0] = 0;
+ ppStrings = (const char**)_alloca( nControlCount * sizeof(const char*) );
+ for ( int j = 0; j < nControlCount; ++j )
+ {
+ ppStrings[j] = pRule->GetSuppressed(j);
+ }
+ qsort( ppStrings, (size_t)nControlCount, (size_t)sizeof(char*), ControlNameSortFunc );
+ for ( int j = 0; j < nControlCount; ++j )
+ {
+ nLen += Q_snprintf( &pTemp[nLen], sizeof(pTemp) - nLen, "%s ", ppStrings[j] );
+ }
+ pItemKeys->SetString( "suppressed", pTemp );
+ pItemKeys->SetInt( "index", i );
+ SetElementKeyValue( pItemKeys, "rule", pRule );
+
+ m_pDominationRulesList->AddItem( pItemKeys, 0, false, false );
+ }
+
+ m_pDominationRulesList->SortList();
+}
+
+
+void CDmeCombinationDominationRulesPanel::NotifyDataChanged()
+{
+ PostActionSignal( new KeyValues( "DmeElementChanged", "DmeCombinationDominationRulesPanel", 2 ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the currently selected domination rule
+//-----------------------------------------------------------------------------
+CDmeCombinationDominationRule* CDmeCombinationDominationRulesPanel::GetSelectedRule( )
+{
+ if ( !m_hCombinationOperator.Get() )
+ return NULL;
+
+ int nSelectedItemCount = m_pDominationRulesList->GetSelectedItemsCount();
+ if ( nSelectedItemCount != 1 )
+ return NULL;
+
+ int nItemID = m_pDominationRulesList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pDominationRulesList->GetItem( nItemID );
+ return GetElementKeyValue<CDmeCombinationDominationRule>( pKeyValues, "rule" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Reorder rules
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnMoveUp( )
+{
+ CDmeCombinationDominationRule* pRule = GetSelectedRule( );
+ if ( !pRule )
+ return;
+
+ m_hCombinationOperator->MoveDominationRuleUp( pRule );
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+void CDmeCombinationDominationRulesPanel::OnMoveDown( )
+{
+ CDmeCombinationDominationRule* pRule = GetSelectedRule( );
+ if ( !pRule )
+ return;
+
+ m_hCombinationOperator->MoveDominationRuleDown( pRule );
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for browsing source files selects something
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnFileSelected( KeyValues *kv )
+{
+ if ( ImportCombinationData( this, m_hCombinationOperator, kv ) )
+ {
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Import domination rules
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnImportDominationRules()
+{
+ char pStartingDir[MAX_PATH];
+ GetModContentSubdirectory( "models", pStartingDir, sizeof(pStartingDir) );
+
+ vgui::FileOpenDialog *pDialog = new vgui::FileOpenDialog( this, "Select File to Import", true, new KeyValues( "ImportDominationRules" ) );
+ pDialog->SetStartDirectoryContext( "combination_system_import", pStartingDir );
+ pDialog->AddFilter( "*.dmx", "Exported model file (*.dmx)", true );
+ pDialog->SetDeleteSelfOnClose( true );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal( false );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnOpenContextMenu( KeyValues *kv )
+{
+ CleanupContextMenu();
+ if ( !m_hCombinationOperator.Get() )
+ return;
+
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel != m_pDominationRulesList )
+ return;
+
+ int nSelectedItemCount = m_pDominationRulesList->GetSelectedItemsCount();
+
+ m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_AddDominationRule", new KeyValues( "AddDominationRule" ), this );
+ if ( nSelectedItemCount > 0 )
+ {
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_RemoveDominationRule", new KeyValues( "RemoveDominationRule" ), this );
+ }
+
+ if ( nSelectedItemCount == 1 )
+ {
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_DuplicateSuppressed", new KeyValues( "DuplicateSuppressed" ), this );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_DuplicateDominators", new KeyValues( "DuplicateDominators" ), this );
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_SelectSuppressed", new KeyValues( "SelectSuppressed" ), this );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_SelectDominators", new KeyValues( "SelectDominators" ), this );
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_MoveUp", new KeyValues( "MoveUp" ), this );
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_MoveDown", new KeyValues( "MoveDown" ), this );
+ }
+
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "#DmeCombinationSystemEditor_ImportDomination", new KeyValues( "ImportDominationRules" ), this );
+
+ vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Selects a particular domination rule
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::SelectRule( CDmeCombinationDominationRule* pRule )
+{
+ for ( int nItemID = m_pDominationRulesList->FirstItem(); nItemID != m_pDominationRulesList->InvalidItemID(); nItemID = m_pDominationRulesList->NextItem( nItemID ) )
+ {
+ KeyValues *pKeyValues = m_pDominationRulesList->GetItem( nItemID );
+ if ( pRule == GetElementKeyValue<CDmeCombinationDominationRule>( pKeyValues, "rule" ) )
+ {
+ m_pDominationRulesList->SetSingleSelectedItem( nItemID );
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Called by the context menu to add dominator rules
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnAddDominationRule( )
+{
+ CDmeCombinationDominationRule* pRule = m_hCombinationOperator->AddDominationRule();
+ RefreshCombinationOperator();
+ SelectRule( pRule );
+ OnSelectSuppressed();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Duplicate suppressed
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnDuplicateSuppressed()
+{
+ CDmeCombinationDominationRule *pSrcRule = GetSelectedRule();
+ if ( !pSrcRule )
+ return;
+
+ CDmeCombinationDominationRule* pRule = m_hCombinationOperator->AddDominationRule();
+ RefreshCombinationOperator();
+ SelectRule( pRule );
+ for ( int i = 0; i < pSrcRule->SuppressedCount(); ++i )
+ {
+ pRule->AddSuppressed( pSrcRule->GetSuppressed( i ) );
+ }
+ OnSelectDominators();
+ NotifyDataChanged();
+}
+
+void CDmeCombinationDominationRulesPanel::OnDuplicateDominators()
+{
+ CDmeCombinationDominationRule *pSrcRule = GetSelectedRule();
+ if ( !pSrcRule )
+ return;
+
+ CDmeCombinationDominationRule* pRule = m_hCombinationOperator->AddDominationRule();
+ RefreshCombinationOperator();
+ SelectRule( pRule );
+ for ( int i = 0; i < pSrcRule->DominatorCount(); ++i )
+ {
+ pRule->AddDominator( pSrcRule->GetDominator( i ) );
+ }
+ OnSelectSuppressed();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the context menu to remove dominator rules
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnRemoveDominationRule( )
+{
+ int nSelectedItemCount = m_pDominationRulesList->GetSelectedItemsCount();
+ for ( int i = 0; i < nSelectedItemCount; ++i )
+ {
+ int nItemID = m_pDominationRulesList->GetSelectedItem( i );
+ KeyValues *pKeyValues = m_pDominationRulesList->GetItem( nItemID );
+
+ CDmeCombinationDominationRule *pRule = GetElementKeyValue<CDmeCombinationDominationRule>( pKeyValues, "rule" );
+ if ( pRule )
+ {
+ m_hCombinationOperator->RemoveDominationRule( pRule );
+ }
+ }
+
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the pickers made in OnSelectDominators + OnSelectSuppressed
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnRawControlPicked( KeyValues *pKeyValues )
+{
+ KeyValues *pControlList = pKeyValues->FindKey( "rawControls" );
+ if ( !pControlList )
+ return;
+
+ KeyValues *pContextKeys = pKeyValues->FindKey( "OnSelectDominators" );
+ if ( pContextKeys )
+ {
+ CDmeCombinationDominationRule *pRule = GetElementKeyValue<CDmeCombinationDominationRule>( pContextKeys, "rule" );
+ if ( !pRule )
+ return;
+
+ pRule->RemoveAllDominators();
+ for ( KeyValues *pKey = pControlList->GetFirstValue(); pKey; pKey = pKey->GetNextValue() )
+ {
+ pRule->AddDominator( pKey->GetName() );
+ }
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+ return;
+ }
+
+ pContextKeys = pKeyValues->FindKey( "OnSelectSuppressed" );
+ if ( pContextKeys )
+ {
+ CDmeCombinationDominationRule *pRule = GetElementKeyValue<CDmeCombinationDominationRule>( pContextKeys, "rule" );
+ if ( !pRule )
+ return;
+
+ pRule->RemoveAllSuppressed();
+ for ( KeyValues *pKey = pControlList->GetFirstValue(); pKey; pKey = pKey->GetNextValue() )
+ {
+ pRule->AddSuppressed( pKey->GetName() );
+ }
+ RefreshCombinationOperator();
+ NotifyDataChanged();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the context menu to change dominator rules
+//-----------------------------------------------------------------------------
+void CDmeCombinationDominationRulesPanel::OnSelectDominators( )
+{
+ CDmeCombinationDominationRule *pRule = GetSelectedRule();
+ if ( !pRule )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "OnSelectDominators" );
+ SetElementKeyValue( pContextKeyValues, "rule", pRule );
+
+ CRawControlPickerFrame *pPicker = new CRawControlPickerFrame( this, "Select Dominator(s)" );
+ pPicker->DoModal( m_hCombinationOperator, pRule, false, pContextKeyValues );
+}
+
+void CDmeCombinationDominationRulesPanel::OnSelectSuppressed( )
+{
+ CDmeCombinationDominationRule *pRule = GetSelectedRule();
+ if ( !pRule )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "OnSelectSuppressed" );
+ SetElementKeyValue( pContextKeyValues, "rule", pRule );
+
+ CRawControlPickerFrame *pPicker = new CRawControlPickerFrame( this, "Select Suppressed" );
+ pPicker->DoModal( m_hCombinationOperator, pRule, true, pContextKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Combination system editor panel
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CDmeCombinationSystemEditorPanel::CDmeCombinationSystemEditorPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
+{
+ m_pEditorSheet = new vgui::PropertySheet( this, "EditorSheet" );
+ m_pEditorSheet->AddActionSignalTarget( this );
+
+ m_pControlsPage = new vgui::PropertyPage( m_pEditorSheet, "ControlsPage" );
+ m_pDominationRulesPage = new vgui::PropertyPage( m_pEditorSheet, "DominationRulesPage" );
+ m_pPropertiesPage = new vgui::PropertyPage( m_pEditorSheet, "PropertiesPage" );
+
+ m_pControlsPanel = new CDmeCombinationControlsPanel( (vgui::Panel*)NULL, "CombinationControls" );
+ m_pControlsPanel->AddActionSignalTarget( this );
+
+ m_pDominationRulesPanel = new CDmeCombinationDominationRulesPanel( (vgui::Panel*)NULL, "DominationRules" );
+ m_pDominationRulesPanel->AddActionSignalTarget( this );
+
+ m_pPropertiesPanel = new CDmeElementPanel( (vgui::Panel*)NULL, "PropertiesPanel" );
+ m_pPropertiesPanel->AddActionSignalTarget( this );
+
+ m_pControlsPanel->LoadControlSettingsAndUserConfig( "resource/dmecombinationsystemeditorpanel_controlspage.res" );
+ m_pDominationRulesPanel->LoadControlSettingsAndUserConfig( "resource/dmecombinationsystemeditorpanel_dominationpage.res" );
+
+ // Load layout settings; has to happen before pinning occurs in code
+ LoadControlSettingsAndUserConfig( "resource/dmecombinationsystemeditorpanel.res" );
+
+ // NOTE: Page adding happens *after* LoadControlSettingsAndUserConfig
+ // because the layout of the sheet is correct at this point.
+ m_pEditorSheet->AddPage( m_pControlsPanel, "Controls" );
+ m_pEditorSheet->AddPage( m_pDominationRulesPanel, "Domination" );
+ m_pEditorSheet->AddPage( m_pPropertiesPanel, "Properties" );
+}
+
+CDmeCombinationSystemEditorPanel::~CDmeCombinationSystemEditorPanel()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Set the scene
+
+//-----------------------------------------------------------------------------
+void CDmeCombinationSystemEditorPanel::SetDmeElement( CDmeCombinationOperator *pComboOp )
+{
+ m_pControlsPanel->SetCombinationOperator( pComboOp );
+ m_pDominationRulesPanel->SetCombinationOperator( pComboOp );
+ m_pPropertiesPanel->SetDmeElement( pComboOp );
+}
+
+CDmeCombinationOperator *CDmeCombinationSystemEditorPanel::GetDmeElement()
+{
+ return m_pControlsPanel->GetCombinationOperator( );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the page changes
+//-----------------------------------------------------------------------------
+void CDmeCombinationSystemEditorPanel::OnPageChanged( )
+{
+ if ( m_pEditorSheet->GetActivePage() == m_pControlsPage )
+ {
+ return;
+ }
+
+ if ( m_pEditorSheet->GetActivePage() == m_pDominationRulesPage )
+ {
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the property editor has made a change
+//-----------------------------------------------------------------------------
+void CDmeCombinationSystemEditorPanel::OnDmeElementChanged( KeyValues *kv )
+{
+ m_pControlsPanel->RefreshCombinationOperator();
+ m_pDominationRulesPanel->RefreshCombinationOperator();
+ m_pPropertiesPanel->Refresh();
+
+ PostActionSignal( new KeyValues( "DmeElementChanged" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Combination system editor frame
+//
+//-----------------------------------------------------------------------------
+CDmeCombinationSystemEditorFrame::CDmeCombinationSystemEditorFrame( vgui::Panel *pParent, const char *pTitle ) :
+ BaseClass( pParent, "DmeCombinationSystemEditorFrame" )
+{
+ SetDeleteSelfOnClose( true );
+ m_pEditor = new CDmeCombinationSystemEditorPanel( this, "DmeCombinationSystemEditorPanel" );
+ m_pEditor->AddActionSignalTarget( this );
+ m_pOpenButton = new vgui::Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
+ m_pCancelButton = new vgui::Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
+ SetBlockDragChaining( true );
+
+ LoadControlSettingsAndUserConfig( "resource/dmecombinationsystemeditorframe.res" );
+
+ SetTitle( pTitle, false );
+}
+
+CDmeCombinationSystemEditorFrame::~CDmeCombinationSystemEditorFrame()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the current scene + animation list
+//-----------------------------------------------------------------------------
+void CDmeCombinationSystemEditorFrame::SetCombinationOperator( CDmeCombinationOperator *pComboSystem )
+{
+ m_pEditor->SetDmeElement( pComboSystem );
+}
+
+
+//-----------------------------------------------------------------------------
+// On command
+//-----------------------------------------------------------------------------
+void CDmeCombinationSystemEditorFrame::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "Open" ) )
+ {
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "Cancel" ) )
+ {
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
+//-----------------------------------------------------------------------------
+// On command
+//-----------------------------------------------------------------------------
+void CDmeCombinationSystemEditorFrame::OnDmeElementChanged()
+{
+ PostActionSignal( new KeyValues( "CombinationOperatorChanged" ) );
+} \ No newline at end of file