|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements the spawnflags page of the Entity Properties dialog.
//
//=============================================================================//
#include "stdafx.h"
#include "hammer.h"
#include "OP_Flags.h"
#include "OP_Entity.h"
#include "ObjectProperties.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
/////////////////////////////////////////////////////////////////////////////
// COP_Flags property page
IMPLEMENT_DYNCREATE(COP_Flags, CObjectPage)
COP_Flags::COP_Flags() : CObjectPage(COP_Flags::IDD) { //{{AFX_DATA_INIT(COP_Flags)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_pEditObjectRuntimeClass = RUNTIME_CLASS(editCEditGameClass); m_nNumSelectedObjects = 0; m_pEntityPage = NULL; }
COP_Flags::~COP_Flags() { }
void COP_Flags::SetEntityPage( COP_Entity *pPage ) { m_pEntityPage = pPage; }
void COP_Flags::DoDataExchange(CDataExchange* pDX) { CObjectPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(COP_Flags)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COP_Flags, CObjectPage) //{{AFX_MSG_MAP(COP_Flags)
ON_CLBN_CHKCHANGE(IDC_CHECKLIST, OnCheckListChange) ON_WM_SIZE() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COP_Flags message handlers
void COP_Flags::UpdateData( int Mode, PVOID pData, bool bCanEdit ) { __super::UpdateData( Mode, pData, bCanEdit );
if(!IsWindow(m_hWnd) || !pData) { return; } CEditGameClass *pObj = (CEditGameClass*) pData;
if (Mode == LoadFirstData) { UpdateForClass(pObj); } else if (Mode == LoadData) { MergeForClass(pObj); } CreateCheckList();
m_CheckList.EnableWindow( m_bCanEdit ? TRUE : FALSE ); }
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool COP_Flags::SaveData( SaveData_Reason_t reason ) { if (!IsWindow(m_hWnd)) { return(false); }
//
// Apply the dialog data to all the objects being edited.
//
FOR_EACH_OBJ( *m_pObjectList, pos ) { CMapClass *pObject = (CUtlReference< CMapClass >)m_pObjectList->Element(pos); CEditGameClass *pEdit = dynamic_cast <CEditGameClass *>(pObject); Assert(pEdit != NULL);
if ( pEdit != NULL ) { for ( int i = 0; i < m_CheckListItems.Count(); i++ ) { CheckListItem currentItem = m_CheckListItems.Element( i ); // don't save tri-stated bit
if ( m_CheckList.GetCheck(i) != 2 ) { pEdit->SetSpawnFlag( currentItem.nItemBit, m_CheckList.GetCheck(i) ? TRUE : FALSE ); } } } }
return(true); }
//-----------------------------------------------------------------------------
// Purpose: This function is used to initialize the flag checklist.
// It is called to place all the flags belonging to the first
// selected object into the temporary CheckListItems vector
//-----------------------------------------------------------------------------
void COP_Flags::UpdateForClass(CEditGameClass* pObj) { extern GameData *pGD;
GDclass * pClass = pGD->ClassForName(pObj->GetClassName());
if(!IsWindow(m_hWnd)) return;
m_nNumSelectedObjects = 1;
m_CheckListItems.RemoveAll();
if(pClass) { GDinputvariable *pVar = pClass->VarForName("spawnflags");
if (pVar) { int nItems = pVar->GetFlagCount();
for ( int i = 0; i < nItems; i++ ) { CheckListItem newItem; newItem.nItemBit = pVar->GetFlagMask( i ); newItem.pszItemString = pVar->GetFlagCaption( i ); newItem.state = pObj->GetSpawnFlag( newItem.nItemBit ) ? 1 : 0; m_CheckListItems.AddToTail( newItem ); } } }
Assert( m_CheckListItems.Count() <= 32 );
for ( int i = 0; i < 32; i++ ) { int nBitPattern = 1 << i; // is spawnflag for this bit set?
if ( pObj->GetSpawnFlag(nBitPattern) ) { int j; // then see if its allowed to be
for ( j = 0; j < m_CheckListItems.Count(); j ++ ) { int nCheckListPattern = m_CheckListItems.Element(j).nItemBit; if ( nCheckListPattern == nBitPattern ) break; } // we fail to find it?
if ( j == m_CheckListItems.Count() ) { CheckListItem newItem; newItem.nItemBit = nBitPattern; newItem.pszItemString = "????"; newItem.state = 1; m_CheckListItems.AddToTail( newItem ); } } } }
//-----------------------------------------------------------------------------
// Purpose: This function is called to combine flags when multiple objects are selected
// It removes flags from the CheckListItem vector that are not present in all selected objects
//-----------------------------------------------------------------------------
void COP_Flags::MergeForClass(CEditGameClass* pObj) { extern GameData *pGD; GDclass * pClass = pGD->ClassForName(pObj->GetClassName());
if( !IsWindow(m_hWnd) ) return;
m_nNumSelectedObjects++;
if( pClass ) { GDinputvariable *pVar = pClass->VarForName("spawnflags");
for ( int i = m_CheckListItems.Count() - 1; i >= 0; i-- ) { bool bFound = false; CheckListItem currentItem = m_CheckListItems.Element( i ); if ( pVar ) { for ( int j = 0; j < pVar->GetFlagCount(); j++ ) { CheckListItem newItem; newItem.nItemBit = pVar->GetFlagMask(j); newItem.pszItemString = pVar->GetFlagCaption(j); if ( newItem == currentItem ) { bFound = true; int nNewState = pObj->GetSpawnFlag( newItem.nItemBit ) ? 1 : 0; if ( currentItem.state != nNewState ) { m_CheckListItems.Element( i ).state = 2; } break; } } } if ( !bFound ) { m_CheckListItems.FastRemove( i ); } } } Assert( m_CheckListItems.Count() <= 32 ); }
//-----------------------------------------------------------------------------
// Purpose: Creates the checklist by stepping through the CheckListItems vector that
// was created during Update/MergeForClass
//-----------------------------------------------------------------------------
void COP_Flags::CreateCheckList() { m_CheckList.ResetContent(); if ( m_nNumSelectedObjects > 1 ) { m_CheckList.SetCheckStyle(BS_AUTO3STATE); }
for ( int i = 0; i < m_CheckListItems.Count(); i++ ) { CheckListItem newItem = m_CheckListItems.Element(i); m_CheckList.InsertString(i, newItem.pszItemString); m_CheckList.SetCheck(i, newItem.state); } }
void COP_Flags::OnUpdateSpawnFlags( unsigned long value ) { for ( int i=0; i < m_CheckListItems.Count(); i++ ) { CheckListItem &item = m_CheckListItems[i]; m_CheckList.SetCheck( i, (value & item.nItemBit) != 0 ); } }
BOOL COP_Flags::OnInitDialog() { CObjectPage::OnInitDialog();
m_nNumSelectedObjects = 0;
// Subclass checklistbox
m_CheckList.SubclassDlgItem(IDC_CHECKLIST, this); m_CheckList.SetCheckStyle(BS_AUTOCHECKBOX); m_CheckList.ResetContent();
CAnchorDef anchorDefs[] = { CAnchorDef( IDC_CHECKLIST, k_eSimpleAnchorAllSides ) }; m_AnchorMgr.Init( GetSafeHwnd(), anchorDefs, ARRAYSIZE( anchorDefs ) ); return TRUE; }
void COP_Flags::OnCheckListChange() { if ( !m_pEntityPage ) return;
unsigned long bitsSet = 0; unsigned long triStateMask = 0;
// This is just like SaveData.. collect the state of all the checks.
for ( int i = 0; i < m_CheckListItems.Count(); i++ ) { CheckListItem currentItem = m_CheckListItems.Element( i ); // If multiple of the selected entities have a different value for this flag,
// note that. The entity page will use triStateMask to denote flags that
// it should leave alone.
if ( m_CheckList.GetCheck(i) == 2 ) triStateMask |= currentItem.nItemBit; else if ( m_CheckList.GetCheck( i ) ) bitsSet |= currentItem.nItemBit; }
m_pEntityPage->OnUpdateSpawnFlags( triStateMask, bitsSet ); }
void COP_Flags::OnSize( UINT nType, int cx, int cy ) { m_AnchorMgr.OnSize(); }
|