mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-22 14:16:50 +00:00
624 lines
14 KiB
C++
624 lines
14 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
// PrefabsDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "hammer.h"
|
|
#include "PrefabsDlg.h"
|
|
#include "Prefabs.h"
|
|
#include "Prefab3D.h"
|
|
#include "EditPrefabDlg.h"
|
|
#include "MapDoc.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPrefabsDlg dialog
|
|
|
|
CPrefabsDlg::CPrefabsDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CPrefabsDlg::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CPrefabsDlg)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
|
|
void CPrefabsDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CPrefabsDlg)
|
|
DDX_Control(pDX, IDC_OBJECTS, m_Objects);
|
|
DDX_Control(pDX, IDC_OBJECTNOTES, m_ObjectNotes);
|
|
DDX_Control(pDX, IDC_LIBRARYNOTES, m_LibraryNotes);
|
|
DDX_Control(pDX, IDC_LIBRARIES, m_Libraries);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CPrefabsDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CPrefabsDlg)
|
|
ON_BN_CLICKED(IDC_ADDLIBRARY, OnAddlibrary)
|
|
ON_BN_CLICKED(IDC_ADDOBJECT, OnAddobject)
|
|
ON_BN_CLICKED(IDC_EDITLIBRARY, OnEditlibrary)
|
|
ON_BN_CLICKED(IDC_EDITOBJECT, OnEditobject)
|
|
ON_BN_CLICKED(IDC_EXPORTOBJECT, OnExportobject)
|
|
ON_CBN_SELCHANGE(IDC_LIBRARIES, OnSelchangeLibraries)
|
|
ON_BN_CLICKED(IDC_REMOVELIBRARY, OnRemovelibrary)
|
|
ON_BN_CLICKED(IDC_REMOVEOBJECT, OnRemoveobject)
|
|
ON_NOTIFY(LVN_ITEMCHANGED, IDC_OBJECTS, OnItemchangedObjects)
|
|
ON_NOTIFY(LVN_ENDLABELEDIT, IDC_OBJECTS, OnEndlabeleditObjects)
|
|
ON_WM_CLOSE()
|
|
//}}AFX_MSG_MAP
|
|
ON_COMMAND_EX(id_EditObjectInfo, HandleEditObjectPopup)
|
|
ON_COMMAND_EX(id_EditObjectData, HandleEditObjectPopup)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPrefabsDlg message handlers
|
|
|
|
void CPrefabsDlg::OnAddobject()
|
|
{
|
|
CPrefabLibrary *pLibrary = GetCurrentLibrary();
|
|
if(!pLibrary)
|
|
return; // no lib, no add
|
|
|
|
CFileDialog dlg(TRUE, NULL, NULL, OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST |
|
|
OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR,
|
|
"Prefab files (*.map;*.rmf;*.os)|*.map; *.rmf; *.os|"
|
|
"Game MAP files (*.map)|*.map|"
|
|
"Worldcraft RMF files (*.rmf)|*.rmf||", this);
|
|
|
|
if(dlg.DoModal() == IDCANCEL)
|
|
return; // aborted
|
|
|
|
// add all these files ..
|
|
char szDir[MAX_PATH], szFiles[2048];
|
|
memcpy(szFiles, dlg.m_ofn.lpstrFile, dlg.m_ofn.nMaxFile);
|
|
strcpy(szDir, dlg.m_ofn.lpstrFile);
|
|
|
|
BOOL bOneFile = FALSE;
|
|
char *p = szFiles + strlen(szDir) + 1;
|
|
if(!p[0])
|
|
{
|
|
bOneFile = TRUE;
|
|
p = szDir; // just one file
|
|
}
|
|
|
|
// disable caching of prefabs
|
|
CPrefab::EnableCaching(FALSE);
|
|
|
|
// get files
|
|
char szFile[MAX_PATH];
|
|
CString strFullPath;
|
|
int iItem = m_Objects.GetItemCount();
|
|
while(1)
|
|
{
|
|
strcpy(szFile, p);
|
|
if(!szFile[0])
|
|
break;
|
|
p += strlen(szFile) + 1;
|
|
|
|
if(!bOneFile)
|
|
strFullPath.Format("%s\\%s", szDir, szFile);
|
|
else
|
|
strFullPath = szFile;
|
|
|
|
// check file type
|
|
CPrefab *pPrefab = NULL;
|
|
|
|
switch(CPrefab::CheckFileType(strFullPath))
|
|
{
|
|
case CPrefab::pftUnknown:
|
|
{
|
|
continue; // no.
|
|
}
|
|
|
|
case CPrefab::pftRMF:
|
|
{
|
|
CPrefabRMF *pNew = new CPrefabRMF;
|
|
pNew->Init(strFullPath, TRUE, CPrefab::lsRMF);
|
|
pPrefab = (CPrefab *)pNew;
|
|
break;
|
|
}
|
|
|
|
case CPrefab::pftMAP:
|
|
{
|
|
CPrefabRMF *pNew = new CPrefabRMF;
|
|
pNew->Init(strFullPath, TRUE, CPrefab::lsMAP);
|
|
pPrefab = (CPrefab *)pNew;
|
|
break;
|
|
}
|
|
|
|
case CPrefab::pftScript:
|
|
{
|
|
Assert(0); // not supported yet
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pPrefab)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// add to current library
|
|
pLibrary->Add(pPrefab);
|
|
// add to objects list
|
|
AddToObjectList(pPrefab, iItem++);
|
|
|
|
if(bOneFile)
|
|
break;
|
|
}
|
|
|
|
// now rewrite library
|
|
pLibrary->Sort();
|
|
pLibrary->Save();
|
|
|
|
CPrefab::FreeAllData(); // free memory
|
|
// re-enable prefab caching
|
|
CPrefab::EnableCaching(TRUE);
|
|
|
|
bCurLibraryModified = FALSE;
|
|
}
|
|
|
|
|
|
void CPrefabsDlg::AddToObjectList(CPrefab *pPrefab, int iItem, BOOL bReplace)
|
|
{
|
|
if(iItem == -1)
|
|
iItem = m_Objects.GetItemCount();
|
|
if(bReplace) // replace existing item
|
|
{
|
|
m_Objects.DeleteItem(iItem);
|
|
}
|
|
iItem = m_Objects.InsertItem(iItem, pPrefab->GetName(),
|
|
pPrefab->GetType() == CPrefab::pftScript ? 1 : 0);
|
|
m_Objects.SetItemData(iItem, pPrefab->GetID());
|
|
|
|
bCurLibraryModified = TRUE;
|
|
}
|
|
|
|
BOOL CPrefabsDlg::HandleEditObjectPopup(UINT nID)
|
|
{
|
|
switch(nID)
|
|
{
|
|
case id_EditObjectInfo:
|
|
EditObjectInfo();
|
|
break;
|
|
case id_EditObjectData:
|
|
EditObjectData();
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL IsValidFilename(LPCTSTR pszString)
|
|
// check for valid windows filename. no drive/dirs allowed.
|
|
{
|
|
LPCTSTR p = pszString;
|
|
while(p[0])
|
|
{
|
|
BYTE ch = BYTE(p[0]);
|
|
++p;
|
|
if(ch > 127 || isalpha(ch) || isdigit(ch) ||
|
|
strchr(" $%`-_@~'!(){}^#&", ch))
|
|
continue;
|
|
// not one of those chars - not correct
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CPrefabsDlg::EditObjectInfo()
|
|
{
|
|
int iSel;
|
|
CPrefab *pPrefab = GetCurrentObject(&iSel);
|
|
|
|
CEditPrefabDlg dlg;
|
|
dlg.m_strName = pPrefab->GetName();
|
|
dlg.m_strDescript = pPrefab->GetNotes();
|
|
|
|
dlg.SetRanges(500, -1);
|
|
|
|
if(dlg.DoModal() == IDCANCEL)
|
|
return;
|
|
|
|
pPrefab->SetName(dlg.m_strName);
|
|
pPrefab->SetNotes(dlg.m_strDescript);
|
|
|
|
AddToObjectList(pPrefab, iSel, TRUE);
|
|
bCurLibraryModified = TRUE;
|
|
}
|
|
|
|
|
|
void CPrefabsDlg::EditObjectData()
|
|
{
|
|
// get application
|
|
CHammer *pApp = (CHammer*) AfxGetApp();
|
|
|
|
if(bCurLibraryModified)
|
|
{
|
|
CPrefabLibrary *pLibrary = GetCurrentLibrary();
|
|
if(pLibrary)
|
|
pLibrary->Save();
|
|
}
|
|
|
|
CMapDoc *pDoc = (CMapDoc*) pApp->pMapDocTemplate->OpenDocumentFile(NULL);
|
|
pDoc->EditPrefab3D(GetCurrentObject()->GetID());
|
|
EndDialog(IDOK);
|
|
}
|
|
|
|
|
|
void CPrefabsDlg::OnEditobject()
|
|
{
|
|
if(!GetCurrentObject()) // nothing
|
|
return;
|
|
|
|
// two stages - name/description OR data itself
|
|
CMenu menu;
|
|
menu.CreatePopupMenu();
|
|
menu.AppendMenu(MF_STRING, id_EditObjectInfo, "Name and Description");
|
|
menu.AppendMenu(MF_STRING, id_EditObjectData, "Prefab Data");
|
|
|
|
// track menu
|
|
CWnd *pButton = GetDlgItem(IDC_EDITOBJECT);
|
|
CRect r;
|
|
pButton->GetWindowRect(r);
|
|
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, r.left, r.bottom,
|
|
this, NULL);
|
|
}
|
|
|
|
void CPrefabsDlg::OnRemoveobject()
|
|
{
|
|
// remove marked objectsss
|
|
int iIndex = m_Objects.GetNextItem(-1, LVNI_SELECTED);
|
|
BOOL bConfirmed = FALSE;
|
|
CPrefabLibrary *pLibrary = GetCurrentLibrary();
|
|
while(iIndex != -1)
|
|
{
|
|
CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iIndex));
|
|
if(pPrefab)
|
|
{
|
|
// delete it
|
|
if(!bConfirmed)
|
|
{
|
|
// do confirmation.
|
|
if(AfxMessageBox("Are you sure you want to delete these "
|
|
"items?", MB_YESNO) == IDNO)
|
|
return; // nope!
|
|
m_Objects.SetRedraw(FALSE); // no redraw while doing this
|
|
}
|
|
|
|
bConfirmed = TRUE;
|
|
|
|
// remove from lib & delete
|
|
pLibrary->Remove(pPrefab);
|
|
delete pPrefab;
|
|
|
|
// delete from list and shift index down so we keep processing
|
|
// correctly
|
|
m_Objects.DeleteItem(iIndex--);
|
|
}
|
|
// get next item
|
|
iIndex = m_Objects.GetNextItem(iIndex, LVNI_SELECTED);
|
|
}
|
|
|
|
// save library
|
|
pLibrary->Save();
|
|
|
|
m_Objects.SetRedraw(TRUE); // redraw objects
|
|
m_Objects.Invalidate();
|
|
}
|
|
|
|
void CPrefabsDlg::OnExportobject()
|
|
{
|
|
int iIndex = m_Objects.GetNextItem(-1, LVNI_SELECTED);
|
|
while(iIndex != -1)
|
|
{
|
|
CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iIndex));
|
|
if(pPrefab)
|
|
{
|
|
// export it
|
|
CString strFilename;
|
|
strFilename = pPrefab->GetName();
|
|
CFileDialog dlg(FALSE, "map", strFilename, OFN_HIDEREADONLY |
|
|
OFN_OVERWRITEPROMPT, "Map files|*.map;*.rmf|", this);
|
|
if(dlg.DoModal() == IDCANCEL)
|
|
return; // nevermind
|
|
strFilename = dlg.GetPathName();
|
|
|
|
int iPos = strFilename.Find('.');
|
|
DWORD dwFlags = CPrefab::lsRMF;
|
|
if(iPos != -1)
|
|
{
|
|
char *p = strFilename.GetBuffer(0);
|
|
if(!strnicmp(p+iPos+1, "map", 3))
|
|
dwFlags = CPrefab::lsMAP;
|
|
}
|
|
|
|
pPrefab->Save(strFilename, dwFlags);
|
|
}
|
|
// get next item
|
|
iIndex = m_Objects.GetNextItem(iIndex, LVNI_SELECTED);
|
|
}
|
|
}
|
|
|
|
void CPrefabsDlg::SetCurObject(int iItem)
|
|
{
|
|
iCurObject = iItem;
|
|
|
|
if(iCurObject == -1)
|
|
{
|
|
m_ObjectNotes.SetWindowText("");
|
|
return;
|
|
}
|
|
|
|
// update data..
|
|
CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iCurObject));
|
|
Assert(pPrefab);
|
|
|
|
m_ObjectNotes.SetWindowText(pPrefab->GetNotes());
|
|
}
|
|
|
|
void CPrefabsDlg::OnItemchangedObjects(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
|
*pResult = 0;
|
|
|
|
if(!(pNMListView->uChanged & LVIF_STATE))
|
|
return;
|
|
|
|
if(pNMListView->uNewState & LVIS_FOCUSED)
|
|
{
|
|
SetCurObject(pNMListView->iItem);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Library mgmt
|
|
//
|
|
|
|
CPrefabLibrary *CPrefabsDlg::GetCurrentLibrary(int *piSel)
|
|
{
|
|
if(piSel)
|
|
piSel[0] = -1;
|
|
|
|
int iSel = m_Libraries.GetCurSel();
|
|
if(iSel == CB_ERR)
|
|
return NULL;
|
|
CPrefabLibrary *pLibrary = CPrefabLibrary::FindID(
|
|
m_Libraries.GetItemData(iSel));
|
|
|
|
if(piSel)
|
|
piSel[0] = iSel;
|
|
return pLibrary;
|
|
}
|
|
|
|
CPrefab *CPrefabsDlg::GetCurrentObject(int *piSel)
|
|
{
|
|
if(piSel)
|
|
piSel[0] = -1;
|
|
|
|
int iSel = iCurObject;
|
|
if(iSel == -1)
|
|
return NULL;
|
|
CPrefab *pPrefab= CPrefab::FindID(m_Objects.GetItemData(iSel));
|
|
|
|
if(piSel)
|
|
piSel[0] = iSel;
|
|
|
|
return pPrefab;
|
|
}
|
|
|
|
void CPrefabsDlg::OnSelchangeLibraries()
|
|
{
|
|
// get last library
|
|
CPrefabLibrary *pLibrary = CPrefabLibrary::FindID(
|
|
m_Libraries.GetItemData(iCurLibrary));
|
|
|
|
// save its index
|
|
if(bCurLibraryModified)
|
|
{
|
|
pLibrary->Save();
|
|
}
|
|
|
|
// update objects list
|
|
m_Objects.DeleteAllItems();
|
|
iCurLibrary = m_Libraries.GetCurSel();
|
|
bCurLibraryModified = FALSE;
|
|
pLibrary = GetCurrentLibrary();
|
|
if(!pLibrary) return;
|
|
|
|
// add objects to object list
|
|
m_Objects.SetRedraw(FALSE);
|
|
POSITION p = ENUM_START;
|
|
CPrefab *pPrefab = pLibrary->EnumPrefabs(p);
|
|
int iItem = 0;
|
|
while(pPrefab)
|
|
{
|
|
AddToObjectList(pPrefab, iItem++);
|
|
pPrefab = pLibrary->EnumPrefabs(p);
|
|
}
|
|
m_Objects.SetRedraw(TRUE);
|
|
m_Objects.Invalidate();
|
|
|
|
// set description window
|
|
m_LibraryNotes.SetWindowText(pLibrary->GetNotes());
|
|
}
|
|
|
|
static int AskAboutInvalidFilename()
|
|
{
|
|
return AfxMessageBox("That's not a valid name - some of the characters aren't\n"
|
|
"acceptable. Try using a name with only A-Z, 0-9, space,\n"
|
|
"and these characters: $%`-_@~'!(){}^#&", MB_OKCANCEL);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CPrefabsDlg::OnAddlibrary()
|
|
{
|
|
Again:
|
|
CEditPrefabDlg dlg;
|
|
if(dlg.DoModal() == IDCANCEL)
|
|
return;
|
|
|
|
// check name
|
|
if(!IsValidFilename(dlg.m_strName))
|
|
{
|
|
if(AskAboutInvalidFilename() == IDOK)
|
|
goto Again;
|
|
return; // nevermind.
|
|
}
|
|
|
|
CPrefabLibraryRMF *pLibrary = new CPrefabLibraryRMF;
|
|
|
|
pLibrary->SetName(dlg.m_strName);
|
|
pLibrary->SetNotes(dlg.m_strDescript);
|
|
|
|
// add to list
|
|
int iIndex = m_Libraries.AddString(pLibrary->GetName());
|
|
m_Libraries.SetItemData(iIndex, pLibrary->GetID());
|
|
|
|
m_Libraries.SetCurSel(iIndex);
|
|
OnSelchangeLibraries(); // to redraw description window
|
|
bCurLibraryModified = TRUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CPrefabsDlg::OnEditlibrary()
|
|
{
|
|
// get selection
|
|
int iSel;
|
|
CPrefabLibrary *pLibrary = GetCurrentLibrary(&iSel);
|
|
if(!pLibrary) return;
|
|
|
|
CEditPrefabDlg dlg;
|
|
dlg.m_strName = pLibrary->GetName();
|
|
dlg.m_strDescript = pLibrary->GetNotes();
|
|
|
|
Again:
|
|
if(dlg.DoModal() == IDCANCEL)
|
|
return;
|
|
|
|
// check name
|
|
if(!IsValidFilename(dlg.m_strName))
|
|
{
|
|
if(AskAboutInvalidFilename() == IDOK)
|
|
goto Again;
|
|
return; // nevermind.
|
|
}
|
|
|
|
pLibrary->SetName(dlg.m_strName);
|
|
pLibrary->SetNotes(dlg.m_strDescript);
|
|
|
|
// set in list
|
|
m_Libraries.SetRedraw(FALSE);
|
|
m_Libraries.DeleteString(iSel);
|
|
int iIndex = m_Libraries.InsertString(iSel, pLibrary->GetName());
|
|
m_Libraries.SetItemData(iIndex, pLibrary->GetID());
|
|
m_Libraries.SetRedraw(TRUE);
|
|
m_Libraries.Invalidate();
|
|
|
|
m_Libraries.SetCurSel(iSel);
|
|
OnSelchangeLibraries(); // to redraw description window
|
|
bCurLibraryModified = TRUE;
|
|
}
|
|
|
|
|
|
void CPrefabsDlg::OnRemovelibrary()
|
|
{
|
|
// get cur library
|
|
int iSel;
|
|
CPrefabLibrary *pLibrary = GetCurrentLibrary(&iSel);
|
|
if (pLibrary == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (AfxMessageBox("Are you sure you want to delete this library from your hard drive?", MB_YESNO) == IDYES)
|
|
{
|
|
pLibrary->DeleteFile();
|
|
delete pLibrary;
|
|
|
|
bCurLibraryModified = FALSE;
|
|
|
|
m_Libraries.DeleteString(iSel);
|
|
m_Libraries.SetCurSel(0);
|
|
OnSelchangeLibraries(); // to redraw description window
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CPrefabsDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
SetCurObject(-1);
|
|
|
|
// make imagelist
|
|
PrefabImages.Create(IDB_PREFABS, 32, 1, RGB(0, 255, 255));
|
|
PrefabImages.SetBkColor(m_Objects.GetBkColor());
|
|
m_Objects.SetImageList(&PrefabImages, LVSIL_NORMAL);
|
|
|
|
// add libraries to list
|
|
POSITION p = ENUM_START;
|
|
CPrefabLibrary *pLibrary = CPrefabLibrary::EnumLibraries(p);
|
|
while(pLibrary)
|
|
{
|
|
int iIndex = m_Libraries.AddString(pLibrary->GetName());
|
|
m_Libraries.SetItemData(iIndex, pLibrary->GetID());
|
|
pLibrary = CPrefabLibrary::EnumLibraries(p);
|
|
}
|
|
|
|
iCurLibrary = 0;
|
|
bCurLibraryModified = FALSE;
|
|
m_Libraries.SetCurSel(0);
|
|
OnSelchangeLibraries();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CPrefabsDlg::OnEndlabeleditObjects(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
|
|
LV_ITEM &item = pDispInfo->item;
|
|
|
|
*pResult = 0;
|
|
|
|
if(item.pszText == NULL)
|
|
return;
|
|
|
|
CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(item.iItem));
|
|
pPrefab->SetName(item.pszText);
|
|
m_Objects.SetItemText(item.iItem, 0, item.pszText);
|
|
bCurLibraryModified = TRUE;
|
|
}
|
|
|
|
void CPrefabsDlg::OnClose()
|
|
{
|
|
// get library
|
|
CPrefabLibrary *pLibrary = GetCurrentLibrary();
|
|
|
|
// save it
|
|
if(bCurLibraryModified && pLibrary)
|
|
{
|
|
pLibrary->Save();
|
|
}
|
|
|
|
CDialog::OnClose();
|
|
}
|