Team Fortress 2 Source Code as on 22/4/2020
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.

1041 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "stdafx.h"
  7. #include "hammer.h"
  8. #include "ObjectBar.h"
  9. #include "Options.h"
  10. #include "ControlBarIDs.h"
  11. #include "Prefabs.h"
  12. #include "Prefab3D.h"
  13. #include "StockSolids.h"
  14. #include "mainfrm.h"
  15. #include "MapSolid.h"
  16. #include "MapWorld.h"
  17. #include "MapDoc.h"
  18. #include "GlobalFunctions.h"
  19. #include "ArchDlg.h"
  20. #include "TorusDlg.h"
  21. #include "ToolManager.h"
  22. #include "mathlib/vector.h"
  23. #include "mapview2d.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include <tier0/memdbgon.h>
  26. #pragma warning( disable : 4355 )
  27. CMapClass *CreateArch(BoundBox *pBox, float fStartAngle, int iSides, float fArc,
  28. int iWallWidth, int iAddHeight, BOOL bPreview);
  29. CMapClass *CreateTorus(BoundBox *pBox, float fStartAngle, int iSides, float fArc, int iWallWidth, float flCrossSectionalRadius,
  30. float fRotationStartAngle, int iRotationSides, float fRotationArc, int iAddHeight, BOOL bPreview);
  31. static int _iNewObjIndex = 0;
  32. static char _szNewObjName[128];
  33. struct SolidTypeInfo_t
  34. {
  35. LPCTSTR pszName;
  36. UINT nFaces;
  37. UINT nFacesMin;
  38. UINT nFacesMax;
  39. bool bEnableFaceControl;
  40. };
  41. SolidTypeInfo_t SolidTypes[] =
  42. {
  43. {"block", 0, 6, 6, false},
  44. {"wedge", 0, 5, 5, false},
  45. {"cylinder", 8, 3, 32, true},
  46. {"spike", 4, 3, 32, true},
  47. {"sphere", 8, 3, 16, true},
  48. {"arch", 8, 3, 128, true},
  49. {"torus", 0, 4, 128, false},
  50. };
  51. BEGIN_MESSAGE_MAP(CObjectBar, CHammerBar)
  52. ON_UPDATE_COMMAND_UI(IDC_CREATELIST, UpdateControl)
  53. ON_UPDATE_COMMAND_UI(IDC_CATEGORYLIST, UpdateControl)
  54. ON_UPDATE_COMMAND_UI(IDC_FACES, UpdateFaceControl)
  55. ON_UPDATE_COMMAND_UI(IDC_FACESSPIN, UpdateFaceControl)
  56. ON_UPDATE_COMMAND_UI(ID_TOOLS_CREATEPREFAB, UpdateControl)
  57. ON_UPDATE_COMMAND_UI(ID_CREATEOBJECT, UpdateControl)
  58. ON_CBN_SELCHANGE(IDC_CATEGORYLIST, OnChangeCategory)
  59. END_MESSAGE_MAP()
  60. //-----------------------------------------------------------------------------
  61. // Purpose: Get the index of the specified solid type.
  62. //-----------------------------------------------------------------------------
  63. static int FindSolidType( const char *pName )
  64. {
  65. for ( int i=0; i < ARRAYSIZE( SolidTypes ); i++ )
  66. {
  67. if ( Q_stricmp( pName, SolidTypes[i].pszName ) == 0 )
  68. return i;
  69. }
  70. return -1;
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Purpose: Get the index of the specified GDClass.
  74. //-----------------------------------------------------------------------------
  75. static int FindGameDataClass( const char *pName )
  76. {
  77. extern GameData *pGD;
  78. if( pGD != NULL )
  79. {
  80. int nCount = pGD->GetClassCount();
  81. for (int i = 0; i < nCount; i++)
  82. {
  83. GDclass *pc = pGD->GetClass(i);
  84. if ( Q_stricmp( pName, pc->GetName() ) == 0 )
  85. return i;
  86. }
  87. }
  88. return -1;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose:
  92. //-----------------------------------------------------------------------------
  93. CObjectBar::CObjectBar()
  94. : CHammerBar(), m_CreateList( this )
  95. {
  96. for(int i = 0; i < MAX_PREV_SEL; i++)
  97. {
  98. m_PrevSel[i].dwGameID = 0;
  99. }
  100. m_dwPrevGameID = (unsigned long)-1;
  101. }
  102. bool CObjectBar::UseRandomYawOnEntityPlacement()
  103. {
  104. return ::SendMessage( ::GetDlgItem( GetSafeHwnd(), IDC_RANDOMYAW ), BM_GETCHECK, 0, 0 ) == BST_CHECKED;
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose:
  108. // Input : pDX -
  109. //-----------------------------------------------------------------------------
  110. void CObjectBar::DoDataExchange(CDataExchange *pDX)
  111. {
  112. CHammerBar::DoDataExchange(pDX);
  113. //{{AFX_DATA_MAP(COP_Entity)
  114. DDX_Control(pDX, IDC_CREATELIST, m_CreateList);
  115. //}}AFX_DATA_MAP
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose: Returns the bounds of the current 3D prefab object.
  119. // Input : *pBox -
  120. // Output : Returns TRUE on success, FALSE on failure.
  121. //-----------------------------------------------------------------------------
  122. BOOL CObjectBar::GetPrefabBounds(BoundBox *pBox)
  123. {
  124. if (ListType != listPrefabs)
  125. {
  126. return FALSE;
  127. }
  128. CPrefab3D *pPrefab = (CPrefab3D *)CPrefab::FindID(_iNewObjIndex);
  129. if (pPrefab != NULL)
  130. {
  131. if (pPrefab->GetType() != pt3D)
  132. {
  133. return(FALSE);
  134. }
  135. if (!pPrefab->IsLoaded())
  136. {
  137. pPrefab->Load();
  138. }
  139. if (!pPrefab->IsLoaded())
  140. {
  141. return(FALSE);
  142. }
  143. CMapWorld *pWorld = pPrefab->GetWorld();
  144. Vector mins;
  145. Vector maxs;
  146. pWorld->GetRender2DBox(mins, maxs);
  147. pBox->SetBounds(mins, maxs);
  148. return(TRUE);
  149. }
  150. return(FALSE);
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose: Find the specified prefab.
  154. //-----------------------------------------------------------------------------
  155. CPrefab* CObjectBar::FindPrefabByName( const char *pName )
  156. {
  157. CPrefabLibrary *pLibrary = CPrefabLibrary::FindID( m_CategoryList.GetItemData(m_CategoryList.GetCurSel() ) );
  158. if ( pLibrary )
  159. {
  160. POSITION p = ENUM_START;
  161. CPrefab *pPrefab = pLibrary->EnumPrefabs( p );
  162. while( pPrefab )
  163. {
  164. if ( Q_stricmp( pName, pPrefab->GetName() ) == 0 )
  165. return pPrefab;
  166. pPrefab = pLibrary->EnumPrefabs( p );
  167. }
  168. }
  169. return NULL;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Purpose:
  173. // Input : pBox -
  174. // pAxes -
  175. // Output :
  176. //-----------------------------------------------------------------------------
  177. CMapClass *CObjectBar::CreateInBox(BoundBox *pBox, CMapView *pView)
  178. {
  179. // primitives:
  180. int axHorz = 0;
  181. int axVert = 1;
  182. CMapView2D *pView2D = dynamic_cast<CMapView2D*>(pView);
  183. if ( pView2D )
  184. {
  185. axHorz = pView2D->axHorz;
  186. axVert = pView2D->axVert;
  187. }
  188. if(ListType == listPrimitives)
  189. {
  190. int nFaces;
  191. char szBuf[128];
  192. m_Faces.GetWindowText(szBuf, 128);
  193. nFaces = atoi(szBuf);
  194. //
  195. // The index into the solid types array is stored in the item data.
  196. //
  197. int nSolidIndex = _iNewObjIndex;
  198. int nFacesMin = SolidTypes[nSolidIndex].nFacesMin;
  199. int nFacesMax = SolidTypes[nSolidIndex].nFacesMax;
  200. //
  201. // Insure that the face count is within legal range (if applicable).
  202. //
  203. if ((SolidTypes[nSolidIndex].bEnableFaceControl) && (nFaces < nFacesMin || nFaces > nFacesMax))
  204. {
  205. CString str;
  206. str.Format("The face count for a %s must be in the range of %d to %d.",
  207. SolidTypes[nSolidIndex].pszName, nFacesMin, nFacesMax);
  208. AfxMessageBox(str);
  209. return NULL;
  210. }
  211. if(nSolidIndex < 5)
  212. {
  213. StockSolid *pStock = NULL;
  214. switch(nSolidIndex)
  215. {
  216. case 0:
  217. pStock = new StockBlock;
  218. break;
  219. case 1:
  220. pStock = new StockWedge;
  221. break;
  222. case 2:
  223. pStock = new StockCylinder;
  224. pStock->SetFieldData(StockCylinder::fieldSideCount, nFaces);
  225. break;
  226. case 3:
  227. pStock = new StockSpike;
  228. pStock->SetFieldData(StockSpike::fieldSideCount, nFaces);
  229. break;
  230. default:
  231. pStock = new StockSphere;
  232. pStock->SetFieldData(StockSphere::fieldSideCount, nFaces);
  233. break;
  234. }
  235. // create a solid
  236. CMapSolid *pSolid = new CMapSolid;
  237. pStock->SetFromBox(pBox);
  238. pStock->CreateMapSolid(pSolid, Options.GetTextureAlignment());
  239. pSolid->SetTexture(GetDefaultTextureName());
  240. delete pStock; // done with you! done!
  241. // return new solid
  242. return pSolid;
  243. }
  244. else if (nSolidIndex == 5)
  245. {
  246. // arch
  247. CArchDlg dlg(pBox->bmins, pBox->bmaxs);
  248. Vector sizebounds;
  249. pBox->GetBoundsSize(sizebounds);
  250. dlg.m_iSides = nFaces;
  251. dlg.SetMaxWallWidth(min((int)sizebounds[axHorz], (int)sizebounds[axVert]));
  252. if(dlg.DoModal() != IDOK)
  253. return NULL;
  254. // save values for next use of arch
  255. dlg.SaveValues();
  256. CMapClass *pArch = CreateArch(pBox, dlg.m_fAngle,
  257. dlg.m_iSides, dlg.m_fArc, dlg.m_iWallWidth,
  258. dlg.m_iAddHeight, FALSE);
  259. const CMapObjectList &SolidList = *pArch->GetChildren();
  260. FOR_EACH_OBJ( SolidList, nSolid )
  261. {
  262. CMapSolid *pSolid = dynamic_cast<CMapSolid *>(SolidList[nSolid]);
  263. if ( pSolid )
  264. pSolid->SetTexture(GetDefaultTextureName());
  265. }
  266. return pArch;
  267. }
  268. else
  269. {
  270. // Torus
  271. CTorusDlg dlg( pBox->bmins, pBox->bmaxs );
  272. Vector sizebounds;
  273. pBox->GetBoundsSize( sizebounds );
  274. dlg.SetMaxWallWidth(min((int)sizebounds[axHorz], (int)sizebounds[axVert]));
  275. if(dlg.DoModal() != IDOK)
  276. return NULL;
  277. // save values for next use of arch
  278. dlg.SaveValues();
  279. CMapClass *pTorus = CreateTorus(pBox, dlg.m_fAngle, dlg.m_iSides, dlg.m_fArc, dlg.m_iWallWidth,
  280. dlg.GetTorusCrossSectionRadius(),
  281. dlg.m_fRotationAngle, dlg.m_iRotationSides, dlg.m_fRotationArc, dlg.m_iAddHeight, FALSE);
  282. const CMapObjectList &SolidList = *pTorus->GetChildren();
  283. FOR_EACH_OBJ( SolidList, nSolid )
  284. {
  285. CMapSolid *pSolid = dynamic_cast<CMapSolid *>(SolidList[nSolid]);
  286. if ( pSolid )
  287. pSolid->SetTexture(GetDefaultTextureName());
  288. }
  289. return pTorus;
  290. }
  291. }
  292. else
  293. {
  294. CPrefab *pPrefab = CPrefab::FindID(_iNewObjIndex);
  295. if (pPrefab != NULL)
  296. {
  297. return(pPrefab->CreateInBox(pBox));
  298. }
  299. }
  300. return NULL;
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Returns the classname of the default entity for the entity creation tool.
  304. //-----------------------------------------------------------------------------
  305. LPCTSTR CObjectBar::GetDefaultEntityClass(void)
  306. {
  307. return _szNewObjName;
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Purpose:
  311. //-----------------------------------------------------------------------------
  312. CMapClass *CObjectBar::BuildPrefabObjectAtPoint( Vector const &HitPos )
  313. {
  314. //
  315. // find prefab
  316. //
  317. CPrefab3D *pPrefab = ( CPrefab3D* )CPrefab::FindID( _iNewObjIndex );
  318. if( !pPrefab )
  319. return NULL;
  320. //
  321. // create prefab bounding box -- centered at hit pos
  322. //
  323. return pPrefab->CreateAtPointAroundOrigin( HitPos );
  324. }
  325. //-----------------------------------------------------------------------------
  326. // Purpose:
  327. //-----------------------------------------------------------------------------
  328. bool CObjectBar::IsEntityToolCreatingPrefab( void )
  329. {
  330. if( ( m_iLastTool == TOOL_ENTITY ) && ( m_CategoryList.GetCurSel() != 0 ) )
  331. return true;
  332. return false;
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose:
  336. //-----------------------------------------------------------------------------
  337. bool CObjectBar::IsEntityToolCreatingEntity( void )
  338. {
  339. if( ( m_iLastTool == TOOL_ENTITY ) && ( m_CategoryList.GetCurSel() == 0 ) )
  340. return true;
  341. return false;
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose:
  345. //-----------------------------------------------------------------------------
  346. void CObjectBar::OnChangeCategory()
  347. {
  348. switch (ListType)
  349. {
  350. case listPrimitives:
  351. {
  352. iBlockSel = -1;
  353. LoadBlockItems();
  354. break;
  355. }
  356. case listPrefabs:
  357. {
  358. if (m_iLastTool == TOOL_BLOCK)
  359. {
  360. iBlockSel = -1;
  361. LoadBlockItems();
  362. }
  363. else if (m_iLastTool == TOOL_ENTITY)
  364. {
  365. iEntitySel = -1;
  366. LoadEntityItems();
  367. }
  368. break;
  369. }
  370. case listEntities:
  371. {
  372. iEntitySel = -1;
  373. LoadEntityItems();
  374. break;
  375. }
  376. default:
  377. {
  378. break;
  379. }
  380. }
  381. DoHideControls();
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Purpose:
  385. // Input : pParentWnd -
  386. // Output : Returns TRUE on success, FALSE on failure.
  387. //-----------------------------------------------------------------------------
  388. BOOL CObjectBar::Create(CWnd *pParentWnd)
  389. {
  390. if (!CHammerBar::Create(pParentWnd, IDD_OBJECTBAR, CBRS_RIGHT, IDCB_OBJECTBAR))
  391. {
  392. return FALSE;
  393. }
  394. SetWindowText("New Objects");
  395. // set up controls
  396. // We only want it to return values that are in our list of suggestions.
  397. m_CreateList.SubclassDlgItem(IDC_CREATELIST, this);
  398. m_CreateList.SetOnlyProvideSuggestions( true );
  399. m_CategoryList.SubclassDlgItem(IDC_CATEGORYLIST, this);
  400. m_Faces.SubclassDlgItem(IDC_FACES, this);
  401. m_FacesSpin.SubclassDlgItem(IDC_FACESSPIN, this);
  402. m_FacesSpin.SetBuddy(&m_Faces);
  403. iBlockSel = -1;
  404. iEntitySel = -1;
  405. m_iLastTool = -1;
  406. LoadBlockCategories();
  407. // outta here
  408. return TRUE;
  409. }
  410. //-----------------------------------------------------------------------------
  411. // Purpose: Load the category list with the list of primitives and object libraries.
  412. //-----------------------------------------------------------------------------
  413. void CObjectBar::LoadBlockCategories( void )
  414. {
  415. m_CategoryList.SetRedraw(FALSE);
  416. // first item is the primitive list
  417. m_CategoryList.ResetContent();
  418. m_CategoryList.AddString("Primitives");
  419. // the next items are the prefab categories (libraries)
  420. LoadPrefabCategories();
  421. // redraw category list
  422. m_CategoryList.SetRedraw(TRUE);
  423. m_CategoryList.Invalidate();
  424. // set initial state
  425. m_CategoryList.SetCurSel( 0 );
  426. }
  427. //-----------------------------------------------------------------------------
  428. // Purpose:
  429. //-----------------------------------------------------------------------------
  430. void CObjectBar::LoadEntityCategories( void )
  431. {
  432. m_CategoryList.SetRedraw( FALSE );
  433. // first item is the primitive list
  434. m_CategoryList.ResetContent();
  435. m_CategoryList.AddString( "Entities" );
  436. // the next items are the prefab categories (libraries)
  437. LoadPrefabCategories();
  438. // redraw category list
  439. m_CategoryList.SetRedraw( TRUE );
  440. m_CategoryList.Invalidate();
  441. // set initial state
  442. m_CategoryList.SetCurSel( 0 );
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Purpose:
  446. //-----------------------------------------------------------------------------
  447. void CObjectBar::LoadPrefabCategories( void )
  448. {
  449. //
  450. // if a long list -- don't update every time
  451. //
  452. m_CategoryList.SetRedraw( FALSE );
  453. //
  454. // add all prefab object libraries to the category list
  455. //
  456. POSITION p = ENUM_START;
  457. CPrefabLibrary *pLibrary = CPrefabLibrary::EnumLibraries( p );
  458. while( pLibrary )
  459. {
  460. int iIndex = m_CategoryList.AddString( pLibrary->GetName() );
  461. m_CategoryList.SetItemData( iIndex, pLibrary->GetID() );
  462. pLibrary = CPrefabLibrary::EnumLibraries( p );
  463. }
  464. m_CategoryList.SetRedraw(TRUE);
  465. m_CategoryList.Invalidate();
  466. }
  467. //-----------------------------------------------------------------------------
  468. // Purpose:
  469. //-----------------------------------------------------------------------------
  470. void CObjectBar::LoadBlockItems( void )
  471. {
  472. //
  473. // verify the block categories are loaded
  474. //
  475. if( m_CategoryList.GetCurSel() == CB_ERR )
  476. {
  477. LoadBlockCategories();
  478. }
  479. //
  480. // load primitive items
  481. //
  482. if( m_CategoryList.GetCurSel() == 0 )
  483. {
  484. // set list type (primitives)
  485. ListType = listPrimitives;
  486. // set list type (primitives)
  487. CUtlVector<CString> suggestions;
  488. for( int i = 0; i < sizeof( SolidTypes ) / sizeof( SolidTypes[0] ); i++)
  489. suggestions.AddToTail( SolidTypes[i].pszName );
  490. m_CreateList.SetSuggestions( suggestions );
  491. }
  492. else
  493. {
  494. LoadPrefabItems();
  495. }
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose:
  499. //-----------------------------------------------------------------------------
  500. void CObjectBar::LoadEntityItems( void )
  501. {
  502. //
  503. // verify the block categories are loaded
  504. //
  505. if( m_CategoryList.GetCurSel() == CB_ERR )
  506. {
  507. LoadEntityCategories();
  508. }
  509. //
  510. // load entity items
  511. //
  512. if( m_CategoryList.GetCurSel() == 0 )
  513. {
  514. // set list type (markers)???
  515. ListType = listEntities;
  516. CUtlVector<CString> suggestions;
  517. extern GameData *pGD;
  518. if( pGD != NULL )
  519. {
  520. int nCount = pGD->GetClassCount();
  521. for (int i = 0; i < nCount; i++)
  522. {
  523. GDclass *pc = pGD->GetClass(i);
  524. if( !pc->IsBaseClass() && !pc->IsSolidClass() )
  525. {
  526. suggestions.AddToTail( pc->GetName() );
  527. }
  528. }
  529. }
  530. m_CreateList.SetSuggestions( suggestions );
  531. }
  532. else
  533. {
  534. LoadPrefabItems();
  535. }
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose:
  539. //-----------------------------------------------------------------------------
  540. void CObjectBar::LoadPrefabItems( void )
  541. {
  542. // set list type (prefabs)
  543. ListType = listPrefabs;
  544. CUtlVector<CString> suggestions;
  545. // get the active library and add the prefabs from it
  546. CPrefabLibrary *pLibrary = CPrefabLibrary::FindID( m_CategoryList.GetItemData(m_CategoryList.GetCurSel() ) );
  547. POSITION p = ENUM_START;
  548. CPrefab *pPrefab = pLibrary->EnumPrefabs( p );
  549. while( pPrefab )
  550. {
  551. suggestions.AddToTail( pPrefab->GetName() );
  552. pPrefab = pLibrary->EnumPrefabs( p );
  553. }
  554. m_CreateList.SetSuggestions( suggestions );
  555. }
  556. //-----------------------------------------------------------------------------
  557. // Purpose:
  558. //-----------------------------------------------------------------------------
  559. void CObjectBar::DoHideControls()
  560. {
  561. // hide controls based on which mode is selected...
  562. if(ListType == listPrimitives)
  563. {
  564. GetDlgItem(ID_INSERTPREFAB_ORIGINAL)->ShowWindow(SW_HIDE);
  565. m_Faces.ShowWindow(SW_SHOW);
  566. m_FacesSpin.ShowWindow(SW_SHOW);
  567. GetDlgItem(IDC_FACESPROMPT)->ShowWindow(SW_SHOW);
  568. }
  569. else if(ListType == listPrefabs)
  570. {
  571. m_Faces.ShowWindow(SW_HIDE);
  572. m_FacesSpin.ShowWindow(SW_HIDE);
  573. GetDlgItem(IDC_FACESPROMPT)->ShowWindow(SW_HIDE);
  574. GetDlgItem(ID_INSERTPREFAB_ORIGINAL)->ShowWindow(SW_SHOW);
  575. }
  576. else if(ListType == listEntities)
  577. {
  578. m_Faces.ShowWindow(SW_HIDE);
  579. m_FacesSpin.ShowWindow(SW_HIDE);
  580. GetDlgItem(IDC_FACESPROMPT)->ShowWindow(SW_HIDE);
  581. GetDlgItem(ID_INSERTPREFAB_ORIGINAL)->ShowWindow(SW_HIDE);
  582. }
  583. // Show the "random yaw" button?
  584. bool bShow = (ListType == listEntities);
  585. GetDlgItem( IDC_RANDOMYAW )->ShowWindow( bShow ? SW_SHOW : SW_HIDE );
  586. }
  587. //-----------------------------------------------------------------------------
  588. // Purpose:
  589. // Input : *pCmdUI -
  590. //-----------------------------------------------------------------------------
  591. void CObjectBar::UpdateControl(CCmdUI *pCmdUI)
  592. {
  593. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  594. switch (pCmdUI->m_nID)
  595. {
  596. case ID_INSERTPREFAB_ORIGINAL:
  597. {
  598. pCmdUI->Enable(ListType == listPrefabs);
  599. break;
  600. }
  601. case IDC_CREATELIST:
  602. case IDC_CATEGORYLIST:
  603. {
  604. BOOL bEnable = FALSE;
  605. if (pDoc)
  606. {
  607. int nTool = pDoc->GetTools()->GetActiveToolID();
  608. if ((nTool == TOOL_ENTITY) || (nTool == TOOL_BLOCK))
  609. {
  610. bEnable = TRUE;
  611. }
  612. }
  613. pCmdUI->Enable(bEnable);
  614. break;
  615. }
  616. default:
  617. {
  618. pCmdUI->Enable( pDoc ? TRUE : FALSE);
  619. break;
  620. }
  621. }
  622. }
  623. //-----------------------------------------------------------------------------
  624. // Purpose:
  625. // Input : *pWnd -
  626. // bModifyWnd -
  627. // Output : Returns TRUE on success, FALSE on failure.
  628. //-----------------------------------------------------------------------------
  629. BOOL CObjectBar::EnableFaceControl(CWnd *pWnd, BOOL bModifyWnd)
  630. {
  631. BOOL bEnable = CMapDoc::GetActiveMapDoc() ? TRUE : FALSE;
  632. if(bEnable)
  633. {
  634. bEnable = FALSE;
  635. //
  636. // Enable the control only if we are dealing with an object the
  637. // that has adjustable faces.
  638. //
  639. if (ListType == listPrimitives)
  640. {
  641. int nSolidIndex = iBlockSel;
  642. if (SolidTypes[nSolidIndex].bEnableFaceControl)
  643. {
  644. bEnable = TRUE;
  645. }
  646. }
  647. }
  648. if(bModifyWnd)
  649. pWnd->EnableWindow(bEnable);
  650. return bEnable;
  651. }
  652. //-----------------------------------------------------------------------------
  653. // Purpose:
  654. // Input : *pCmdUI -
  655. //-----------------------------------------------------------------------------
  656. void CObjectBar::UpdateFaceControl(CCmdUI *pCmdUI)
  657. {
  658. pCmdUI->Enable(EnableFaceControl(GetDlgItem(pCmdUI->m_nID), FALSE));
  659. }
  660. //-----------------------------------------------------------------------------
  661. // Purpose: Called when a new item has been selected in the combo box.
  662. //-----------------------------------------------------------------------------
  663. void CObjectBar::OnTextChanged( const char *pSelection )
  664. {
  665. char szBuf[128];
  666. switch (ListType)
  667. {
  668. case listPrimitives:
  669. {
  670. _iNewObjIndex = FindSolidType( pSelection );
  671. Assert( _iNewObjIndex != -1 );
  672. //
  673. // Save current value from the faces edit control. The next time this primitive is
  674. // selected the value will be restored.
  675. //
  676. if (iBlockSel != -1)
  677. {
  678. int nSolidIndex = iBlockSel;
  679. m_Faces.GetWindowText(szBuf, 128);
  680. SolidTypes[nSolidIndex].nFaces = atoi(szBuf);
  681. }
  682. iBlockSel = _iNewObjIndex;
  683. break;
  684. }
  685. case listPrefabs:
  686. {
  687. CPrefab *pPrefab = FindPrefabByName( pSelection );
  688. Assert( pPrefab );
  689. if ( pPrefab )
  690. {
  691. _iNewObjIndex = pPrefab->GetID();
  692. if (m_iLastTool == TOOL_BLOCK )
  693. {
  694. iBlockSel = _iNewObjIndex;
  695. }
  696. else if( m_iLastTool == TOOL_ENTITY )
  697. {
  698. iEntitySel = _iNewObjIndex;
  699. }
  700. }
  701. break;
  702. }
  703. case listEntities:
  704. {
  705. _iNewObjIndex = FindGameDataClass( pSelection );
  706. Assert( _iNewObjIndex != -1 );
  707. if ( _iNewObjIndex != -1 )
  708. {
  709. Q_strncpy( _szNewObjName, pSelection, sizeof( _szNewObjName ) );
  710. }
  711. break;
  712. }
  713. }
  714. if (ListType != listPrimitives)
  715. return;
  716. EnableFaceControl(&m_Faces, TRUE);
  717. EnableFaceControl(&m_FacesSpin, TRUE);
  718. int nSolidIndex = _iNewObjIndex;
  719. m_FacesSpin.SetRange(SolidTypes[nSolidIndex].nFacesMin, SolidTypes[nSolidIndex].nFacesMax);
  720. m_FacesSpin.SetPos(SolidTypes[nSolidIndex].nFaces);
  721. itoa(SolidTypes[nSolidIndex].nFaces, szBuf, 10);
  722. m_Faces.SetWindowText(szBuf);
  723. }
  724. //-----------------------------------------------------------------------------
  725. // Purpose:
  726. // Input : dwGameID -
  727. // piNewIndex -
  728. // Output :
  729. //-----------------------------------------------------------------------------
  730. int CObjectBar::GetPrevSelIndex(DWORD dwGameID, int *piNewIndex)
  731. {
  732. for(int i = 0; i < MAX_PREV_SEL; i++)
  733. {
  734. if(m_PrevSel[i].dwGameID == 0 && piNewIndex)
  735. *piNewIndex = i;
  736. if(m_PrevSel[i].dwGameID == dwGameID)
  737. return i;
  738. }
  739. return -1;
  740. }
  741. //-----------------------------------------------------------------------------
  742. // Purpose:
  743. // Input : pMsg -
  744. // Output : Returns TRUE on success, FALSE on failure.
  745. //-----------------------------------------------------------------------------
  746. BOOL CObjectBar::PreTranslateMessage(MSG* pMsg)
  747. {
  748. //
  749. // See if the message is a keydown and the current focus window is the
  750. // ComboBox in the ObjectBar!
  751. //
  752. /*static BOOL bRecurse = FALSE;
  753. if (pMsg->message == WM_KEYDOWN && !bRecurse)
  754. {
  755. if (GetFocus() == &m_CreateList)
  756. {
  757. //AfxMessageBox("Ok");
  758. bRecurse = TRUE;
  759. m_CreateList.SendMessage(WM_CHAR, pMsg->wParam, pMsg->lParam);
  760. bRecurse = FALSE;
  761. return TRUE;
  762. }
  763. }
  764. */
  765. return CHammerBar::PreTranslateMessage(pMsg);
  766. }
  767. //-----------------------------------------------------------------------------
  768. // Purpose:
  769. // Input : iTool -
  770. //-----------------------------------------------------------------------------
  771. void CObjectBar::UpdateListForTool( int iTool )
  772. {
  773. //
  774. // initialize for new "game config"
  775. //
  776. int iPrevSel = 0;
  777. if (m_dwPrevGameID != g_pGameConfig->dwID)
  778. {
  779. //
  780. // save current game id and save
  781. //
  782. m_dwPrevGameID = g_pGameConfig->dwID;
  783. GetPrevSelIndex( g_pGameConfig->dwID, &iPrevSel );
  784. m_PrevSel[iPrevSel].dwGameID = g_pGameConfig->dwID;
  785. m_PrevSel[iPrevSel].block.strCategory = "Primitives";
  786. m_PrevSel[iPrevSel].block.strItem = "block";
  787. m_PrevSel[iPrevSel].entity.strCategory = "Entities";
  788. m_PrevSel[iPrevSel].entity.strItem = g_pGameConfig->szDefaultPoint;
  789. }
  790. // get game id previously selected data index
  791. iPrevSel = GetPrevSelIndex( m_dwPrevGameID );
  792. if (iPrevSel == -1)
  793. return;
  794. //
  795. // Save last known selection state for previous tool
  796. //
  797. if (m_iLastTool == TOOL_BLOCK)
  798. {
  799. int iCategory = m_CategoryList.GetCurSel();
  800. if( iCategory != -1 )
  801. {
  802. m_CategoryList.GetLBText( iCategory, m_PrevSel[iPrevSel].block.strCategory );
  803. m_PrevSel[iPrevSel].block.strItem = m_CreateList.GetCurrentItem();
  804. }
  805. else
  806. {
  807. m_PrevSel[iPrevSel].block.strCategory = "";
  808. m_PrevSel[iPrevSel].block.strItem = "";
  809. }
  810. }
  811. else if (m_iLastTool == TOOL_ENTITY)
  812. {
  813. int iCategory = m_CategoryList.GetCurSel();
  814. if( iCategory != -1 )
  815. {
  816. m_CategoryList.GetLBText( iCategory, m_PrevSel[iPrevSel].entity.strCategory );
  817. m_PrevSel[iPrevSel].entity.strItem = m_CreateList.GetCurrentItem();
  818. }
  819. else
  820. {
  821. m_PrevSel[iPrevSel].entity.strCategory = "";
  822. m_PrevSel[iPrevSel].entity.strItem = "";
  823. }
  824. }
  825. // save tool for next pass
  826. m_iLastTool = iTool;
  827. //
  828. // update new for new tool
  829. //
  830. if (iTool == TOOL_BLOCK)
  831. {
  832. //
  833. // load block categories and items
  834. //
  835. LoadBlockCategories();
  836. m_CategoryList.SelectString( -1, m_PrevSel[iPrevSel].block.strCategory );
  837. LoadBlockItems();
  838. m_CreateList.SelectItem( m_PrevSel[iPrevSel].block.strItem );
  839. OnTextChanged( m_PrevSel[iPrevSel].block.strItem );
  840. iBlockSel = FindSolidType( m_PrevSel[iPrevSel].block.strItem );
  841. Assert( iBlockSel >= 0 );
  842. // hide/show appropriate controls
  843. DoHideControls();
  844. //
  845. // enable/disable face controls
  846. //
  847. EnableFaceControl( &m_Faces, TRUE );
  848. EnableFaceControl( &m_FacesSpin, TRUE );
  849. }
  850. else if (iTool == TOOL_ENTITY)
  851. {
  852. //
  853. // load entity categories and items
  854. //
  855. LoadEntityCategories();
  856. m_CategoryList.SelectString( -1, m_PrevSel[iPrevSel].entity.strCategory );
  857. LoadEntityItems();
  858. m_CreateList.SelectItem( m_PrevSel[iPrevSel].entity.strItem );
  859. OnTextChanged( m_PrevSel[iPrevSel].entity.strItem );
  860. iEntitySel = FindGameDataClass( m_PrevSel[iPrevSel].entity.strItem );
  861. // hide/show appropriate controls
  862. DoHideControls();
  863. //
  864. // enable/disable face controls
  865. //
  866. EnableFaceControl( &m_Faces, TRUE );
  867. EnableFaceControl( &m_FacesSpin, TRUE );
  868. }
  869. else
  870. {
  871. m_CategoryList.ResetContent();
  872. m_CreateList.Clear();
  873. DoHideControls();
  874. }
  875. }