Counter Strike : Global Offensive Source Code
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.

1994 lines
64 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dme_controls/BaseAnimSetControlGroupPanel.h"
  7. #include "vgui_controls/TreeView.h"
  8. #include "vgui_controls/Menu.h"
  9. #include "vgui_controls/Button.h"
  10. #include "vgui_controls/ImageList.h"
  11. #include "vgui_controls/Tooltip.h"
  12. #include "tier1/KeyValues.h"
  13. #include "movieobjects/dmeanimationset.h"
  14. #include "movieobjects/dmegamemodel.h"
  15. #include "movieobjects/dmerig.h"
  16. #include "movieobjects/dmetransformcontrol.h"
  17. #include "dme_controls/BaseAnimSetAttributeSliderPanel.h"
  18. #include "dme_controls/BaseAnimationSetEditor.h"
  19. #include "dme_controls/dmecontrols_utils.h"
  20. #include "vgui/ISystem.h"
  21. #include "vgui/ISurface.h"
  22. #include "vgui/IInput.h"
  23. #include "vgui/IVGui.h"
  24. #include "vgui/ILocalize.h"
  25. // memdbgon must be the last include file in a .cpp file!!!
  26. #include "tier0/memdbgon.h"
  27. using namespace vgui;
  28. enum StateIcons_t
  29. {
  30. STATE_ICON_WORK_CAMERA_PARENT_ACTIVE,
  31. STATE_ICON_WORK_CAMERA_PARENT_HIDDEN,
  32. STATE_ICON_DAG_LOCKED,
  33. STATE_ICON_DAG_LOCKED_PARTIAL,
  34. STATE_ICON_DAG_LOCKED_WORLD,
  35. STATE_ICON_DAG_LOCKED_WORLD_PARTIAL,
  36. STATE_ICON_COUNT
  37. };
  38. enum StateIconSetType_t
  39. {
  40. STATE_ICON_SET_INVALID,
  41. STATE_ICON_SET_GROUP,
  42. STATE_ICON_SET_CONTROL_POSITION,
  43. STATE_ICON_SET_CONTROL_ROTATION,
  44. };
  45. //-----------------------------------------------------------------------------
  46. // A panel containing a set of icons providing information about the state of
  47. // an animation group tree item.
  48. //-----------------------------------------------------------------------------
  49. class CAnimGroupStateIconSet : public Panel
  50. {
  51. DECLARE_CLASS_SIMPLE( CAnimGroupStateIconSet, Panel );
  52. // The sole purpose of the icon button is to allow right clicks
  53. // to be handled and used for context menu creation.
  54. class IconButton : public Button
  55. {
  56. DECLARE_CLASS_SIMPLE( IconButton, Button );
  57. public:
  58. IconButton( CAnimGroupStateIconSet *pIconSet, const char *pName )
  59. : Button( pIconSet, pName, "" )
  60. , m_pIconSet( pIconSet )
  61. {}
  62. void OnMousePressed( MouseCode code )
  63. {
  64. if ( code == MOUSE_RIGHT )
  65. {
  66. m_pIconSet->IconButtonRightClick();
  67. return;
  68. }
  69. BaseClass::OnMousePressed( code );
  70. }
  71. CAnimGroupStateIconSet *const m_pIconSet;
  72. };
  73. public:
  74. CAnimGroupStateIconSet( Panel *pParent, const char *pchName, StateIconSetType_t stateType, CDmeDag *pDag, ImageList &imageList, const int *pImageIndexMap );
  75. virtual void ApplySchemeSettings( IScheme *pScheme );
  76. virtual void PerformLayout();
  77. virtual bool IsDroppable( CUtlVector< KeyValues * > &msglist );
  78. virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist );
  79. void IconButtonRightClick();
  80. void UpdateState();
  81. private:
  82. MESSAGE_FUNC( OnLockDagButton, "LockDagButton" );
  83. static const CDmeDag *GetDagFromDragElement( CDmElement *pElement );
  84. static const int LOCKED_TOOLTIP_DELAY = 750;
  85. static const int UNLOCKED_TOOLTIP_DELAY = 1500;
  86. ImageList &m_ImageList;
  87. const int *const m_pImageIndexMap;
  88. const int m_StateType;
  89. CDmeDag *m_pDag;
  90. IconButton *m_pLockButton;
  91. };
  92. CAnimGroupStateIconSet::CAnimGroupStateIconSet( Panel *pParent, const char *pchName, StateIconSetType_t itemType, CDmeDag *pDag, ImageList &imageList, const int *pImageIndexMap )
  93. : BaseClass( pParent, "AnimGroupStateIconSet" )
  94. , m_ImageList( imageList )
  95. , m_pImageIndexMap( pImageIndexMap )
  96. , m_StateType( itemType )
  97. , m_pDag( pDag )
  98. , m_pLockButton( NULL )
  99. {
  100. m_pLockButton = new IconButton( this, "LockButton" );
  101. m_pLockButton->SetVisible( true );
  102. m_pLockButton->AddActionSignalTarget( this );
  103. m_pLockButton->SetCommand( new KeyValues( "LockDagButton" ) );
  104. m_pLockButton->SetKeyBoardInputEnabled( false );
  105. vgui::BaseTooltip *pTooltip = m_pLockButton->GetTooltip();
  106. if ( pTooltip )
  107. {
  108. pTooltip->SetTooltipDelay( UNLOCKED_TOOLTIP_DELAY );
  109. pTooltip->SetText( "#LockButtonTip" );
  110. pTooltip->SetTooltipFormatToSingleLine();
  111. }
  112. SetDropEnabled( true );
  113. }
  114. void CAnimGroupStateIconSet::ApplySchemeSettings( IScheme *pScheme )
  115. {
  116. BaseClass::ApplySchemeSettings( pScheme );
  117. Color buttonColor = pScheme->GetColor( "Frame.BgColor", Color( 0, 0, 0, 0 ) );
  118. SetBgColor( buttonColor );
  119. if ( m_pLockButton )
  120. {
  121. m_pLockButton->SetDefaultBorder( pScheme->GetBorder( "DepressedBorder" ) );
  122. }
  123. }
  124. void CAnimGroupStateIconSet::PerformLayout()
  125. {
  126. int nHeight = GetTall();
  127. if ( m_pLockButton )
  128. {
  129. m_pLockButton->SetBounds( 1, 1, nHeight - 1, nHeight - 1 );
  130. }
  131. }
  132. const CDmeDag *CAnimGroupStateIconSet::GetDagFromDragElement( CDmElement *pElement )
  133. {
  134. if ( pElement == NULL )
  135. return NULL;
  136. const CDmeDag *pDag = NULL;
  137. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( pElement );
  138. if ( pTransformControl )
  139. {
  140. pDag = pTransformControl->GetDag();
  141. }
  142. else
  143. {
  144. pDag = CastElement< CDmeDag >( pElement );
  145. }
  146. return pDag;
  147. }
  148. bool CAnimGroupStateIconSet::IsDroppable( CUtlVector< KeyValues * > &msglist )
  149. {
  150. int nCount = msglist.Count();
  151. if ( nCount != 1 )
  152. return false;
  153. KeyValues *pData = msglist[ 0 ];
  154. CDmElement *pElement = GetElementKeyValue< CDmElement >( pData, "dmeelement" );
  155. const CDmeDag *pParentDag = GetDagFromDragElement( pElement );
  156. if ( pParentDag == NULL )
  157. return false;
  158. // Can't parent a dag to is child
  159. if ( m_pDag->IsAncestorOfDag( pParentDag ) )
  160. return false;
  161. // Can't parent a dag to itself.
  162. if ( m_pDag == pParentDag )
  163. return false;
  164. return true;
  165. }
  166. void CAnimGroupStateIconSet::OnPanelDropped( CUtlVector< KeyValues * >& msglist )
  167. {
  168. int nCount = msglist.Count();
  169. if ( nCount == 1 )
  170. {
  171. KeyValues *pData = msglist[ 0 ];
  172. CDmElement *pElement = GetElementKeyValue< CDmElement >( pData, "dmeelement" );
  173. const CDmElement *pParentDag = GetDagFromDragElement( pElement );
  174. if ( pParentDag )
  175. {
  176. bool bPosition = ( ( m_StateType == STATE_ICON_SET_GROUP ) || ( m_StateType == STATE_ICON_SET_CONTROL_POSITION ) );
  177. bool bRotation = ( ( m_StateType == STATE_ICON_SET_GROUP ) || ( m_StateType == STATE_ICON_SET_CONTROL_ROTATION ) );
  178. KeyValues *pMsgKv = new KeyValues( "SetOverrideParent" );
  179. pMsgKv->SetInt( "targetDag", m_pDag->GetHandle() );
  180. pMsgKv->SetInt( "parentDag", pParentDag->GetHandle() );
  181. pMsgKv->SetBool( "position", bPosition );
  182. pMsgKv->SetBool( "rotation", bRotation );
  183. PostMessage( GetParent(), pMsgKv, 0.0f );
  184. }
  185. }
  186. }
  187. void CAnimGroupStateIconSet::IconButtonRightClick()
  188. {
  189. bool bPosition = ( ( m_StateType == STATE_ICON_SET_GROUP ) || ( m_StateType == STATE_ICON_SET_CONTROL_POSITION ) );
  190. bool bRotation = ( ( m_StateType == STATE_ICON_SET_GROUP ) || ( m_StateType == STATE_ICON_SET_CONTROL_ROTATION ) );
  191. KeyValues *pMsgKv = new KeyValues( "OpenLockContextMenu" );
  192. pMsgKv->SetInt( "targetDag", m_pDag->GetHandle() );
  193. pMsgKv->SetBool( "position", bPosition );
  194. pMsgKv->SetBool( "rotation", bRotation );
  195. PostMessage( GetParent(), pMsgKv, 0.0f );
  196. }
  197. void CAnimGroupStateIconSet::UpdateState()
  198. {
  199. if ( m_pDag == NULL )
  200. return;
  201. m_pLockButton->ClearImages();
  202. vgui::BaseTooltip *pTooltip = m_pLockButton->GetTooltip();
  203. bool bPos = false;
  204. bool bRot = false;
  205. const CDmeDag *pOverrideParent = m_pDag->GetOverrideParent( bPos, bRot, true );
  206. if ( pOverrideParent != NULL )
  207. {
  208. bool bLockedToWorld = ( pOverrideParent->GetParent() == NULL );
  209. int nFullLockedIcon = bLockedToWorld ? STATE_ICON_DAG_LOCKED_WORLD : STATE_ICON_DAG_LOCKED;
  210. int nPartialLockedIcon = bLockedToWorld ? STATE_ICON_DAG_LOCKED_WORLD_PARTIAL : STATE_ICON_DAG_LOCKED_PARTIAL;
  211. // Change the image to the grayed out version if both position and rotation are not overridden
  212. int nImageIndex = 0;
  213. if ( m_StateType == STATE_ICON_SET_GROUP )
  214. {
  215. nImageIndex = ( bPos && bRot ) ? m_pImageIndexMap[ nFullLockedIcon ] : m_pImageIndexMap[ nPartialLockedIcon ];
  216. }
  217. else if ( ( ( m_StateType == STATE_ICON_SET_CONTROL_POSITION ) && bPos ) ||
  218. ( ( m_StateType == STATE_ICON_SET_CONTROL_ROTATION ) && bRot ) )
  219. {
  220. nImageIndex = m_pImageIndexMap[ nFullLockedIcon ];
  221. }
  222. // Update the image of on the button
  223. vgui::IImage *pLockImage = m_ImageList.GetImage( nImageIndex );
  224. m_pLockButton->AddImage( pLockImage, 0 );
  225. // Update the tool tip text describing what dag is new parent
  226. if ( pTooltip )
  227. {
  228. if ( bLockedToWorld )
  229. {
  230. pTooltip->SetText( "#LockedToWorld" );
  231. }
  232. else
  233. {
  234. const wchar_t *pLabel = g_pVGuiLocalize->Find( "#LockedTo" );
  235. if ( pLabel )
  236. {
  237. char itemText[ 32 ];
  238. char tipText[ 64 ];
  239. g_pVGuiLocalize->ConvertUnicodeToANSI( pLabel, itemText, sizeof( itemText ) );
  240. V_snprintf( tipText, sizeof( tipText ), "%s %s", itemText, pOverrideParent->GetName() );
  241. pTooltip->SetText( tipText );
  242. }
  243. }
  244. pTooltip->SetTooltipDelay( LOCKED_TOOLTIP_DELAY );
  245. }
  246. }
  247. else
  248. {
  249. pTooltip->SetTooltipDelay( UNLOCKED_TOOLTIP_DELAY );
  250. pTooltip->SetText( "#LockButtonTip" );
  251. }
  252. }
  253. void CAnimGroupStateIconSet::OnLockDagButton()
  254. {
  255. if ( m_pDag )
  256. {
  257. bool bPosition = ( ( m_StateType == STATE_ICON_SET_GROUP ) || ( m_StateType == STATE_ICON_SET_CONTROL_POSITION ) );
  258. bool bRotation = ( ( m_StateType == STATE_ICON_SET_GROUP ) || ( m_StateType == STATE_ICON_SET_CONTROL_ROTATION ) );
  259. KeyValues *pMsgKv = new KeyValues( "ToggleDagLock" );
  260. pMsgKv->SetInt( "targetDag", m_pDag->GetHandle() );
  261. pMsgKv->SetBool( "position", bPosition );
  262. pMsgKv->SetBool( "rotation", bRotation );
  263. PostMessage( GetParent(), pMsgKv, 0.0f );
  264. }
  265. }
  266. //-----------------------------------------------------------------------------
  267. // Shows the tree view of the animation groups
  268. //-----------------------------------------------------------------------------
  269. class CAnimGroupTree : public TreeView
  270. {
  271. DECLARE_CLASS_SIMPLE( CAnimGroupTree, TreeView );
  272. public:
  273. CAnimGroupTree( Panel *parent, const char *panelName, CBaseAnimSetControlGroupPanel *groupPanel, bool bStateInterface );
  274. virtual ~CAnimGroupTree();
  275. virtual bool IsItemDroppable( int itemIndex, bool bInsertBefore, CUtlVector< KeyValues * >& msglist );
  276. virtual void OnItemDropped( int itemIndex, bool bInsertBefore, CUtlVector< KeyValues * >& msglist );
  277. virtual bool CanCurrentlyEditLabel( int nItemIndex ) const;
  278. virtual void OnLabelChanged( int nItemIndex, char const *pOldString, char const *pNewString );
  279. virtual void GetSelectedItemsForDrag( int nPrimaryDragItem, CUtlVector< int >& list );
  280. virtual void GenerateDragDataForItem( int itemIndex, KeyValues *msg );
  281. virtual void GenerateContextMenu( int itemIndex, int x, int y );
  282. virtual void GenerateChildrenOfNode(int itemIndex);
  283. virtual void RemoveItem(int itemIndex, bool bPromoteChildren, bool bRecursivelyRemove = false );
  284. virtual void RemoveAll();
  285. virtual void ApplySchemeSettings( IScheme *pScheme );
  286. virtual void PaintBackground();
  287. virtual void PerformLayout();
  288. virtual void OnTick();
  289. virtual void OnMousePressed( MouseCode code );
  290. // Item add helpers
  291. int AddAnimationSetToTree( CDmeAnimationSet *pAnimSet );
  292. int AddControlGroupToTree( int parentIndex, CDmeControlGroup *pControlGroup, CDmeControlGroup *pParentGroup, CDmeAnimationSet *pAnimSet );
  293. int AddControlToTree( int parentIndex, CDmElement *pControl, CDmeControlGroup *pControlGroup, CDmeAnimationSet *pAnimSet );
  294. void AddTransformComponentsToTree( int parentIndex, CDmeTransformControl *pTransformControl, CDmeControlGroup *pControlGroup, CDmeAnimationSet *pAnimSet, TransformComponent_t nComponentFlags );
  295. CDmElement *GetTreeItemData( int nTreeIndex, AnimTreeItemType_t *pItemType = NULL,
  296. CDmeAnimationSet **ppParentAnimationSet = NULL,
  297. CDmeControlGroup **ppParentControlGroup = NULL ) const;
  298. // Get the component flags associated with the specified item
  299. TransformComponent_t GetItemComponentFlags( int nTreeIndex ) const;
  300. // Get the control group associated with the specified tree item
  301. CDmeControlGroup *GetControlGroupForTreeItem( int nTreeItemIndex ) const;
  302. // Get the state icon set panel associated with the specified tree item
  303. CAnimGroupStateIconSet *GetTreeItemStateIconSet( int nTreeItemIndex );
  304. // Get the dag node associated with the specified tree item
  305. CDmeDag *GetDagForTreeItem( int nTreeItemIndex ) const;
  306. // Find the child of the specified item which has the specified element as its "handle" value
  307. int FindChildItemForElement( int nParentIndex, const CDmElement *pElement, TransformComponent_t nComponentFlags = TRANSFORM_COMPONENT_NONE );
  308. // Find the index of the the tree view item that has the specified element as its "handle" value
  309. int FindItemForElement( const CDmElement *pElement, TransformComponent_t nComponentFlags = TRANSFORM_COMPONENT_NONE );
  310. // Build the tree view items from the root down to the specified animation set
  311. int BuildTreeToAnimationSet( CDmeAnimationSet *pAnimationSet );
  312. // Build the tree view items from the root down to the specified control group
  313. int BuildTreeToGroup( CDmeControlGroup *pGroup, CDmeAnimationSet *pAnimationSet );
  314. // Build the tree view items from the root down to the specified control
  315. void BuildTreeToControl( const CDmElement *pElement, TransformComponent_t nComponentFlags );
  316. // Set the selection state on the specified item
  317. void SetItemSelectionState( int nItemIndex, SelectionState_t selectionState );
  318. // Get the selection state of the specified item
  319. SelectionState_t GetItemSelectionState( int nItemIndex ) const;
  320. // Get a list of the controls which are fully selected and whose parents are not fully selected
  321. void GetSelectionRootItems( CUtlVector< int > &selectedItems ) const;
  322. private:
  323. MESSAGE_FUNC( OnClearWorkCameraParent, "ClearWorkCameraParent" );
  324. MESSAGE_FUNC_INT( OnResetTransformPivot, "OnResetTransformPivot", viewCenter );
  325. MESSAGE_FUNC_PARAMS( OnToggleDagLock, "ToggleDagLock", params );
  326. MESSAGE_FUNC_PARAMS( OnSetOverrideParent, "SetOverrideParent", params );
  327. MESSAGE_FUNC_PARAMS( OnOpenLockContextMenu, "OpenLockContextMenu", params );
  328. void CleanupContextMenu();
  329. virtual void OnContextMenuSelection( int itemIndex );
  330. int AddItemToTree(
  331. AnimTreeItemType_t itemType,
  332. const char *label,
  333. int parentIndex,
  334. const Color& fg,
  335. CDmElement *pElement,
  336. CDmeAnimationSet *pAnimSet,
  337. CDmeControlGroup *pControlGroup,
  338. bool bExpandable,
  339. SelectionState_t selection,
  340. TransformComponent_t nComponentFlags );
  341. Color ModifyColorByGroupState( const Color &baseColor, CDmeControlGroup *pControlGroup );
  342. void AddDmeControlGroup( int nParentItemIndex, CDmeAnimationSet *pAnimationSet, CDmeControlGroup *pGroup );
  343. bool VisibleControlsBelow_R( CDmeControlGroup *pGroup );
  344. static bool CanAddDragIntoGroup( const CDmeControlGroup *pTargetGroup, const CDmElement *pTargetElement, const CDmElement *pDragElement, bool bInsertBefore );
  345. static SelectionState_t GetSelectionStateForFlags( int nBaseFlags, int nSelectionFlags );
  346. vgui::DHANDLE< vgui::Menu > m_hContextMenu;
  347. CBaseAnimSetControlGroupPanel *m_pGroupPanel;
  348. Button *m_pWorkCameraParentButton;
  349. ImageList m_Images;
  350. int m_StateIconIndices[ STATE_ICON_COUNT ];
  351. Color m_RootColor;
  352. Color m_StateColumnColor;
  353. int m_nStateColumnWidth;
  354. bool m_bStateInterface;
  355. };
  356. CAnimGroupTree::CAnimGroupTree( Panel *parent, const char *panelName, CBaseAnimSetControlGroupPanel *groupPanel, bool bStateInterface ) :
  357. BaseClass( parent, panelName ),
  358. m_pGroupPanel( groupPanel ),
  359. m_Images( false ),
  360. m_RootColor( 128, 128, 128, 255 ),
  361. m_StateColumnColor( 0, 0, 0, 0 ),
  362. m_nStateColumnWidth( 0 ),
  363. m_bStateInterface( bStateInterface )
  364. {
  365. if ( m_bStateInterface )
  366. {
  367. m_nStateColumnWidth = 20;
  368. SetTreeIndent( m_nStateColumnWidth - 2 );
  369. }
  370. SetShowRootNode( false );
  371. SetDragEnabledItems( true );
  372. SetAllowLabelEditing( true );
  373. SetEnableInsertDropLocation( true );
  374. m_pWorkCameraParentButton = new Button( this, "workCameraParent", "" );
  375. m_pWorkCameraParentButton->SetVisible( false );
  376. m_pWorkCameraParentButton->AddActionSignalTarget( this );
  377. m_pWorkCameraParentButton->SetCommand( new KeyValues( "ClearWorkCameraParent" ) );
  378. m_pWorkCameraParentButton->SetKeyBoardInputEnabled( false );
  379. m_StateIconIndices[ STATE_ICON_WORK_CAMERA_PARENT_ACTIVE ] = m_Images.AddImage( scheme()->GetImage( "tools/ifm/icon_referenceframe_active", false ) );
  380. m_StateIconIndices[ STATE_ICON_WORK_CAMERA_PARENT_HIDDEN ] = m_Images.AddImage( scheme()->GetImage( "tools/ifm/icon_referenceframe_active_hidden", false ) );
  381. m_StateIconIndices[ STATE_ICON_DAG_LOCKED ] = m_Images.AddImage( scheme()->GetImage( "tools/ifm/icon_dag_locked", false ) );
  382. m_StateIconIndices[ STATE_ICON_DAG_LOCKED_PARTIAL ] = m_Images.AddImage( scheme()->GetImage( "tools/ifm/icon_dag_locked_grey", false ) );
  383. m_StateIconIndices[ STATE_ICON_DAG_LOCKED_WORLD ] = m_Images.AddImage( scheme()->GetImage( "tools/ifm/icon_dag_locked_world", false ) );
  384. m_StateIconIndices[ STATE_ICON_DAG_LOCKED_WORLD_PARTIAL ] = m_Images.AddImage( scheme()->GetImage( "tools/ifm/icon_dag_locked_world_grey", false ) );
  385. ivgui()->AddTickSignal( GetVPanel(), 0 );
  386. }
  387. CAnimGroupTree::~CAnimGroupTree()
  388. {
  389. CleanupContextMenu();
  390. }
  391. void CAnimGroupTree::ApplySchemeSettings( IScheme *pScheme )
  392. {
  393. BaseClass::ApplySchemeSettings( pScheme );
  394. m_RootColor = pScheme->GetColor( "AnimSet.RootColor", Color( 128, 128, 128, 255 ) );
  395. m_StateColumnColor = pScheme->GetColor( "Frame.BgColor", Color( 0, 0, 0, 0 ) );
  396. SetFont( pScheme->GetFont( "DefaultBold", IsProportional() ) );
  397. }
  398. int CAnimGroupTree::AddAnimationSetToTree( CDmeAnimationSet *pAnimSet )
  399. {
  400. // Don't add the animation set if the root control group is not visible
  401. CDmeControlGroup *pRootGroup = pAnimSet->GetRootControlGroup();
  402. if ( !m_pGroupPanel->m_pController->IsControlGroupVisible( pRootGroup ) )
  403. return -1;
  404. int parentIndex = GetRootItemIndex();
  405. SelectionState_t selection = m_pGroupPanel->m_pController->GetSelectionState( pAnimSet );
  406. Color groupColor = ModifyColorByGroupState( m_RootColor, pRootGroup );
  407. return AddItemToTree( ANIMTREE_ITEM_ANIMSET, pAnimSet->GetName(), parentIndex, groupColor, pAnimSet, pAnimSet, NULL, true, selection, TRANSFORM_COMPONENT_NONE );
  408. }
  409. int CAnimGroupTree::AddControlGroupToTree( int parentIndex, CDmeControlGroup *pControlGroup, CDmeControlGroup *pParentGroup, CDmeAnimationSet *pAnimSet )
  410. {
  411. SelectionState_t selection = m_pGroupPanel->m_pController->GetSelectionState( pControlGroup );
  412. Color groupColor = ModifyColorByGroupState( pControlGroup->GroupColor(), pControlGroup );
  413. return AddItemToTree( ANIMTREE_ITEM_GROUP, pControlGroup->GetName(), parentIndex, groupColor, pControlGroup, pAnimSet, pParentGroup, true, selection, TRANSFORM_COMPONENT_NONE );
  414. }
  415. int CAnimGroupTree::AddControlToTree( int parentIndex, CDmElement *pControl, CDmeControlGroup *pControlGroup, CDmeAnimationSet *pAnimSet )
  416. {
  417. SelectionState_t selection = m_pGroupPanel->m_pController->GetSelectionState( pControl );
  418. bool bTransformControl = pControl->IsA( CDmeTransformControl::GetStaticTypeSymbol() );
  419. TransformComponent_t nComponentFlags = bTransformControl ? TRANSFORM_COMPONENT_ALL : TRANSFORM_COMPONENT_NONE;
  420. Color controlColor = ModifyColorByGroupState( pControlGroup->ControlColor(), pControlGroup );
  421. return AddItemToTree( ANIMTREE_ITEM_CONTROL, pControl->GetName(), parentIndex, controlColor, pControl, pAnimSet, pControlGroup, bTransformControl, selection, nComponentFlags );
  422. }
  423. SelectionState_t CAnimGroupTree::GetSelectionStateForFlags( int nBaseFlags, int nSelectionFlags )
  424. {
  425. int nMaskedFlags = nBaseFlags & nSelectionFlags;
  426. if ( nMaskedFlags == nBaseFlags )
  427. return SEL_ALL;
  428. return ( ( nMaskedFlags > 0 ) ? SEL_SOME : SEL_NONE );
  429. }
  430. void CAnimGroupTree::AddTransformComponentsToTree( int nParentIndex, CDmeTransformControl *pControl, CDmeControlGroup *pControlGroup, CDmeAnimationSet *pAnimSet, TransformComponent_t nParentComponentFlags )
  431. {
  432. int nSelectionFlags = m_pGroupPanel->m_pController->GetSelectionComponentFlags( pControl );
  433. const char *pName = pControl->GetName();
  434. Color color = ModifyColorByGroupState( pControlGroup->ControlColor(), pControlGroup );
  435. if ( nParentComponentFlags == TRANSFORM_COMPONENT_ALL )
  436. {
  437. SelectionState_t posSelection = GetSelectionStateForFlags( TRANSFORM_COMPONENT_POSITION, nSelectionFlags );
  438. SelectionState_t rotSelection = GetSelectionStateForFlags( TRANSFORM_COMPONENT_ROTATION, nSelectionFlags );
  439. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - pos", pName ), nParentIndex, color, pControl, pAnimSet, pControlGroup, true, posSelection, TRANSFORM_COMPONENT_POSITION );
  440. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - rot", pName ), nParentIndex, color, pControl, pAnimSet, pControlGroup, true, rotSelection, TRANSFORM_COMPONENT_ROTATION );
  441. }
  442. else if ( nParentComponentFlags == TRANSFORM_COMPONENT_POSITION )
  443. {
  444. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - pos.x", pName ), nParentIndex, color, pControl, pAnimSet, NULL, false, GetSelectionStateForFlags( TRANSFORM_COMPONENT_POSITION_X, nSelectionFlags ), TRANSFORM_COMPONENT_POSITION_X );
  445. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - pos.y", pName ), nParentIndex, color, pControl, pAnimSet, NULL, false, GetSelectionStateForFlags( TRANSFORM_COMPONENT_POSITION_Y, nSelectionFlags ), TRANSFORM_COMPONENT_POSITION_Y );
  446. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - pos.z", pName ), nParentIndex, color, pControl, pAnimSet, NULL, false, GetSelectionStateForFlags( TRANSFORM_COMPONENT_POSITION_Z, nSelectionFlags ), TRANSFORM_COMPONENT_POSITION_Z );
  447. }
  448. else if ( nParentComponentFlags == TRANSFORM_COMPONENT_ROTATION )
  449. {
  450. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - rot.x", pName ), nParentIndex, color, pControl, pAnimSet, NULL, false, GetSelectionStateForFlags( TRANSFORM_COMPONENT_ROTATION_X, nSelectionFlags ), TRANSFORM_COMPONENT_ROTATION_X );
  451. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - rot.y", pName ), nParentIndex, color, pControl, pAnimSet, NULL, false, GetSelectionStateForFlags( TRANSFORM_COMPONENT_ROTATION_Y, nSelectionFlags ), TRANSFORM_COMPONENT_ROTATION_Y );
  452. AddItemToTree( ANIMTREE_ITEM_COMPONENT, CFmtStr( "%s - rot.z", pName ), nParentIndex, color, pControl, pAnimSet, NULL, false, GetSelectionStateForFlags( TRANSFORM_COMPONENT_ROTATION_Z, nSelectionFlags ), TRANSFORM_COMPONENT_ROTATION_Z );
  453. }
  454. }
  455. Color CAnimGroupTree::ModifyColorByGroupState( const Color &baseColor, CDmeControlGroup *pControlGroup )
  456. {
  457. Color groupColor = baseColor;
  458. int nAlpha = ( pControlGroup->IsSelectable() && pControlGroup->IsVisible() ) ? 255 : 64;
  459. groupColor.SetColor( groupColor.r(), groupColor.g(), groupColor.b(), nAlpha );
  460. return groupColor;
  461. }
  462. int CAnimGroupTree::AddItemToTree( AnimTreeItemType_t itemType, const char *label, int parentIndex, const Color& fg, CDmElement *pElement, CDmeAnimationSet *pAnimSet, CDmeControlGroup *pControlGroup, bool bExpandable, SelectionState_t selection, TransformComponent_t nComponentFlags )
  463. {
  464. DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
  465. DmElementHandle_t hAnimSet = pAnimSet ? pAnimSet->GetHandle() : DMELEMENT_HANDLE_INVALID;
  466. DmElementHandle_t hControlGroup = pControlGroup ? pControlGroup->GetHandle() : DMELEMENT_HANDLE_INVALID;
  467. KeyValues *kv = new KeyValues( "item", "text", label );
  468. kv->SetInt( "droppable", 1 );
  469. kv->SetInt( "itemType", ( int )itemType );
  470. kv->SetInt( "handle", ( int )hElement );
  471. kv->SetInt( "animset", ( int )hAnimSet );
  472. kv->SetInt( "controlgroup", ( int )hControlGroup );
  473. kv->SetInt( "selection", ( int )selection );
  474. kv->SetInt( "componentFlags", ( int )nComponentFlags );
  475. kv->SetInt( "Expand", bExpandable ? 1 : 0 );
  476. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( pElement );
  477. CDmeTransform *pTransform = ( pTransformControl != NULL ) ? pTransformControl->GetTransform() : NULL;
  478. CDmeDag *pDag = ( pTransform != NULL ) ? pTransform->GetDag() : NULL;
  479. if ( m_bStateInterface )
  480. {
  481. StateIconSetType_t stateIconSetType = STATE_ICON_SET_INVALID;
  482. if ( itemType == ANIMTREE_ITEM_COMPONENT )
  483. {
  484. if ( nComponentFlags == TRANSFORM_COMPONENT_POSITION )
  485. {
  486. stateIconSetType = STATE_ICON_SET_CONTROL_POSITION;
  487. }
  488. else if ( nComponentFlags == TRANSFORM_COMPONENT_ROTATION )
  489. {
  490. stateIconSetType = STATE_ICON_SET_CONTROL_ROTATION;
  491. }
  492. }
  493. else if ( itemType == ANIMTREE_ITEM_CONTROL )
  494. {
  495. stateIconSetType = STATE_ICON_SET_GROUP;
  496. }
  497. if ( pDag && ( stateIconSetType != STATE_ICON_SET_INVALID ) )
  498. {
  499. CAnimGroupStateIconSet *pIconSet = new CAnimGroupStateIconSet( this, label, stateIconSetType, pDag, m_Images, m_StateIconIndices );
  500. kv->SetPtr( "stateIconSet", pIconSet );
  501. }
  502. }
  503. int idx = AddItem( kv, parentIndex );
  504. SetItemFgColor( idx, fg );
  505. SetItemSelectionTextColor( idx, fg );
  506. SetSilentMode( true );
  507. if ( selection == SEL_ALL || selection == SEL_SOME )
  508. {
  509. Color color = ( selection == SEL_ALL ) ? Color( 128, 128, 128, 128 ) : Color( 128, 128, 64, 64 );
  510. SetItemSelectionBgColor( idx, color );
  511. SetItemSelectionUnfocusedBgColor( idx, color );
  512. AddSelectedItem( idx, false, false, true );
  513. }
  514. else
  515. {
  516. Color color( 0, 0, 0, 128 );
  517. SetItemSelectionBgColor( idx, color );
  518. SetItemSelectionUnfocusedBgColor( idx, color );
  519. RemoveSelectedItem( idx );
  520. }
  521. if ( ( itemType == ANIMTREE_ITEM_GROUP ) || ( itemType == ANIMTREE_ITEM_ANIMSET ) )
  522. {
  523. SetLabelEditingAllowed( idx, true );
  524. }
  525. SetSilentMode( false );
  526. ExpandItem( idx, false );
  527. kv->deleteThis();
  528. return idx;
  529. }
  530. CDmElement *CAnimGroupTree::GetTreeItemData( int nTreeIndex, AnimTreeItemType_t *pItemType /*= NULL */,
  531. CDmeAnimationSet **ppParentAnimationSet /*= NULL*/,
  532. CDmeControlGroup **ppControlGroup /*= NULL*/ ) const
  533. {
  534. KeyValues *kv = GetItemData( nTreeIndex );
  535. if ( !kv )
  536. return NULL;
  537. if ( pItemType )
  538. {
  539. *pItemType = static_cast< AnimTreeItemType_t >( kv->GetInt( "itemType" ) );
  540. }
  541. if ( ppParentAnimationSet )
  542. {
  543. *ppParentAnimationSet = GetElementKeyValue< CDmeAnimationSet >( kv, "animset" );
  544. }
  545. if ( ppControlGroup )
  546. {
  547. *ppControlGroup = GetElementKeyValue< CDmeControlGroup >( kv, "controlgroup" );
  548. }
  549. return GetElementKeyValue< CDmElement >( kv, "handle" );
  550. }
  551. TransformComponent_t CAnimGroupTree::GetItemComponentFlags( int nTreeIndex ) const
  552. {
  553. KeyValues *kv = GetItemData( nTreeIndex );
  554. return static_cast< TransformComponent_t >( kv->GetInt( "componentFlags" ) );
  555. }
  556. CDmeControlGroup *CAnimGroupTree::GetControlGroupForTreeItem( int nItemIndex ) const
  557. {
  558. CDmElement *pElement = GetTreeItemData( nItemIndex, NULL );
  559. CDmeControlGroup *pControlGroup = NULL;
  560. const CDmeAnimationSet *pAnimationSet = CastElement< CDmeAnimationSet >( pElement );
  561. if ( pAnimationSet )
  562. {
  563. pControlGroup = pAnimationSet->GetRootControlGroup();
  564. }
  565. else
  566. {
  567. pControlGroup = CastElement< CDmeControlGroup >( pElement );
  568. }
  569. return pControlGroup;
  570. }
  571. CAnimGroupStateIconSet *CAnimGroupTree::GetTreeItemStateIconSet( int nTreeIndex )
  572. {
  573. KeyValues *kv = GetItemData( nTreeIndex );
  574. if ( !kv )
  575. return NULL;
  576. return static_cast< CAnimGroupStateIconSet * >( kv->GetPtr( "stateIconSet" ) );
  577. }
  578. CDmeDag *CAnimGroupTree::GetDagForTreeItem( int nTreeItemIndex ) const
  579. {
  580. AnimTreeItemType_t itemType;
  581. CDmElement *pElement = GetTreeItemData( nTreeItemIndex, &itemType );
  582. if ( !pElement && itemType != ANIMTREE_ITEM_GROUP )
  583. return NULL;
  584. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( pElement );
  585. if ( pTransformControl == NULL )
  586. return NULL;
  587. CDmeTransform *pTransform = pTransformControl->GetTransform();
  588. if ( !pTransform )
  589. return NULL;
  590. return pTransform->GetDag();
  591. }
  592. void CAnimGroupTree::CleanupContextMenu()
  593. {
  594. if ( m_hContextMenu.Get() )
  595. {
  596. delete m_hContextMenu.Get();
  597. m_hContextMenu = NULL;
  598. }
  599. }
  600. bool CAnimGroupTree::CanAddDragIntoGroup( const CDmeControlGroup *pTargetGroup, const CDmElement *pTargetElement, const CDmElement *pDragElement, bool bInsertBefore )
  601. {
  602. const static CUtlSymbolLarge symControls = g_pDataModel->GetSymbol( "controls" );
  603. if ( ( pTargetGroup == NULL ) || ( pDragElement == NULL ) || ( pTargetElement == NULL ) )
  604. return false;
  605. // Cannot drag a group into itself
  606. if ( pDragElement == pTargetGroup )
  607. return false;
  608. CDmeAnimationSet *pTargetGroupAnimSet = pTargetGroup->FindAnimationSet( true );
  609. CDmeAnimationSet *pDragGroupAnimSet = NULL;
  610. const CDmeControlGroup *pDragGroup = CastElement< CDmeControlGroup >( pDragElement );
  611. bool bTargetElenentIsGroup = pTargetElement->IsA( CDmeControlGroup::GetStaticTypeSymbol() );
  612. if ( pDragGroup )
  613. {
  614. // Cannot drag a group into a group that already exists in its sub-tree
  615. if ( pDragGroup->IsAncestorOfGroup( pTargetGroup ) )
  616. return false;
  617. // Cannot insert a group before a control
  618. if ( bInsertBefore && !bTargetElenentIsGroup )
  619. return false;
  620. CDmeControlGroup *pDragGroupParent = pDragGroup->FindParent();
  621. pDragGroupAnimSet = ( pDragGroupParent != NULL ) ? pDragGroupParent->FindAnimationSet( true ) : NULL;
  622. }
  623. else
  624. {
  625. // Cannot insert a control before a group
  626. if ( bInsertBefore && bTargetElenentIsGroup )
  627. return false;
  628. // Find the animation set to which the control belongs
  629. pDragGroupAnimSet = FindReferringElement< CDmeAnimationSet >( pDragElement, symControls );
  630. }
  631. // If a control group is in the sub-tree of an animation set it must remain in the sub-tree of that animation set,
  632. // it is not in the sub-tree of an animation set it must not be added to the sub-tree of any other animation set.
  633. if ( pDragGroupAnimSet != pTargetGroupAnimSet )
  634. return false;
  635. return true;
  636. }
  637. bool CAnimGroupTree::IsItemDroppable( int nItemIndex, bool bInsertBefore, CUtlVector< KeyValues * >& msglist )
  638. {
  639. if ( msglist.Count() == 0 )
  640. return false;
  641. CDmeControlGroup *pParentControlGroup = NULL;
  642. CDmElement *pTargetElement = GetTreeItemData( nItemIndex, NULL, NULL, &pParentControlGroup );
  643. if ( pTargetElement == NULL )
  644. return false;
  645. CDmeControlGroup *pTargetControlGroup = GetControlGroupForTreeItem( nItemIndex );
  646. const CDmeControlGroup *pNewParentGroup = bInsertBefore ? pParentControlGroup : pTargetControlGroup;
  647. // See if there are any messages in the list that will apply to the control group
  648. int nMsgCount = msglist.Count();
  649. for ( int iMsg = 0; iMsg < nMsgCount; ++iMsg )
  650. {
  651. KeyValues *pData = msglist[ iMsg ];
  652. if ( pData == NULL )
  653. continue;
  654. if ( pData->FindKey( "color" ) )
  655. {
  656. if ( pTargetControlGroup != NULL )
  657. return true;
  658. }
  659. const CDmElement *pDragElement = GetElementKeyValue< CDmElement >( pData, "dmeelement" );
  660. if ( CanAddDragIntoGroup( pNewParentGroup, pTargetElement, pDragElement, bInsertBefore ) )
  661. return true;
  662. }
  663. return false;
  664. }
  665. void CAnimGroupTree::OnItemDropped( int nItemIndex, bool bInsertBefore, CUtlVector< KeyValues * >& msglist )
  666. {
  667. if ( !IsItemDroppable( nItemIndex, bInsertBefore, msglist ) )
  668. return;
  669. CDmeControlGroup *pParentControlGroup = NULL;
  670. CDmeAnimationSet *pTargetAnimSet = NULL;
  671. CDmElement *pTargetElement = GetTreeItemData( nItemIndex, NULL, &pTargetAnimSet, &pParentControlGroup );
  672. if ( pTargetElement == NULL )
  673. return;
  674. CDmeControlGroup *pTargetControlGroup = GetControlGroupForTreeItem( nItemIndex );
  675. CDmeControlGroup *pNewParentGroup = bInsertBefore ? pParentControlGroup : pTargetControlGroup;
  676. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Drop onto control group" );
  677. int nMsgCount = msglist.Count();
  678. for ( int iMsg = 0; iMsg < nMsgCount; ++iMsg )
  679. {
  680. KeyValues *pData = msglist[ iMsg ];
  681. if ( pData == NULL )
  682. continue;
  683. if ( pData->FindKey( "color" ) )
  684. {
  685. Color clr = pData->GetColor( "color" );
  686. SetItemFgColor( nItemIndex, clr );
  687. SetItemSelectionTextColor( nItemIndex, clr );
  688. pTargetControlGroup->SetGroupColor( clr, false );
  689. }
  690. CDmElement *pDragElement = GetElementKeyValue< CDmElement >( pData, "dmeelement" );
  691. if ( CanAddDragIntoGroup( pNewParentGroup, pTargetElement, pDragElement, bInsertBefore ) )
  692. {
  693. CDmeControlGroup *pDragGroup = CastElement< CDmeControlGroup >( pDragElement );
  694. if ( pDragGroup )
  695. {
  696. pNewParentGroup->AddChild( pDragGroup, ( bInsertBefore ? pTargetControlGroup : NULL ) );
  697. }
  698. else
  699. {
  700. pNewParentGroup->AddControl( pDragElement, ( bInsertBefore ? pTargetElement : NULL ) );
  701. }
  702. if ( pTargetAnimSet )
  703. {
  704. CDmeControlGroup *pRootControlGroup = pTargetAnimSet->GetRootControlGroup();
  705. if ( pRootControlGroup )
  706. {
  707. pRootControlGroup->DestroyEmptyChildren();
  708. }
  709. }
  710. }
  711. }
  712. }
  713. void CAnimGroupTree::GetSelectedItemsForDrag( int nPrimaryDragItem, CUtlVector< int >& list )
  714. {
  715. // The item actually being dragged will be the first item in the selection list,
  716. // since ancestors of this primary item may also be in the selection we can't
  717. // drag the whole selection, but we do want to drag the siblings of the item.
  718. // So iterate the selection and add any siblings of the primary selected item.
  719. CUtlVector< int > selectedItems;
  720. GetSelectedItems( selectedItems );
  721. int nNumSelected = selectedItems.Count();
  722. if ( nNumSelected <= 0 )
  723. return;
  724. AnimTreeItemType_t itemType;
  725. CDmeControlGroup *pPrimaryParentGroup = NULL;
  726. GetTreeItemData( nPrimaryDragItem, &itemType, NULL, &pPrimaryParentGroup );
  727. if ( itemType == ANIMTREE_ITEM_COMPONENT )
  728. return;
  729. for ( int i = 0 ; i < nNumSelected; ++i )
  730. {
  731. CDmeControlGroup *pParentGroup = NULL;
  732. GetTreeItemData( selectedItems[ i ], &itemType, NULL, &pParentGroup );
  733. if ( ( pPrimaryParentGroup == pParentGroup ) && ( itemType != ANIMTREE_ITEM_COMPONENT ) )
  734. {
  735. list.AddToTail( selectedItems[ i ] );
  736. }
  737. }
  738. }
  739. void CAnimGroupTree::GenerateDragDataForItem( int nItemIndex, KeyValues *msg )
  740. {
  741. AnimTreeItemType_t itemType;
  742. CDmElement *pElement = GetTreeItemData( nItemIndex, &itemType );
  743. if ( ( pElement ) && ( itemType != ANIMTREE_ITEM_COMPONENT ) )
  744. {
  745. msg->SetInt( "dmeelement", pElement->GetHandle() );
  746. }
  747. }
  748. bool CAnimGroupTree::CanCurrentlyEditLabel( int nItemIndex ) const
  749. {
  750. // The item must still be in the selection
  751. if ( IsItemSelected( nItemIndex ) == false )
  752. return false;
  753. // Parents or children of the item may be selected, but siblings must not be selected.
  754. int nParentIndex = GetItemParent( nItemIndex );
  755. CUtlVector< int > selectedItems;
  756. GetSelectedItems( selectedItems );
  757. int nSelectedItems = selectedItems.Count();
  758. for ( int iItem = 0; iItem < nSelectedItems; ++iItem )
  759. {
  760. int nSelectedItem = selectedItems[ iItem ];
  761. if ( nItemIndex == nSelectedItem )
  762. continue;
  763. if ( GetItemParent( nSelectedItem) == nParentIndex )
  764. return false;
  765. }
  766. return true;
  767. }
  768. void CAnimGroupTree::OnLabelChanged( int nItemIndex, char const *pOldString, char const *pNewString )
  769. {
  770. CUndoScopeGuard undoSg( "Change group label" );
  771. CDmElement *pElement = GetTreeItemData( nItemIndex );
  772. CDmeControlGroup *pControlGroup = CastElement< CDmeControlGroup >( pElement );
  773. CDmeAnimationSet *pAnimationSet = CastElement< CDmeAnimationSet >( pElement );
  774. if ( pControlGroup )
  775. {
  776. CDmeControlGroup *pRootGroup = pControlGroup->FindRootControlGroup();
  777. if ( pRootGroup && pRootGroup->FindChildByName( pNewString, true ) )
  778. {
  779. CUtlVector< DmElementHandle_t > childList;
  780. pRootGroup->GetAllChildren( childList );
  781. int nIndex = GenerateUniqueNameIndex( pNewString, childList, 0 );
  782. CFmtStr newName( "%s%d", pNewString, nIndex );
  783. pControlGroup->SetName( newName.Access() );
  784. // Force the tree display to update to reflect the modified name
  785. m_pGroupPanel->RebuildTree( true );
  786. }
  787. else
  788. {
  789. pControlGroup->SetName( pNewString );
  790. }
  791. }
  792. else if ( pAnimationSet )
  793. {
  794. KeyValues *pMsgKV = new KeyValues( "SetAnimationSetName", "text", pNewString );
  795. SetElementKeyValue( pMsgKV, "animset", pAnimationSet );
  796. PostMessage( m_pGroupPanel->GetEditor(), pMsgKV, 0.0f );
  797. }
  798. }
  799. // override to open a custom context menu on a node being selected and right-clicked
  800. void CAnimGroupTree::GenerateContextMenu( int itemIndex, int x, int y )
  801. {
  802. PostMessage( GetParent(), new KeyValues( "TreeViewOpenContextMenu", "itemID", itemIndex ), 0.0f );
  803. }
  804. //-----------------------------------------------------------------------------
  805. // Purpose: Override the default right click selection behavior so that the
  806. // clicked item becomes the first selected item.
  807. //-----------------------------------------------------------------------------
  808. void CAnimGroupTree::OnContextMenuSelection( int itemIndex )
  809. {
  810. // Select the item, if it was already selected
  811. // this should make it the first selected item.
  812. AddSelectedItem( itemIndex, !IsItemSelected( itemIndex ) );
  813. Assert( GetFirstSelectedItem() == itemIndex );
  814. }
  815. void CAnimGroupTree::OnClearWorkCameraParent()
  816. {
  817. m_pGroupPanel->m_pController->SetWorkCameraParent( NULL );
  818. }
  819. void CAnimGroupTree::OnResetTransformPivot( int viewCenter )
  820. {
  821. PostMessage( m_pGroupPanel->GetEditor(), new KeyValues( "ResetTransformPivot", "viewCenter", viewCenter ), 0.0f );
  822. }
  823. void CAnimGroupTree::OnToggleDagLock( KeyValues *pParams )
  824. {
  825. PostMessage( m_pGroupPanel->GetEditor(), pParams->MakeCopy(), 0.0f );
  826. // Cause perform layout to be run so that the lock icons
  827. // are updated after the message has been processed.
  828. InvalidateLayout();
  829. }
  830. void CAnimGroupTree::OnSetOverrideParent( KeyValues *pParams )
  831. {
  832. PostMessage( m_pGroupPanel->GetEditor(), pParams->MakeCopy(), 0.0f );
  833. InvalidateLayout();
  834. }
  835. void CAnimGroupTree::OnOpenLockContextMenu( KeyValues *pParams )
  836. {
  837. PostMessage( m_pGroupPanel->GetEditor(), pParams->MakeCopy(), 0.0f );
  838. }
  839. void CAnimGroupTree::OnMousePressed( MouseCode code )
  840. {
  841. int mx, my;
  842. input()->GetCursorPos( mx, my );
  843. ScreenToLocal( mx, my );
  844. int idx = FindItemUnderMouse( mx, my );
  845. // The default tree behavior ignores the width of the item when testing against the mouse. For
  846. // the animation set editor only the actual are of the item should be considered under the mouse.
  847. if ( IsItemIDValid( idx ) )
  848. {
  849. int xPos, yPos, width, height;
  850. GetItemBounds( idx, xPos, yPos, width, height );
  851. if ( ( mx < xPos ) || ( my < yPos ) || ( mx > ( xPos + width ) ) || ( my > ( yPos + height) ) )
  852. {
  853. idx = -1;
  854. }
  855. }
  856. bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  857. if ( !ctrl )
  858. {
  859. if ( code == MOUSE_RIGHT )
  860. {
  861. PostMessage( GetParent(), new KeyValues( "TreeViewOpenContextMenu", "itemID", idx ), 0.0f );
  862. }
  863. else
  864. {
  865. BaseClass::OnMousePressed( code );
  866. }
  867. return;
  868. }
  869. if ( !IsItemIDValid( idx ) || ( mx >= ( 20 + m_nStateColumnWidth ) ) )
  870. {
  871. BaseClass::OnMousePressed( code );
  872. return;
  873. }
  874. CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( GetTreeItemData( idx ) );
  875. if ( pTransformControl )
  876. {
  877. CDmeDag *pDag = pTransformControl->GetDag();
  878. m_pGroupPanel->m_pController->SetWorkCameraParent( pDag );
  879. }
  880. }
  881. void CAnimGroupTree::PaintBackground()
  882. {
  883. BaseClass::PaintBackground();
  884. if ( m_bStateInterface )
  885. {
  886. int nHeight = GetTall();
  887. vgui::surface()->DrawSetColor( m_StateColumnColor );
  888. vgui::surface()->DrawFilledRect( 0, 0, m_nStateColumnWidth, nHeight );
  889. }
  890. }
  891. void CAnimGroupTree::PerformLayout()
  892. {
  893. BaseClass::PerformLayout();
  894. for ( int itemID = FirstItem(); itemID != InvalidItemID(); itemID = NextItem( itemID ) )
  895. {
  896. CAnimGroupStateIconSet *pIconSet = GetTreeItemStateIconSet( itemID );
  897. if ( pIconSet == NULL )
  898. continue;
  899. int nPosX, nPosY, nWidth, nHeight;
  900. if ( GetItemBounds( itemID, nPosX, nPosY, nWidth, nHeight ) )
  901. {
  902. pIconSet->UpdateState();
  903. pIconSet->SetBounds( 0, nPosY, nHeight, nHeight );
  904. pIconSet->SetVisible( true );
  905. }
  906. else
  907. {
  908. pIconSet->SetVisible( false );
  909. }
  910. }
  911. }
  912. void CAnimGroupTree::OnTick()
  913. {
  914. BaseClass::OnTick();
  915. int nWorkCameraParentItem = -1;
  916. if ( CDmeDag *pWorkCameraParent = m_pGroupPanel->GetWorkCameraParent() )
  917. {
  918. for ( int itemID = FirstItem(); itemID != InvalidItemID(); itemID = NextItem( itemID ) )
  919. {
  920. CDmeDag *pDag = GetDagForTreeItem( itemID );
  921. if ( pDag == pWorkCameraParent )
  922. {
  923. nWorkCameraParentItem = itemID;
  924. break;
  925. }
  926. }
  927. }
  928. m_pWorkCameraParentButton->SetVisible( nWorkCameraParentItem != -1 );
  929. if ( nWorkCameraParentItem != -1 )
  930. {
  931. int x = 0, y = 0, w = 0, h = 0;
  932. GetItemBounds( nWorkCameraParentItem, x, y, w, h );
  933. m_pWorkCameraParentButton->SetBounds( 1 + m_nStateColumnWidth, y + 1, h - 2, h - 2 );
  934. m_pWorkCameraParentButton->ClearImages();
  935. m_pWorkCameraParentButton->AddImage( m_Images.GetImage( m_StateIconIndices[ STATE_ICON_WORK_CAMERA_PARENT_ACTIVE ] ), 0 );
  936. }
  937. }
  938. void CAnimGroupTree::RemoveItem( int itemIndex, bool bPromoteChildren, bool bRecursivelyRemove )
  939. {
  940. // The tree view implementation uses negative item indices to indicate
  941. // recursion, here we don't care, we just want the current item being removed.
  942. int nActualIndex = ( itemIndex < 0 ) ? -itemIndex : itemIndex;
  943. CAnimGroupStateIconSet *pIconSet = GetTreeItemStateIconSet( nActualIndex );
  944. if ( pIconSet )
  945. {
  946. delete pIconSet;
  947. }
  948. BaseClass::RemoveItem( itemIndex, bPromoteChildren, bRecursivelyRemove );
  949. }
  950. void CAnimGroupTree::RemoveAll()
  951. {
  952. for ( int itemID = FirstItem(); itemID != InvalidItemID(); itemID = NextItem( itemID ) )
  953. {
  954. CAnimGroupStateIconSet *pIconSet = GetTreeItemStateIconSet( itemID );
  955. if ( pIconSet )
  956. {
  957. delete pIconSet;
  958. }
  959. }
  960. BaseClass::RemoveAll();
  961. }
  962. bool CAnimGroupTree::VisibleControlsBelow_R( CDmeControlGroup *pGroup )
  963. {
  964. // If the group is not visible itself then it
  965. // cannot have any visible controls below it.
  966. if ( !m_pGroupPanel->m_pController->IsControlGroupVisible( pGroup ) )
  967. return false;
  968. // The group is visible and has controls itself then it has
  969. // visible controls below it, no need to go farther.
  970. if ( pGroup->Controls().Count() > 0 )
  971. return true;
  972. // If the group did not have any controls itself, check all of its children recursively,
  973. // if any are visible and have controls then there are visible controls below this group.
  974. const CDmaElementArray< CDmeControlGroup > &children = pGroup->Children();
  975. int nNumChildren = children.Count();
  976. for ( int iChild = 0; iChild < nNumChildren; ++iChild )
  977. {
  978. CDmeControlGroup *pChild = children[ iChild ];
  979. if ( pChild == NULL )
  980. continue;
  981. if ( VisibleControlsBelow_R( pChild ) )
  982. return true;
  983. }
  984. return false;
  985. }
  986. void CAnimGroupTree::AddDmeControlGroup( int nParentItemIndex, CDmeAnimationSet *pAnimationSet, CDmeControlGroup *pGroup )
  987. {
  988. Assert( pGroup );
  989. Assert( pAnimationSet );
  990. // Add the sub-groups
  991. const CDmaElementArray< CDmeControlGroup > &subGroups = pGroup->Children();
  992. int nGroups = subGroups.Count();
  993. for ( int iGroup = 0; iGroup < nGroups; ++iGroup )
  994. {
  995. CDmeControlGroup *pSubGroup = subGroups[ iGroup ];
  996. if ( pSubGroup == NULL )
  997. continue;
  998. if ( !VisibleControlsBelow_R( pSubGroup ) )
  999. continue;
  1000. AddControlGroupToTree( nParentItemIndex, pSubGroup, pGroup, pAnimationSet );
  1001. }
  1002. // Add the controls
  1003. const CDmaElementArray< CDmElement > &controls = pGroup->Controls();
  1004. int nControls = controls.Count();
  1005. for ( int iControl = 0; iControl < nControls; ++iControl )
  1006. {
  1007. CDmElement *pControl = controls[ iControl ];
  1008. if ( pControl )
  1009. {
  1010. AddControlToTree( nParentItemIndex, pControl, pGroup, pAnimationSet );
  1011. }
  1012. }
  1013. }
  1014. void CAnimGroupTree::GenerateChildrenOfNode(int itemIndex)
  1015. {
  1016. BaseClass::GenerateChildrenOfNode( itemIndex );
  1017. // Make sure the children are only generated once.
  1018. if ( GetNumChildren( itemIndex ) > 0 )
  1019. return;
  1020. if ( itemIndex == GetRootItemIndex() )
  1021. {
  1022. CDmeFilmClip *pFilmClip = m_pGroupPanel->m_pController->GetAnimationSetClip();
  1023. CAnimSetGroupAnimSetTraversal traversal( pFilmClip );
  1024. while ( CDmeAnimationSet *pAnimSet = traversal.Next() )
  1025. {
  1026. AddAnimationSetToTree( pAnimSet );
  1027. }
  1028. return;
  1029. }
  1030. // Get type for item
  1031. KeyValues *kv = GetItemData( itemIndex );
  1032. if ( kv )
  1033. {
  1034. AnimTreeItemType_t itemType = static_cast< AnimTreeItemType_t >( kv->GetInt( "itemType" ) );
  1035. CDmElement *pElement = GetElementKeyValue< CDmElement >( kv, "handle" );
  1036. CDmeAnimationSet *pAnimationSet = CastElement< CDmeAnimationSet >( GetElementKeyValue< CDmElement >( kv, "animset" ) );
  1037. CDmeControlGroup *pControlGroup = CastElement< CDmeControlGroup >( GetElementKeyValue< CDmElement >( kv, "controlgroup" ) );
  1038. TransformComponent_t nComponentFlags = static_cast< TransformComponent_t >( kv->GetInt( "componentFlags" ) );
  1039. switch ( itemType )
  1040. {
  1041. default:
  1042. break;
  1043. case ANIMTREE_ITEM_ANIMSET:
  1044. // Under anim set we get 1-N groups, expandable if they have children or controls
  1045. {
  1046. Assert( pAnimationSet );
  1047. CDmeControlGroup *pRootGroup = pAnimationSet->GetRootControlGroup();
  1048. AddDmeControlGroup( itemIndex, pAnimationSet, pRootGroup );
  1049. }
  1050. break;
  1051. case ANIMTREE_ITEM_GROUP:
  1052. // Under group we have subgroups and controls
  1053. {
  1054. Assert( pAnimationSet );
  1055. Assert( pElement );
  1056. CDmeControlGroup *pGroup = CastElement< CDmeControlGroup >( pElement );
  1057. Assert( pGroup );
  1058. AddDmeControlGroup( itemIndex, pAnimationSet, pGroup );
  1059. }
  1060. break;
  1061. case ANIMTREE_ITEM_CONTROL:
  1062. case ANIMTREE_ITEM_COMPONENT:
  1063. // Under transform controls are the position and rotation components
  1064. {
  1065. Assert( pControlGroup );
  1066. Assert( pAnimationSet );
  1067. Assert( pElement );
  1068. CDmeTransformControl *pTranformControl = CastElement< CDmeTransformControl >( pElement );
  1069. if ( pTranformControl )
  1070. {
  1071. AddTransformComponentsToTree( itemIndex, pTranformControl, pControlGroup, pAnimationSet, nComponentFlags );
  1072. }
  1073. }
  1074. break;
  1075. }
  1076. }
  1077. }
  1078. //-----------------------------------------------------------------------------
  1079. // Find the child of the specified item which has the specified element as its
  1080. // "handle" value
  1081. //-----------------------------------------------------------------------------
  1082. int CAnimGroupTree::FindChildItemForElement( int nParentIndex, const CDmElement *pElement, TransformComponent_t nComponentFlags )
  1083. {
  1084. int nChildren = GetNumChildren( nParentIndex );
  1085. for ( int iChild = 0; iChild < nChildren; ++iChild )
  1086. {
  1087. int nChildIndex = GetChild( nParentIndex, iChild );
  1088. KeyValues *pItemData = GetItemData( nChildIndex );
  1089. if ( !pItemData )
  1090. continue;
  1091. CDmElement *pItemElement = GetElementKeyValue< CDmElement >( pItemData, "handle" );
  1092. if ( pItemElement == pElement )
  1093. {
  1094. if ( nComponentFlags == 0 )
  1095. return nChildIndex;
  1096. TransformComponent_t nItemComponentFlags = static_cast< TransformComponent_t >( pItemData->GetInt( "componentFlags" ) );
  1097. if ( nItemComponentFlags == nComponentFlags )
  1098. return nChildIndex;
  1099. if ( ( nItemComponentFlags & nComponentFlags ) == nComponentFlags )
  1100. {
  1101. GenerateChildrenOfNode( nChildIndex );
  1102. int nSubChildIndex = FindChildItemForElement( nChildIndex, pElement, nComponentFlags );
  1103. if ( nSubChildIndex >= 0 )
  1104. return nChildIndex;
  1105. }
  1106. }
  1107. }
  1108. return -1;
  1109. }
  1110. //-----------------------------------------------------------------------------
  1111. // Find the index of the the tree view item that has the specified element as
  1112. // its "handle" value
  1113. //-----------------------------------------------------------------------------
  1114. int CAnimGroupTree::FindItemForElement( const CDmElement *pElement, TransformComponent_t nComponentFlags )
  1115. {
  1116. int highest = GetHighestItemID();
  1117. for ( int i = 0; i < highest; ++i )
  1118. {
  1119. if ( !IsItemIDValid( i ) )
  1120. continue;
  1121. KeyValues *pItemData = GetItemData( i );
  1122. if ( !pItemData )
  1123. continue;
  1124. CDmElement *pItemElement = GetElementKeyValue< CDmElement >( pItemData, "handle" );
  1125. if ( pItemElement == pElement )
  1126. {
  1127. TransformComponent_t nItemComponentFlags = static_cast< TransformComponent_t >( pItemData->GetInt( "componentFlags" ) );
  1128. if ( ( nItemComponentFlags == nComponentFlags ) || ( nComponentFlags == 0 ) )
  1129. return i;
  1130. }
  1131. }
  1132. return -1;
  1133. }
  1134. //-----------------------------------------------------------------------------
  1135. // Build the tree view items from the root down to the specified animation set
  1136. //-----------------------------------------------------------------------------
  1137. int CAnimGroupTree::BuildTreeToAnimationSet( CDmeAnimationSet *pAnimationSet )
  1138. {
  1139. if ( pAnimationSet == NULL )
  1140. return -1;
  1141. // Check to see if the animation set is already has an item, if so just return that.
  1142. int nItemIndex = FindItemForElement( pAnimationSet );
  1143. // If the item was not found find or create the item for the animation set group containing
  1144. // the animation set and then create all its children, including the animation set being looked for.
  1145. if ( nItemIndex < 0 )
  1146. {
  1147. int nParentItemIndex = GetRootItemIndex();
  1148. GenerateChildrenOfNode( nParentItemIndex );
  1149. nItemIndex = FindChildItemForElement( nParentItemIndex, pAnimationSet );
  1150. }
  1151. return nItemIndex;
  1152. }
  1153. //-----------------------------------------------------------------------------
  1154. // Build the tree view items from the root down to the specified control group
  1155. //-----------------------------------------------------------------------------
  1156. int CAnimGroupTree::BuildTreeToGroup( CDmeControlGroup *pGroup, CDmeAnimationSet *pAnimationSet )
  1157. {
  1158. if ( ( pGroup == NULL ) || ( pAnimationSet == NULL ) )
  1159. return -1;
  1160. // Check to see if the group is already has an item, if so just return that.
  1161. int nItemIndex = FindItemForElement( pGroup );
  1162. if ( nItemIndex < 0 )
  1163. {
  1164. int nParentItemIndex = -1;
  1165. if ( pAnimationSet->GetRootControlGroup() == pGroup )
  1166. {
  1167. nParentItemIndex = BuildTreeToAnimationSet( pAnimationSet );
  1168. return nParentItemIndex;
  1169. }
  1170. else
  1171. {
  1172. CDmeControlGroup* pParentGroup = pGroup->FindParent();
  1173. nParentItemIndex = BuildTreeToGroup( pParentGroup, pAnimationSet );
  1174. }
  1175. if ( nParentItemIndex >= 0 )
  1176. {
  1177. GenerateChildrenOfNode( nParentItemIndex );
  1178. nItemIndex = FindChildItemForElement( nParentItemIndex, pGroup );
  1179. }
  1180. }
  1181. return nItemIndex;
  1182. }
  1183. //-----------------------------------------------------------------------------
  1184. // Build the tree view items from the root down to the specified control
  1185. //-----------------------------------------------------------------------------
  1186. void CAnimGroupTree::BuildTreeToControl( const CDmElement *pControl, TransformComponent_t nComponentFlags )
  1187. {
  1188. if ( pControl == NULL )
  1189. return;
  1190. // Find the animation set to which the control belongs
  1191. CDmeAnimationSet *pAnimationSet = FindAncestorReferencingElement< CDmeAnimationSet >( pControl );
  1192. if ( pAnimationSet == NULL )
  1193. return;
  1194. // Check to see if the control is already has an item, if so just return that.
  1195. int nItemIndex = FindItemForElement( pControl, nComponentFlags );
  1196. // If the item for the control was not found, find the group containing the control
  1197. // and make sure it has an item in the tree and the generate the children for that
  1198. // item which will include the item for the control being looked for.
  1199. if ( nItemIndex < 0 )
  1200. {
  1201. int nParentItemIndex = -1;
  1202. CDmeControlGroup *pGroup = CDmeControlGroup::FindGroupContainingControl( pControl );
  1203. nParentItemIndex = BuildTreeToGroup( pGroup, pAnimationSet );
  1204. if ( nParentItemIndex >= 0 )
  1205. {
  1206. GenerateChildrenOfNode( nParentItemIndex );
  1207. nItemIndex = FindChildItemForElement( nParentItemIndex, pControl, nComponentFlags );
  1208. }
  1209. }
  1210. if ( nItemIndex >= 0 )
  1211. {
  1212. MakeItemVisible( nItemIndex );
  1213. }
  1214. }
  1215. //-----------------------------------------------------------------------------
  1216. // Set the selection state on the specified item
  1217. //-----------------------------------------------------------------------------
  1218. void CAnimGroupTree::SetItemSelectionState( int nItemIndex, SelectionState_t selectionState )
  1219. {
  1220. KeyValues *pItemData = GetItemData( nItemIndex );
  1221. if ( pItemData )
  1222. {
  1223. pItemData->SetInt( "selection", ( int )selectionState );
  1224. }
  1225. }
  1226. //-----------------------------------------------------------------------------
  1227. // Get the selection state of the specified item
  1228. //-----------------------------------------------------------------------------
  1229. SelectionState_t CAnimGroupTree::GetItemSelectionState( int nItemIndex ) const
  1230. {
  1231. KeyValues *pItemData = GetItemData( nItemIndex );
  1232. if ( pItemData == NULL)
  1233. return SEL_EMPTY;
  1234. return ( SelectionState_t )( pItemData->GetInt( "selection" ) );
  1235. }
  1236. //-----------------------------------------------------------------------------
  1237. // Get a list of the controls which are fully selected and whose parents are
  1238. // not fully selected
  1239. //-----------------------------------------------------------------------------
  1240. void CAnimGroupTree::GetSelectionRootItems( CUtlVector< int > &rootSelectedItems ) const
  1241. {
  1242. CUtlVector< int > selectedItems;
  1243. GetSelectedItems( selectedItems );
  1244. int nNumSelectedItems = selectedItems.Count();
  1245. rootSelectedItems.EnsureCapacity( nNumSelectedItems );
  1246. for ( int iItem = 0; iItem < nNumSelectedItems; ++iItem )
  1247. {
  1248. int nItemIndex = selectedItems[ iItem ];
  1249. // Skip any items which are not fully selected
  1250. if ( GetItemSelectionState( nItemIndex ) != SEL_ALL )
  1251. continue;
  1252. // Skip any items whose parent is fully selected
  1253. int nParentIndex = GetItemParent( nItemIndex );
  1254. if ( GetItemSelectionState( nParentIndex ) == SEL_ALL )
  1255. continue;
  1256. rootSelectedItems.AddToTail( nItemIndex );
  1257. }
  1258. }
  1259. CBaseAnimSetControlGroupPanel::CBaseAnimSetControlGroupPanel( vgui::Panel *parent, const char *className, CBaseAnimationSetEditor *editor, bool bControlStateInterface ) :
  1260. BaseClass( parent, className ),
  1261. m_pController( NULL )
  1262. {
  1263. m_hEditor = editor;
  1264. m_pController = editor->GetController();
  1265. m_pController->AddControlSelectionChangedListener( this );
  1266. m_hGroups = SETUP_PANEL( new CAnimGroupTree( this, "AnimSetGroups", this, bControlStateInterface ) );
  1267. m_hGroups->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  1268. m_hGroups->SetAllowMultipleSelections( true );
  1269. m_hGroups->AddItem( new KeyValues( "root" ), -1 ); // add (invisible) root
  1270. }
  1271. CBaseAnimSetControlGroupPanel::~CBaseAnimSetControlGroupPanel()
  1272. {
  1273. }
  1274. void CBaseAnimSetControlGroupPanel::ApplySchemeSettings( IScheme *pScheme )
  1275. {
  1276. BaseClass::ApplySchemeSettings( pScheme );
  1277. m_FullSelectionColor = pScheme->GetColor( "AnimSet.FullSelectionColor" , Color( 128, 128, 128, 128 ) );
  1278. m_PartialSelectionColor = pScheme->GetColor( "AnimSet.PartialSelectionColor" , Color( 128, 128, 64, 64 ) );
  1279. m_ContextMenuHighlightColor = pScheme->GetColor( "AnimSet.ContextMenuSelectionColor", Color( 255, 153, 0, 255 ) );
  1280. // Normally we shouldn't have to call this but ApplySchemeSettings is called directly
  1281. // by the animation set editor, so normal solve traverse isn't performed in that case.
  1282. m_hGroups->ApplySchemeSettings( pScheme );
  1283. }
  1284. void CBaseAnimSetControlGroupPanel::SelectAnimTreeItem( int itemIndex, ESelectionMode selectionMode )
  1285. {
  1286. AnimTreeItemType_t itemType;
  1287. CDmElement *pElement = m_hGroups->GetTreeItemData( itemIndex, &itemType );
  1288. if ( !pElement )
  1289. return;
  1290. switch ( itemType )
  1291. {
  1292. case ANIMTREE_ITEM_ANIMSET:
  1293. if ( CDmeAnimationSet *pAnimSet = CastElement< CDmeAnimationSet >( pElement ) )
  1294. {
  1295. m_pController->SelectAnimationSet( pAnimSet, selectionMode );
  1296. }
  1297. break;
  1298. case ANIMTREE_ITEM_GROUP:
  1299. if ( CDmeControlGroup *pGroup = CastElement< CDmeControlGroup >( pElement ) )
  1300. {
  1301. m_pController->SelectControlGroup( pGroup, selectionMode );
  1302. }
  1303. break;
  1304. case ANIMTREE_ITEM_CONTROL:
  1305. m_pController->SelectControl( pElement, selectionMode );
  1306. break;
  1307. case ANIMTREE_ITEM_COMPONENT:
  1308. TransformComponent_t nComponentFlags = m_hGroups->GetItemComponentFlags( itemIndex );
  1309. m_pController->SelectControl( pElement, selectionMode, nComponentFlags );
  1310. break;
  1311. }
  1312. }
  1313. void CBaseAnimSetControlGroupPanel::OnControlSelectionChanged()
  1314. {
  1315. UpdateSelection();
  1316. }
  1317. void CBaseAnimSetControlGroupPanel::ExpandTreeToControl( const CDmElement *pSelection, TransformComponent_t nComponentFlags )
  1318. {
  1319. m_hGroups->BuildTreeToControl( pSelection, nComponentFlags );
  1320. }
  1321. void CBaseAnimSetControlGroupPanel::OnTreeViewStartRangeSelection()
  1322. {
  1323. m_pController->SetRangeSelectionState( true );
  1324. }
  1325. void CBaseAnimSetControlGroupPanel::OnTreeViewFinishRangeSelection()
  1326. {
  1327. m_pController->SetRangeSelectionState( false );
  1328. }
  1329. void CBaseAnimSetControlGroupPanel::OnTreeViewItemSelected( int itemIndex, int replaceSelection )
  1330. {
  1331. SelectAnimTreeItem( itemIndex, replaceSelection ? SELECTION_SET : SELECTION_ADD );
  1332. }
  1333. void CBaseAnimSetControlGroupPanel::OnTreeViewItemDeselected( int itemIndex )
  1334. {
  1335. SelectAnimTreeItem( itemIndex, SELECTION_REMOVE );
  1336. }
  1337. void CBaseAnimSetControlGroupPanel::OnTreeViewItemSelectionCleared()
  1338. {
  1339. m_pController->ClearSelection();
  1340. }
  1341. void CBaseAnimSetControlGroupPanel::ChangeAnimationSetClip( CDmeFilmClip *pFilmClip )
  1342. {
  1343. RebuildTree( false );
  1344. }
  1345. void CBaseAnimSetControlGroupPanel::OnControlsAddedOrRemoved()
  1346. {
  1347. RebuildTree( true );
  1348. }
  1349. //-----------------------------------------------------------------------------
  1350. // Purpose: Rebuild the tree view from the current control selection hierarchy
  1351. //-----------------------------------------------------------------------------
  1352. void CBaseAnimSetControlGroupPanel::RebuildTree( bool bRestoreExpansion )
  1353. {
  1354. if ( bRestoreExpansion )
  1355. {
  1356. CUtlVector< ElementExpansion_t > expandedNodes( 0, m_hGroups->GetItemCount() );
  1357. CollectExpandedItems( expandedNodes, m_hGroups->GetRootItemIndex() );
  1358. m_hGroups->SetSilentMode( true );
  1359. m_hGroups->RemoveAll();
  1360. m_hGroups->SetSilentMode( false );
  1361. m_hGroups->AddItem( new KeyValues( "root" ), -1 ); // add (invisible) root
  1362. m_hGroups->ExpandItem( m_hGroups->GetRootItemIndex(), true );
  1363. ExpandItems( expandedNodes );
  1364. UpdateSelection();
  1365. }
  1366. else
  1367. {
  1368. m_hGroups->SetSilentMode( true );
  1369. m_hGroups->RemoveAll();
  1370. m_hGroups->SetSilentMode( false );
  1371. m_hGroups->AddItem( new KeyValues( "root" ), -1 ); // add (invisible) root
  1372. if ( CDmeFilmClip *pFilmClip = m_pController->GetAnimationSetClip() )
  1373. {
  1374. CAnimSetGroupAnimSetTraversal traversal( pFilmClip );
  1375. while ( CDmeAnimationSet *pAnimSet = traversal.Next() )
  1376. {
  1377. m_hGroups->AddAnimationSetToTree( pAnimSet );
  1378. }
  1379. m_hGroups->ExpandItem( m_hGroups->GetRootItemIndex(), true );
  1380. }
  1381. }
  1382. }
  1383. // pre-order traversal so that we can ExpandItems linearly
  1384. void CBaseAnimSetControlGroupPanel::CollectExpandedItems( CUtlVector< ElementExpansion_t > &expandedNodes, int nItemIndex )
  1385. {
  1386. if ( nItemIndex == m_hGroups->InvalidItemID() )
  1387. return;
  1388. AnimTreeItemType_t itemType;
  1389. CDmElement *pElement = m_hGroups->GetTreeItemData( nItemIndex, &itemType );
  1390. if ( !m_hGroups->IsItemExpanded( nItemIndex ) )
  1391. return;
  1392. ElementExpansion_t *pExpansionInfo = NULL;
  1393. if ( pElement )
  1394. {
  1395. int nIndex = expandedNodes.AddToTail();
  1396. pExpansionInfo = &expandedNodes[ nIndex ];
  1397. pExpansionInfo->m_pElement = pElement;
  1398. pExpansionInfo->m_ComponentFlags = TRANSFORM_COMPONENT_NONE;
  1399. }
  1400. int nChildren = m_hGroups->GetNumChildren( nItemIndex );
  1401. for ( int i = 0; i < nChildren; ++i )
  1402. {
  1403. int nChildIndex = m_hGroups->GetChild( nItemIndex, i );
  1404. AnimTreeItemType_t childItemType;
  1405. m_hGroups->GetTreeItemData( nChildIndex, &childItemType );
  1406. if ( childItemType == ANIMTREE_ITEM_COMPONENT )
  1407. {
  1408. if ( m_hGroups->IsItemExpanded( nChildIndex ) && pExpansionInfo )
  1409. {
  1410. pExpansionInfo->m_ComponentFlags |= m_hGroups->GetItemComponentFlags( nChildIndex );
  1411. }
  1412. }
  1413. else
  1414. {
  1415. CollectExpandedItems( expandedNodes, nChildIndex );
  1416. }
  1417. }
  1418. }
  1419. // assumes expandedNodes have parents before children (ie expandedNodes is a pre-order traversal)
  1420. void CBaseAnimSetControlGroupPanel::ExpandItems( const CUtlVector< ElementExpansion_t > &expandedNodes )
  1421. {
  1422. int nExpandedNodes = expandedNodes.Count();
  1423. for ( int i = 0; i < nExpandedNodes; ++i )
  1424. {
  1425. CDmElement *pElement = expandedNodes[ i ].m_pElement;
  1426. int nItemIndex = m_hGroups->FindItemForElement( pElement );
  1427. if ( nItemIndex != m_hGroups->InvalidItemID() )
  1428. {
  1429. m_hGroups->ExpandItem( nItemIndex, true );
  1430. TransformComponent_t expandedComponents = expandedNodes[ i ].m_ComponentFlags;
  1431. if ( expandedComponents == TRANSFORM_COMPONENT_NONE )
  1432. continue;
  1433. int nChildren = m_hGroups->GetNumChildren( nItemIndex );
  1434. for ( int i = 0; i < nChildren; ++i )
  1435. {
  1436. int nChildIndex = m_hGroups->GetChild( nItemIndex, i );
  1437. AnimTreeItemType_t childItemType;
  1438. m_hGroups->GetTreeItemData( nChildIndex, &childItemType );
  1439. TransformComponent_t childComponents = m_hGroups->GetItemComponentFlags( nChildIndex );
  1440. if ( ( childItemType == ANIMTREE_ITEM_COMPONENT ) && ( childComponents & expandedComponents ) )
  1441. {
  1442. m_hGroups->ExpandItem( nChildIndex, true );
  1443. }
  1444. }
  1445. }
  1446. }
  1447. }
  1448. void CBaseAnimSetControlGroupPanel::UpdateSelection()
  1449. {
  1450. if ( !m_hGroups )
  1451. return;
  1452. m_hGroups->SetSilentMode( true );
  1453. m_hGroups->ClearSelection();
  1454. m_hGroups->SetSilentMode( false );
  1455. UpdateSelection_R( m_hGroups->GetRootItemIndex() );
  1456. }
  1457. SelectionState_t CBaseAnimSetControlGroupPanel::UpdateSelection_R( int nParentIndex )
  1458. {
  1459. if ( nParentIndex == m_hGroups->InvalidItemID() )
  1460. return SEL_EMPTY;
  1461. SelectionState_t selection = SEL_EMPTY;
  1462. int nChildren = m_hGroups->GetNumChildren( nParentIndex );
  1463. if ( nChildren > 0 )
  1464. {
  1465. for ( int i = 0; i < nChildren; ++i )
  1466. {
  1467. int nChildIndex = m_hGroups->GetChild( nParentIndex, i );
  1468. selection += UpdateSelection_R( nChildIndex );
  1469. }
  1470. }
  1471. else
  1472. {
  1473. // check actual controls
  1474. AnimTreeItemType_t itemType;
  1475. CDmElement *pElement = m_hGroups->GetTreeItemData( nParentIndex, &itemType );
  1476. if ( !pElement )
  1477. return SEL_EMPTY;
  1478. switch ( itemType )
  1479. {
  1480. case ANIMTREE_ITEM_ANIMSET:
  1481. if ( CDmeAnimationSet *pAnimSet = CastElement< CDmeAnimationSet >( pElement ) )
  1482. {
  1483. selection = m_pController->GetSelectionState( pAnimSet );
  1484. }
  1485. break;
  1486. case ANIMTREE_ITEM_GROUP:
  1487. if ( CDmeControlGroup *pGroup = CastElement< CDmeControlGroup >( pElement ) )
  1488. {
  1489. selection = m_pController->GetSelectionState( pGroup );
  1490. }
  1491. break;
  1492. case ANIMTREE_ITEM_CONTROL:
  1493. selection = m_pController->GetSelectionState( pElement );
  1494. break;
  1495. case ANIMTREE_ITEM_COMPONENT:
  1496. TransformComponent_t nComponentFlags = m_hGroups->GetItemComponentFlags( nParentIndex );
  1497. selection = m_pController->GetSelectionState( pElement, nComponentFlags );
  1498. break;
  1499. }
  1500. }
  1501. m_hGroups->SetItemSelectionState( nParentIndex, selection );
  1502. if ( selection == SEL_SOME || selection == SEL_ALL )
  1503. {
  1504. Color color = ( selection == SEL_ALL ) ? m_FullSelectionColor : m_PartialSelectionColor;
  1505. m_hGroups->SetItemSelectionBgColor( nParentIndex, color );
  1506. m_hGroups->SetItemSelectionUnfocusedBgColor( nParentIndex, color );
  1507. m_hGroups->SetSilentMode( true );
  1508. m_hGroups->AddSelectedItem( nParentIndex, false, false, false );
  1509. m_hGroups->SetSilentMode( false );
  1510. }
  1511. return selection;
  1512. }
  1513. CDmeDag *CBaseAnimSetControlGroupPanel::GetWorkCameraParent()
  1514. {
  1515. return m_pController->GetWorkCameraParent();
  1516. }
  1517. //-----------------------------------------------------------------------------
  1518. // Purpose: Handle the request of the tree view to create a context menu
  1519. //-----------------------------------------------------------------------------
  1520. void CBaseAnimSetControlGroupPanel::OnTreeViewOpenContextMenu( int itemID )
  1521. {
  1522. if ( itemID >= 0 )
  1523. {
  1524. m_hGroups->SetItemSelectionUnfocusedBgColor( itemID, m_ContextMenuHighlightColor );
  1525. }
  1526. KeyValues *pItemData = m_hGroups->GetItemData( itemID );
  1527. m_hEditor->OpenTreeViewContextMenu( pItemData );
  1528. }
  1529. //-----------------------------------------------------------------------------
  1530. // Create a new control group containing the selected controls
  1531. //-----------------------------------------------------------------------------
  1532. void CBaseAnimSetControlGroupPanel::CreateGroupFromSelectedControls()
  1533. {
  1534. CUtlVector< int > selectedItems;
  1535. m_hGroups->GetSelectionRootItems( selectedItems );
  1536. int nNumSelectedItems = selectedItems.Count();
  1537. if ( nNumSelectedItems < 0 )
  1538. return;
  1539. CDmeControlGroup *pCommonAncestor = NULL;
  1540. for ( int iItem = 0; iItem < nNumSelectedItems; ++iItem )
  1541. {
  1542. int nItemIndex = selectedItems[ iItem ];
  1543. AnimTreeItemType_t itemType;
  1544. CDmeControlGroup *pParentControlGroup = NULL;
  1545. m_hGroups->GetTreeItemData( nItemIndex, &itemType, NULL, &pParentControlGroup );
  1546. // Currently not allowed to group animation sets
  1547. if ( itemType == ANIMTREE_ITEM_ANIMSET )
  1548. return;
  1549. if ( pCommonAncestor )
  1550. {
  1551. pCommonAncestor = pParentControlGroup->FindCommonAncestor( pCommonAncestor );
  1552. }
  1553. else
  1554. {
  1555. pCommonAncestor = pParentControlGroup;
  1556. }
  1557. // If any of the selected items do not have a common
  1558. // ancestor, do not allow the group to be created.
  1559. if ( pCommonAncestor == NULL )
  1560. return;
  1561. }
  1562. // If the selected items did not share a common ancestor a new group cannot be created
  1563. if ( pCommonAncestor == NULL )
  1564. return;
  1565. // Generate a name for the new group which is unique among the children of the group it will belong to.
  1566. const CDmeControlGroup *pRootGroup = pCommonAncestor->FindRootControlGroup();
  1567. if ( pRootGroup == NULL)
  1568. return;
  1569. CUtlVector< DmElementHandle_t > childList;
  1570. pRootGroup->GetAllChildren( childList );
  1571. int nIndex = GenerateUniqueNameIndex( "group", childList, 1 );
  1572. CFmtStr groupName( "group%d", nIndex );
  1573. // Create the new group and make it a child of the common ancestor
  1574. CDmeControlGroup *pNewGroup = pCommonAncestor->CreateControlGroup( groupName );
  1575. // Add the selected items to the new group
  1576. if ( pNewGroup )
  1577. {
  1578. for ( int iItem = 0; iItem < nNumSelectedItems; ++iItem )
  1579. {
  1580. int nItemIndex = selectedItems[ iItem ];
  1581. AnimTreeItemType_t itemType;
  1582. CDmElement *pElement = m_hGroups->GetTreeItemData( nItemIndex, &itemType );
  1583. if ( itemType == ANIMTREE_ITEM_GROUP )
  1584. {
  1585. pNewGroup->AddChild( CastElement< CDmeControlGroup >( pElement ) );
  1586. }
  1587. else if ( itemType == ANIMTREE_ITEM_CONTROL )
  1588. {
  1589. pNewGroup->AddControl( pElement );
  1590. }
  1591. }
  1592. // Clean up any empty children which may have been left in the tree.
  1593. pCommonAncestor->DestroyEmptyChildren();
  1594. // Rebuild the tree so that it includes the new group
  1595. RebuildTree( true );
  1596. // Find the item corresponding to the new group and set it label editing mode.
  1597. int nNewItemIndex = m_hGroups->FindItemForElement( pNewGroup );
  1598. m_hGroups->MakeItemVisible( nNewItemIndex );
  1599. m_hGroups->StartEditingLabel( nNewItemIndex );
  1600. }
  1601. }