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.
1436 lines
36 KiB
1436 lines
36 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "stdafx.h" |
|
#include "hammer.h" |
|
#include "ObjectProperties.h" |
|
#include "ObjectPage.h" |
|
#include "OP_Flags.h" |
|
#include "OP_Groups.h" |
|
#include "OP_Entity.h" |
|
#include "OP_Output.h" |
|
#include "OP_Model.h" |
|
#include "OP_Input.h" |
|
#include "MapDoc.h" |
|
#include "MapView.h" |
|
#include "MapEntity.h" |
|
#include "MapGroup.h" |
|
#include "MapInstance.h" |
|
#include "MapSolid.h" |
|
#include "MapStudioModel.h" |
|
#include "MapWorld.h" |
|
#include "History.h" |
|
#include "GlobalFunctions.h" |
|
#include "Selection.h" |
|
#include "CustomMessages.h" |
|
#include "Camera.h" |
|
#include "Manifest.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
// |
|
// Layout types for remembering the last layout of the dialog. We could |
|
// also remember this as an array of booleans for which pages were visible. |
|
// |
|
enum LayoutType_t |
|
{ |
|
ltZero, // Special enums for initialization |
|
ltNone, |
|
|
|
ltSolid, // Enable groups only |
|
ltSolidMulti, // Enable none |
|
ltEntity, // Enable entity, flags, groups |
|
ltEntityMulti, // Enable entity, flags |
|
ltWorld, // Enable entity, flags, groups |
|
ltModelEntity, // Enable entity, flags, groups, model, |
|
ltMulti // Enable none |
|
}; |
|
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(CObjectProperties, CPropertySheet) |
|
|
|
|
|
BEGIN_MESSAGE_MAP(CObjectProperties, CPropertySheet) |
|
//{{AFX_MSG_MAP(CObjectProperties) |
|
ON_WM_KILLFOCUS() |
|
ON_WM_ACTIVATE() |
|
ON_WM_CLOSE() |
|
ON_WM_PAINT() |
|
ON_WM_SIZE() |
|
ON_WM_SHOWWINDOW() |
|
ON_WM_CREATE() |
|
ON_COMMAND(IDOK, OnApply ) |
|
ON_COMMAND(ID_APPLY_NOW, OnApply ) |
|
ON_COMMAND(IDCANCEL, OnCancel) |
|
ON_COMMAND(IDI_INPUT, OnInputs) |
|
ON_COMMAND(IDI_OUTPUT, OnOutputs) |
|
ON_COMMAND(IDD_EDIT_INSTANCE, OnEditInstance) |
|
//}}AFX_MSG_MAP |
|
END_MESSAGE_MAP() |
|
|
|
IMPLEMENT_DYNAMIC(editCMapClass, CObject); |
|
IMPLEMENT_DYNAMIC(editCEditGameClass, CObject); |
|
|
|
|
|
static editCMapClass e_CMapClass; |
|
static editCEditGameClass e_CEditGameClass; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor. |
|
//----------------------------------------------------------------------------- |
|
CObjectProperties::CObjectProperties(void) : |
|
CPropertySheet() |
|
{ |
|
m_bDummy = false; |
|
m_pDummy = NULL; |
|
m_pInputButton = NULL; |
|
m_pOutputButton = NULL; |
|
m_pInstanceButton = NULL; |
|
m_pOrgObjects = NULL; |
|
m_bDataDirty = false; |
|
m_bCanEdit = false; |
|
|
|
CreatePages(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor. |
|
// Input : nIDCaption - |
|
// pParentWnd - |
|
// iSelectPage - |
|
//----------------------------------------------------------------------------- |
|
CObjectProperties::CObjectProperties(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) |
|
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage) |
|
{ |
|
m_bDummy = false; |
|
m_pDummy = NULL; |
|
m_pInputButton = NULL; |
|
m_pOutputButton = NULL; |
|
m_pInstanceButton = NULL; |
|
m_bCanEdit = false; |
|
|
|
CreatePages(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor. |
|
// Input : pszCaption - |
|
// pParentWnd - |
|
// iSelectPage - |
|
//----------------------------------------------------------------------------- |
|
CObjectProperties::CObjectProperties(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) |
|
:CPropertySheet(pszCaption, pParentWnd, iSelectPage) |
|
{ |
|
m_bDummy = false; |
|
m_pDummy = NULL; |
|
m_pInputButton = NULL; |
|
m_pOutputButton = NULL; |
|
m_pInstanceButton = NULL; |
|
m_bCanEdit = false; |
|
|
|
CreatePages(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor. |
|
//----------------------------------------------------------------------------- |
|
CObjectProperties::~CObjectProperties() |
|
{ |
|
delete m_pDummy; |
|
|
|
delete m_pEntity; |
|
delete m_pFlags; |
|
delete m_pGroups; |
|
delete m_pOutput; |
|
delete m_pInput; |
|
delete m_pModel; |
|
|
|
delete m_pInputButton; |
|
delete m_pOutputButton; |
|
delete m_pInstanceButton; |
|
|
|
delete[] m_ppPages; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Creates all possible pages and attaches our object list to them. |
|
// Not all will be used depending on the types of objects being edited. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::CreatePages(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::CreatePages", "Object Properties" ); |
|
|
|
m_pEntity = new COP_Entity; |
|
m_pEntity->SetObjectList(&m_DstObjects); |
|
|
|
m_pFlags = new COP_Flags; |
|
m_pFlags->SetObjectList(&m_DstObjects); |
|
|
|
// There are some dependencies between the entity and flags tabs since |
|
// they both edit the spawnflags property. |
|
m_pEntity->SetFlagsPage( m_pFlags ); |
|
m_pFlags->SetEntityPage( m_pEntity ); |
|
|
|
m_pGroups = new COP_Groups; |
|
m_pGroups->SetObjectList(&m_DstObjects); |
|
|
|
m_pOutput = new COP_Output; |
|
m_pOutput->SetObjectList(&m_DstObjects); |
|
|
|
m_pInput = new COP_Input; |
|
m_pInput->SetObjectList(&m_DstObjects); |
|
|
|
m_pModel = new COP_Model; |
|
m_pModel->SetObjectList(&m_DstObjects); |
|
|
|
m_pDummy = new CPropertyPage(IDD_OBJPAGE_DUMMY); |
|
|
|
m_ppPages = NULL; |
|
m_nPages = 0; |
|
|
|
m_pLastActivePage = NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pType - |
|
//----------------------------------------------------------------------------- |
|
PVOID CObjectProperties::GetEditObject(CRuntimeClass *pType) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::GetEditObject", "Object Properties" ); |
|
|
|
if (pType == RUNTIME_CLASS(editCMapClass)) |
|
{ |
|
return PVOID((CMapClass*)&e_CMapClass); |
|
} |
|
else if (pType == RUNTIME_CLASS(editCEditGameClass)) |
|
{ |
|
return PVOID((CEditGameClass*)&e_CEditGameClass); |
|
} |
|
|
|
Assert(0); |
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pobj - |
|
// pType - |
|
//----------------------------------------------------------------------------- |
|
PVOID CObjectProperties::GetEditObjectFromMapObject(CMapClass *pobj, CRuntimeClass *pType) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::GetEditObjectFromMapObject", "Object Properties" ); |
|
|
|
if (pType == RUNTIME_CLASS(editCMapClass)) |
|
{ |
|
return PVOID(pobj); |
|
} |
|
else if (pType == RUNTIME_CLASS(editCEditGameClass)) |
|
{ |
|
if (pobj->IsMapClass(MAPCLASS_TYPE(CMapEntity))) |
|
{ |
|
return PVOID((CEditGameClass*)((CMapEntity*)pobj)); |
|
} |
|
|
|
if (pobj->IsMapClass(MAPCLASS_TYPE(CMapWorld))) |
|
{ |
|
return PVOID((CEditGameClass*)((CMapWorld*)pobj)); |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pobj - |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::CopyDataToEditObjects(CMapClass *pobj) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::CopyDataToEditObjects", "Object Properties" ); |
|
|
|
// |
|
// All copies here are done without updating object dependencies, because |
|
// we're copying to a place that is outside of the world. |
|
// |
|
e_CMapClass.CopyFrom(pobj, false); |
|
|
|
if (pobj->IsMapClass(MAPCLASS_TYPE(CMapEntity))) |
|
{ |
|
e_CEditGameClass.CopyFrom((CEditGameClass *)((CMapEntity *)pobj)); |
|
} |
|
else if (pobj->IsMapClass(MAPCLASS_TYPE(CMapWorld))) |
|
{ |
|
e_CEditGameClass.CopyFrom((CEditGameClass *)((CMapWorld *)pobj)); |
|
} |
|
} |
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: |
|
// Input : nState - |
|
//------------------------------------------------------------------------------ |
|
void CObjectProperties::SetOutputButtonState(int nState) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::SetOutputButtonState", "Object Properties" ); |
|
|
|
if (nState == CONNECTION_GOOD) |
|
{ |
|
m_pOutputButton->SetIcon(m_hIconOutputGood); |
|
m_pOutputButton->ShowWindow(SW_SHOW); |
|
m_pOutputButton->Invalidate(); |
|
m_pOutputButton->UpdateWindow(); |
|
} |
|
else if (nState == CONNECTION_BAD) |
|
{ |
|
m_pOutputButton->SetIcon(m_hIconOutputBad); |
|
m_pOutputButton->ShowWindow(SW_SHOW); |
|
m_pOutputButton->Invalidate(); |
|
m_pOutputButton->UpdateWindow(); |
|
} |
|
else |
|
{ |
|
m_pOutputButton->ShowWindow(SW_HIDE); |
|
m_pOutputButton->Invalidate(); |
|
m_pOutputButton->UpdateWindow(); |
|
} |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: |
|
// Input : nState - |
|
//------------------------------------------------------------------------------ |
|
void CObjectProperties::SetInputButtonState(int nState) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::SetInputButtonState", "Object Properties" ); |
|
|
|
if (nState == CONNECTION_GOOD) |
|
{ |
|
m_pInputButton->SetIcon(m_hIconInputGood); |
|
m_pInputButton->ShowWindow(SW_SHOW); |
|
m_pInputButton->Invalidate(); |
|
m_pInputButton->UpdateWindow(); |
|
} |
|
else if (nState == CONNECTION_BAD) |
|
{ |
|
m_pInputButton->SetIcon(m_hIconInputBad); |
|
m_pInputButton->ShowWindow(SW_SHOW); |
|
m_pInputButton->Invalidate(); |
|
m_pInputButton->UpdateWindow(); |
|
} |
|
else |
|
{ |
|
m_pInputButton->ShowWindow(SW_HIDE); |
|
m_pInputButton->Invalidate(); |
|
m_pInputButton->UpdateWindow(); |
|
} |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: Set icon being displayed on output button. |
|
//------------------------------------------------------------------------------ |
|
void CObjectProperties::UpdateOutputButton(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::UpdateOutputButton", "Object Properties" ); |
|
|
|
if (!m_pOutputButton) |
|
{ |
|
return; |
|
} |
|
|
|
bool bHaveConnection = false; |
|
bool bIgnoreHiddenTargets = false; |
|
if ( m_pOutput ) |
|
bIgnoreHiddenTargets = !m_pOutput->ShouldShowHiddenTargets(); |
|
|
|
FOR_EACH_OBJ( m_DstObjects, pos ) |
|
{ |
|
CMapClass *pObject = m_DstObjects.Element(pos); |
|
|
|
if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity)))) |
|
{ |
|
CMapEntity *pEntity = (CMapEntity *)pObject; |
|
int nStatus = CEntityConnection::ValidateOutputConnections(pEntity, true, bIgnoreHiddenTargets); |
|
if (nStatus == CONNECTION_BAD) |
|
{ |
|
SetOutputButtonState(CONNECTION_BAD); |
|
return; |
|
} |
|
else if (nStatus == CONNECTION_GOOD) |
|
{ |
|
bHaveConnection = true; |
|
} |
|
} |
|
} |
|
if (bHaveConnection) |
|
{ |
|
SetOutputButtonState(CONNECTION_GOOD); |
|
} |
|
else |
|
{ |
|
SetOutputButtonState(CONNECTION_NONE); |
|
} |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: Set icon being displayed on input button. |
|
//------------------------------------------------------------------------------ |
|
void CObjectProperties::UpdateInputButton() |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::UpdateInputButton", "Object Properties" ); |
|
|
|
if (!m_pInputButton) |
|
{ |
|
return; |
|
} |
|
|
|
bool bHaveConnection = false; |
|
|
|
FOR_EACH_OBJ( m_DstObjects, pos ) |
|
{ |
|
CMapClass *pObject = m_DstObjects.Element(pos); |
|
|
|
if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity)))) |
|
{ |
|
CMapEntity *pEntity = (CMapEntity *)pObject; |
|
int nStatus = CEntityConnection::ValidateInputConnections(pEntity, false); |
|
if (nStatus == CONNECTION_BAD) |
|
{ |
|
SetInputButtonState(CONNECTION_BAD); |
|
return; |
|
} |
|
else if (nStatus == CONNECTION_GOOD) |
|
{ |
|
bHaveConnection = true; |
|
} |
|
} |
|
} |
|
if (bHaveConnection) |
|
{ |
|
SetInputButtonState(CONNECTION_GOOD); |
|
} |
|
else |
|
{ |
|
SetInputButtonState(CONNECTION_NONE); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Finds/Creates the buttons. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::CreateButtons(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::CreateButtons", "Object Properties" ); |
|
|
|
#if 0 |
|
// Get the screen location of the hidden apply button(ID_APPLY_NOW) |
|
rect rcButton; |
|
pApplyButton->GetWindowRect( &rcButton ); |
|
|
|
// Grab, enable and rename the OK button to be Apply |
|
// (Because <enter> only accelerates IDOK) |
|
// and we dont want "OK" (apply+close) functionality |
|
CButton *pOKButton = reinterpret_cast<CButton *>(GetDlgItem(IDOK)); |
|
pOKButton->SetWindowTextA("Apply"); |
|
pOKButton->EnableWindow(); |
|
pOKButton->ShowWindow(SW_SHOWNA); |
|
pOKButton->MoveWindow(&rcButton); |
|
#else |
|
// Grab, enable and DONT show the OK button |
|
// (Because <enter> only accelerates IDOK) |
|
// and we dont want "OK" (apply+close) functionality |
|
CButton *pOKButton = reinterpret_cast<CButton *>(GetDlgItem(IDOK)); |
|
pOKButton->EnableWindow(); |
|
// Dont show the window, just make it active to forward <enter> -> IDOK -> OnApply |
|
|
|
// Grab and enable & show the hidden Apply button too |
|
CButton *pApplyButton = reinterpret_cast<CButton *>(GetDlgItem(ID_APPLY_NOW)); |
|
pApplyButton->SetButtonStyle( pApplyButton->GetButtonStyle() | BS_DEFPUSHBUTTON ); |
|
pApplyButton->EnableWindow(); |
|
pApplyButton->ShowWindow(SW_SHOWNA); |
|
#endif |
|
// Grab and enable & show the hidden Cancel button too |
|
CButton *pCancelButton = reinterpret_cast<CButton *>(GetDlgItem(IDCANCEL)); |
|
pCancelButton->EnableWindow(); |
|
pCancelButton->ShowWindow(SW_SHOWNA); |
|
|
|
// |
|
// Load Icons |
|
// |
|
CWinApp *pApp = AfxGetApp(); |
|
m_hIconOutputGood = pApp->LoadIcon(IDI_OUTPUT); |
|
m_hIconOutputBad = pApp->LoadIcon(IDI_OUTPUTBAD); |
|
m_hIconInputGood = pApp->LoadIcon(IDI_INPUT); |
|
m_hIconInputBad = pApp->LoadIcon(IDI_INPUTBAD); |
|
|
|
// Create buttons to display connection status icons |
|
CRect rect; |
|
GetWindowRect(&rect); |
|
rect.InflateRect(0, 0, 0, 32); |
|
MoveWindow(&rect, FALSE); |
|
GetClientRect(&rect); |
|
|
|
m_pInputButton = new CButton; |
|
m_pInputButton->Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_ICON|BS_FLAT, CRect(6,rect.bottom - 34,38,rect.bottom - 2), this, IDI_INPUT); |
|
|
|
m_pOutputButton = new CButton; |
|
m_pOutputButton->Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_ICON|BS_FLAT, CRect(40,rect.bottom - 34,72,rect.bottom - 2), this, IDI_OUTPUT); |
|
|
|
m_pInstanceButton = new CButton; |
|
m_pInstanceButton->Create( _T( "Edit Instance" ), WS_CHILD|WS_VISIBLE|BS_TEXT, CRect( 6, rect.bottom - 28, 140, rect.bottom - 4 ), this, IDD_EDIT_INSTANCE ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns the appropriate page layout for the current object list. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::GetTabsForLayout(LayoutType_t eLayoutType, bool &bEntity, bool &bGroups, bool &bFlags, bool &bModel) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::GetTabsForLayout", "Object Properties" ); |
|
|
|
bEntity = bGroups = bFlags = bModel = false; |
|
|
|
switch (eLayoutType) |
|
{ |
|
case ltEntity: |
|
case ltEntityMulti: |
|
case ltModelEntity: |
|
{ |
|
bFlags = true; |
|
bEntity = true; |
|
bGroups = true; |
|
bModel = (eLayoutType == ltModelEntity); |
|
break; |
|
} |
|
|
|
case ltSolid: |
|
{ |
|
bGroups = true; |
|
break; |
|
} |
|
|
|
case ltWorld: |
|
{ |
|
bEntity = true; |
|
break; |
|
} |
|
|
|
case ltMulti: |
|
case ltSolidMulti: |
|
{ |
|
bGroups = true; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns the appropriate page layout for the current object list. |
|
//----------------------------------------------------------------------------- |
|
LayoutType_t CObjectProperties::GetLayout(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::GetLayout", "Object Properties" ); |
|
|
|
LayoutType_t eLayoutType = ltNone; |
|
|
|
if ((m_DstObjects.Count() == 0) || (CMapDoc::GetActiveMapDoc() == NULL)) |
|
{ |
|
eLayoutType = ltNone; |
|
} |
|
else |
|
{ |
|
// |
|
// Figure out which layout to use based on the objects being edited. |
|
// |
|
bool bFirst = true; |
|
MAPCLASSTYPE PrevType = MAPCLASS_TYPE(CMapEntity); |
|
|
|
FOR_EACH_OBJ( m_DstObjects, pos ) |
|
{ |
|
CMapClass *pObject = m_DstObjects.Element(pos); |
|
MAPCLASSTYPE ThisType = pObject->GetType(); |
|
|
|
if (bFirst) |
|
{ |
|
bFirst = false; |
|
|
|
if (ThisType == MAPCLASS_TYPE(CMapEntity)) |
|
{ |
|
CMapEntity *pEntity = (CMapEntity *)pObject; |
|
|
|
// |
|
// Only show the model tab when we have a single entity selected that |
|
// has a model helper. |
|
// |
|
if (m_DstObjects.Count() == 1) |
|
{ |
|
if (pEntity->GetChildOfType((CMapStudioModel *)NULL)) |
|
{ |
|
eLayoutType = ltModelEntity; |
|
} |
|
else |
|
{ |
|
eLayoutType = ltEntity; |
|
} |
|
} |
|
else |
|
{ |
|
eLayoutType = ltEntityMulti; |
|
} |
|
} |
|
else if ((ThisType == MAPCLASS_TYPE(CMapSolid)) || |
|
(ThisType == MAPCLASS_TYPE(CMapGroup))) |
|
{ |
|
eLayoutType = (m_DstObjects.Count() == 1) ? ltSolid : ltSolidMulti; |
|
} |
|
else if (ThisType == MAPCLASS_TYPE(CMapWorld)) |
|
{ |
|
eLayoutType = ltWorld; |
|
} |
|
} |
|
else if (ThisType != PrevType) |
|
{ |
|
eLayoutType = ltMulti; |
|
} |
|
|
|
PrevType = ThisType; |
|
} |
|
} |
|
|
|
return eLayoutType; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::RestoreActivePage(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::RestoreActivePage", "Object Properties" ); |
|
|
|
// |
|
// Try to restore the previously active page. If it is not in the page list |
|
// just activate page zero. |
|
// |
|
bool bPageSet = false; |
|
for (int i = 0; i < m_nPages; i++) |
|
{ |
|
if (m_ppPages[i] == m_pLastActivePage) |
|
{ |
|
SetActivePage(m_pLastActivePage); |
|
bPageSet = true; |
|
break; |
|
} |
|
} |
|
|
|
if (!bPageSet) |
|
{ |
|
SetActivePage(0); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::SaveActivePage(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::SaveActivePage", "Object Properties" ); |
|
|
|
CObjectPage *pPage = (CObjectPage *)GetActivePage(); |
|
if (pPage != NULL) |
|
{ |
|
m_pLastActivePage = pPage; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets up pages to display based on "m_DstObjects". |
|
// Output : Returns TRUE if the page structure changed, FALSE if not. |
|
//----------------------------------------------------------------------------- |
|
BOOL CObjectProperties::SetupPages(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::SetupPages", "Object Properties" ); |
|
|
|
static bool bFirstTime = true; |
|
static LayoutType_t eLastLayoutType = ltZero; |
|
static LayoutType_t eLastValidLayoutType = ltZero; |
|
|
|
// |
|
// Save the current active page. |
|
// |
|
if ((eLastLayoutType != ltZero) && (eLastLayoutType != ltNone)) |
|
{ |
|
SaveActivePage(); |
|
} |
|
|
|
// |
|
// Determine the appropriate layout for the current object list. |
|
// |
|
LayoutType_t eLayoutType = GetLayout(); |
|
|
|
bool bEntity; |
|
bool bGroups; |
|
bool bFlags; |
|
bool bModel; |
|
GetTabsForLayout(eLayoutType, bEntity, bGroups, bFlags, bModel); |
|
|
|
// |
|
// If the layout has not changed, we're done. All the pages are already set up. |
|
// |
|
if (eLayoutType == eLastLayoutType) |
|
{ |
|
// |
|
// Try to restore the previously active page. If it has been deleted just |
|
// activate page zero. |
|
// |
|
RestoreActivePage(); |
|
return(FALSE); |
|
} |
|
|
|
// |
|
// Forget the last active page when the layout changes from one |
|
// valid layout to another (such as from entity to solid). |
|
// Don't reset when switching between model entities and non-model entities, |
|
// because it's annoying to be switched away from the Outputs tab. |
|
// |
|
if ((eLayoutType != ltNone) && (eLayoutType != eLastValidLayoutType) && |
|
!((eLayoutType == ltEntity) && (eLastValidLayoutType == ltModelEntity)) && |
|
!((eLayoutType == ltModelEntity) && (eLastValidLayoutType == ltEntity))) |
|
{ |
|
m_pLastActivePage = NULL; |
|
eLastValidLayoutType = eLayoutType; |
|
} |
|
|
|
eLastLayoutType = eLayoutType; |
|
|
|
CObjectPage::s_bRESTRUCTURING = TRUE; |
|
|
|
UINT nAddPages = bEntity + bGroups + bFlags + bModel; |
|
|
|
// don't want to change focus .. just pages! |
|
CWnd *pActiveWnd = GetActiveWindow(); |
|
|
|
bool bDisabledraw = false; |
|
if (::IsWindow(m_hWnd) && IsWindowVisible()) |
|
{ |
|
SetRedraw(FALSE); |
|
bDisabledraw = true; |
|
} |
|
|
|
if (!m_bDummy && (nAddPages == 0)) |
|
{ |
|
AddPage(m_pDummy); |
|
m_bDummy = true; |
|
} |
|
else if (m_bDummy && (nAddPages > 0)) |
|
{ |
|
RemovePage(m_pDummy); |
|
m_bDummy = false; |
|
} |
|
|
|
struct |
|
{ |
|
bool m_bIsVisible; |
|
bool m_bWantVisible; |
|
CObjectPage *m_pPage; |
|
} pages[] = |
|
{ |
|
{false, bEntity, m_pEntity}, |
|
{false, bEntity, m_pOutput}, |
|
{false, bEntity, m_pInput}, |
|
{false, bModel, m_pModel}, |
|
{false, bFlags, m_pFlags}, |
|
{false, bGroups, m_pGroups} |
|
}; |
|
|
|
// First, remove pages that we don't want visible. |
|
// Also store if they're visible. |
|
for ( int i=0; i < ARRAYSIZE( pages ); i++ ) |
|
{ |
|
pages[i].m_bIsVisible = ( GetPageIndex( pages[i].m_pPage ) != -1 ); |
|
if ( pages[i].m_bIsVisible && !pages[i].m_bWantVisible) |
|
{ |
|
// It's visible but they don't want it there. |
|
RemovePage( pages[i].m_pPage ); |
|
pages[i].m_bIsVisible = false; |
|
} |
|
} |
|
|
|
// We're about to add pages, but it'll only add them to the right of what's already there, |
|
// so we must get rid of anything to the right of our leftmost addition. |
|
for ( int i=0; i < ARRAYSIZE( pages ); i++ ) |
|
{ |
|
if ( !pages[i].m_bIsVisible && pages[i].m_bWantVisible ) |
|
{ |
|
// Ok, page i needs to be on, so nuke everything to the right of it. |
|
for ( int j=i+1; j < ARRAYSIZE( pages ); j++ ) |
|
{ |
|
if ( pages[j].m_bIsVisible ) |
|
{ |
|
RemovePage( pages[j].m_pPage ); |
|
pages[j].m_bIsVisible = false; |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
|
|
for ( int i=0; i < ARRAYSIZE( pages ); i++ ) |
|
{ |
|
if ( !pages[i].m_bIsVisible && pages[i].m_bWantVisible ) |
|
AddPage( pages[i].m_pPage ); |
|
} |
|
|
|
// |
|
// Store active pages in our array. |
|
// |
|
if (!m_bDummy) |
|
{ |
|
delete[] m_ppPages; |
|
m_nPages = GetPageCount(); |
|
m_ppPages = new CObjectPage*[m_nPages]; |
|
|
|
for (int i = 0; i < m_nPages; i++) |
|
{ |
|
m_ppPages[i] = (CObjectPage *)GetPage(i); |
|
m_ppPages[i]->m_bFirstTimeActive = true; |
|
m_ppPages[i]->m_bHasUpdatedData = false; |
|
} |
|
} |
|
|
|
CObjectPage::s_bRESTRUCTURING = FALSE; |
|
|
|
//VPROF_BUDGET( "CObjectProperties::RestoreActivePage", "Object Properties" ); |
|
RestoreActivePage(); |
|
|
|
// |
|
// Enable redraws if they were disabled above. |
|
// |
|
if (bDisabledraw) |
|
{ |
|
SetRedraw(TRUE); |
|
Invalidate(FALSE); |
|
} |
|
|
|
// Set button status |
|
UpdateOutputButton(); |
|
UpdateInputButton(); |
|
|
|
if (pActiveWnd != NULL) |
|
{ |
|
pActiveWnd->SetActiveWindow(); |
|
} |
|
|
|
bFirstTime = false; |
|
|
|
return TRUE; // pages changed - return true |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: Set object properties dialogue to the Output tab and highlight |
|
// the given item |
|
// Input : pConnection - |
|
//------------------------------------------------------------------------------ |
|
void CObjectProperties::SetPageToOutput(CEntityConnection *pConnection) |
|
{ |
|
if ( m_bDataDirty ) |
|
ReloadData(); |
|
|
|
SetActivePage(m_pOutput); |
|
m_pOutput->SetSelectedConnection(pConnection); |
|
} |
|
|
|
void CObjectProperties::SetPageToInput(CEntityConnection *pConnection) |
|
{ |
|
if ( m_bDataDirty ) |
|
ReloadData(); |
|
|
|
SetActivePage(m_pInput); |
|
|
|
m_pInput->SetSelectedConnection(pConnection); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::SaveData(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::SaveData", "Object Properties" ); |
|
|
|
// |
|
// Make sure window is visible - don't want to save otherwise. |
|
// |
|
if (!IsWindowVisible()) |
|
{ |
|
return; |
|
} |
|
|
|
// we should never save in a dirty state |
|
if ( m_bDataDirty ) |
|
return; |
|
|
|
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); |
|
if (!pDoc || !m_DstObjects.Count() || m_bDummy) |
|
{ |
|
return; |
|
} |
|
|
|
// |
|
// Transfer all page data to the objects being edited. |
|
// |
|
GetHistory()->MarkUndoPosition( pDoc->GetSelection()->GetList(), "Change Properties"); |
|
|
|
// Don't keep all the world's children when we're editing the world, because |
|
// that's really slow (and pointless since all we're changing is keyvalues). |
|
bool bKeptWorld = false; |
|
if (m_DstObjects.Count() == 1) |
|
{ |
|
CMapClass *pObject = m_DstObjects.Element( 0 ); |
|
if ( IsWorldObject(pObject) ) |
|
{ |
|
GetHistory()->KeepNoChildren(pObject); |
|
bKeptWorld = true; |
|
} |
|
} |
|
|
|
if (!bKeptWorld) |
|
{ |
|
GetHistory()->Keep(&m_DstObjects); |
|
} |
|
|
|
for (int i = 0; i < m_nPages; i++) |
|
{ |
|
// |
|
// Pages that have never been shown have no hwnd. |
|
// |
|
if (IsWindow(m_ppPages[i]->m_hWnd) && m_ppPages[i]->m_bHasUpdatedData ) |
|
{ |
|
m_ppPages[i]->SaveData(); |
|
} |
|
} |
|
|
|
// Objects may have changed. Update the views. |
|
|
|
pDoc->SetModifiedFlag(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Submits the objects to be edited to the property pages so they can |
|
// update their controls. |
|
// Input : iPage - Page index or -1 to update all pages. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::LoadDataForPages(int iPage) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::LoadDataForPages", "Object Properties" ); |
|
|
|
if (m_bDummy) |
|
{ |
|
return; |
|
} |
|
|
|
// |
|
// Determine whether we are editing multiple objects or not. |
|
// |
|
bool bMultiEdit = (m_DstObjects.Count() > 1); |
|
m_bCanEdit = true; |
|
|
|
// |
|
// Submit the edit objects to each page one at a time. |
|
// |
|
int nMode = CObjectPage::LoadFirstData; |
|
|
|
FOR_EACH_OBJ( m_DstObjects, pos ) |
|
{ |
|
CMapClass *pobj = m_DstObjects.Element(pos); |
|
|
|
if ( pobj->IsEditable() == false ) |
|
{ |
|
m_bCanEdit = false; |
|
} |
|
|
|
if (iPage != -1) |
|
{ |
|
// |
|
// Specific page. |
|
// |
|
m_ppPages[iPage]->SetMultiEdit(bMultiEdit); |
|
|
|
void *pObject = GetEditObjectFromMapObject(pobj, m_ppPages[iPage]->GetEditObjectRuntimeClass()); |
|
if (pObject != NULL) |
|
{ |
|
m_ppPages[iPage]->UpdateData(nMode, pObject, m_bCanEdit); |
|
m_ppPages[iPage]->m_bHasUpdatedData = true; |
|
} |
|
} |
|
else for (int i = 0; i < m_nPages; i++) |
|
{ |
|
// |
|
// All pages. |
|
// |
|
m_ppPages[i]->SetMultiEdit(bMultiEdit); |
|
|
|
// This page hasn't even been shown yet. Don't bother updating its data. |
|
if (m_ppPages[i]->m_bFirstTimeActive) |
|
continue; |
|
|
|
void *pObject = GetEditObjectFromMapObject(pobj, m_ppPages[i]->GetEditObjectRuntimeClass()); |
|
if (pObject != NULL) |
|
{ |
|
m_ppPages[i]->UpdateData(nMode, pObject, m_bCanEdit); |
|
m_ppPages[i]->m_bHasUpdatedData = true; |
|
} |
|
} |
|
|
|
nMode = CObjectPage::LoadData; |
|
} |
|
|
|
CButton *pApplyButton = reinterpret_cast<CButton *>(GetDlgItem(ID_APPLY_NOW)); |
|
pApplyButton->EnableWindow( ( m_bCanEdit ? TRUE : FALSE ) ); |
|
|
|
// |
|
// Tell the pages that we are done submitting data. |
|
// |
|
if (iPage != -1) |
|
{ |
|
// |
|
// Specific page. |
|
// |
|
m_ppPages[iPage]->UpdateData(CObjectPage::LoadFinished, NULL, m_bCanEdit); |
|
} |
|
else for (int i = 0; i < m_nPages; i++) |
|
{ |
|
// |
|
// All pages. |
|
// |
|
|
|
// This page hasn't even been shown yet. Don't bother updating its data. |
|
if (m_ppPages[i]->m_bFirstTimeActive) |
|
continue; |
|
|
|
m_ppPages[i]->UpdateData(CObjectPage::LoadFinished, NULL, m_bCanEdit); |
|
} |
|
|
|
// |
|
// Update the input/output icons based on the new data. |
|
// |
|
UpdateOutputButton(); |
|
UpdateInputButton(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds the object to m_DstObjects unless it is a group, in which case |
|
// it is expanded (recursively) to its children. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::AddObjectExpandGroups(CMapClass *pObject) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::AddObjectExpandGroups", "Object Properties" ); |
|
|
|
if (pObject->IsGroup()) |
|
{ |
|
const CMapObjectList *pChildren = pObject->GetChildren(); |
|
|
|
FOR_EACH_OBJ( *pChildren, pos ) |
|
{ |
|
AddObjectExpandGroups( pChildren->Element(pos) ); |
|
} |
|
} |
|
else |
|
{ |
|
m_DstObjects.AddToTail(pObject); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Updates the property page data when the selection contents change. |
|
// Input : pObjects - List of currently selected objects. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::ReloadData() |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::LoadData", "Object Properties" ); |
|
|
|
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); |
|
|
|
// |
|
// Disable window so it does not gain focus during this operation. |
|
// |
|
EnableWindow(FALSE); |
|
|
|
|
|
// |
|
// Transfer the objects from pObjects to m_DstObjects, expanding |
|
// groups to their member children. |
|
// |
|
m_DstObjects.RemoveAll(); |
|
if ( m_pOrgObjects ) |
|
{ |
|
FOR_EACH_OBJ( (*m_pOrgObjects), pos ) |
|
{ |
|
AddObjectExpandGroups( m_pOrgObjects->Element(pos) ); |
|
} |
|
} |
|
|
|
m_pInstanceButton->ShowWindow( SW_HIDE ); |
|
|
|
// |
|
// If there is only one object selected, copy its data to our temporary |
|
// edit objects. |
|
// |
|
if (m_DstObjects.Count() == 1) |
|
{ |
|
// |
|
// Copy the single destination object's data to our temporary |
|
// edit objects. |
|
// |
|
CMapClass *pobj = m_DstObjects.Element(0); |
|
CopyDataToEditObjects( pobj ); |
|
|
|
// |
|
// Set the window title to include the object's description. |
|
// |
|
char szTitle[MAX_PATH]; |
|
sprintf(szTitle, "Object Properties: %s", pobj->GetDescription()); |
|
SetWindowText(szTitle); |
|
|
|
CManifestInstance *pManifestInstance = dynamic_cast< CManifestInstance * >( pobj ); |
|
if ( pManifestInstance ) |
|
{ |
|
CManifest *pManifest = CMapDoc::GetManifest(); |
|
|
|
if ( pManifest ) |
|
{ |
|
ShowWindow( SW_HIDE ); |
|
if ( pDoc ) |
|
{ |
|
pDoc->UpdateAllViews( MAPVIEW_UPDATE_SELECTION | MAPVIEW_UPDATE_TOOL | MAPVIEW_RENDER_NOW ); |
|
} |
|
pManifest->SetPrimaryMap( pManifestInstance->GetManifestMap() ); |
|
return; |
|
} |
|
} |
|
|
|
CMapEntity *pEntity = dynamic_cast< CMapEntity * >( pobj ); |
|
if ( pEntity ) |
|
{ |
|
if ( strcmpi( pEntity->GetClassName(), "func_instance" ) == 0 ) |
|
{ |
|
pDoc->PopulateInstance( pEntity ); |
|
CMapInstance *pMapInstance = pEntity->GetChildOfType( ( CMapInstance * )NULL ); |
|
if ( pMapInstance && pMapInstance->GetInstancedMap() ) |
|
{ |
|
m_pInstanceButton->ShowWindow( SW_SHOW ); |
|
} |
|
} |
|
else if ( strcmpi( pEntity->GetClassName(), "func_instance_parms" ) == 0 ) |
|
{ |
|
if ( pDoc ) |
|
{ |
|
pDoc->PopulateInstanceParms( pEntity ); |
|
} |
|
} |
|
} |
|
|
|
} |
|
else if (m_DstObjects.Count() > 1) |
|
{ |
|
SetWindowText("Object Properties: multiple objects"); |
|
} |
|
else |
|
{ |
|
SetWindowText("Object Properties"); |
|
} |
|
|
|
SetupPages(); |
|
LoadDataForPages(); |
|
|
|
EnableWindow(TRUE); |
|
|
|
m_bDataDirty = false; |
|
} |
|
|
|
|
|
BOOL CObjectProperties::OnInitDialog() |
|
{ |
|
BOOL b = CPropertySheet::OnInitDialog(); |
|
SetWindowText("Object Properties"); |
|
|
|
CreateButtons(); |
|
UpdateAnchors( NULL ); |
|
|
|
return b; |
|
} |
|
|
|
|
|
void CObjectProperties::UpdateAnchors( CWnd *pPage ) |
|
{ |
|
if ( !GetSafeHwnd() ) |
|
return; |
|
|
|
// Anchor stuff. |
|
HWND hTab = NULL; |
|
if ( GetTabControl() ) |
|
hTab = GetTabControl()->GetSafeHwnd(); |
|
|
|
CAnchorDef anchorDefs[] = |
|
{ |
|
CAnchorDef( IDOK, k_eSimpleAnchorBottomRight ), |
|
CAnchorDef( ID_APPLY_NOW, k_eSimpleAnchorBottomRight ), |
|
CAnchorDef( IDCANCEL, k_eSimpleAnchorBottomRight ), |
|
CAnchorDef( IDI_INPUT, k_eSimpleAnchorBottomRight ), |
|
CAnchorDef( IDI_OUTPUT, k_eSimpleAnchorBottomRight ), |
|
CAnchorDef( IDD_EDIT_INSTANCE, k_eSimpleAnchorBottomRight ), |
|
CAnchorDef( hTab, k_eSimpleAnchorAllSides ), |
|
CAnchorDef( pPage ? pPage->GetSafeHwnd() : (HWND)NULL, k_eSimpleAnchorAllSides ) |
|
}; |
|
m_AnchorMgr.Init( GetSafeHwnd(), anchorDefs, ARRAYSIZE( anchorDefs ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Closes the object properties dialog, saving changes. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnClose(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::OnClose", "Object Properties" ); |
|
OnApply(); |
|
|
|
ShowWindow(SW_HIDE); |
|
} |
|
|
|
void CObjectProperties::OnPaint() |
|
{ |
|
CPaintDC dc(this); // device context for painting |
|
|
|
if ( m_bDataDirty ) |
|
ReloadData(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : bShow - |
|
// nStatus - |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnShowWindow(BOOL bShow, UINT nStatus) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::OnShowWindow", "Object Properties" ); |
|
|
|
// Forget the last active page when the window is hidden or shown. |
|
// FIXME: SetupPages calls SaveActivePage, so we must switch to page 0 here |
|
SetActivePage(0); |
|
m_pLastActivePage = NULL; |
|
|
|
CPropertySheet::OnShowWindow(bShow, nStatus); |
|
|
|
for (int i = 0; i < m_nPages; i++) |
|
{ |
|
m_ppPages[i]->OnShowPropertySheet(bShow, nStatus); |
|
} |
|
} |
|
|
|
|
|
void CObjectProperties::OnSize( UINT nType, int cx, int cy ) |
|
{ |
|
m_AnchorMgr.OnSize(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles the Apply button. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnApply(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::OnApply", "Object Properties" ); |
|
|
|
if ( !m_bCanEdit ) |
|
{ |
|
return; |
|
} |
|
|
|
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); |
|
if ( !pDoc ) |
|
return; |
|
|
|
//We lock visgroup updates here because activities in the object properties dialog can |
|
//change visgroups which, if updated, will change the object properties, causing problems. |
|
//All visgroup updates will occur at the end of this apply operation. |
|
bool bLocked = pDoc->VisGroups_LockUpdates( true ); |
|
|
|
for (int i = 0; i < m_nPages; i++) |
|
{ |
|
if (!m_ppPages[i]->OnApply()) |
|
{ |
|
return; |
|
} |
|
} |
|
|
|
// |
|
// Save and reload the data so the GUI updates. |
|
// |
|
SaveData(); |
|
|
|
ReloadData(); |
|
|
|
// Pass along the apply message to the entities. |
|
FOR_EACH_OBJ( m_DstObjects, pos ) |
|
{ |
|
CMapClass *pObject = m_DstObjects.Element( pos ); |
|
if ( pObject ) |
|
{ |
|
pObject->OnApply(); |
|
} |
|
} |
|
|
|
if ( bLocked ) |
|
{ |
|
pDoc->VisGroups_LockUpdates( false ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles <return> keys sent to OK -> apply instead |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnOK(void) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::OnClose", "Object Properties" ); |
|
OnApply(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles the Apply button. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnCancel(void) |
|
{ |
|
ShowWindow(SW_HIDE); |
|
|
|
// reload original data and overwrite any changes made prio |
|
ReloadData(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles the input icon button. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnInputs(void) |
|
{ |
|
SetActivePage(m_pInput); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles the output icon button. |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnOutputs(void) |
|
{ |
|
SetActivePage(m_pOutput); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: handle the pushing of the Edit Instance button. Will attempt to |
|
// switch to the map document containing the instance. |
|
// Input : none |
|
// Output : none |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::OnEditInstance(void) |
|
{ |
|
if (m_DstObjects.Count() == 1) |
|
{ |
|
CMapClass *pObj = m_DstObjects.Element( 0 ); |
|
CMapEntity *pEntity = dynamic_cast< CMapEntity * >( pObj ); |
|
|
|
if ( pEntity ) |
|
{ |
|
EnumChildrenPos_t pos; |
|
CMapClass *pChild = pEntity->GetFirstDescendent( pos ); |
|
while ( pChild != NULL ) |
|
{ |
|
CMapInstance *pMapInstance = dynamic_cast< CMapInstance * >( pChild ); |
|
if ( pMapInstance != NULL ) |
|
{ |
|
OnClose(); |
|
|
|
pMapInstance->SwitchTo(); |
|
} |
|
|
|
pChild = pEntity->GetNextDescendent( pos ); |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
int CObjectProperties::OnCreate(LPCREATESTRUCT lpCreateStruct) |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::OnCreate", "Object Properties" ); |
|
|
|
lpCreateStruct->dwExStyle |= WS_EX_TOOLWINDOW; |
|
|
|
if (CPropertySheet::OnCreate(lpCreateStruct) == -1) |
|
{ |
|
return -1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
void CObjectProperties::SetObjectList(const CMapObjectList *pObjectList) |
|
{ |
|
m_pOrgObjects = pObjectList; |
|
MarkDataDirty(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CObjectProperties::MarkDataDirty() |
|
{ |
|
//VPROF_BUDGET( "CObjectProperties::RefreshData", "Object Properties" ); |
|
|
|
// if flag already set, dont touch anything |
|
if ( m_bDataDirty ) |
|
return; |
|
|
|
for (int i = 0; i < m_nPages; i++) |
|
{ |
|
if (m_ppPages[i]->m_hWnd) |
|
{ |
|
m_ppPages[i]->RememberState(); |
|
m_ppPages[i]->MarkDataDirty(); |
|
} |
|
} |
|
|
|
Invalidate( false ); |
|
|
|
m_DstObjects.RemoveAll(); |
|
|
|
m_bDataDirty = true; |
|
} |
|
|
|
|