diff options
Diffstat (limited to 'vgui2/dme_controls/BaseAnimSetControlGroupPanel.cpp')
| -rw-r--r-- | vgui2/dme_controls/BaseAnimSetControlGroupPanel.cpp | 523 |
1 files changed, 523 insertions, 0 deletions
diff --git a/vgui2/dme_controls/BaseAnimSetControlGroupPanel.cpp b/vgui2/dme_controls/BaseAnimSetControlGroupPanel.cpp new file mode 100644 index 0000000..abbafef --- /dev/null +++ b/vgui2/dme_controls/BaseAnimSetControlGroupPanel.cpp @@ -0,0 +1,523 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= +#include "dme_controls/BaseAnimSetControlGroupPanel.h" +#include "vgui_controls/TreeView.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "movieobjects/dmeanimationset.h" +#include "dme_controls/BaseAnimSetAttributeSliderPanel.h" +#include "dme_controls/BaseAnimationSetEditor.h" +#include "dme_controls/dmecontrols_utils.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; + + +//----------------------------------------------------------------------------- +// Shows the tree view of the animation groups +//----------------------------------------------------------------------------- +class CAnimGroupTree : public TreeView +{ + DECLARE_CLASS_SIMPLE( CAnimGroupTree, TreeView ); +public: + CAnimGroupTree( Panel *parent, const char *panelName, CBaseAnimSetControlGroupPanel *groupPanel ); + virtual ~CAnimGroupTree(); + + virtual bool IsItemDroppable( int itemIndex, CUtlVector< KeyValues * >& msglist ); + virtual void OnItemDropped( int itemIndex, CUtlVector< KeyValues * >& msglist ); + virtual void GenerateContextMenu( int itemIndex, int x, int y ); + +private: + MESSAGE_FUNC( OnImportAnimation, "ImportAnimation" ); + + void CleanupContextMenu(); + + vgui::DHANDLE< vgui::Menu > m_hContextMenu; + CBaseAnimSetControlGroupPanel *m_pGroupPanel; +}; + +CAnimGroupTree::CAnimGroupTree( Panel *parent, const char *panelName, CBaseAnimSetControlGroupPanel *groupPanel ) : + BaseClass( parent, panelName ), + m_pGroupPanel( groupPanel ) +{ +} + +CAnimGroupTree::~CAnimGroupTree() +{ + CleanupContextMenu(); +} + +void CAnimGroupTree::CleanupContextMenu() +{ + if ( m_hContextMenu.Get() ) + { + delete m_hContextMenu.Get(); + m_hContextMenu = NULL; + } +} + +bool CAnimGroupTree::IsItemDroppable( int itemIndex, CUtlVector< KeyValues * >& msglist ) +{ + if ( msglist.Count() != 1 ) + return false; + + KeyValues *data = msglist[ 0 ]; + if ( !data ) + return false; + + if ( !data->FindKey( "color" ) ) + return false; + + KeyValues *itemData = GetItemData( itemIndex ); + if ( !itemData->FindKey( "handle" ) ) + return false; + DmElementHandle_t handle = (DmElementHandle_t)itemData->GetInt( "handle" ); + if ( handle == DMELEMENT_HANDLE_INVALID ) + return false; + + return true; +} + +void CAnimGroupTree::OnItemDropped( int itemIndex, CUtlVector< KeyValues * >& msglist ) +{ + if ( !IsItemDroppable( itemIndex, msglist ) ) + return; + + KeyValues *data = msglist[ 0 ]; + if ( !data ) + return; + + KeyValues *itemData = GetItemData( itemIndex ); + + CDmElement *group = GetElementKeyValue< CDmElement >( itemData, "handle" ); + Assert( m_pGroupPanel ); + Color clr = data->GetColor( "color" ); + SetItemFgColor( itemIndex, clr ); + SetItemSelectionTextColor( itemIndex, clr ); + + if ( group ) + { + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Change Group Color" ); + group->SetValue< Color >( "treeColor", clr ); + } +} + +void CAnimGroupTree::OnImportAnimation() +{ + PostMessage( m_pGroupPanel->m_hEditor, new KeyValues( "ImportAnimation", "visibleOnly", "1" ), 0.0f ); +} + +// override to open a custom context menu on a node being selected and right-clicked +void CAnimGroupTree::GenerateContextMenu( int itemIndex, int x, int y ) +{ + CleanupContextMenu(); + m_hContextMenu = new Menu( this, "ActionMenu" ); + m_hContextMenu->AddMenuItem( "#ImportAnimation", new KeyValues( "ImportAnimation" ), this ); + Menu::PlaceContextMenu( this, m_hContextMenu.Get() ); +} + + + +CBaseAnimSetControlGroupPanel::CBaseAnimSetControlGroupPanel( vgui::Panel *parent, const char *className, CBaseAnimationSetEditor *editor ) : + BaseClass( parent, className ), + m_bStartItemWasSelected( false ), + m_SliderNames( 0, 0, true ) +{ + m_hEditor = editor; + m_hGroups = new CAnimGroupTree( this, "AnimSetGroups", this ); + m_hGroups->SetMultipleItemDragEnabled( true ); + m_hGroups->SetAutoResize + ( + Panel::PIN_TOPLEFT, + Panel::AUTORESIZE_DOWNANDRIGHT, + 0, 0, + 0, 0 + ); + m_hGroups->SetAllowMultipleSelections( true ); +} + +CBaseAnimSetControlGroupPanel::~CBaseAnimSetControlGroupPanel() +{ +} + +static int AddItemToTree( TreeView *tv, const char *label, int parentIndex, const Color& fg, int groupNumber, int handle ) +{ + Color bgColor( 128, 128, 128, 128 ); + + KeyValues *kv = new KeyValues( "item", "text", label ); + kv->SetInt( "groupNumber", groupNumber ); + kv->SetInt( "droppable", 1 ); + kv->SetInt( "handle", handle ); + int idx = tv->AddItem( kv, parentIndex ); + tv->SetItemFgColor( idx, fg ); + tv->SetItemSelectionTextColor( idx, fg ); + tv->SetItemSelectionBgColor( idx, bgColor ); + tv->SetItemSelectionUnfocusedBgColor( idx, bgColor ); + + tv->RemoveSelectedItem( idx ); + tv->ExpandItem( idx, false ); + + kv->deleteThis(); + + return idx; +} + +void CBaseAnimSetControlGroupPanel::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + m_hGroups->SetFont( pScheme->GetFont( "DefaultBold", IsProportional() ) ); +} + +void CBaseAnimSetControlGroupPanel::OnTreeViewItemSelectionCleared() +{ + // We check the entire group manually + OnTreeViewItemSelected( -1 ); +} + +void CBaseAnimSetControlGroupPanel::OnTreeViewItemDeselected( int itemIndex ) +{ + OnTreeViewItemSelected( -1 ); +} + +void CBaseAnimSetControlGroupPanel::OnTreeViewItemSelected( int itemIndex ) +{ + if ( !m_AnimSet.Get() ) + return; + + // Build the list of selected groups, and notify the attribute slider panel + CUtlVector< int > selection; + m_hGroups->GetSelectedItems( selection ); + + const CDmaElementArray<> &groups = m_AnimSet->GetSelectionGroups(); + int groupCount = groups.Count(); + + int i; + int rootIndex = m_hGroups->GetRootItemIndex(); + + bool selectionHasRoot = false; + for ( i = 0 ; i < selection.Count(); ++i ) + { + if ( selection[ i ] == rootIndex ) + { + selectionHasRoot = true; + break; + } + } + + m_SliderNames.RemoveAll(); + + if ( selectionHasRoot ) + { + for ( i = 0; i < groups.Count(); ++i ) + { + CDmElement *element = groups[ i ]; + if ( !element ) + continue; + + const CDmrStringArray array( element, "selectedControls" ); + if ( array.IsValid() ) + { + for ( int j = 0 ; j < array.Count(); ++j ) + { + const char *sliderName = array[ j ]; + if ( sliderName && *sliderName ) + { + m_SliderNames.AddString( sliderName ); + } + } + } + } + } + else + { + for ( i = 0 ; i < selection.Count(); ++i ) + { + if ( selection[ i ] == rootIndex ) + continue; + + KeyValues *kv = m_hGroups->GetItemData( selection[ i ] ); + if ( !kv ) + continue; + + int groupNumber = kv->GetInt( "groupNumber" ); + if ( groupNumber < 0 || groupNumber >= groupCount ) + { + const char *sliderName = kv->GetString( "text" ); + if ( sliderName && *sliderName ) + { + m_SliderNames.AddString( sliderName ); + } + continue; + } + + CDmElement *element = groups[ groupNumber ]; + if ( !element ) + continue; + + const CDmrStringArray array( element, "selectedControls" ); + if ( array.IsValid() ) + { + for ( int j = 0 ; j < array.Count(); ++j ) + { + const char *sliderName = array[ j ]; + if ( sliderName && *sliderName ) + { + m_SliderNames.AddString( sliderName ); + } + } + } + } + } + + // now notify the attribute slider panel + CBaseAnimSetAttributeSliderPanel *attSliders = m_hEditor->GetAttributeSlider(); + if ( attSliders ) + { + attSliders->SetVisibleControlsForSelectionGroup( m_SliderNames ); + } +} + +void CBaseAnimSetControlGroupPanel::ChangeAnimationSet( CDmeAnimationSet *newAnimSet ) +{ + bool changed = m_AnimSet.Get() != newAnimSet ? true : false; + + m_AnimSet = newAnimSet; + + if ( !m_AnimSet.Get() ) + { + m_hGroups->RemoveAll(); + m_hSelectableIndices.RemoveAll(); + m_GroupList.RemoveAll(); + return; + } + + // Compare groups + bool bRebuildGroups = false; + const CDmaElementArray< CDmElement > &groups = m_AnimSet->GetSelectionGroups(); + int c = groups.Count(); + if ( c != m_GroupList.Count() ) + { + bRebuildGroups = true; + } + else + { + for ( int i = 0; i < c; ++i ) + { + CDmElement *group = groups[ i ]; + if ( group == m_GroupList[ i ].Get() ) + { + continue; + } + + bRebuildGroups = true; + break; + } + } + + if ( bRebuildGroups ) + { + m_hGroups->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultBold", IsProportional() ) ); + + // Build a tree of every open item in the tree view + OpenItemTree_t openItems; + int nRootIndex = m_hGroups->GetRootItemIndex(); + if ( nRootIndex != -1 ) + { + BuildOpenItemList( openItems, openItems.InvalidIndex(), nRootIndex ); + } + + m_hGroups->RemoveAll(); + m_hSelectableIndices.RemoveAll(); + m_GroupList.RemoveAll(); + + + // Create root + int rootIndex = AddItemToTree( m_hGroups, "root", -1, Color( 128, 128, 128, 255 ), -1, (int)DMELEMENT_HANDLE_INVALID ); + + Color defaultColor( 0, 128, 255, 255 ); + + CAppUndoScopeGuard *guard = NULL; + + for ( int i = 0; i < c; ++i ) + { + CDmElement *group = groups[ i ]; + + if ( !group->HasAttribute( "treeColor" ) ) + { + if ( !guard ) + { + guard = new CAppUndoScopeGuard( NOTIFY_SETDIRTYFLAG, "Set Default Colors" ); + } + group->SetValue< Color >( "treeColor", defaultColor ); + } + int groupIndex = AddItemToTree( m_hGroups, group->GetName(), rootIndex, group->GetValue< Color >( "treeColor" ), i, (int)group->GetHandle() ); + + const CDmrStringArray array( group, "selectedControls" ); + if ( array.IsValid() ) + { + for ( int j = 0 ; j < array.Count(); ++j ) + { + AddItemToTree( m_hGroups, array[ j ], groupIndex, Color( 200, 200, 200, 255 ), -1, (int)DMELEMENT_HANDLE_INVALID ); + } + } + m_hSelectableIndices.AddToTail( groupIndex ); + + m_GroupList.AddToTail( group->GetHandle() ); + } + + if ( ( nRootIndex >= 0 ) && ( rootIndex >= 0 ) && !changed ) + { + // Iterate through all previously open items and expand them if they exist + if ( openItems.Root() != openItems.InvalidIndex() ) + { + ExpandOpenItems( openItems, openItems.Root(), rootIndex, true ); + } + } + else + { + m_hGroups->ExpandItem( rootIndex, true ); + } + + if ( guard ) + { + delete guard; + } + } + + if ( changed ) + { + for ( int i = 0; i < m_hSelectableIndices.Count(); ++i ) + { + + m_hGroups->AddSelectedItem( m_hSelectableIndices[ i ], + false, // don't clear selection + true, // put focus on tree + false ); // don't expand tree to make all of these visible... + } + } +} + + +//----------------------------------------------------------------------------- +// Expands all items in the open item tree if they exist +//----------------------------------------------------------------------------- +void CBaseAnimSetControlGroupPanel::ExpandOpenItems( OpenItemTree_t &tree, int nOpenTreeIndex, int nItemIndex, bool makeVisible ) +{ + int i = tree.FirstChild( nOpenTreeIndex ); + if ( nOpenTreeIndex != tree.InvalidIndex() ) + { + TreeInfo_t& info = tree[ nOpenTreeIndex ]; + if ( info.m_nFlags & EP_EXPANDED ) + { + // Expand the item + m_hGroups->ExpandItem( nItemIndex , true ); + } + if ( info.m_nFlags & EP_SELECTED ) + { + m_hGroups->AddSelectedItem( nItemIndex, false, false ); + if ( makeVisible ) + { + m_hGroups->MakeItemVisible( nItemIndex ); + } + } + } + + while ( i != tree.InvalidIndex() ) + { + TreeInfo_t& info = tree[ i ]; + // Look for a match + int nChildIndex = FindTreeItem( nItemIndex, info.m_Item ); + if ( nChildIndex != -1 ) + { + ExpandOpenItems( tree, i, nChildIndex, makeVisible ); + } + else + { + if ( info.m_nFlags & EP_SELECTED ) + { + // Look for preserved item + nChildIndex = FindTreeItem( nItemIndex, info.m_Item ); + if ( nChildIndex != -1 ) + { + m_hGroups->AddSelectedItem( nChildIndex, false, false ); + if ( makeVisible ) + { + m_hGroups->MakeItemVisible( nChildIndex ); + } + } + } + } + i = tree.NextSibling( i ); + } +} + +void CBaseAnimSetControlGroupPanel::FillInDataForItem( TreeItem_t &item, int nItemIndex ) +{ + KeyValues *data = m_hGroups->GetItemData( nItemIndex ); + if ( !data ) + return; + + item.m_pAttributeName = data->GetString( "text" ); +} + +//----------------------------------------------------------------------------- +// Builds a list of open items +//----------------------------------------------------------------------------- +void CBaseAnimSetControlGroupPanel::BuildOpenItemList( OpenItemTree_t &tree, int nParent, int nItemIndex ) +{ + KeyValues *data = m_hGroups->GetItemData( nItemIndex ); + if ( !data ) + return; + + bool expanded = m_hGroups->IsItemExpanded( nItemIndex ); + bool selected = m_hGroups->IsItemSelected( nItemIndex ); + + int flags = 0; + if ( expanded ) + { + flags |= EP_EXPANDED; + } + if ( selected ) + { + flags |= EP_SELECTED; + } + + int nChild = tree.InsertChildAfter( nParent, tree.InvalidIndex() ); + TreeInfo_t &info = tree[nChild]; + FillInDataForItem( info.m_Item, nItemIndex ); + info.m_nFlags = flags; + + // Deal with children + int nCount = m_hGroups->GetNumChildren( nItemIndex ); + for ( int i = 0; i < nCount; ++i ) + { + int nChildIndex = m_hGroups->GetChild( nItemIndex, i ); + BuildOpenItemList( tree, nChild, nChildIndex ); + } +} +//----------------------------------------------------------------------------- +// Finds the tree index of a child matching the particular element + attribute +//----------------------------------------------------------------------------- +int CBaseAnimSetControlGroupPanel::FindTreeItem( int nParentIndex, const TreeItem_t &info ) +{ + // Look for a match + int nCount = m_hGroups->GetNumChildren( nParentIndex ); + for ( int i = nCount; --i >= 0; ) + { + int nChildIndex = m_hGroups->GetChild( nParentIndex, i ); + KeyValues *data = m_hGroups->GetItemData( nChildIndex ); + Assert( data ); + + const char *pAttributeName = data->GetString( "text" ); + if ( !Q_stricmp( pAttributeName, info.m_pAttributeName ) ) + { + return nChildIndex; + } + } + return -1; +} |