mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-22 14:16:50 +00:00
574 lines
14 KiB
C++
574 lines
14 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Singleton dialog that generates and presents the entity report.
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "stdafx.h"
|
|
#include "EntityReportDlg.h"
|
|
#include "fgdlib/GameData.h"
|
|
#include "GlobalFunctions.h"
|
|
#include "History.h"
|
|
#include "MainFrm.h"
|
|
#include "MapEntity.h"
|
|
#include "MapInstance.h"
|
|
#include "MapView2D.h"
|
|
#include "MapWorld.h"
|
|
#include "ObjectProperties.h"
|
|
#include "hammer.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
|
|
static CEntityReportDlg *s_pDlg = NULL;
|
|
static char *pszIniSection = "EntityReportDlg";
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Static function
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::ShowEntityReport(CMapDoc *pDoc, CWnd *pwndParent)
|
|
{
|
|
if (!s_pDlg)
|
|
{
|
|
s_pDlg = new CEntityReportDlg(pDoc, pwndParent);
|
|
s_pDlg->Create(IDD, pwndParent);
|
|
}
|
|
|
|
s_pDlg->ShowWindow(SW_SHOW);
|
|
s_pDlg->GenerateReport();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Private constructor.
|
|
//-----------------------------------------------------------------------------
|
|
CEntityReportDlg::CEntityReportDlg(CMapDoc *pDoc, CWnd* pParent /*=NULL*/)
|
|
: CDialog(CEntityReportDlg::IDD, pParent)
|
|
{
|
|
m_pDoc = pDoc;
|
|
|
|
CWinApp *pApp = AfxGetApp();
|
|
|
|
m_bFilterByKeyvalue = pApp->GetProfileInt(pszIniSection, "FilterByKeyvalue", FALSE);
|
|
m_bFilterByClass = pApp->GetProfileInt(pszIniSection, "FilterByClass", FALSE);
|
|
m_bFilterByHidden = pApp->GetProfileInt(pszIniSection, "FilterByHidden", TRUE);
|
|
m_iFilterByType = pApp->GetProfileInt(pszIniSection, "FilterByType", 0);
|
|
m_bExact = pApp->GetProfileInt(pszIniSection, "Exact", FALSE);
|
|
|
|
m_szFilterClass = pApp->GetProfileString(pszIniSection, "FilterClass", "");
|
|
m_szFilterKey = pApp->GetProfileString(pszIniSection, "FilterKey", "");
|
|
m_szFilterValue = pApp->GetProfileString(pszIniSection, "FilterValue", "");
|
|
|
|
m_bFilterTextChanged = FALSE;
|
|
|
|
//{{AFX_DATA_INIT(CEntityReportDlg)
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
void CEntityReportDlg::SaveToIni()
|
|
{
|
|
CWinApp *pApp = AfxGetApp();
|
|
|
|
pApp->WriteProfileInt(pszIniSection, "FilterByKeyvalue", m_bFilterByKeyvalue);
|
|
pApp->WriteProfileInt(pszIniSection, "FilterByClass", m_bFilterByClass);
|
|
pApp->WriteProfileInt(pszIniSection, "FilterByHidden", m_bFilterByHidden);
|
|
pApp->WriteProfileInt(pszIniSection, "FilterByType", m_iFilterByType);
|
|
pApp->WriteProfileInt(pszIniSection, "Exact", m_bExact);
|
|
|
|
pApp->WriteProfileString(pszIniSection, "FilterClass", m_szFilterClass);
|
|
pApp->WriteProfileString(pszIniSection, "FilterKey", m_szFilterKey);
|
|
pApp->WriteProfileString(pszIniSection, "FilterValue", m_szFilterValue);
|
|
}
|
|
|
|
void CEntityReportDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CEntityReportDlg)
|
|
DDX_Control(pDX, IDC_EXACTVALUE, m_cExact);
|
|
DDX_Control(pDX, IDC_FILTERCLASS, m_cFilterClass);
|
|
DDX_Control(pDX, IDC_FILTERBYCLASS, m_cFilterByClass);
|
|
DDX_Control(pDX, IDC_ENTITIES, m_cEntities);
|
|
DDX_Control(pDX, IDC_FILTERVALUE, m_cFilterValue);
|
|
DDX_Control(pDX, IDC_FILTERKEY, m_cFilterKey);
|
|
DDX_Control(pDX, IDC_FILTERBYTYPE, m_cFilterByType);
|
|
DDX_Control(pDX, IDC_FILTERBYKEYVALUE, m_cFilterByKeyvalue);
|
|
DDX_Control(pDX, IDC_FILTERBYHIDDEN, m_cFilterByHidden);
|
|
//}}AFX_DATA_MAP
|
|
|
|
DDX_Check(pDX, IDC_EXACTVALUE, m_bExact);
|
|
DDX_Check(pDX, IDC_FILTERBYCLASS, m_bFilterByClass);
|
|
DDX_Radio(pDX, IDC_FILTERBYTYPE, m_iFilterByType);
|
|
DDX_Text(pDX, IDC_FILTERCLASS, m_szFilterClass);
|
|
DDX_Text(pDX, IDC_FILTERVALUE, m_szFilterValue);
|
|
DDX_Text(pDX, IDC_FILTERKEY, m_szFilterKey);
|
|
DDX_Check(pDX, IDC_FILTERBYKEYVALUE, m_bFilterByKeyvalue);
|
|
DDX_Check(pDX, IDC_FILTERBYHIDDEN, m_bFilterByHidden);
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CEntityReportDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CEntityReportDlg)
|
|
ON_BN_CLICKED(IDC_DELETE, OnDelete)
|
|
ON_BN_CLICKED(IDC_FILTERBYHIDDEN, OnFilterbyhidden)
|
|
ON_BN_CLICKED(IDC_FILTERBYKEYVALUE, OnFilterbykeyvalue)
|
|
ON_BN_CLICKED(IDC_FILTERBYTYPE, OnFilterbytype)
|
|
ON_EN_CHANGE(IDC_FILTERKEY, OnChangeFilterkey)
|
|
ON_EN_CHANGE(IDC_FILTERVALUE, OnChangeFiltervalue)
|
|
ON_BN_CLICKED(IDC_GOTO, OnGoto)
|
|
ON_BN_CLICKED(IDC_PROPERTIES, OnProperties)
|
|
ON_WM_TIMER()
|
|
ON_CBN_EDITCHANGE(IDC_FILTERCLASS, OnEditchangeFilterclass)
|
|
ON_BN_CLICKED(IDC_FILTERBYCLASS, OnFilterbyclass)
|
|
ON_CBN_SELCHANGE(IDC_FILTERCLASS, OnSelchangeFilterclass)
|
|
ON_BN_CLICKED(IDC_RADIO2, OnFilterbytype)
|
|
ON_BN_CLICKED(IDC_RADIO3, OnFilterbytype)
|
|
ON_BN_CLICKED(IDC_EXACTVALUE, OnExactvalue)
|
|
ON_LBN_SELCHANGE(IDC_ENTITIES, OnSelChangeEntityList)
|
|
ON_LBN_DBLCLK(IDC_ENTITIES, OnDblClkEntityList)
|
|
ON_WM_DESTROY()
|
|
ON_WM_CLOSE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Deletes the marked objects.
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnDelete(void)
|
|
{
|
|
if (AfxMessageBox("Delete Objects?", MB_YESNO) == IDNO)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetHistory()->MarkUndoPosition(NULL, "Delete Objects");
|
|
|
|
int iSel = m_cEntities.GetCurSel();
|
|
|
|
//
|
|
// Build a list of objects to delete.
|
|
//
|
|
CMapObjectList Objects;
|
|
for (int i = 0; i < m_cEntities.GetCount(); i++)
|
|
{
|
|
if (!m_cEntities.GetSel(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
CMapEntity *pEntity = (CMapEntity *)m_cEntities.GetItemDataPtr(i);
|
|
Objects.AddToTail(pEntity);
|
|
m_cEntities.DeleteString(i);
|
|
--i;
|
|
}
|
|
|
|
m_pDoc->DeleteObjectList(Objects);
|
|
|
|
//
|
|
// Update the list box selection.
|
|
//
|
|
if (iSel >= m_cEntities.GetCount())
|
|
{
|
|
iSel = m_cEntities.GetCount() - 1;
|
|
}
|
|
m_cEntities.SetCurSel(iSel);
|
|
}
|
|
|
|
|
|
void CEntityReportDlg::OnFilterbyhidden()
|
|
{
|
|
m_bFilterByHidden = m_cFilterByHidden.GetCheck();
|
|
UpdateEntityList();
|
|
}
|
|
|
|
void CEntityReportDlg::OnFilterbykeyvalue()
|
|
{
|
|
m_bFilterByKeyvalue = m_cFilterByKeyvalue.GetCheck();
|
|
UpdateEntityList();
|
|
|
|
m_cFilterKey.EnableWindow(m_bFilterByKeyvalue);
|
|
m_cFilterValue.EnableWindow(m_bFilterByKeyvalue);
|
|
m_cExact.EnableWindow(m_bFilterByKeyvalue);
|
|
}
|
|
|
|
void CEntityReportDlg::OnFilterbytype()
|
|
{
|
|
// walk all children in group
|
|
int iButton = 0;
|
|
HWND hWndCtrl = ::GetDlgItem(m_hWnd, IDC_FILTERBYTYPE);
|
|
do {
|
|
// control in group is a radio button
|
|
if(::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0)
|
|
break;
|
|
iButton++;
|
|
hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT);
|
|
} while(hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP));
|
|
|
|
m_iFilterByType = iButton;
|
|
UpdateEntityList();
|
|
}
|
|
|
|
void CEntityReportDlg::OnChangeFilterkey()
|
|
{
|
|
m_cFilterKey.GetWindowText(m_szFilterKey);
|
|
m_szFilterKey.MakeUpper();
|
|
m_dwFilterTime = time(NULL);
|
|
m_bFilterTextChanged = TRUE;
|
|
}
|
|
|
|
void CEntityReportDlg::OnChangeFiltervalue()
|
|
{
|
|
m_cFilterValue.GetWindowText(m_szFilterValue);
|
|
m_szFilterValue.MakeUpper();
|
|
m_dwFilterTime = time(NULL);
|
|
m_bFilterTextChanged = TRUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Centers the 2D and 3D views on the selected entities.
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnGoto()
|
|
{
|
|
CMapDoc *pMapDoc = MarkSelectedEntities();
|
|
|
|
if ( pMapDoc )
|
|
{
|
|
pMapDoc->ShowWindow( true );
|
|
pMapDoc->CenterViewsOnSelection();
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
CMapDoc *CEntityReportDlg::MarkSelectedEntities()
|
|
{
|
|
CUtlVector< CMapDoc * > FoundMaps;
|
|
|
|
for(int i = 0; i < m_cEntities.GetCount(); i++)
|
|
{
|
|
if(!m_cEntities.GetSel(i))
|
|
continue;
|
|
CMapEntity *pEntity = (CMapEntity*) m_cEntities.GetItemDataPtr(i);
|
|
CMapClass *pTopMapClass = pEntity;
|
|
while( pTopMapClass->GetParent() )
|
|
{
|
|
pTopMapClass = pTopMapClass->GetParent();
|
|
}
|
|
CMapWorld *pMapWorld = dynamic_cast< CMapWorld * >( pTopMapClass );
|
|
if ( pMapWorld )
|
|
{
|
|
CMapDoc *pMapDoc = pMapWorld->GetOwningDocument();
|
|
|
|
if ( FoundMaps.Find( pMapDoc ) == -1 )
|
|
{
|
|
FoundMaps.AddToTail( pMapDoc );
|
|
pMapDoc->SelectObject( NULL, scClear|scSaveChanges );
|
|
}
|
|
|
|
pMapDoc->SelectObject( pEntity, scSelect );
|
|
}
|
|
}
|
|
|
|
if ( FoundMaps.Count() == 1 )
|
|
{
|
|
return FoundMaps[ 0 ];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CEntityReportDlg::OnProperties()
|
|
{
|
|
CMapDoc *pMapDoc = MarkSelectedEntities();
|
|
|
|
if ( pMapDoc )
|
|
{
|
|
pMapDoc->ShowWindow( true );
|
|
GetMainWnd()->pObjectProperties->ShowWindow(SW_SHOW);
|
|
}
|
|
}
|
|
|
|
void CEntityReportDlg::OnTimer(UINT nIDEvent)
|
|
{
|
|
CDialog::OnTimer(nIDEvent);
|
|
|
|
// check filters
|
|
if(!m_bFilterTextChanged)
|
|
return;
|
|
|
|
if((time(NULL) - m_dwFilterTime) > 1)
|
|
{
|
|
m_bFilterTextChanged = FALSE;
|
|
m_dwFilterTime = time(NULL);
|
|
UpdateEntityList();
|
|
}
|
|
}
|
|
|
|
BOOL AddEntityToList(CMapEntity *pEntity, CEntityReportDlg *pDlg)
|
|
{
|
|
char szString[256];
|
|
|
|
// nope.
|
|
if (!pDlg->m_bFilterByHidden && !pEntity->IsVisible())
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
if (!pDlg->m_pDoc->selection.IsEmpty() && !pEntity->IsSelected())
|
|
{
|
|
return TRUE;
|
|
}
|
|
*/
|
|
|
|
if (pDlg->m_iFilterByType)
|
|
{
|
|
if (pDlg->m_iFilterByType == 1 && pEntity->IsPlaceholder())
|
|
{
|
|
return TRUE;
|
|
}
|
|
if (pDlg->m_iFilterByType == 2 && !pEntity->IsPlaceholder())
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
const char* pszClassName = pEntity->GetClassName();
|
|
|
|
if ( pEntity && stricmp( pszClassName, "func_instance" ) == 0 )
|
|
{
|
|
CMapInstance *pMapInstance = pEntity->GetChildOfType( ( CMapInstance * )NULL );
|
|
if ( pMapInstance )
|
|
{
|
|
CMapDoc *pMapDoc = pMapInstance->GetInstancedMap();
|
|
if ( pMapDoc )
|
|
{
|
|
CMapWorld *pWorld = pMapDoc->GetMapWorld();
|
|
|
|
pWorld->EnumChildren(ENUMMAPCHILDRENPROC(AddEntityToList), DWORD(pDlg), MAPCLASS_TYPE(CMapEntity));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pDlg->m_bFilterByClass)
|
|
{
|
|
if (pDlg->m_szFilterClass.IsEmpty())
|
|
{
|
|
if (pszClassName[0])
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
V_strcpy_safe( szString, pEntity->GetClassName() );
|
|
strupr(szString);
|
|
if (!strstr(szString, pDlg->m_szFilterClass))
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
strcpy(szString, pszClassName);
|
|
|
|
BOOL bAdd = TRUE;
|
|
|
|
if(pDlg->m_bFilterByKeyvalue)
|
|
bAdd = FALSE;
|
|
|
|
MDkeyvalue tmpkv;
|
|
for (int i = pEntity->GetFirstKeyValue(); i != pEntity->GetInvalidKeyValue(); i=pEntity->GetNextKeyValue( i ) )
|
|
{
|
|
// if filtering by keyvalue, check!
|
|
if (pDlg->m_bFilterByKeyvalue && !bAdd && !pDlg->m_szFilterValue.IsEmpty())
|
|
{
|
|
// first, check key
|
|
if (pDlg->m_szFilterKey.IsEmpty() || !strcmpi(pDlg->m_szFilterKey, pEntity->GetKey(i)))
|
|
{
|
|
// now, check value
|
|
char szTmp1[128], szTmp2[128];
|
|
V_strcpy_safe( szTmp1, pEntity->GetKeyValue( i ) );
|
|
strupr(szTmp1);
|
|
strcpy(szTmp2, pDlg->m_szFilterValue);
|
|
if ((!pDlg->m_bExact && strstr(szTmp1, szTmp2)) || !strcmpi(szTmp1, szTmp2))
|
|
{
|
|
bAdd = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char* pszName = pEntity->GetKey(i);
|
|
|
|
GDclass *pClass = pEntity->GetClass();
|
|
if (pClass != NULL)
|
|
{
|
|
GDinputvariable *pVar = pClass->VarForName(pEntity->GetKey(i));
|
|
if (!pVar || !pVar->IsReportable())
|
|
{
|
|
continue;
|
|
}
|
|
pszName = pVar->GetLongName();
|
|
}
|
|
|
|
sprintf(szString + strlen(szString), "\t%s \"%s\"", pszName, pEntity->GetKeyValue(i));
|
|
|
|
if (pClass == NULL)
|
|
{
|
|
break; // just do first if no class
|
|
}
|
|
}
|
|
|
|
if(bAdd)
|
|
{
|
|
int iIndex = pDlg->m_cEntities.AddString(szString);
|
|
pDlg->m_cEntities.SetItemDataPtr(iIndex, PVOID(pEntity));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::UpdateEntityList(void)
|
|
{
|
|
m_bFilterTextChanged = FALSE;
|
|
|
|
m_cEntities.SetRedraw(FALSE);
|
|
m_cEntities.ResetContent();
|
|
|
|
int x = 80;
|
|
m_cEntities.SetTabStops(x);
|
|
|
|
m_szFilterValue.MakeUpper();
|
|
m_szFilterKey.MakeUpper();
|
|
m_szFilterClass.MakeUpper();
|
|
|
|
// add items to list
|
|
CMapWorld *pWorld = m_pDoc->GetMapWorld();
|
|
pWorld->EnumChildren(ENUMMAPCHILDRENPROC(AddEntityToList), DWORD(this), MAPCLASS_TYPE(CMapEntity));
|
|
|
|
m_cEntities.SetRedraw(TRUE);
|
|
m_cEntities.Invalidate();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::GenerateReport()
|
|
{
|
|
CString str;
|
|
int nCount = pGD->GetClassCount();
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
GDclass *pc = pGD->GetClass(i);
|
|
if(!pc->IsBaseClass())
|
|
{
|
|
str = pc->GetName();
|
|
if(str != "worldspawn")
|
|
m_cFilterClass.AddString(str);
|
|
}
|
|
}
|
|
|
|
SetTimer(1, 500, NULL);
|
|
|
|
OnFilterbykeyvalue();
|
|
OnFilterbytype();
|
|
OnFilterbyclass();
|
|
}
|
|
|
|
void CEntityReportDlg::OnEditchangeFilterclass()
|
|
{
|
|
m_cFilterClass.GetWindowText(m_szFilterClass);
|
|
m_szFilterClass.MakeUpper();
|
|
m_dwFilterTime = time(NULL);
|
|
m_bFilterTextChanged = TRUE;
|
|
}
|
|
|
|
void CEntityReportDlg::OnFilterbyclass()
|
|
{
|
|
m_bFilterByClass = m_cFilterByClass.GetCheck();
|
|
UpdateEntityList();
|
|
|
|
m_cFilterClass.EnableWindow(m_bFilterByClass);
|
|
}
|
|
|
|
void CEntityReportDlg::OnSelchangeFilterclass()
|
|
{
|
|
int iSel = m_cFilterClass.GetCurSel();
|
|
m_cFilterClass.GetLBText(iSel, m_szFilterClass);
|
|
m_szFilterClass.MakeUpper();
|
|
UpdateEntityList();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnSelChangeEntityList()
|
|
{
|
|
MarkSelectedEntities();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnDblClkEntityList()
|
|
{
|
|
CMapDoc *pMapDoc = MarkSelectedEntities();
|
|
|
|
if ( pMapDoc )
|
|
{
|
|
pMapDoc->ShowWindow( true );
|
|
pMapDoc->CenterViewsOnSelection();
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnExactvalue()
|
|
{
|
|
m_bExact = m_cExact.GetCheck();
|
|
UpdateEntityList();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnOK()
|
|
{
|
|
DestroyWindow();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnClose()
|
|
{
|
|
DestroyWindow();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called when our window is being destroyed.
|
|
//-----------------------------------------------------------------------------
|
|
void CEntityReportDlg::OnDestroy()
|
|
{
|
|
SaveToIni();
|
|
s_pDlg = NULL;
|
|
delete this;
|
|
}
|