//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Implements the groups page of the Object Properties dialog. This // allows the user to edit which visgroups the selected objects belong to. // //=============================================================================// #include "stdafx.h" #include "hammer.h" #include "MapWorld.h" #include "OP_Groups.h" #include "EditGroups.h" #include "GlobalFunctions.h" #include "CustomMessages.h" #include "ObjectProperties.h" #include "VisGroup.h" // memdbgon must be the last include file in a .cpp file!!! #include const char *NO_GROUP_STRING = "(no group)"; const DWORD NO_GROUP_ID = 0xffff; const DWORD VALUE_DIFFERENT_ID = 0xfffe; static const unsigned int g_uToggleStateMsg = ::RegisterWindowMessage(GROUPLIST_MSG_TOGGLE_STATE); BEGIN_MESSAGE_MAP(COP_Groups, CObjectPage) //{{AFX_MSG_MAP(COP_Groups) ON_BN_CLICKED(IDC_EDITGROUPS, OnEditgroups) ON_REGISTERED_MESSAGE(g_uToggleStateMsg, OnListToggleState) ON_WM_SIZE() //}}AFX_MSG_MAP ON_WM_SETFOCUS() END_MESSAGE_MAP() IMPLEMENT_DYNCREATE(COP_Groups, CObjectPage) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- COP_Groups::COP_Groups() : CObjectPage(COP_Groups::IDD) { //{{AFX_DATA_INIT(COP_Groups) //}}AFX_DATA_INIT m_pEditObjectRuntimeClass = RUNTIME_CLASS(editCMapClass); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- COP_Groups::~COP_Groups() { } //----------------------------------------------------------------------------- // Purpose: // Input : pDX - //----------------------------------------------------------------------------- void COP_Groups::DoDataExchange(CDataExchange* pDX) { CObjectPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(COP_Model) DDX_Control(pDX, IDC_EDITGROUPS, m_EditGroupsControl); //}}AFX_DATA_MAP } //----------------------------------------------------------------------------- // Purpose: // Input : b - //----------------------------------------------------------------------------- void COP_Groups::SetMultiEdit(bool b) { CObjectPage::SetMultiEdit(b); } //----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool COP_Groups::SaveData( SaveData_Reason_t reason ) { if (!IsWindow(m_hWnd)) { return false; } int nCount = m_cGroups.GetVisGroupCount(); for (int i = 0; i < nCount; i++) { CVisGroup *pVisGroup = m_cGroups.GetVisGroup(i); // Don't let users edit Auto VisGroup membership! if ( pVisGroup->IsAutoVisGroup() ) continue; int nCheck = m_cGroups.GetCheck(pVisGroup); if (nCheck != -1) { FOR_EACH_OBJ( *m_pObjectList, pos ) { CMapClass *pObject = (CUtlReference< CMapClass >)m_pObjectList->Element(pos); if (nCheck) { pObject->AddVisGroup(pVisGroup); } else { pObject->RemoveVisGroup(pVisGroup); } } } } return true; } //----------------------------------------------------------------------------- // Purpose: // Input : Mode - // pData - //----------------------------------------------------------------------------- void COP_Groups::UpdateData( int Mode, void *pData, bool bCanEdit ) { __super::UpdateData( Mode, pData, bCanEdit ); if ( !IsWindow(m_hWnd) ) { return; } static int s_checkState[128]; if (Mode == LoadData || Mode == LoadFirstData) { CMapClass *pObject = (CMapClass *)pData; if (Mode == LoadFirstData) { UpdateGroupList(); // // Loading the first object. check each group this object is in. // int nCount = m_cGroups.GetVisGroupCount(); for (int i = 0; i < nCount; i++) { CVisGroup *pVisGroup = m_cGroups.GetVisGroup(i); s_checkState[i] = pObject->IsInVisGroup(pVisGroup); } } else { // // Loading subsequent objects. // int nCount = m_cGroups.GetVisGroupCount(); for (int i = 0; i < nCount; i++) { if ( s_checkState[i] != -1) { CVisGroup *pVisGroup = m_cGroups.GetVisGroup(i); if ( pObject->IsInVisGroup(pVisGroup) != s_checkState[i] ) { s_checkState[i] = -1; } } } } } else if ( Mode == LoadFinished ) { int nCount = m_cGroups.GetVisGroupCount(); for (int i = 0; i < nCount; i++) { CVisGroup *pVisGroup = m_cGroups.GetVisGroup(i); m_cGroups.SetCheck(pVisGroup, s_checkState[i]); } } m_cGroups.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) ); m_EditGroupsControl.EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COP_Groups::UpdateGroupList(void) { if (!IsWindow(m_hWnd)) { return; } m_cGroups.SetRedraw(false); m_cGroups.DeleteAllItems(); CVisGroup *pAuto = NULL; CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if (pDoc != NULL) { int nCount = pDoc->VisGroups_GetRootCount(); for (int i = 0; i < nCount; i++) { CVisGroup *pGroup = pDoc->VisGroups_GetRootVisGroup(i); if (stricmp(pGroup->GetName(), "Auto") != 0) { m_cGroups.AddVisGroup(pGroup); } else { pAuto = pGroup; } } // We can't reassign membership to auto visgroups, and rarely need to check membership, // so add the "Auto" visgroup last so that it doesn't get in the way. if (pAuto) { m_cGroups.AddVisGroup(pAuto); } } m_cGroups.ExpandAll(); // If this ever gets slow we could pass a param into ExpandAll to not expand "Auto" if (pAuto) { m_cGroups.CollapseItem(pAuto); } m_cGroups.SetRedraw(true); m_cGroups.Invalidate(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COP_Groups::OnEditgroups() { CEditGroups dlg; dlg.DoModal(); UpdateGroupList(); // dvs: TODO: update the check state for all groups } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- BOOL COP_Groups::OnInitDialog() { CObjectPage::OnInitDialog(); m_cGroups.SubclassDlgItem(IDC_GROUPS, this); m_cGroups.EnableChecks(); CAnchorDef anchorDefs[] = { CAnchorDef( IDC_GROUPS, k_eSimpleAnchorAllSides ), CAnchorDef( IDC_EDITGROUPS, k_eSimpleAnchorBottomRight ) }; m_AnchorMgr.Init( GetSafeHwnd(), anchorDefs, ARRAYSIZE( anchorDefs ) ); return TRUE; } //----------------------------------------------------------------------------- // Purpose: Called when the check state of a group is toggled in the groups list. // Input : wParam - Index of item in the groups list that was toggled. // lParam - New check state. // Output : Returns zero. //----------------------------------------------------------------------------- LRESULT COP_Groups::OnListToggleState(WPARAM wParam, LPARAM lParam) { CVisGroup *pVisGroup = (CVisGroup *)wParam; // Don't let users edit Auto VisGroup membership! if ( pVisGroup->IsAutoVisGroup() ) return 0; m_cGroups.SetCheck(pVisGroup, (int)lParam); return 0; } //----------------------------------------------------------------------------- // Purpose: // Input : *pOld - //----------------------------------------------------------------------------- void COP_Groups::OnSetFocus(CWnd *pOld) { // fixme: //UpdateGrouplist(); CPropertyPage::OnSetFocus(pOld); } void COP_Groups::OnSize( UINT nType, int cx, int cy ) { m_AnchorMgr.OnSize(); }