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.

1043 lines
25 KiB

  1. //========= Copyright � 1996-2005, 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. CMapClass *pMapClass = (CUtlReference< CMapClass >)SolidList[nSolid];
  263. CMapSolid *pSolid = dynamic_cast<CMapSolid *>(pMapClass);
  264. if ( pSolid )
  265. pSolid->SetTexture(GetDefaultTextureName());
  266. }
  267. return pArch;
  268. }
  269. else
  270. {
  271. // Torus
  272. CTorusDlg dlg( pBox->bmins, pBox->bmaxs );
  273. Vector sizebounds;
  274. pBox->GetBoundsSize( sizebounds );
  275. dlg.SetMaxWallWidth(min((int)sizebounds[axHorz], (int)sizebounds[axVert]));
  276. if(dlg.DoModal() != IDOK)
  277. return NULL;
  278. // save values for next use of arch
  279. dlg.SaveValues();
  280. CMapClass *pTorus = CreateTorus(pBox, dlg.m_fAngle, dlg.m_iSides, dlg.m_fArc, dlg.m_iWallWidth,
  281. dlg.GetTorusCrossSectionRadius(),
  282. dlg.m_fRotationAngle, dlg.m_iRotationSides, dlg.m_fRotationArc, dlg.m_iAddHeight, FALSE);
  283. const CMapObjectList &SolidList = *pTorus->GetChildren();
  284. FOR_EACH_OBJ( SolidList, nSolid )
  285. {
  286. CMapClass *pMapClass = (CUtlReference< CMapClass >)SolidList[nSolid];
  287. CMapSolid *pSolid = dynamic_cast<CMapSolid *>( pMapClass );
  288. if ( pSolid )
  289. pSolid->SetTexture(GetDefaultTextureName());
  290. }
  291. return pTorus;
  292. }
  293. }
  294. else
  295. {
  296. CPrefab *pPrefab = CPrefab::FindID(_iNewObjIndex);
  297. if (pPrefab != NULL)
  298. {
  299. return(pPrefab->CreateInBox(pBox));
  300. }
  301. }
  302. return NULL;
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Purpose: Returns the classname of the default entity for the entity creation tool.
  306. //-----------------------------------------------------------------------------
  307. LPCTSTR CObjectBar::GetDefaultEntityClass(void)
  308. {
  309. return _szNewObjName;
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Purpose:
  313. //-----------------------------------------------------------------------------
  314. CMapClass *CObjectBar::BuildPrefabObjectAtPoint( Vector const &HitPos )
  315. {
  316. //
  317. // find prefab
  318. //
  319. CPrefab3D *pPrefab = ( CPrefab3D* )CPrefab::FindID( _iNewObjIndex );
  320. if( !pPrefab )
  321. return NULL;
  322. //
  323. // create prefab bounding box -- centered at hit pos
  324. //
  325. return pPrefab->CreateAtPointAroundOrigin( HitPos );
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Purpose:
  329. //-----------------------------------------------------------------------------
  330. bool CObjectBar::IsEntityToolCreatingPrefab( void )
  331. {
  332. if( ( m_iLastTool == TOOL_ENTITY ) && ( m_CategoryList.GetCurSel() != 0 ) )
  333. return true;
  334. return false;
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Purpose:
  338. //-----------------------------------------------------------------------------
  339. bool CObjectBar::IsEntityToolCreatingEntity( void )
  340. {
  341. if( ( m_iLastTool == TOOL_ENTITY ) && ( m_CategoryList.GetCurSel() == 0 ) )
  342. return true;
  343. return false;
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Purpose:
  347. //-----------------------------------------------------------------------------
  348. void CObjectBar::OnChangeCategory()
  349. {
  350. switch (ListType)
  351. {
  352. case listPrimitives:
  353. {
  354. iBlockSel = -1;
  355. LoadBlockItems();
  356. break;
  357. }
  358. case listPrefabs:
  359. {
  360. if (m_iLastTool == TOOL_BLOCK)
  361. {
  362. iBlockSel = -1;
  363. LoadBlockItems();
  364. }
  365. else if (m_iLastTool == TOOL_ENTITY)
  366. {
  367. iEntitySel = -1;
  368. LoadEntityItems();
  369. }
  370. break;
  371. }
  372. case listEntities:
  373. {
  374. iEntitySel = -1;
  375. LoadEntityItems();
  376. break;
  377. }
  378. default:
  379. {
  380. break;
  381. }
  382. }
  383. DoHideControls();
  384. }
  385. //-----------------------------------------------------------------------------
  386. // Purpose:
  387. // Input : pParentWnd -
  388. // Output : Returns TRUE on success, FALSE on failure.
  389. //-----------------------------------------------------------------------------
  390. BOOL CObjectBar::Create(CWnd *pParentWnd)
  391. {
  392. if (!CHammerBar::Create(pParentWnd, IDD_OBJECTBAR, CBRS_RIGHT, IDCB_OBJECTBAR))
  393. {
  394. return FALSE;
  395. }
  396. SetWindowText("New Objects");
  397. // set up controls
  398. // We only want it to return values that are in our list of suggestions.
  399. m_CreateList.SubclassDlgItem(IDC_CREATELIST, this);
  400. m_CreateList.SetOnlyProvideSuggestions( true );
  401. m_CategoryList.SubclassDlgItem(IDC_CATEGORYLIST, this);
  402. m_Faces.SubclassDlgItem(IDC_FACES, this);
  403. m_FacesSpin.SubclassDlgItem(IDC_FACESSPIN, this);
  404. m_FacesSpin.SetBuddy(&m_Faces);
  405. iBlockSel = -1;
  406. iEntitySel = -1;
  407. m_iLastTool = -1;
  408. LoadBlockCategories();
  409. // outta here
  410. return TRUE;
  411. }
  412. //-----------------------------------------------------------------------------
  413. // Purpose: Load the category list with the list of primitives and object libraries.
  414. //-----------------------------------------------------------------------------
  415. void CObjectBar::LoadBlockCategories( void )
  416. {
  417. m_CategoryList.SetRedraw(FALSE);
  418. // first item is the primitive list
  419. m_CategoryList.ResetContent();
  420. m_CategoryList.AddString("Primitives");
  421. // the next items are the prefab categories (libraries)
  422. LoadPrefabCategories();
  423. // redraw category list
  424. m_CategoryList.SetRedraw(TRUE);
  425. m_CategoryList.Invalidate();
  426. // set initial state
  427. m_CategoryList.SetCurSel( 0 );
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose:
  431. //-----------------------------------------------------------------------------
  432. void CObjectBar::LoadEntityCategories( void )
  433. {
  434. m_CategoryList.SetRedraw( FALSE );
  435. // first item is the primitive list
  436. m_CategoryList.ResetContent();
  437. m_CategoryList.AddString( "Entities" );
  438. // the next items are the prefab categories (libraries)
  439. LoadPrefabCategories();
  440. // redraw category list
  441. m_CategoryList.SetRedraw( TRUE );
  442. m_CategoryList.Invalidate();
  443. // set initial state
  444. m_CategoryList.SetCurSel( 0 );
  445. }
  446. //-----------------------------------------------------------------------------
  447. // Purpose:
  448. //-----------------------------------------------------------------------------
  449. void CObjectBar::LoadPrefabCategories( void )
  450. {
  451. //
  452. // if a long list -- don't update every time
  453. //
  454. m_CategoryList.SetRedraw( FALSE );
  455. //
  456. // add all prefab object libraries to the category list
  457. //
  458. POSITION p = ENUM_START;
  459. CPrefabLibrary *pLibrary = CPrefabLibrary::EnumLibraries( p );
  460. while( pLibrary )
  461. {
  462. int iIndex = m_CategoryList.AddString( pLibrary->GetName() );
  463. m_CategoryList.SetItemData( iIndex, pLibrary->GetID() );
  464. pLibrary = CPrefabLibrary::EnumLibraries( p );
  465. }
  466. m_CategoryList.SetRedraw(TRUE);
  467. m_CategoryList.Invalidate();
  468. }
  469. //-----------------------------------------------------------------------------
  470. // Purpose:
  471. //-----------------------------------------------------------------------------
  472. void CObjectBar::LoadBlockItems( void )
  473. {
  474. //
  475. // verify the block categories are loaded
  476. //
  477. if( m_CategoryList.GetCurSel() == CB_ERR )
  478. {
  479. LoadBlockCategories();
  480. }
  481. //
  482. // load primitive items
  483. //
  484. if( m_CategoryList.GetCurSel() == 0 )
  485. {
  486. // set list type (primitives)
  487. ListType = listPrimitives;
  488. // set list type (primitives)
  489. CUtlVector<CString> suggestions;
  490. for( int i = 0; i < sizeof( SolidTypes ) / sizeof( SolidTypes[0] ); i++)
  491. suggestions.AddToTail( SolidTypes[i].pszName );
  492. m_CreateList.SetSuggestions( suggestions );
  493. }
  494. else
  495. {
  496. LoadPrefabItems();
  497. }
  498. }
  499. //-----------------------------------------------------------------------------
  500. // Purpose:
  501. //-----------------------------------------------------------------------------
  502. void CObjectBar::LoadEntityItems( void )
  503. {
  504. //
  505. // verify the block categories are loaded
  506. //
  507. if( m_CategoryList.GetCurSel() == CB_ERR )
  508. {
  509. LoadEntityCategories();
  510. }
  511. //
  512. // load entity items
  513. //
  514. if( m_CategoryList.GetCurSel() == 0 )
  515. {
  516. // set list type (markers)???
  517. ListType = listEntities;
  518. CUtlVector<CString> suggestions;
  519. extern GameData *pGD;
  520. if( pGD != NULL )
  521. {
  522. int nCount = pGD->GetClassCount();
  523. for (int i = 0; i < nCount; i++)
  524. {
  525. GDclass *pc = pGD->GetClass(i);
  526. if( !pc->IsBaseClass() && !pc->IsSolidClass() )
  527. {
  528. suggestions.AddToTail( pc->GetName() );
  529. }
  530. }
  531. }
  532. m_CreateList.SetSuggestions( suggestions );
  533. }
  534. else
  535. {
  536. LoadPrefabItems();
  537. }
  538. }
  539. //-----------------------------------------------------------------------------
  540. // Purpose:
  541. //-----------------------------------------------------------------------------
  542. void CObjectBar::LoadPrefabItems( void )
  543. {
  544. // set list type (prefabs)
  545. ListType = listPrefabs;
  546. CUtlVector<CString> suggestions;
  547. // get the active library and add the prefabs from it
  548. CPrefabLibrary *pLibrary = CPrefabLibrary::FindID( m_CategoryList.GetItemData(m_CategoryList.GetCurSel() ) );
  549. POSITION p = ENUM_START;
  550. CPrefab *pPrefab = pLibrary->EnumPrefabs( p );
  551. while( pPrefab )
  552. {
  553. suggestions.AddToTail( pPrefab->GetName() );
  554. pPrefab = pLibrary->EnumPrefabs( p );
  555. }
  556. m_CreateList.SetSuggestions( suggestions );
  557. }
  558. //-----------------------------------------------------------------------------
  559. // Purpose:
  560. //-----------------------------------------------------------------------------
  561. void CObjectBar::DoHideControls()
  562. {
  563. // hide controls based on which mode is selected...
  564. if(ListType == listPrimitives)
  565. {
  566. GetDlgItem(ID_INSERTPREFAB_ORIGINAL)->ShowWindow(SW_HIDE);
  567. m_Faces.ShowWindow(SW_SHOW);
  568. m_FacesSpin.ShowWindow(SW_SHOW);
  569. GetDlgItem(IDC_FACESPROMPT)->ShowWindow(SW_SHOW);
  570. }
  571. else if(ListType == listPrefabs)
  572. {
  573. m_Faces.ShowWindow(SW_HIDE);
  574. m_FacesSpin.ShowWindow(SW_HIDE);
  575. GetDlgItem(IDC_FACESPROMPT)->ShowWindow(SW_HIDE);
  576. GetDlgItem(ID_INSERTPREFAB_ORIGINAL)->ShowWindow(SW_SHOW);
  577. }
  578. else if(ListType == listEntities)
  579. {
  580. m_Faces.ShowWindow(SW_HIDE);
  581. m_FacesSpin.ShowWindow(SW_HIDE);
  582. GetDlgItem(IDC_FACESPROMPT)->ShowWindow(SW_HIDE);
  583. GetDlgItem(ID_INSERTPREFAB_ORIGINAL)->ShowWindow(SW_HIDE);
  584. }
  585. // Show the "random yaw" button?
  586. bool bShow = (ListType == listEntities);
  587. GetDlgItem( IDC_RANDOMYAW )->ShowWindow( bShow ? SW_SHOW : SW_HIDE );
  588. }
  589. //-----------------------------------------------------------------------------
  590. // Purpose:
  591. // Input : *pCmdUI -
  592. //-----------------------------------------------------------------------------
  593. void CObjectBar::UpdateControl(CCmdUI *pCmdUI)
  594. {
  595. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  596. switch (pCmdUI->m_nID)
  597. {
  598. case ID_INSERTPREFAB_ORIGINAL:
  599. {
  600. pCmdUI->Enable(ListType == listPrefabs);
  601. break;
  602. }
  603. case IDC_CREATELIST:
  604. case IDC_CATEGORYLIST:
  605. {
  606. BOOL bEnable = FALSE;
  607. if (pDoc)
  608. {
  609. int nTool = pDoc->GetTools()->GetActiveToolID();
  610. if ((nTool == TOOL_ENTITY) || (nTool == TOOL_BLOCK))
  611. {
  612. bEnable = TRUE;
  613. }
  614. }
  615. pCmdUI->Enable(bEnable);
  616. break;
  617. }
  618. default:
  619. {
  620. pCmdUI->Enable( pDoc ? TRUE : FALSE);
  621. break;
  622. }
  623. }
  624. }
  625. //-----------------------------------------------------------------------------
  626. // Purpose:
  627. // Input : *pWnd -
  628. // bModifyWnd -
  629. // Output : Returns TRUE on success, FALSE on failure.
  630. //-----------------------------------------------------------------------------
  631. BOOL CObjectBar::EnableFaceControl(CWnd *pWnd, BOOL bModifyWnd)
  632. {
  633. BOOL bEnable = CMapDoc::GetActiveMapDoc() ? TRUE : FALSE;
  634. if(bEnable)
  635. {
  636. bEnable = FALSE;
  637. //
  638. // Enable the control only if we are dealing with an object the
  639. // that has adjustable faces.
  640. //
  641. if (ListType == listPrimitives)
  642. {
  643. int nSolidIndex = iBlockSel;
  644. if (SolidTypes[nSolidIndex].bEnableFaceControl)
  645. {
  646. bEnable = TRUE;
  647. }
  648. }
  649. }
  650. if(bModifyWnd)
  651. pWnd->EnableWindow(bEnable);
  652. return bEnable;
  653. }
  654. //-----------------------------------------------------------------------------
  655. // Purpose:
  656. // Input : *pCmdUI -
  657. //-----------------------------------------------------------------------------
  658. void CObjectBar::UpdateFaceControl(CCmdUI *pCmdUI)
  659. {
  660. pCmdUI->Enable(EnableFaceControl(GetDlgItem(pCmdUI->m_nID), FALSE));
  661. }
  662. //-----------------------------------------------------------------------------
  663. // Purpose: Called when a new item has been selected in the combo box.
  664. //-----------------------------------------------------------------------------
  665. void CObjectBar::OnTextChanged( const char *pSelection )
  666. {
  667. char szBuf[128];
  668. switch (ListType)
  669. {
  670. case listPrimitives:
  671. {
  672. _iNewObjIndex = FindSolidType( pSelection );
  673. Assert( _iNewObjIndex != -1 );
  674. //
  675. // Save current value from the faces edit control. The next time this primitive is
  676. // selected the value will be restored.
  677. //
  678. if (iBlockSel != -1)
  679. {
  680. int nSolidIndex = iBlockSel;
  681. m_Faces.GetWindowText(szBuf, 128);
  682. SolidTypes[nSolidIndex].nFaces = atoi(szBuf);
  683. }
  684. iBlockSel = _iNewObjIndex;
  685. break;
  686. }
  687. case listPrefabs:
  688. {
  689. CPrefab *pPrefab = FindPrefabByName( pSelection );
  690. Assert( pPrefab );
  691. if ( pPrefab )
  692. {
  693. _iNewObjIndex = pPrefab->GetID();
  694. if (m_iLastTool == TOOL_BLOCK )
  695. {
  696. iBlockSel = _iNewObjIndex;
  697. }
  698. else if( m_iLastTool == TOOL_ENTITY )
  699. {
  700. iEntitySel = _iNewObjIndex;
  701. }
  702. }
  703. break;
  704. }
  705. case listEntities:
  706. {
  707. _iNewObjIndex = FindGameDataClass( pSelection );
  708. Assert( _iNewObjIndex != -1 );
  709. if ( _iNewObjIndex != -1 )
  710. {
  711. Q_strncpy( _szNewObjName, pSelection, sizeof( _szNewObjName ) );
  712. }
  713. break;
  714. }
  715. }
  716. if (ListType != listPrimitives)
  717. return;
  718. EnableFaceControl(&m_Faces, TRUE);
  719. EnableFaceControl(&m_FacesSpin, TRUE);
  720. int nSolidIndex = _iNewObjIndex;
  721. m_FacesSpin.SetRange(SolidTypes[nSolidIndex].nFacesMin, SolidTypes[nSolidIndex].nFacesMax);
  722. m_FacesSpin.SetPos(SolidTypes[nSolidIndex].nFaces);
  723. itoa(SolidTypes[nSolidIndex].nFaces, szBuf, 10);
  724. m_Faces.SetWindowText(szBuf);
  725. }
  726. //-----------------------------------------------------------------------------
  727. // Purpose:
  728. // Input : dwGameID -
  729. // piNewIndex -
  730. // Output :
  731. //-----------------------------------------------------------------------------
  732. int CObjectBar::GetPrevSelIndex(DWORD dwGameID, int *piNewIndex)
  733. {
  734. for(int i = 0; i < MAX_PREV_SEL; i++)
  735. {
  736. if(m_PrevSel[i].dwGameID == 0 && piNewIndex)
  737. *piNewIndex = i;
  738. if(m_PrevSel[i].dwGameID == dwGameID)
  739. return i;
  740. }
  741. return -1;
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose:
  745. // Input : pMsg -
  746. // Output : Returns TRUE on success, FALSE on failure.
  747. //-----------------------------------------------------------------------------
  748. BOOL CObjectBar::PreTranslateMessage(MSG* pMsg)
  749. {
  750. //
  751. // See if the message is a keydown and the current focus window is the
  752. // ComboBox in the ObjectBar!
  753. //
  754. /*static BOOL bRecurse = FALSE;
  755. if (pMsg->message == WM_KEYDOWN && !bRecurse)
  756. {
  757. if (GetFocus() == &m_CreateList)
  758. {
  759. //AfxMessageBox("Ok");
  760. bRecurse = TRUE;
  761. m_CreateList.SendMessage(WM_CHAR, pMsg->wParam, pMsg->lParam);
  762. bRecurse = FALSE;
  763. return TRUE;
  764. }
  765. }
  766. */
  767. return CHammerBar::PreTranslateMessage(pMsg);
  768. }
  769. //-----------------------------------------------------------------------------
  770. // Purpose:
  771. // Input : iTool -
  772. //-----------------------------------------------------------------------------
  773. void CObjectBar::UpdateListForTool( int iTool )
  774. {
  775. //
  776. // initialize for new "game config"
  777. //
  778. int iPrevSel = 0;
  779. if (m_dwPrevGameID != g_pGameConfig->dwID)
  780. {
  781. //
  782. // save current game id and save
  783. //
  784. m_dwPrevGameID = g_pGameConfig->dwID;
  785. GetPrevSelIndex( g_pGameConfig->dwID, &iPrevSel );
  786. m_PrevSel[iPrevSel].dwGameID = g_pGameConfig->dwID;
  787. m_PrevSel[iPrevSel].block.strCategory = "Primitives";
  788. m_PrevSel[iPrevSel].block.strItem = "block";
  789. m_PrevSel[iPrevSel].entity.strCategory = "Entities";
  790. m_PrevSel[iPrevSel].entity.strItem = g_pGameConfig->szDefaultPoint;
  791. }
  792. // get game id previously selected data index
  793. iPrevSel = GetPrevSelIndex( m_dwPrevGameID );
  794. if (iPrevSel == -1)
  795. return;
  796. //
  797. // Save last known selection state for previous tool
  798. //
  799. if (m_iLastTool == TOOL_BLOCK)
  800. {
  801. int iCategory = m_CategoryList.GetCurSel();
  802. if( iCategory != -1 )
  803. {
  804. m_CategoryList.GetLBText( iCategory, m_PrevSel[iPrevSel].block.strCategory );
  805. m_PrevSel[iPrevSel].block.strItem = m_CreateList.GetCurrentItem();
  806. }
  807. else
  808. {
  809. m_PrevSel[iPrevSel].block.strCategory = "";
  810. m_PrevSel[iPrevSel].block.strItem = "";
  811. }
  812. }
  813. else if (m_iLastTool == TOOL_ENTITY)
  814. {
  815. int iCategory = m_CategoryList.GetCurSel();
  816. if( iCategory != -1 )
  817. {
  818. m_CategoryList.GetLBText( iCategory, m_PrevSel[iPrevSel].entity.strCategory );
  819. m_PrevSel[iPrevSel].entity.strItem = m_CreateList.GetCurrentItem();
  820. }
  821. else
  822. {
  823. m_PrevSel[iPrevSel].entity.strCategory = "";
  824. m_PrevSel[iPrevSel].entity.strItem = "";
  825. }
  826. }
  827. // save tool for next pass
  828. m_iLastTool = iTool;
  829. //
  830. // update new for new tool
  831. //
  832. if (iTool == TOOL_BLOCK)
  833. {
  834. //
  835. // load block categories and items
  836. //
  837. LoadBlockCategories();
  838. m_CategoryList.SelectString( -1, m_PrevSel[iPrevSel].block.strCategory );
  839. LoadBlockItems();
  840. m_CreateList.SelectItem( m_PrevSel[iPrevSel].block.strItem );
  841. OnTextChanged( m_PrevSel[iPrevSel].block.strItem );
  842. iBlockSel = FindSolidType( m_PrevSel[iPrevSel].block.strItem );
  843. Assert( iBlockSel >= 0 );
  844. // hide/show appropriate controls
  845. DoHideControls();
  846. //
  847. // enable/disable face controls
  848. //
  849. EnableFaceControl( &m_Faces, TRUE );
  850. EnableFaceControl( &m_FacesSpin, TRUE );
  851. }
  852. else if (iTool == TOOL_ENTITY)
  853. {
  854. //
  855. // load entity categories and items
  856. //
  857. LoadEntityCategories();
  858. m_CategoryList.SelectString( -1, m_PrevSel[iPrevSel].entity.strCategory );
  859. LoadEntityItems();
  860. m_CreateList.SelectItem( m_PrevSel[iPrevSel].entity.strItem );
  861. OnTextChanged( m_PrevSel[iPrevSel].entity.strItem );
  862. iEntitySel = FindGameDataClass( m_PrevSel[iPrevSel].entity.strItem );
  863. // hide/show appropriate controls
  864. DoHideControls();
  865. //
  866. // enable/disable face controls
  867. //
  868. EnableFaceControl( &m_Faces, TRUE );
  869. EnableFaceControl( &m_FacesSpin, TRUE );
  870. }
  871. else
  872. {
  873. m_CategoryList.ResetContent();
  874. m_CreateList.Clear();
  875. DoHideControls();
  876. }
  877. }