Counter Strike : Global Offensive Source Code
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.

623 lines
14 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // PrefabsDlg.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "hammer.h"
  12. #include "PrefabsDlg.h"
  13. #include "Prefabs.h"
  14. #include "Prefab3D.h"
  15. #include "EditPrefabDlg.h"
  16. #include "MapDoc.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include <tier0/memdbgon.h>
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CPrefabsDlg dialog
  21. CPrefabsDlg::CPrefabsDlg(CWnd* pParent /*=NULL*/)
  22. : CDialog(CPrefabsDlg::IDD, pParent)
  23. {
  24. //{{AFX_DATA_INIT(CPrefabsDlg)
  25. // NOTE: the ClassWizard will add member initialization here
  26. //}}AFX_DATA_INIT
  27. }
  28. void CPrefabsDlg::DoDataExchange(CDataExchange* pDX)
  29. {
  30. CDialog::DoDataExchange(pDX);
  31. //{{AFX_DATA_MAP(CPrefabsDlg)
  32. DDX_Control(pDX, IDC_OBJECTS, m_Objects);
  33. DDX_Control(pDX, IDC_OBJECTNOTES, m_ObjectNotes);
  34. DDX_Control(pDX, IDC_LIBRARYNOTES, m_LibraryNotes);
  35. DDX_Control(pDX, IDC_LIBRARIES, m_Libraries);
  36. //}}AFX_DATA_MAP
  37. }
  38. BEGIN_MESSAGE_MAP(CPrefabsDlg, CDialog)
  39. //{{AFX_MSG_MAP(CPrefabsDlg)
  40. ON_BN_CLICKED(IDC_ADDLIBRARY, OnAddlibrary)
  41. ON_BN_CLICKED(IDC_ADDOBJECT, OnAddobject)
  42. ON_BN_CLICKED(IDC_EDITLIBRARY, OnEditlibrary)
  43. ON_BN_CLICKED(IDC_EDITOBJECT, OnEditobject)
  44. ON_BN_CLICKED(IDC_EXPORTOBJECT, OnExportobject)
  45. ON_CBN_SELCHANGE(IDC_LIBRARIES, OnSelchangeLibraries)
  46. ON_BN_CLICKED(IDC_REMOVELIBRARY, OnRemovelibrary)
  47. ON_BN_CLICKED(IDC_REMOVEOBJECT, OnRemoveobject)
  48. ON_NOTIFY(LVN_ITEMCHANGED, IDC_OBJECTS, OnItemchangedObjects)
  49. ON_NOTIFY(LVN_ENDLABELEDIT, IDC_OBJECTS, OnEndlabeleditObjects)
  50. ON_WM_CLOSE()
  51. //}}AFX_MSG_MAP
  52. ON_COMMAND_EX(id_EditObjectInfo, HandleEditObjectPopup)
  53. ON_COMMAND_EX(id_EditObjectData, HandleEditObjectPopup)
  54. END_MESSAGE_MAP()
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CPrefabsDlg message handlers
  57. void CPrefabsDlg::OnAddobject()
  58. {
  59. CPrefabLibrary *pLibrary = GetCurrentLibrary();
  60. if(!pLibrary)
  61. return; // no lib, no add
  62. CFileDialog dlg(TRUE, NULL, NULL, OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST |
  63. OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR,
  64. "Prefab files (*.map;*.rmf;*.os)|*.map; *.rmf; *.os|"
  65. "Game MAP files (*.map)|*.map|"
  66. "Worldcraft RMF files (*.rmf)|*.rmf||", this);
  67. if(dlg.DoModal() == IDCANCEL)
  68. return; // aborted
  69. // add all these files ..
  70. char szDir[MAX_PATH], szFiles[2048];
  71. memcpy(szFiles, dlg.m_ofn.lpstrFile, dlg.m_ofn.nMaxFile);
  72. strcpy(szDir, dlg.m_ofn.lpstrFile);
  73. BOOL bOneFile = FALSE;
  74. char *p = szFiles + strlen(szDir) + 1;
  75. if(!p[0])
  76. {
  77. bOneFile = TRUE;
  78. p = szDir; // just one file
  79. }
  80. // disable caching of prefabs
  81. CPrefab::EnableCaching(FALSE);
  82. // get files
  83. char szFile[MAX_PATH];
  84. CString strFullPath;
  85. int iItem = m_Objects.GetItemCount();
  86. while(1)
  87. {
  88. strcpy(szFile, p);
  89. if(!szFile[0])
  90. break;
  91. p += strlen(szFile) + 1;
  92. if(!bOneFile)
  93. strFullPath.Format("%s\\%s", szDir, szFile);
  94. else
  95. strFullPath = szFile;
  96. // check file type
  97. CPrefab *pPrefab = NULL;
  98. switch(CPrefab::CheckFileType(strFullPath))
  99. {
  100. case CPrefab::pftUnknown:
  101. {
  102. continue; // no.
  103. }
  104. case CPrefab::pftRMF:
  105. {
  106. CPrefabRMF *pNew = new CPrefabRMF;
  107. pNew->Init(strFullPath, TRUE, CPrefab::lsRMF);
  108. pPrefab = (CPrefab *)pNew;
  109. break;
  110. }
  111. case CPrefab::pftMAP:
  112. {
  113. CPrefabRMF *pNew = new CPrefabRMF;
  114. pNew->Init(strFullPath, TRUE, CPrefab::lsMAP);
  115. pPrefab = (CPrefab *)pNew;
  116. break;
  117. }
  118. case CPrefab::pftScript:
  119. {
  120. Assert(0); // not supported yet
  121. break;
  122. }
  123. }
  124. if (!pPrefab)
  125. {
  126. continue;
  127. }
  128. // add to current library
  129. pLibrary->Add(pPrefab);
  130. // add to objects list
  131. AddToObjectList(pPrefab, iItem++);
  132. if(bOneFile)
  133. break;
  134. }
  135. // now rewrite library
  136. pLibrary->Sort();
  137. pLibrary->Save();
  138. CPrefab::FreeAllData(); // free memory
  139. // re-enable prefab caching
  140. CPrefab::EnableCaching(TRUE);
  141. bCurLibraryModified = FALSE;
  142. }
  143. void CPrefabsDlg::AddToObjectList(CPrefab *pPrefab, int iItem, BOOL bReplace)
  144. {
  145. if(iItem == -1)
  146. iItem = m_Objects.GetItemCount();
  147. if(bReplace) // replace existing item
  148. {
  149. m_Objects.DeleteItem(iItem);
  150. }
  151. iItem = m_Objects.InsertItem(iItem, pPrefab->GetName(),
  152. pPrefab->GetType() == CPrefab::pftScript ? 1 : 0);
  153. m_Objects.SetItemData(iItem, pPrefab->GetID());
  154. bCurLibraryModified = TRUE;
  155. }
  156. BOOL CPrefabsDlg::HandleEditObjectPopup(UINT nID)
  157. {
  158. switch(nID)
  159. {
  160. case id_EditObjectInfo:
  161. EditObjectInfo();
  162. break;
  163. case id_EditObjectData:
  164. EditObjectData();
  165. break;
  166. }
  167. return TRUE;
  168. }
  169. static BOOL IsValidFilename(LPCTSTR pszString)
  170. // check for valid windows filename. no drive/dirs allowed.
  171. {
  172. LPCTSTR p = pszString;
  173. while(p[0])
  174. {
  175. BYTE ch = BYTE(p[0]);
  176. ++p;
  177. if(ch > 127 || V_isalpha(ch) || V_isdigit(ch) ||
  178. strchr(" $%`-_@~'!(){}^#&", ch))
  179. continue;
  180. // not one of those chars - not correct
  181. return FALSE;
  182. }
  183. return TRUE;
  184. }
  185. void CPrefabsDlg::EditObjectInfo()
  186. {
  187. int iSel;
  188. CPrefab *pPrefab = GetCurrentObject(&iSel);
  189. CEditPrefabDlg dlg;
  190. dlg.m_strName = pPrefab->GetName();
  191. dlg.m_strDescript = pPrefab->GetNotes();
  192. dlg.SetRanges(500, -1);
  193. if(dlg.DoModal() == IDCANCEL)
  194. return;
  195. pPrefab->SetName(dlg.m_strName);
  196. pPrefab->SetNotes(dlg.m_strDescript);
  197. AddToObjectList(pPrefab, iSel, TRUE);
  198. bCurLibraryModified = TRUE;
  199. }
  200. void CPrefabsDlg::EditObjectData()
  201. {
  202. // get application
  203. CHammer *pApp = (CHammer*) AfxGetApp();
  204. if(bCurLibraryModified)
  205. {
  206. CPrefabLibrary *pLibrary = GetCurrentLibrary();
  207. if(pLibrary)
  208. pLibrary->Save();
  209. }
  210. CMapDoc *pDoc = (CMapDoc*) pApp->pMapDocTemplate->OpenDocumentFile(NULL);
  211. pDoc->EditPrefab3D(GetCurrentObject()->GetID());
  212. EndDialog(IDOK);
  213. }
  214. void CPrefabsDlg::OnEditobject()
  215. {
  216. if(!GetCurrentObject()) // nothing
  217. return;
  218. // two stages - name/description OR data itself
  219. CMenu menu;
  220. menu.CreatePopupMenu();
  221. menu.AppendMenu(MF_STRING, id_EditObjectInfo, "Name and Description");
  222. menu.AppendMenu(MF_STRING, id_EditObjectData, "Prefab Data");
  223. // track menu
  224. CWnd *pButton = GetDlgItem(IDC_EDITOBJECT);
  225. CRect r;
  226. pButton->GetWindowRect(r);
  227. menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, r.left, r.bottom,
  228. this, NULL);
  229. }
  230. void CPrefabsDlg::OnRemoveobject()
  231. {
  232. // remove marked objectsss
  233. int iIndex = m_Objects.GetNextItem(-1, LVNI_SELECTED);
  234. BOOL bConfirmed = FALSE;
  235. CPrefabLibrary *pLibrary = GetCurrentLibrary();
  236. while(iIndex != -1)
  237. {
  238. CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iIndex));
  239. if(pPrefab)
  240. {
  241. // delete it
  242. if(!bConfirmed)
  243. {
  244. // do confirmation.
  245. if(AfxMessageBox("Are you sure you want to delete these "
  246. "items?", MB_YESNO) == IDNO)
  247. return; // nope!
  248. m_Objects.SetRedraw(FALSE); // no redraw while doing this
  249. }
  250. bConfirmed = TRUE;
  251. // remove from lib & delete
  252. pLibrary->Remove(pPrefab);
  253. delete pPrefab;
  254. // delete from list and shift index down so we keep processing
  255. // correctly
  256. m_Objects.DeleteItem(iIndex--);
  257. }
  258. // get next item
  259. iIndex = m_Objects.GetNextItem(iIndex, LVNI_SELECTED);
  260. }
  261. // save library
  262. pLibrary->Save();
  263. m_Objects.SetRedraw(TRUE); // redraw objects
  264. m_Objects.Invalidate();
  265. }
  266. void CPrefabsDlg::OnExportobject()
  267. {
  268. int iIndex = m_Objects.GetNextItem(-1, LVNI_SELECTED);
  269. while(iIndex != -1)
  270. {
  271. CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iIndex));
  272. if(pPrefab)
  273. {
  274. // export it
  275. CString strFilename;
  276. strFilename = pPrefab->GetName();
  277. CFileDialog dlg(FALSE, "map", strFilename, OFN_HIDEREADONLY |
  278. OFN_OVERWRITEPROMPT, "Map files|*.map;*.rmf|", this);
  279. if(dlg.DoModal() == IDCANCEL)
  280. return; // nevermind
  281. strFilename = dlg.GetPathName();
  282. int iPos = strFilename.Find('.');
  283. DWORD dwFlags = CPrefab::lsRMF;
  284. if(iPos != -1)
  285. {
  286. char *p = strFilename.GetBuffer(0);
  287. if(!strnicmp(p+iPos+1, "map", 3))
  288. dwFlags = CPrefab::lsMAP;
  289. }
  290. pPrefab->Save(strFilename, dwFlags);
  291. }
  292. // get next item
  293. iIndex = m_Objects.GetNextItem(iIndex, LVNI_SELECTED);
  294. }
  295. }
  296. void CPrefabsDlg::SetCurObject(int iItem)
  297. {
  298. iCurObject = iItem;
  299. if(iCurObject == -1)
  300. {
  301. m_ObjectNotes.SetWindowText("");
  302. return;
  303. }
  304. // update data..
  305. CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iCurObject));
  306. Assert(pPrefab);
  307. m_ObjectNotes.SetWindowText(pPrefab->GetNotes());
  308. }
  309. void CPrefabsDlg::OnItemchangedObjects(NMHDR* pNMHDR, LRESULT* pResult)
  310. {
  311. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  312. *pResult = 0;
  313. if(!(pNMListView->uChanged & LVIF_STATE))
  314. return;
  315. if(pNMListView->uNewState & LVIS_FOCUSED)
  316. {
  317. SetCurObject(pNMListView->iItem);
  318. }
  319. }
  320. //
  321. // Library mgmt
  322. //
  323. CPrefabLibrary *CPrefabsDlg::GetCurrentLibrary(int *piSel)
  324. {
  325. if(piSel)
  326. piSel[0] = -1;
  327. int iSel = m_Libraries.GetCurSel();
  328. if(iSel == CB_ERR)
  329. return NULL;
  330. CPrefabLibrary *pLibrary = CPrefabLibrary::FindID(
  331. m_Libraries.GetItemData(iSel));
  332. if(piSel)
  333. piSel[0] = iSel;
  334. return pLibrary;
  335. }
  336. CPrefab *CPrefabsDlg::GetCurrentObject(int *piSel)
  337. {
  338. if(piSel)
  339. piSel[0] = -1;
  340. int iSel = iCurObject;
  341. if(iSel == -1)
  342. return NULL;
  343. CPrefab *pPrefab= CPrefab::FindID(m_Objects.GetItemData(iSel));
  344. if(piSel)
  345. piSel[0] = iSel;
  346. return pPrefab;
  347. }
  348. void CPrefabsDlg::OnSelchangeLibraries()
  349. {
  350. // get last library
  351. CPrefabLibrary *pLibrary = CPrefabLibrary::FindID(
  352. m_Libraries.GetItemData(iCurLibrary));
  353. // save its index
  354. if(bCurLibraryModified)
  355. {
  356. pLibrary->Save();
  357. }
  358. // update objects list
  359. m_Objects.DeleteAllItems();
  360. iCurLibrary = m_Libraries.GetCurSel();
  361. bCurLibraryModified = FALSE;
  362. pLibrary = GetCurrentLibrary();
  363. if(!pLibrary) return;
  364. // add objects to object list
  365. m_Objects.SetRedraw(FALSE);
  366. POSITION p = ENUM_START;
  367. CPrefab *pPrefab = pLibrary->EnumPrefabs(p);
  368. int iItem = 0;
  369. while(pPrefab)
  370. {
  371. AddToObjectList(pPrefab, iItem++);
  372. pPrefab = pLibrary->EnumPrefabs(p);
  373. }
  374. m_Objects.SetRedraw(TRUE);
  375. m_Objects.Invalidate();
  376. // set description window
  377. m_LibraryNotes.SetWindowText(pLibrary->GetNotes());
  378. }
  379. static int AskAboutInvalidFilename()
  380. {
  381. return AfxMessageBox("That's not a valid name - some of the characters aren't\n"
  382. "acceptable. Try using a name with only A-Z, 0-9, space,\n"
  383. "and these characters: $%`-_@~'!(){}^#&", MB_OKCANCEL);
  384. }
  385. //-----------------------------------------------------------------------------
  386. // Purpose:
  387. //-----------------------------------------------------------------------------
  388. void CPrefabsDlg::OnAddlibrary()
  389. {
  390. Again:
  391. CEditPrefabDlg dlg;
  392. if(dlg.DoModal() == IDCANCEL)
  393. return;
  394. // check name
  395. if(!IsValidFilename(dlg.m_strName))
  396. {
  397. if(AskAboutInvalidFilename() == IDOK)
  398. goto Again;
  399. return; // nevermind.
  400. }
  401. CPrefabLibraryRMF *pLibrary = new CPrefabLibraryRMF;
  402. pLibrary->SetName(dlg.m_strName);
  403. pLibrary->SetNotes(dlg.m_strDescript);
  404. // add to list
  405. int iIndex = m_Libraries.AddString(pLibrary->GetName());
  406. m_Libraries.SetItemData(iIndex, pLibrary->GetID());
  407. m_Libraries.SetCurSel(iIndex);
  408. OnSelchangeLibraries(); // to redraw description window
  409. bCurLibraryModified = TRUE;
  410. }
  411. //-----------------------------------------------------------------------------
  412. // Purpose:
  413. //-----------------------------------------------------------------------------
  414. void CPrefabsDlg::OnEditlibrary()
  415. {
  416. // get selection
  417. int iSel;
  418. CPrefabLibrary *pLibrary = GetCurrentLibrary(&iSel);
  419. if(!pLibrary) return;
  420. CEditPrefabDlg dlg;
  421. dlg.m_strName = pLibrary->GetName();
  422. dlg.m_strDescript = pLibrary->GetNotes();
  423. Again:
  424. if(dlg.DoModal() == IDCANCEL)
  425. return;
  426. // check name
  427. if(!IsValidFilename(dlg.m_strName))
  428. {
  429. if(AskAboutInvalidFilename() == IDOK)
  430. goto Again;
  431. return; // nevermind.
  432. }
  433. pLibrary->SetName(dlg.m_strName);
  434. pLibrary->SetNotes(dlg.m_strDescript);
  435. // set in list
  436. m_Libraries.SetRedraw(FALSE);
  437. m_Libraries.DeleteString(iSel);
  438. int iIndex = m_Libraries.InsertString(iSel, pLibrary->GetName());
  439. m_Libraries.SetItemData(iIndex, pLibrary->GetID());
  440. m_Libraries.SetRedraw(TRUE);
  441. m_Libraries.Invalidate();
  442. m_Libraries.SetCurSel(iSel);
  443. OnSelchangeLibraries(); // to redraw description window
  444. bCurLibraryModified = TRUE;
  445. }
  446. void CPrefabsDlg::OnRemovelibrary()
  447. {
  448. // get cur library
  449. int iSel;
  450. CPrefabLibrary *pLibrary = GetCurrentLibrary(&iSel);
  451. if (pLibrary == NULL)
  452. {
  453. return;
  454. }
  455. if (AfxMessageBox("Are you sure you want to delete this library from your hard drive?", MB_YESNO) == IDYES)
  456. {
  457. pLibrary->DeleteFile();
  458. delete pLibrary;
  459. bCurLibraryModified = FALSE;
  460. m_Libraries.DeleteString(iSel);
  461. m_Libraries.SetCurSel(0);
  462. OnSelchangeLibraries(); // to redraw description window
  463. }
  464. }
  465. BOOL CPrefabsDlg::OnInitDialog()
  466. {
  467. CDialog::OnInitDialog();
  468. SetCurObject(-1);
  469. // make imagelist
  470. PrefabImages.Create(IDB_PREFABS, 32, 1, RGB(0, 255, 255));
  471. PrefabImages.SetBkColor(m_Objects.GetBkColor());
  472. m_Objects.SetImageList(&PrefabImages, LVSIL_NORMAL);
  473. // add libraries to list
  474. POSITION p = ENUM_START;
  475. CPrefabLibrary *pLibrary = CPrefabLibrary::EnumLibraries(p);
  476. while(pLibrary)
  477. {
  478. int iIndex = m_Libraries.AddString(pLibrary->GetName());
  479. m_Libraries.SetItemData(iIndex, pLibrary->GetID());
  480. pLibrary = CPrefabLibrary::EnumLibraries(p);
  481. }
  482. iCurLibrary = 0;
  483. bCurLibraryModified = FALSE;
  484. m_Libraries.SetCurSel(0);
  485. OnSelchangeLibraries();
  486. return TRUE;
  487. }
  488. void CPrefabsDlg::OnEndlabeleditObjects(NMHDR* pNMHDR, LRESULT* pResult)
  489. {
  490. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  491. LV_ITEM &item = pDispInfo->item;
  492. *pResult = 0;
  493. if(item.pszText == NULL)
  494. return;
  495. CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(item.iItem));
  496. pPrefab->SetName(item.pszText);
  497. m_Objects.SetItemText(item.iItem, 0, item.pszText);
  498. bCurLibraryModified = TRUE;
  499. }
  500. void CPrefabsDlg::OnClose()
  501. {
  502. // get library
  503. CPrefabLibrary *pLibrary = GetCurrentLibrary();
  504. // save it
  505. if(bCurLibraryModified && pLibrary)
  506. {
  507. pLibrary->Save();
  508. }
  509. CDialog::OnClose();
  510. }