317 lines
7.8 KiB
C++
317 lines
7.8 KiB
C++
//========= Copyright 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(void)
|
|
{
|
|
if (!IsWindow(m_hWnd))
|
|
{
|
|
return(false);
|
|
}
|
|
|
|
//
|
|
// Apply the dialog data to all the objects being edited.
|
|
//
|
|
FOR_EACH_OBJ( *m_pObjectList, pos )
|
|
{
|
|
CMapClass *pObject = 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();
|
|
}
|