You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
523 lines
13 KiB
523 lines
13 KiB
//========= 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; |
|
}
|
|
|