diff options
Diffstat (limited to 'hammer/prefabsdlg.cpp')
| -rw-r--r-- | hammer/prefabsdlg.cpp | 623 |
1 files changed, 623 insertions, 0 deletions
diff --git a/hammer/prefabsdlg.cpp b/hammer/prefabsdlg.cpp new file mode 100644 index 0000000..67eceaf --- /dev/null +++ b/hammer/prefabsdlg.cpp @@ -0,0 +1,623 @@ +//========= 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(); +} |