csgo-2018-source/hammer/dlglistmanage.cpp

361 lines
8.8 KiB
C++
Raw Permalink Normal View History

2021-07-25 12:11:47 +08:00
//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "stdafx.h"
#include "hammer.h"
#include "filesystem.h"
#include "mapclass.h"
#include "mapentity.h"
#include "history.h"
#include "dlglistmanage.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
BEGIN_MESSAGE_MAP( CDlgListManage, CDialog )
ON_WM_SIZE()
ON_WM_GETMINMAXINFO()
ON_BN_CLICKED(IDC_SCRIPT_LIST_ADD, &CDlgListManage::OnBnClickedScriptListAdd)
ON_BN_CLICKED(IDC_SCRIPT_LIST_REMOVE, &CDlgListManage::OnBnClickedScriptListRemove)
ON_BN_CLICKED(IDC_SCRIPT_LIST_EDIT, &CDlgListManage::OnBnClickedScriptListEdit)
END_MESSAGE_MAP()
CDlgListManage::CDlgListManage(CWnd *pParent, IDlgListManageBrowse *pBrowseImpl, const CMapObjectList *pObjectList)
: CDialog(CDlgListManage::IDD, pParent)
{
m_pBrowseImpl = pBrowseImpl;
m_rcDialog.SetRectEmpty();
m_pObjectList = pObjectList;
}
static bool StringLessFunc( CString const &a, CString const &b )
{
return (a < b);
}
void CDlgListManage::PopulateScriptList( void )
{
// Clear us out!
m_ScriptList.ResetContent();
// Populate the list
CUtlMap<CString, int> mapStrings( StringLessFunc ); // A map of strings to their counts
// Iterate through all map objects currently being edited
FOR_EACH_OBJ( *m_pObjectList, pos )
{
const CMapClass *pObject = m_pObjectList->Element( pos );
if ( (pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity))) )
{
CMapEntity *pEntity = (CMapEntity *)pObject;
CString strScriptName = pEntity->GetKeyValue( "vscripts" );
// Only consider this if we have strings here!
if ( strScriptName.IsEmpty() )
continue;
int nStart = 0;
CString strToken = strScriptName.Tokenize( " ", nStart );
// Now, iterate through all the listed scripts in the entity and check their counts
while( strToken != "" )
{
// If we've removed this, filter it out
if ( m_vSubtractions.Find( strToken ) != m_vSubtractions.InvalidIndex() )
{
strToken = strScriptName.Tokenize( " ", nStart );
continue;
}
// Also, keep a map into the global scripts we're adding for later!
int nIndex = mapStrings.Find( strToken );
if ( nIndex != mapStrings.InvalidIndex() )
{
mapStrings[nIndex]++;
}
else
{
int nIndex = mapStrings.Insert( strToken );
mapStrings[nIndex] = 1;
}
// Continue to the next token
strToken = strScriptName.Tokenize( " ", nStart );
}
}
}
// Include new additions
FOR_EACH_VEC( m_vAdditions, itr )
{
int nIndex = mapStrings.Insert( m_vAdditions[itr] );
mapStrings[nIndex] = m_pObjectList->Count(); // Always added to all edited members
}
// Now go through and add things to the list with proper coloring
FOR_EACH_MAP( mapStrings, itr )
{
// If it's the same for every object, it's bold
if ( mapStrings[itr] == m_pObjectList->Count() )
{
if ( m_pObjectList->Count() == 1 )
{
// Normal (single instance)
m_ScriptList.AddItemText( mapStrings.Key( itr ), LISTFONT_NORMAL );
}
else
{
// Bold (multiple instances)
m_ScriptList.AddItemText( mapStrings.Key( itr ), LISTFONT_BOLD );
}
}
else
{
// Red (different)
m_ScriptList.AddItemText( mapStrings.Key( itr ), LISTFONT_DUPLICATE );
}
}
}
void CDlgListManage::UpdateScriptChanges( void )
{
// Nothing to do currently!
}
void CDlgListManage::SaveScriptChanges( void )
{
GetHistory()->MarkUndoPosition( NULL, "VScript update" );
// Iterate through all map objects currently being edited
FOR_EACH_OBJ( *m_pObjectList, pos )
{
const CMapClass *pObject = m_pObjectList->Element( pos );
if ( (pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity))) )
{
CMapEntity *pEntity = (CMapEntity *)pObject;
CString strScriptName = pEntity->GetKeyValue( "vscripts" );
GetHistory()->Keep( pEntity );
// Add in all new additions
FOR_EACH_VEC( m_vAdditions, itr )
{
// Do we already have this in the list somehow?
if ( strScriptName.Find( m_vAdditions[itr], 0 ) != -1 )
continue;
// Append it
strScriptName += " " + m_vAdditions[itr];
}
// Subtract things we deleted
FOR_EACH_VEC( m_vSubtractions, itr )
{
// Find an occurence of this string in our base strings
int nIndex = strScriptName.Find( m_vSubtractions[itr], 0 );
if ( nIndex == -1 )
continue;
// Kill it!
int nEndIndex = strScriptName.Find( ' ', nIndex );
if ( nEndIndex == -1 )
{
nEndIndex = strlen( strScriptName ); // Really? You can't ask a CString its length?
}
strScriptName.Delete( nIndex, (nEndIndex-nIndex) );
}
// Done!
pEntity->SetKeyValue( "vscripts", strScriptName );
}
}
// Clear it
m_vAdditions.RemoveAll();
m_vSubtractions.RemoveAll();
}
void CDlgListManage::DoDataExchange( CDataExchange* pDX )
{
DDX_Control( pDX, IDC_SCRIPT_LIST, m_ScriptList );
CDialog::DoDataExchange(pDX);
if ( pDX->m_bSaveAndValidate )
{
UpdateScriptChanges();
}
else
{
PopulateScriptList();
}
}
BOOL CDlgListManage::OnInitDialog()
{
BOOL bResult = CDialog::OnInitDialog();
GetWindowRect( m_rcDialog );
int arrCtlIds[] = { IDOK, IDCANCEL, IDC_SCRIPT_LIST, IDC_BROWSE };
int riFlags[] = { ResizeInfo_t::RI_TOP_AND_LEFT, ResizeInfo_t::RI_TOP_AND_LEFT, ResizeInfo_t::RI_WIDTH_AND_HEIGHT, ResizeInfo_t::RI_TOP };
for ( int k = 0; k < ARRAYSIZE( arrCtlIds ); ++ k )
{
CWnd *pWnd = GetDlgItem( arrCtlIds[ k ] );
if ( !pWnd )
continue;
ResizeInfo_t ri;
ri.flags = riFlags[k];
pWnd->GetWindowRect( ri.rc );
this->ScreenToClient( ri.rc );
m_ctlInfo[ arrCtlIds[ k ] ] = ri;
}
if ( !m_pBrowseImpl )
{
if ( CWnd *pWnd = GetDlgItem( IDC_BROWSE ) )
pWnd->ShowWindow( SW_HIDE );
}
return bResult;
}
void CDlgListManage::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize( nType, cx, cy );
CRect rcDialog;
GetWindowRect( rcDialog );
int dx = rcDialog.Width() - m_rcDialog.Width();
int dy = rcDialog.Height() - m_rcDialog.Height();
for ( POSITION pos = m_ctlInfo.GetStartPosition(); pos; )
{
int ctlId;
ResizeInfo_t ri;
m_ctlInfo.GetNextAssoc( pos, ctlId, ri );
CWnd *pWnd = GetDlgItem( ctlId );
if ( !pWnd )
continue;
CRect rcWnd = ri.rc;
if ( ri.flags & ResizeInfo_t::RI_HEIGHT )
rcWnd.bottom += dy;
if ( ri.flags & ResizeInfo_t::RI_WIDTH )
rcWnd.right += dx;
if ( ri.flags & ResizeInfo_t::RI_LEFT )
rcWnd.OffsetRect( dx, 0 );
if ( ri.flags & ResizeInfo_t::RI_TOP )
rcWnd.OffsetRect( 0, dy );
pWnd->MoveWindow( rcWnd );
}
}
void CDlgListManage::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
CDialog::OnGetMinMaxInfo( lpMMI );
if ( !m_rcDialog.IsRectEmpty() )
{
lpMMI->ptMinTrackSize.x = m_rcDialog.Width();
lpMMI->ptMinTrackSize.y = m_rcDialog.Height();
}
}
void CDlgListManage::OnBnClickedScriptListAdd()
{
// Launch a browse window
CStringList lstBrowse;
if ( m_pBrowseImpl == NULL || m_pBrowseImpl->HandleBrowse( lstBrowse ) == false )
return;
// Nothing was added!
if ( lstBrowse.IsEmpty() )
return;
// Operate on all strings we got back from the browser
for ( POSITION pos = lstBrowse.GetHeadPosition(); pos; )
{
const CString &strTemp = lstBrowse.GetNext( pos );
// Update our change lists
m_vSubtractions.FindAndRemove( strTemp );
// Don't add twice!
if ( m_vAdditions.Find( strTemp ) == -1 )
{
m_vAdditions.AddToTail( strTemp );
}
}
UpdateData();
UpdateData( FALSE );
}
void CDlgListManage::OnBnClickedScriptListRemove()
{
// Remove the current selection
int nSelectedItem = m_ScriptList.GetCurSel();
if ( nSelectedItem != LB_ERR )
{
CString strOldText;
m_ScriptList.GetText( nSelectedItem, strOldText );
// Update our change lists
m_vAdditions.FindAndRemove( strOldText );
// Don't add twice!
if ( m_vSubtractions.Find( strOldText ) == -1 )
{
m_vSubtractions.AddToTail( strOldText );
}
// Kill the line
m_ScriptList.DeleteString( nSelectedItem );
// Move our current selection around based on where we are in the list
if ( nSelectedItem >= m_ScriptList.GetCount() )
{
nSelectedItem = m_ScriptList.GetCount() - 1;
}
m_ScriptList.SetCurSel( nSelectedItem ); // Don't lose selection (annoying for multi-delete)
}
// Now update to reflect the change
UpdateData();
}
void CDlgListManage::OnBnClickedScriptListEdit()
{
// Get what they've currently selected
int nSelectedItem = m_ScriptList.GetCurSel();
if ( nSelectedItem == LB_ERR )
return;
// Get the file they've selected
CString strSelectedText;
m_ScriptList.GetText( nSelectedItem, strSelectedText );
// Cobble together a complete filename
CString strFilename = "scripts\\vscripts\\" + strSelectedText;
char pFullPath[MAX_PATH];
if ( g_pFullFileSystem->GetLocalPath( strFilename, pFullPath, MAX_PATH ) )
{
ShellExecute( NULL, "open", pFullPath, NULL, NULL, SW_SHOWNORMAL );
}
}