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.

1179 lines
27 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "Box3D.h"
  9. #include "GlobalFunctions.h"
  10. #include "MainFrm.h" // dvs: hack for tools migration code
  11. #include "MapDoc.h"
  12. #include "MapView2D.h"
  13. #include "Options.h"
  14. #include "Render2D.h"
  15. #include "Render3D.h"
  16. #include "RenderUtils.h"
  17. #include "resource.h"
  18. #include "StatusBarIDs.h"
  19. #include "hammer_mathlib.h"
  20. #include "vgui/Cursor.h"
  21. #include "HammerVGui.h"
  22. #include <VGuiMatSurface/IMatSystemSurface.h>
  23. #include "camera.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include <tier0/memdbgon.h>
  26. #pragma warning(disable:4244)
  27. extern float g_MAX_MAP_COORD; // dvs: move these into Globals.h!!
  28. extern float g_MIN_MAP_COORD; // dvs: move these into Globals.h!!
  29. WorldUnits_t Box3D::m_eWorldUnits = Units_None;
  30. //-----------------------------------------------------------------------------
  31. // Purpose:
  32. //-----------------------------------------------------------------------------
  33. Box3D::Box3D(void)
  34. {
  35. SetEmpty();
  36. SetDrawFlags(0);
  37. m_TranslateMode = modeScale;
  38. m_vTranslationFixPoint.Init();
  39. m_TranslateHandle.Init();
  40. m_bEnableHandles = true;
  41. SetDrawColors(Options.colors.clrToolHandle, Options.colors.clrToolBlock);
  42. }
  43. void Box3D::SetEmpty()
  44. {
  45. Tool3D::SetEmpty();
  46. ResetBounds();
  47. if ( m_pDocument )
  48. {
  49. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  50. }
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. // Input : pView -
  55. // pt - Point in client coordinates.
  56. // bValidOnly -
  57. // Output :
  58. //-----------------------------------------------------------------------------
  59. int Box3D::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles)
  60. {
  61. bool bHit = false;
  62. if ( pView->HitTest( ptClient, bmins, bmaxs ) )
  63. {
  64. // The point is inside the main rect.
  65. m_LastHitTestHandle.Init();
  66. bHit = true;
  67. }
  68. if ( !m_bEnableHandles || !bTestHandles )
  69. {
  70. // Handles are turned off, so we don't need to do any more testing.
  71. // Return whether we hit the main rect or not.
  72. return bHit;
  73. }
  74. // check if we hit a handle
  75. Vector handles[3*3*3];
  76. int numHandles = GetVisibleHandles( handles, pView, m_TranslateMode );
  77. Vector vOffset(HANDLE_OFFSET,HANDLE_OFFSET,HANDLE_OFFSET);
  78. if ( pView->IsOrthographic() )
  79. {
  80. vOffset /= pView->GetCamera()->GetZoom();
  81. }
  82. else
  83. {
  84. vOffset.Init();
  85. }
  86. Vector vCenter = (bmins+bmaxs)/2;
  87. Vector vDelta = (bmaxs + vOffset) - vCenter;
  88. for ( int i = 0; i<numHandles; i++ )
  89. {
  90. Vector pos = vCenter + vDelta * handles[i];
  91. if ( HitRect( pView, ptClient, pos, HANDLE_RADIUS ) )
  92. {
  93. // remember handle found
  94. m_LastHitTestHandle = handles[i];
  95. bHit = true;
  96. break;
  97. }
  98. }
  99. return bHit;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose: Set the cursor based on the hit test results and current translate mode.
  103. // Input : eHandleHit - The handle that the cursor is over.
  104. // eTransformMode - The current transform mode of the tool - scale, rotate, or shear.
  105. //-----------------------------------------------------------------------------
  106. unsigned long Box3D::UpdateCursor(CMapView *pView, const Vector &vHandleHit, TransformMode_t eTransformMode)
  107. {
  108. if ( eTransformMode == modeMove || vHandleHit.IsZero() )
  109. return vgui::dc_sizeall;
  110. if ( eTransformMode == modeNone )
  111. return vgui::dc_arrow;
  112. if (eTransformMode == modeRotate)
  113. return g_pMatSystemSurface->CreateCursorFromFile("Resource/rotate.cur");
  114. // cursor icon depends on handle and map view :
  115. Vector2D ptOrigin; pView->WorldToClient( ptOrigin, Vector(0,0,0) );
  116. Vector2D ptHit; pView->WorldToClient( ptHit, vHandleHit );
  117. Vector2D pt; pt.x = ptHit.x - ptOrigin.x; pt.y = ptHit.y - ptOrigin.y;
  118. if (eTransformMode == modeScale)
  119. {
  120. if ( pt.x > 0 )
  121. {
  122. if ( pt.y > 0 )
  123. return vgui::dc_sizenwse;
  124. else if ( pt.y < 0 )
  125. return vgui::dc_sizenesw;
  126. else
  127. return vgui::dc_sizewe;
  128. }
  129. else if ( pt.x < 0 )
  130. {
  131. if ( pt.y > 0 )
  132. return vgui::dc_sizenesw;
  133. else if ( pt.y < 0 )
  134. return vgui::dc_sizenwse;
  135. else
  136. return vgui::dc_sizewe;
  137. }
  138. else // pt.x == 0
  139. {
  140. if ( pt.y != 0 )
  141. return vgui::dc_sizens;
  142. else
  143. return vgui::dc_sizeall;
  144. }
  145. }
  146. else if (eTransformMode == modeShear)
  147. {
  148. if ( pt.x == 0 )
  149. return vgui::dc_sizewe;
  150. else
  151. return vgui::dc_sizens;
  152. }
  153. return vgui::dc_none;
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose:
  157. // Input : bEnable -
  158. //-----------------------------------------------------------------------------
  159. void Box3D::EnableHandles(bool bEnable)
  160. {
  161. m_bEnableHandles = bEnable;
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose: Finds the corner nearest to a given point in world coordinates.
  165. // Output : Returns the corner in world coordinates (axThird is always 0).
  166. //-----------------------------------------------------------------------------
  167. const Vector Box3D::NearestCorner( const Vector2D &vPoint, CMapView *pView, const Vector *pCustomHandleBox )
  168. {
  169. Vector vHandles[3*3*3];
  170. float fBestDist = 999999.9f;
  171. Vector vBestCorner(0,0,0);
  172. int nFace = -1;
  173. Vector start,end,pos;
  174. pView->BuildRay( vPoint, start,end );
  175. float dist = IntersectionLineAABBox( bmins, bmaxs, start, end, nFace );
  176. if ( dist < 0 )
  177. return vBestCorner;
  178. // get point where we hit the bbox
  179. pos = end-start; VectorNormalize( pos );
  180. pos = start + pos*dist;
  181. // mode rotate has only corner handles
  182. int nNumHandles = GetVisibleHandles( vHandles, pView, modeRotate );
  183. for ( int i=0; i<nNumHandles; i++ )
  184. {
  185. Vector vecCorner;
  186. HandleToWorld( vecCorner, vHandles[i], pCustomHandleBox );
  187. float distance = VectorLength( vecCorner - pos );
  188. if ( distance < fBestDist )
  189. {
  190. fBestDist = distance;
  191. vBestCorner = vecCorner;
  192. }
  193. }
  194. return vBestCorner;
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Purpose:
  198. // Input : pt -
  199. // ptForceMoveRef -
  200. // Output : Returns TRUE if pt hits a handle or is in box area, FALSE otherwise.
  201. //-----------------------------------------------------------------------------
  202. void Box3D::StartTranslation(
  203. CMapView *pView,
  204. const Vector2D &vPoint,
  205. const Vector &vHandleOrigin,
  206. const Vector *pRefPoint,
  207. const Vector *pCustomHandleBox )
  208. {
  209. if ( vHandleOrigin.IsZero() )
  210. {
  211. // we hit the main body, switch to move translation then
  212. m_LastTranslateMode = m_TranslateMode;
  213. m_TranslateMode = modeMove;
  214. }
  215. m_TranslateHandle = vHandleOrigin;
  216. m_bPreventOverlap = true;
  217. if ( pRefPoint )
  218. {
  219. // transformation reference point was given
  220. m_vTranslationFixPoint = *pRefPoint;
  221. }
  222. else
  223. {
  224. // build reference point based on mode & handle
  225. if (m_TranslateMode == modeRotate)
  226. {
  227. // user center of object for rotation
  228. m_vTranslationFixPoint = (bmins + bmaxs) / 2;
  229. }
  230. else if (m_TranslateMode == modeMove)
  231. {
  232. // chose nearest corner to
  233. m_vTranslationFixPoint = NearestCorner( vPoint, pView, pCustomHandleBox );
  234. }
  235. else
  236. {
  237. // find opposite point to handle
  238. m_vTranslationFixPoint.Init();
  239. for ( int i=0; i<3; i++ )
  240. {
  241. float handle = m_TranslateHandle[i];
  242. if ( handle > 0 )
  243. {
  244. m_vTranslationFixPoint[i] = bmins[i];
  245. }
  246. else if ( handle < 0 )
  247. {
  248. m_vTranslationFixPoint[i] = bmaxs[i];
  249. }
  250. }
  251. }
  252. }
  253. // get axis normals from picked face
  254. Vector v1,v2,v3,vOrigin;
  255. // if no valid translation handle, cull against BBox
  256. if ( m_TranslateMode == modeMove )
  257. {
  258. int nFace;
  259. pView->BuildRay( vPoint, v1, v2 );
  260. IntersectionLineAABBox( bmins, bmaxs, v1, v2, nFace );
  261. if ( nFace >= 0 )
  262. {
  263. // get axis & normals of face we hit
  264. GetAxisFromFace( nFace, v1, v2, v3 );
  265. }
  266. else
  267. {
  268. pView->GetBestTransformPlane( v1,v2,v3 );
  269. }
  270. vOrigin = m_vTranslationFixPoint;
  271. }
  272. else
  273. {
  274. pView->GetBestTransformPlane( v1,v2,v3 );
  275. HandleToWorld( vOrigin, m_TranslateHandle );
  276. }
  277. // set temp transformation plane
  278. SetTransformationPlane(vOrigin, v1, v2, v3 );
  279. // align translation plane to world origin
  280. ProjectOnTranslationPlane( vec3_origin, vOrigin, 0 );
  281. // set transformation plane
  282. SetTransformationPlane(vOrigin, v1, v2, v3 );
  283. Tool3D::StartTranslation( pView, vPoint, false );
  284. m_TransformMatrix.Identity();
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Purpose:
  288. // Input : pszBuf -
  289. //-----------------------------------------------------------------------------
  290. void Box3D::GetStatusString(char *pszBuf)
  291. {
  292. *pszBuf = '\0';
  293. Vector mins(0,0,0);
  294. Vector maxs(0,0,0);
  295. if ( IsValidBox() )
  296. {
  297. mins = bmins;
  298. maxs = bmaxs;
  299. }
  300. if ( IsTranslating() )
  301. {
  302. TranslateBox( mins, maxs );
  303. }
  304. Vector size = maxs - mins;
  305. Vector center = ( maxs + mins ) * 0.5f;
  306. if ( !IsTranslating() || m_TranslateMode == modeScale || m_TranslateMode == modeMove )
  307. {
  308. if (!IsEmpty())
  309. {
  310. if ( IsTranslating() && m_TranslateMode == modeMove )
  311. {
  312. center = m_vTranslationFixPoint;
  313. TranslatePoint( center );
  314. }
  315. switch (m_eWorldUnits)
  316. {
  317. case Units_None:
  318. {
  319. sprintf(pszBuf, " %dw %dl %dh @(%.0f %.0f %.0f)",
  320. (int)fabs(size.x), (int)fabs(size.y), (int)fabs(size.z),
  321. center.x,center.y,center.z );
  322. break;
  323. }
  324. case Units_Inches:
  325. {
  326. sprintf(pszBuf, " %d\"w %d\"l %d\"h", (int)fabs(size.x), (int)fabs(size.y), (int)fabs(size.z));
  327. break;
  328. }
  329. case Units_Feet_Inches:
  330. {
  331. int nFeetWide = (int)fabs(size.x) / 12;
  332. int nInchesWide = (int)fabs(size.x) % 12;
  333. int nFeetLong = (int)fabs(size.y) / 12;
  334. int nInchesLong = (int)fabs(size.y) % 12;
  335. int nFeetHigh = (int)fabs(size.z) / 12;
  336. int nInchesHigh = (int)fabs(size.z) % 12;
  337. sprintf(pszBuf, " %d' %d\"w %d' %d\"l %d' %d\"h", nFeetWide, nInchesWide, nFeetLong, nInchesLong, nFeetHigh, nInchesHigh);
  338. break;
  339. }
  340. }
  341. }
  342. }
  343. else if ( m_TranslateMode == modeShear )
  344. {
  345. sprintf(pszBuf, " shear: %d %d %d ", (int)m_vTranslation.x, (int)m_vTranslation.y, (int)m_vTranslation.z );
  346. }
  347. else if ( m_TranslateMode == modeRotate )
  348. {
  349. int rotAxis = GetTransformationAxis();
  350. if ( rotAxis != -1 )
  351. {
  352. sprintf(pszBuf, " %.2f%c", m_vTranslation[abs(rotAxis+2)%3], 0xF8);
  353. }
  354. else
  355. {
  356. sprintf(pszBuf, " %.2f %.2f %.2f%c", m_vTranslation.x, m_vTranslation.y, m_vTranslation.z, 0xF8);
  357. }
  358. }
  359. else
  360. {
  361. Assert( 0 );
  362. }
  363. }
  364. //-----------------------------------------------------------------------------
  365. // Purpose:
  366. //-----------------------------------------------------------------------------
  367. void Box3D::UpdateStatusBar()
  368. {
  369. char szBuf[MAX_PATH];
  370. GetStatusString(szBuf);
  371. SetStatusText(SBI_SIZE, szBuf);
  372. }
  373. int Box3D::GetVisibleHandles( Vector *handles, CMapView *pView, int nMode )
  374. {
  375. bool bCorners, bEdges, bFaces;
  376. bool bIs2D = pView->IsOrthographic();
  377. Vector vViewAxis = pView->GetViewAxis();
  378. Vector vViewPoint; pView->GetCamera()->GetViewPoint( vViewPoint );
  379. if ( bIs2D )
  380. {
  381. bCorners = false;
  382. bEdges = nMode == modeRotate || nMode == modeScale;
  383. bFaces = nMode == modeShear || nMode == modeScale;
  384. }
  385. else
  386. {
  387. bCorners = nMode == modeRotate || nMode == modeScale;
  388. bEdges = nMode == modeScale;
  389. bFaces = nMode == modeShear;
  390. }
  391. if ( !bCorners && !bEdges && !bFaces )
  392. return 0;
  393. int count = 0;
  394. for ( int x = -1; x < 2; x++ )
  395. {
  396. if ( bIs2D && (x != 0) && (fabs(vViewAxis.x) == 1) )
  397. continue;
  398. for ( int y = -1; y < 2; y++ )
  399. {
  400. if ( bIs2D && (y != 0) && (fabs(vViewAxis.y) == 1) )
  401. continue;
  402. for ( int z = -1; z<2; z++)
  403. {
  404. if ( bIs2D && (z != 0) && (fabs(vViewAxis.z) == 1) )
  405. continue;
  406. int n = abs(x) + abs(y) + abs(z);
  407. if ( n == 0 )
  408. {
  409. // don't add center as handle
  410. continue;
  411. }
  412. else if ( n == 1 )
  413. {
  414. if ( !bFaces )
  415. continue;
  416. }
  417. else if ( n == 2 )
  418. {
  419. if ( !bEdges )
  420. continue;
  421. }
  422. else
  423. {
  424. if ( !bCorners )
  425. continue;
  426. }
  427. if ( !bIs2D )
  428. {
  429. Vector vHandle; HandleToWorld( vHandle, Vector(x,y,z) );
  430. Vector vDelta = vHandle - vViewPoint;
  431. float fDistance = VectorLength( vDelta );
  432. // Avoid divide by zero.
  433. if ( !fDistance )
  434. continue;
  435. vDelta /= fDistance; // normalize
  436. if ( DotProduct(vDelta,vViewAxis) < 0 )
  437. continue;
  438. int nFace;
  439. float fIntersection = IntersectionLineAABBox( bmins, bmaxs, vViewPoint, vViewPoint+vDelta*99999, nFace );
  440. if ( fIntersection >= 0 && fIntersection*1.01 < fDistance )
  441. continue;
  442. }
  443. // add handle as visible
  444. handles[count] = Vector(x,y,z);
  445. count++;
  446. }
  447. }
  448. }
  449. return count;
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Purpose:
  453. // Input : ptWorld - point to update with in world coordinates
  454. // uConstraints -
  455. // dragSize -
  456. // Output :
  457. //-----------------------------------------------------------------------------
  458. bool Box3D::UpdateTranslation(const Vector &vUpdate, UINT uConstraints)
  459. {
  460. if (m_TranslateMode == modeNone)
  461. {
  462. return false;
  463. }
  464. else if ( m_TranslateMode == modeRotate )
  465. {
  466. Vector vCenter; ProjectOnTranslationPlane( m_vTranslationFixPoint, vCenter );
  467. Vector vStart; HandleToWorld( vStart, m_TranslateHandle );
  468. Vector v1 = vStart-vCenter; VectorNormalize( v1 );
  469. Vector v2 = (vStart+vUpdate)-vCenter; VectorNormalize( v2 );
  470. float volume = DotProduct( m_vPlaneNormal, CrossProduct( v1, v2) );
  471. float angle = RAD2DEG( acos( DotProduct( v1,v2) ) );
  472. if (uConstraints & constrainSnap)
  473. {
  474. angle += 7.5;
  475. angle -= fmod(double(angle), double(15.0));
  476. }
  477. else
  478. {
  479. angle += 0.25;
  480. angle -= fmod(double(angle), double(.5));
  481. }
  482. if ( volume < 0 )
  483. angle = -angle;
  484. if ( fabs(m_vPlaneNormal.x) == 1 )
  485. m_vTranslation.z = (m_vPlaneNormal.x>0)?angle:-angle;
  486. else if ( fabs(m_vPlaneNormal.y) == 1 )
  487. m_vTranslation.x = (m_vPlaneNormal.y>0)?angle:-angle;
  488. else if ( fabs(m_vPlaneNormal.z) == 1 )
  489. m_vTranslation.y = (m_vPlaneNormal.z>0)?angle:-angle;
  490. }
  491. else
  492. {
  493. if ( vUpdate == m_vTranslation )
  494. return false; // no change
  495. m_vTranslation = vUpdate;
  496. // restrict translation, snap to grid, prevent overlap etc
  497. // make sure reference point snaps if enabled
  498. if ( uConstraints )
  499. {
  500. // project back on projection plane
  501. Vector pos;
  502. if ( m_TranslateMode == modeMove )
  503. {
  504. // when moving opbject make sure reference point is on grid
  505. pos = m_vTranslationFixPoint;
  506. }
  507. else
  508. {
  509. // otherwise translated handle should be on grid
  510. HandleToWorld( pos, m_TranslateHandle);
  511. }
  512. ProjectOnTranslationPlane( pos + m_vTranslation, m_vTranslation, uConstraints );
  513. m_vTranslation -= pos;
  514. }
  515. if ( m_TranslateMode == modeScale )
  516. {
  517. for ( int i=0; i<3; i++ )
  518. {
  519. float handle = m_TranslateHandle[i];
  520. if ( handle > 0 )
  521. {
  522. float newMaxs = bmaxs[i] + m_vTranslation[i];
  523. if( m_bPreventOverlap && newMaxs <= bmins[i] )
  524. {
  525. m_vTranslation[i] = bmins[i] - bmaxs[i] + 1;
  526. }
  527. }
  528. else if ( handle < 0 )
  529. {
  530. float newMins = bmins[i] + m_vTranslation[i];
  531. if( m_bPreventOverlap && newMins >= bmaxs[i] )
  532. {
  533. m_vTranslation[i] = bmaxs[i] - bmins[i] - 1;
  534. }
  535. }
  536. }
  537. }
  538. }
  539. UpdateTransformMatrix();
  540. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  541. return true;
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Purpose:
  545. // Input : dwHandleColor -
  546. // dwBoxColor -
  547. //-----------------------------------------------------------------------------
  548. void Box3D::SetDrawColors(COLORREF dwHandleColor, COLORREF dwBoxColor)
  549. {
  550. if (dwHandleColor != 0xffffffff)
  551. {
  552. m_clrHandle = dwHandleColor;
  553. }
  554. if (dwBoxColor != 0xffffffff)
  555. {
  556. m_clrBox = dwBoxColor;
  557. }
  558. }
  559. //-----------------------------------------------------------------------------
  560. // Purpose:
  561. // Input : *pt -
  562. //-----------------------------------------------------------------------------
  563. void Box3D::TranslatePoint(Vector& pt)
  564. {
  565. TransformPoint( m_TransformMatrix, pt );
  566. }
  567. const VMatrix& Box3D::GetTransformMatrix()
  568. {
  569. return m_TransformMatrix;
  570. }
  571. void Box3D::UpdateTransformMatrix()
  572. {
  573. m_TransformMatrix.Identity();
  574. if ( m_TranslateMode == modeNone )
  575. {
  576. return;
  577. }
  578. else if ( m_TranslateMode == modeMove )
  579. {
  580. m_TransformMatrix.SetTranslation( m_vTranslation );
  581. return;
  582. }
  583. else if ( m_TranslateMode == modeScale )
  584. {
  585. Vector vScale( 1,1,1);
  586. Vector vMove(0,0,0);
  587. Vector vSize = bmaxs-bmins;
  588. for ( int i=0; i<3; i++ )
  589. {
  590. float handle = m_TranslateHandle[i];
  591. if ( vSize[i] == 0 )
  592. continue;
  593. if ( handle > 0 )
  594. {
  595. vScale[i] = (m_vTranslation[i]+vSize[i]) / vSize[i];
  596. vMove[i] = m_vTranslation[i] / 2;
  597. }
  598. else if ( handle < 0 )
  599. {
  600. vScale[i] = (-m_vTranslation[i]+vSize[i]) / vSize[i];
  601. vMove[i] = m_vTranslation[i] / 2;
  602. }
  603. }
  604. m_TransformMatrix = m_TransformMatrix.Scale( vScale );
  605. m_TransformMatrix.SetTranslation( vMove );
  606. }
  607. else if ( m_TranslateMode == modeShear )
  608. {
  609. Vector vSize = bmaxs-bmins;
  610. int axisS = -1; // shear axis that wont change
  611. int axisA = -1; // first shear axis
  612. int axisB = -1; // second shear axis
  613. for ( int i=0; i<3; i++ )
  614. {
  615. float handle = m_TranslateHandle[i];
  616. if ( handle > 0 )
  617. {
  618. Assert( axisS == -1);
  619. axisS = i;
  620. }
  621. else if ( handle < 0 )
  622. {
  623. Assert( axisS == -1);
  624. axisS = i;
  625. vSize *= -1;
  626. }
  627. else
  628. {
  629. if ( axisA == -1 )
  630. axisA = i;
  631. else
  632. axisB = i;
  633. }
  634. }
  635. Assert( (axisA!=-1) && (axisB!=-1) && (axisS!=-1) );
  636. m_TransformMatrix.m[axisA][axisS] = (m_vTranslation[axisA])/(vSize[axisS]);
  637. m_TransformMatrix.m[axisB][axisS] = (m_vTranslation[axisB])/(vSize[axisS]);
  638. }
  639. else if ( m_TranslateMode == modeRotate )
  640. {
  641. QAngle angle = *(QAngle*)&m_vTranslation; // buuuhhh
  642. m_TransformMatrix.SetupMatrixOrgAngles( vec3_origin, angle );
  643. }
  644. // apply m_vTranslationFixPoint offset
  645. Vector offset;
  646. m_TransformMatrix.V3Mul( m_vTranslationFixPoint, offset );
  647. offset = m_vTranslationFixPoint - offset;
  648. m_TransformMatrix.m[0][3] += offset[0];
  649. m_TransformMatrix.m[1][3] += offset[1];
  650. m_TransformMatrix.m[2][3] += offset[2];
  651. }
  652. void Box3D::TranslateBox(Vector& mins, Vector& maxs)
  653. {
  654. if ( m_TranslateMode == modeNone )
  655. {
  656. return;
  657. }
  658. if ( m_TranslateMode == modeMove )
  659. {
  660. mins += m_vTranslation;
  661. maxs += m_vTranslation;
  662. }
  663. else if ( m_TranslateMode == modeScale )
  664. {
  665. for ( int i=0; i<3; i++ )
  666. {
  667. float handle = m_TranslateHandle[i];
  668. if ( handle > 0 )
  669. {
  670. maxs[i] += m_vTranslation[i];
  671. }
  672. else if ( handle < 0 )
  673. {
  674. mins[i] += m_vTranslation[i];
  675. }
  676. }
  677. }
  678. else if ( m_TranslateMode == modeShear )
  679. {
  680. TranslatePoint( mins );
  681. TranslatePoint( maxs );
  682. }
  683. else if ( m_TranslateMode == modeRotate )
  684. {
  685. TranslatePoint( mins );
  686. TranslatePoint( maxs );
  687. }
  688. NormalizeBox( mins, maxs );
  689. }
  690. //-----------------------------------------------------------------------------
  691. // Purpose:
  692. // Input : bSave -
  693. //-----------------------------------------------------------------------------
  694. void Box3D::FinishTranslation(bool bSave)
  695. {
  696. if( bSave )
  697. {
  698. Vector newMins = bmins;
  699. Vector newMaxs = bmaxs;
  700. TranslateBox( newMins, newMaxs );
  701. LimitBox( newMins, newMaxs, g_MAX_MAP_COORD );
  702. SetBounds( newMins, newMaxs );
  703. m_bEmpty = false;
  704. }
  705. // if we are finished with moving the selection, switch back to the
  706. // original translation mode
  707. if ( m_TranslateMode == modeMove )
  708. {
  709. m_TranslateMode = m_LastTranslateMode;
  710. }
  711. Tool3D::FinishTranslation(bSave);
  712. }
  713. //-----------------------------------------------------------------------------
  714. // Purpose:
  715. //-----------------------------------------------------------------------------
  716. void Box3D::ToggleTranslateMode(void)
  717. {
  718. if( m_TranslateMode == modeMove )
  719. {
  720. m_TranslateMode = modeScale;
  721. }
  722. else if( m_TranslateMode == modeScale )
  723. {
  724. m_TranslateMode = modeRotate;
  725. }
  726. else if( m_TranslateMode == modeRotate )
  727. {
  728. m_TranslateMode = modeShear;
  729. }
  730. else if( m_TranslateMode == modeShear )
  731. {
  732. m_TranslateMode = modeScale; // don't go back to move mode
  733. }
  734. }
  735. //-----------------------------------------------------------------------------
  736. // Purpose:
  737. // Input : dwFlags -
  738. //-----------------------------------------------------------------------------
  739. void Box3D::SetDrawFlags(DWORD dwFlags)
  740. {
  741. m_dwDrawFlags = dwFlags;
  742. }
  743. void Box3D::RenderHandles2D(CRender2D *pRender, const Vector &mins, const Vector &maxs)
  744. {
  745. Vector handles[3*3*3];
  746. int numHandles = GetVisibleHandles( handles, pRender->GetView(), m_TranslateMode );
  747. if ( numHandles == 0 )
  748. return;
  749. pRender->SetHandleColor( GetRValue(m_clrHandle), GetGValue(m_clrHandle), GetBValue(m_clrHandle) );
  750. if ( m_TranslateMode == modeRotate )
  751. {
  752. pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CIRCLE );
  753. }
  754. else
  755. {
  756. pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_SQUARE );
  757. }
  758. Vector vCenter = (mins+maxs)/2;
  759. Vector vDelta = maxs - vCenter;
  760. Vector2D vOffset;
  761. bool bPopMode = pRender->BeginClientSpace();
  762. for ( int i=0; i<numHandles; i++)
  763. {
  764. pRender->TransformNormal( vOffset, handles[i] );
  765. vOffset.x = fsign(vOffset.x);
  766. vOffset.y = fsign(vOffset.y);
  767. vOffset*=HANDLE_OFFSET;
  768. Vector pos = vCenter + vDelta * handles[i];
  769. pRender->DrawHandle( pos, &vOffset );
  770. }
  771. if ( bPopMode )
  772. pRender->EndClientSpace();
  773. }
  774. void Box3D::RenderHandles3D(CRender3D *pRender, const Vector &mins, const Vector &maxs)
  775. {
  776. Vector handles[3*3*3];
  777. int numHandles = GetVisibleHandles( handles, pRender->GetView(), m_TranslateMode );
  778. if ( numHandles == 0 )
  779. return;
  780. Vector vCenter = (mins+maxs)/2;
  781. Vector vDelta = maxs - vCenter;
  782. if ( m_TranslateMode == modeRotate )
  783. {
  784. pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CIRCLE );
  785. }
  786. else
  787. {
  788. pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_SQUARE );
  789. }
  790. pRender->SetHandleColor( GetRValue(m_clrHandle), GetGValue(m_clrHandle), GetBValue(m_clrHandle) );
  791. pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ );
  792. bool bPopMode = pRender->BeginClientSpace();
  793. for ( int i=0; i<numHandles; i++)
  794. {
  795. Vector pos = vCenter + vDelta * handles[i];
  796. pRender->DrawHandle( pos );
  797. }
  798. if ( bPopMode )
  799. pRender->EndClientSpace();
  800. pRender->PopRenderMode();
  801. }
  802. void Box3D::HandleToWorld( Vector &vWorld, const Vector &vHandle, const Vector *pCustomHandleBox)
  803. {
  804. Vector vCenter, vDelta;
  805. if ( pCustomHandleBox )
  806. {
  807. vCenter = (pCustomHandleBox[0] + pCustomHandleBox[1]) / 2;
  808. vDelta = pCustomHandleBox[1] - vCenter;
  809. }
  810. else
  811. {
  812. vCenter = (bmins+bmaxs)/2;
  813. vDelta = bmaxs - vCenter;
  814. }
  815. vWorld = vCenter + (vDelta * vHandle);
  816. }
  817. //-----------------------------------------------------------------------------
  818. // Purpose:
  819. // Input : *pDC -
  820. // bounds -
  821. //-----------------------------------------------------------------------------
  822. void Box3D::RenderTool2D(CRender2D *pRender)
  823. {
  824. Vector mins = bmins;
  825. Vector maxs = bmaxs;
  826. CMapView2D *pView = (CMapView2D*)pRender->GetView();
  827. Assert( pRender );
  828. if ( IsTranslating() )
  829. {
  830. TranslateBox( mins, maxs );
  831. }
  832. else if ( IsEmpty() )
  833. {
  834. return;
  835. }
  836. if ( m_dwDrawFlags & boundstext)
  837. {
  838. DrawBoundsText(pRender, mins, maxs, DBT_TOP | DBT_LEFT);
  839. }
  840. if ( IsTranslating() )
  841. {
  842. pRender->PushRenderMode( RENDER_MODE_DOTTED );
  843. pRender->SetDrawColor( GetRValue(Options.colors.clrToolDrag), GetGValue(Options.colors.clrToolDrag), GetBValue(Options.colors.clrToolDrag) );
  844. }
  845. else if (!(m_dwDrawFlags & thicklines))
  846. {
  847. pRender->PushRenderMode( RENDER_MODE_DOTTED );
  848. pRender->SetDrawColor( GetRValue(m_clrBox), GetGValue(m_clrBox), GetBValue(m_clrBox) );
  849. }
  850. else
  851. {
  852. pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ );
  853. pRender->SetDrawColor( GetRValue(m_clrBox), GetGValue(m_clrBox), GetBValue(m_clrBox) );
  854. }
  855. // render bounds
  856. if ( !IsTranslating() || m_TranslateMode == modeScale || m_TranslateMode == modeMove )
  857. {
  858. // draw simple rectangle
  859. pRender->DrawRectangle( mins, maxs, false, 0 );
  860. }
  861. else
  862. {
  863. // during rotation or shearing, draw transformed bounding box
  864. Vector v[4];
  865. // init all points to center
  866. v[0] = v[1] = v[2] = v[3] = (bmins+bmaxs) / 2;
  867. int axis = pView->axHorz;
  868. v[0][axis] = v[1][axis] = bmins[axis];
  869. v[2][axis] = v[3][axis] = bmaxs[axis];
  870. axis = pView->axVert;
  871. v[1][axis] = v[2][axis] = bmins[axis];
  872. v[0][axis] = v[3][axis] = bmaxs[axis];
  873. for ( int i=0; i<4; i++)
  874. {
  875. TranslatePoint( v[i] );
  876. }
  877. pRender->DrawLine( v[0], v[1] );
  878. pRender->DrawLine( v[1], v[2] );
  879. pRender->DrawLine( v[2], v[3] );
  880. pRender->DrawLine( v[3], v[0] );
  881. }
  882. pRender->PopRenderMode();
  883. // draw a cross for translation origin in move or rotation mode
  884. if ( IsTranslating() )
  885. {
  886. if ( m_TranslateMode == modeMove || m_TranslateMode == modeRotate )
  887. {
  888. Vector vec = m_vTranslationFixPoint;
  889. if ( m_TranslateMode == modeMove )
  890. {
  891. TranslatePoint( vec );
  892. }
  893. // draw 'X'
  894. pRender->SetHandleStyle( 7, CRender::HANDLE_CROSS );
  895. pRender->SetHandleColor( GetRValue(Options.colors.clrToolDrag), GetGValue(Options.colors.clrToolDrag), GetBValue(Options.colors.clrToolDrag) );
  896. pRender->DrawHandle( vec );
  897. }
  898. }
  899. else if ( m_bEnableHandles )
  900. {
  901. RenderHandles2D( pRender, mins, maxs );
  902. }
  903. }
  904. //-----------------------------------------------------------------------------
  905. // Purpose: Renders this region as a wireframe box.
  906. // Input : pRender - 3D Renderer.
  907. //-----------------------------------------------------------------------------
  908. void Box3D::RenderTool3D(CRender3D *pRender)
  909. {
  910. if ( IsTranslating() )
  911. {
  912. VMatrix matrix = GetTransformMatrix();
  913. pRender->BeginLocalTransfrom( matrix );
  914. }
  915. else if (IsEmpty())
  916. {
  917. return;
  918. }
  919. pRender->PushRenderMode( RENDER_MODE_FLAT );
  920. pRender->SetDrawColor( GetRValue(m_clrBox), GetGValue(m_clrBox), GetBValue(m_clrBox) );
  921. pRender->DrawBox( bmins, bmaxs );
  922. pRender->PopRenderMode();
  923. if ( IsTranslating() )
  924. {
  925. pRender->EndLocalTransfrom();
  926. if ( m_TranslateMode == modeMove || m_TranslateMode == modeRotate )
  927. {
  928. Vector vec = m_vTranslationFixPoint;
  929. if ( m_TranslateMode == modeMove )
  930. {
  931. TranslatePoint( vec );
  932. }
  933. // draw 'X'
  934. pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ );
  935. pRender->SetHandleStyle( 7, CRender::HANDLE_CROSS );
  936. pRender->SetHandleColor( GetRValue(Options.colors.clrToolDrag), GetGValue(Options.colors.clrToolDrag), GetBValue(Options.colors.clrToolDrag) );
  937. pRender->DrawHandle( vec );
  938. pRender->PopRenderMode();
  939. }
  940. }
  941. else if ( m_bEnableHandles )
  942. {
  943. RenderHandles3D( pRender, bmins, bmaxs );
  944. };
  945. }
  946. //-----------------------------------------------------------------------------
  947. // Purpose:
  948. // Input : *vecStart -
  949. // *mins -
  950. // *maxs -
  951. //-----------------------------------------------------------------------------
  952. void Box3D::StartNew( CMapView *pView, const Vector2D &vPoint, const Vector &vecStart, const Vector &vecSize )
  953. {
  954. //Setup our info
  955. m_TranslateMode = modeScale;
  956. m_TranslateHandle = Vector( 1, 1, 1 );
  957. bmins = vecStart;
  958. bmaxs = vecStart+vecSize;
  959. NormalizeBox( bmins, bmaxs );
  960. StartTranslation( pView, vPoint, Vector( 1, 1, 1 ) );
  961. m_bPreventOverlap = false;
  962. m_bEmpty = false;
  963. }