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.

451 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "MapDoc.h"
  9. #include "MapView2D.h"
  10. #include "MapView3D.h"
  11. #include "Tool3D.h"
  12. #include "hammer_mathlib.h"
  13. #include "vgui/Cursor.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include <tier0/memdbgon.h>
  16. #pragma warning(disable:4244)
  17. //-----------------------------------------------------------------------------
  18. // Purpose:
  19. //-----------------------------------------------------------------------------
  20. Tool3D::Tool3D(void)
  21. {
  22. m_vPlaneNormal.Init();
  23. m_vPlaneOrigin.Init();
  24. m_bIsTranslating = false;
  25. for ( int i=0;i<2; i++ )
  26. {
  27. m_bMouseDown[i] = false;
  28. m_bMouseDragged[i] = false;
  29. m_vMouseStart[i].Init();
  30. }
  31. m_vMousePos.Init();
  32. }
  33. void Tool3D::StartTranslation( CMapView *pView, const Vector2D &vClickPoint, bool bUseDefaultPlane )
  34. {
  35. if ( bUseDefaultPlane )
  36. {
  37. Vector vecHorz, vecVert,vecThird;
  38. pView->GetBestTransformPlane( vecHorz, vecVert,vecThird );
  39. SetTransformationPlane( vec3_origin, vecHorz, vecVert, vecThird );
  40. }
  41. m_vTranslation.Init();
  42. ProjectTranslation( pView, vClickPoint, m_vTranslationStart, 0 );
  43. m_bIsTranslating = true;
  44. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  45. }
  46. bool Tool3D::UpdateTranslation(CMapView *pView, const Vector2D &vPoint, UINT nFlags)
  47. {
  48. Vector vTransform;
  49. ProjectTranslation( pView, vPoint, vTransform, 0 );
  50. vTransform -= m_vTranslationStart;
  51. return UpdateTranslation( vTransform, nFlags );
  52. }
  53. bool Tool3D::UpdateTranslation(const Vector &vUpdate, UINT flags /* = 0 */)
  54. {
  55. if ( m_vTranslation == vUpdate )
  56. return false;
  57. m_vTranslation = vUpdate;
  58. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  59. return true;
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose:
  63. // Input : bSave -
  64. //-----------------------------------------------------------------------------
  65. void Tool3D::FinishTranslation(bool bSave)
  66. {
  67. m_bIsTranslating = false;
  68. if ( bSave )
  69. {
  70. // assume the tool changed an object
  71. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_OBJECTS );
  72. }
  73. else
  74. {
  75. // just update the tool
  76. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  77. }
  78. }
  79. void Tool3D::TranslatePoint(Vector& vPos)
  80. {
  81. vPos += m_vTranslation; // most simple translation
  82. }
  83. int Tool3D::HitTest(CMapView *pView, const Vector &vecWorld, bool bTestHandles)
  84. {
  85. Vector2D vClient;
  86. pView->WorldToClient( vClient, vecWorld );
  87. return HitTest( pView, vClient, bTestHandles );
  88. }
  89. bool Tool3D::HitRect(CMapView *pView, const Vector2D &vPoint, const Vector &vCenter, int extent )
  90. {
  91. Vector2D vClientCenter;
  92. pView->WorldToClient( vClientCenter, vCenter );
  93. if ( vPoint.x < (vClientCenter.x-extent) || vPoint.x > ( vClientCenter.x+extent) )
  94. return false;
  95. if ( vPoint.y < (vClientCenter.y-extent) || vPoint.y > ( vClientCenter.y+extent) )
  96. return false;
  97. return true;
  98. }
  99. int Tool3D::GetTransformationAxis()
  100. {
  101. if ( fabs( m_vPlaneNormal.x ) == 1 )
  102. {
  103. return 0;
  104. }
  105. else if ( fabs( m_vPlaneNormal.y ) == 1 )
  106. {
  107. return 1;
  108. }
  109. else if ( fabs( m_vPlaneNormal.z ) == 1 )
  110. {
  111. return 2;
  112. }
  113. else
  114. return -1;
  115. }
  116. void Tool3D::SetTransformationPlane( const Vector &vOrigin, const Vector &vHorz, const Vector &vVert, const Vector &vNormal )
  117. {
  118. Assert( DotProduct(vNormal,vVert) == 0 );
  119. Assert( DotProduct(vNormal,vHorz) == 0 );
  120. Assert( vNormal.Length() > 0.9999 && vNormal.Length() < 1.0001 );
  121. m_vPlaneOrigin = vOrigin;
  122. m_vPlaneNormal = vNormal;
  123. m_vPlaneHorz = vHorz;
  124. m_vPlaneVert = vVert;
  125. }
  126. unsigned int Tool3D::GetConstraints(unsigned int nKeyFlags)
  127. {
  128. unsigned int uConstraints = 0;
  129. bool bDisableSnap = (GetKeyState(VK_MENU) & 0x8000)!=0;
  130. if ( !bDisableSnap )
  131. {
  132. uConstraints |= constrainSnap;
  133. if ( !m_pDocument->IsSnapEnabled() )
  134. {
  135. uConstraints |= constrainIntSnap;
  136. }
  137. }
  138. return uConstraints;
  139. }
  140. void Tool3D::ProjectOnTranslationPlane( const Vector &vWorld, Vector &vTransform, int nFlags )
  141. {
  142. if ( !nFlags )
  143. {
  144. float frac = DotProduct( m_vPlaneNormal, m_vPlaneOrigin-vWorld );
  145. vTransform = vWorld + frac*m_vPlaneNormal;
  146. }
  147. else
  148. {
  149. Vector v0 = vWorld - m_vPlaneOrigin;
  150. Vector vOut;
  151. if ( !SolveLinearEquation( v0, m_vPlaneHorz, m_vPlaneVert, m_vPlaneNormal, vOut) )
  152. {
  153. vTransform.Init();
  154. return;
  155. }
  156. if ( nFlags & constrainOnlyHorz )
  157. {
  158. vOut.y = 0;
  159. }
  160. if ( nFlags & constrainOnlyVert )
  161. {
  162. vOut.x = 0;
  163. }
  164. if ( nFlags & constrainSnap )
  165. {
  166. if ( nFlags & constrainIntSnap )
  167. {
  168. // just snap to next integer
  169. vOut.x = V_rint(vOut.x);
  170. vOut.y = V_rint(vOut.y);
  171. }
  172. else
  173. {
  174. // snap to user grid
  175. float flGridSpacing = m_pDocument->GetGridSpacing();
  176. if ( nFlags & constrainHalfSnap )
  177. {
  178. flGridSpacing *= 0.5f;
  179. }
  180. vOut.y = V_rint(vOut.y / flGridSpacing) * flGridSpacing;
  181. vOut.x = V_rint(vOut.x / flGridSpacing) * flGridSpacing;
  182. }
  183. }
  184. vTransform = m_vPlaneOrigin + vOut.x * m_vPlaneHorz + vOut.y * m_vPlaneVert;
  185. }
  186. }
  187. void Tool3D::ProjectTranslation( CMapView *pView, const Vector2D &vPoint, Vector &vTransform, int nFlags )
  188. {
  189. Vector vStart, vEnd;
  190. pView->BuildRay( vPoint, vStart, vEnd );
  191. Vector vLine = vEnd-vStart;
  192. if ( !nFlags )
  193. {
  194. // simple plane & line intersection
  195. float d1 = DotProduct( m_vPlaneNormal, m_vPlaneOrigin-vStart );
  196. float d2 = DotProduct( m_vPlaneNormal, vLine );
  197. if ( d2 == 0 )
  198. {
  199. // line & plane are parallel !
  200. vTransform.Init();
  201. return;
  202. }
  203. vTransform = vStart + (d1/d2) *vLine;
  204. return;
  205. }
  206. Vector v0 = vStart - m_vPlaneOrigin;
  207. Vector vOut;
  208. if ( !SolveLinearEquation( v0, m_vPlaneHorz, m_vPlaneVert, -vLine, vOut) )
  209. {
  210. vTransform.Init();
  211. return;
  212. }
  213. if ( nFlags & constrainOnlyHorz )
  214. {
  215. vOut.y = 0;
  216. }
  217. if ( nFlags & constrainOnlyVert )
  218. {
  219. vOut.x = 0;
  220. }
  221. if ( nFlags & constrainSnap )
  222. {
  223. if ( nFlags & constrainIntSnap )
  224. {
  225. // just snap to next integer
  226. vOut.x = V_rint(vOut.x);
  227. vOut.y = V_rint(vOut.y);
  228. }
  229. else
  230. {
  231. // snap to user grid
  232. float flGridSpacing = m_pDocument->GetGridSpacing();
  233. if ( nFlags & constrainHalfSnap )
  234. {
  235. flGridSpacing *= 0.5f;
  236. }
  237. vOut.y = V_rint(vOut.y / flGridSpacing) * flGridSpacing;
  238. vOut.x = V_rint(vOut.x / flGridSpacing) * flGridSpacing;
  239. }
  240. }
  241. vTransform = m_vPlaneOrigin + vOut.x * m_vPlaneHorz + vOut.y * m_vPlaneVert;
  242. }
  243. bool Tool3D::OnLMouseDown2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint )
  244. {
  245. m_bMouseDown[MOUSE_LEFT] = true;
  246. m_bMouseDragged[MOUSE_LEFT] = false;
  247. m_vMousePos = m_vMouseStart[MOUSE_LEFT] = vPoint;
  248. pView->SetCapture();
  249. return true;
  250. }
  251. bool Tool3D::OnLMouseUp2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint )
  252. {
  253. m_vMousePos = vPoint;
  254. m_bMouseDown[MOUSE_LEFT] = false;
  255. m_bMouseDragged[MOUSE_LEFT] = false;
  256. ReleaseCapture();
  257. return true;
  258. }
  259. bool Tool3D::OnRMouseDown2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint )
  260. {
  261. m_bMouseDown[MOUSE_RIGHT] = true;
  262. m_bMouseDragged[MOUSE_RIGHT] = false;
  263. m_vMousePos = m_vMouseStart[MOUSE_RIGHT] = vPoint;
  264. pView->SetCapture();
  265. return true;
  266. }
  267. bool Tool3D::OnRMouseUp2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint )
  268. {
  269. m_vMousePos = vPoint;
  270. m_bMouseDown[MOUSE_RIGHT] = false;
  271. m_bMouseDragged[MOUSE_RIGHT] = false;
  272. ReleaseCapture();
  273. return true;
  274. }
  275. bool Tool3D::OnMouseMove2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint )
  276. {
  277. m_vMousePos = vPoint;
  278. for ( int i=0;i<2;i++)
  279. {
  280. if ( m_bMouseDown[i] )
  281. {
  282. if ( !m_bMouseDragged[i] )
  283. {
  284. // check if mouse was dragged if button is pressed down
  285. Vector2D sizeDragged = vPoint - m_vMouseStart[i];
  286. if ((abs(sizeDragged.x) > DRAG_THRESHHOLD) || (abs(sizeDragged.y) > DRAG_THRESHHOLD))
  287. {
  288. // If here, means we've dragged the mouse
  289. m_bMouseDragged[i] = true;
  290. }
  291. }
  292. // Make sure the point is visible.
  293. pView->ToolScrollToPoint( vPoint );
  294. }
  295. }
  296. return true;
  297. }
  298. bool Tool3D::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  299. {
  300. m_bMouseDown[MOUSE_LEFT] = true;
  301. m_bMouseDragged[MOUSE_LEFT] = false;
  302. m_vMousePos = m_vMouseStart[MOUSE_LEFT] = vPoint;
  303. return true;
  304. }
  305. bool Tool3D::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  306. {
  307. m_vMousePos = vPoint;
  308. m_bMouseDown[MOUSE_LEFT] = false;
  309. m_bMouseDragged[MOUSE_LEFT] = false;
  310. ::ReleaseCapture();
  311. return true;
  312. }
  313. bool Tool3D::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  314. {
  315. m_bMouseDown[MOUSE_RIGHT] = true;
  316. m_bMouseDragged[MOUSE_RIGHT] = false;
  317. m_vMousePos = m_vMouseStart[MOUSE_RIGHT] = vPoint;
  318. return true;
  319. }
  320. bool Tool3D::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  321. {
  322. m_vMousePos = vPoint;
  323. m_bMouseDown[MOUSE_RIGHT] = false;
  324. m_bMouseDragged[MOUSE_RIGHT] = false;
  325. ::ReleaseCapture();
  326. return true;
  327. }
  328. bool Tool3D::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  329. {
  330. m_vMousePos = vPoint;
  331. for ( int i=0;i<2;i++)
  332. {
  333. if ( m_bMouseDown[i] )
  334. {
  335. if ( !m_bMouseDragged[i] )
  336. {
  337. // check if mouse was dragged if button is pressed down
  338. Vector2D sizeDragged = vPoint - m_vMouseStart[i];
  339. if ((abs(sizeDragged.x) > DRAG_THRESHHOLD) || (abs(sizeDragged.y) > DRAG_THRESHHOLD))
  340. {
  341. // If here, means we've dragged the mouse
  342. m_bMouseDragged[i] = true;
  343. }
  344. }
  345. // Make sure the point is visible.
  346. // pView->ToolScrollToPoint( vPoint );
  347. }
  348. }
  349. pView->SetCursor( vgui::dc_arrow );
  350. return true;
  351. }
  352. void Tool3D::RenderTranslationPlane(CRender *pRender)
  353. {
  354. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  355. pRender->SetDrawColor( Color(128,128,128) );
  356. Vector viewPoint,vOffset;
  357. ProjectTranslation( pRender->GetView(), m_vMousePos, viewPoint, constrainSnap );
  358. float fGrid = m_pDocument->GetGridSpacing();
  359. int nSteps = 16;
  360. vOffset = m_vPlaneVert * (fGrid * nSteps);
  361. for (int h=-nSteps;h<=nSteps;h++)
  362. {
  363. Vector pos = viewPoint + ( m_vPlaneHorz * ( fGrid*h ) );
  364. pRender->DrawLine( pos+vOffset, pos-vOffset );
  365. }
  366. vOffset = m_vPlaneHorz * (fGrid * nSteps);
  367. for (int v=-nSteps;v<=nSteps;v++)
  368. {
  369. Vector pos = viewPoint + ( m_vPlaneVert * ( fGrid*v ) );
  370. pRender->DrawLine( pos+vOffset, pos-vOffset );
  371. }
  372. pRender->PopRenderMode();
  373. }