diff options
Diffstat (limited to 'hammer/tool3d.cpp')
| -rw-r--r-- | hammer/tool3d.cpp | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/hammer/tool3d.cpp b/hammer/tool3d.cpp new file mode 100644 index 0000000..be83868 --- /dev/null +++ b/hammer/tool3d.cpp @@ -0,0 +1,452 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include "MapDoc.h" +#include "MapView2D.h" +#include "MapView3D.h" +#include "Tool3D.h" +#include "hammer_mathlib.h" +#include "vgui/Cursor.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + +#pragma warning(disable:4244) + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Tool3D::Tool3D(void) +{ + m_vPlaneNormal.Init(); + m_vPlaneOrigin.Init(); + m_bIsTranslating = false; + + for ( int i=0;i<2; i++ ) + { + m_bMouseDown[i] = false; + m_bMouseDragged[i] = false; + m_vMouseStart[i].Init(); + } + + m_vMousePos.Init(); +} + + +void Tool3D::StartTranslation( CMapView *pView, const Vector2D &vClickPoint, bool bUseDefaultPlane ) +{ + if ( bUseDefaultPlane ) + { + Vector vecHorz, vecVert,vecThird; + pView->GetBestTransformPlane( vecHorz, vecVert,vecThird ); + SetTransformationPlane( vec3_origin, vecHorz, vecVert, vecThird ); + } + + m_vTranslation.Init(); + ProjectTranslation( pView, vClickPoint, m_vTranslationStart, 0 ); + m_bIsTranslating = true; + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); +} + +bool Tool3D::UpdateTranslation(CMapView *pView, const Vector2D &vPoint, UINT nFlags) +{ + Vector vTransform; + ProjectTranslation( pView, vPoint, vTransform, 0 ); + vTransform -= m_vTranslationStart; + return UpdateTranslation( vTransform, nFlags ); +} + +bool Tool3D::UpdateTranslation(const Vector &vUpdate, UINT flags /* = 0 */) +{ + if ( m_vTranslation == vUpdate ) + return false; + + m_vTranslation = vUpdate; + + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : bSave - +//----------------------------------------------------------------------------- +void Tool3D::FinishTranslation(bool bSave) +{ + m_bIsTranslating = false; + + if ( bSave ) + { + // assume the tool changed an object + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_OBJECTS ); + } + else + { + // just update the tool + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); + } +} + +void Tool3D::TranslatePoint(Vector& vPos) +{ + vPos += m_vTranslation; // most simple translation +} + +int Tool3D::HitTest(CMapView *pView, const Vector &vecWorld, bool bTestHandles) +{ + Vector2D vClient; + pView->WorldToClient( vClient, vecWorld ); + return HitTest( pView, vClient, bTestHandles ); +} + +bool Tool3D::HitRect(CMapView *pView, const Vector2D &vPoint, const Vector &vCenter, int extent ) +{ + Vector2D vClientCenter; + pView->WorldToClient( vClientCenter, vCenter ); + + if ( vPoint.x < (vClientCenter.x-extent) || vPoint.x > ( vClientCenter.x+extent) ) + return false; + + if ( vPoint.y < (vClientCenter.y-extent) || vPoint.y > ( vClientCenter.y+extent) ) + return false; + + return true; +} + +int Tool3D::GetTransformationAxis() +{ + if ( fabs( m_vPlaneNormal.x ) == 1 ) + { + return 0; + } + else if ( fabs( m_vPlaneNormal.y ) == 1 ) + { + return 1; + } + else if ( fabs( m_vPlaneNormal.z ) == 1 ) + { + return 2; + } + else + return -1; +} + +void Tool3D::SetTransformationPlane( const Vector &vOrigin, const Vector &vHorz, const Vector &vVert, const Vector &vNormal ) +{ + Assert( DotProduct(vNormal,vVert) == 0 ); + Assert( DotProduct(vNormal,vHorz) == 0 ); + Assert( vNormal.Length() > 0.9999 && vNormal.Length() < 1.0001 ); + + m_vPlaneOrigin = vOrigin; + m_vPlaneNormal = vNormal; + m_vPlaneHorz = vHorz; + m_vPlaneVert = vVert; +} + +unsigned int Tool3D::GetConstraints(unsigned int nKeyFlags) +{ + unsigned int uConstraints = 0; + + bool bDisableSnap = (GetKeyState(VK_MENU) & 0x8000)!=0; + + if ( !bDisableSnap ) + { + uConstraints |= constrainSnap; + + if ( !m_pDocument->IsSnapEnabled() ) + { + uConstraints |= constrainIntSnap; + } + } + + return uConstraints; +} + +void Tool3D::ProjectOnTranslationPlane( const Vector &vWorld, Vector &vTransform, int nFlags ) +{ + if ( !nFlags ) + { + float frac = DotProduct( m_vPlaneNormal, m_vPlaneOrigin-vWorld ); + vTransform = vWorld + frac*m_vPlaneNormal; + } + else + { + Vector v0 = vWorld - m_vPlaneOrigin; + Vector vOut; + + if ( !SolveLinearEquation( v0, m_vPlaneHorz, m_vPlaneVert, m_vPlaneNormal, vOut) ) + { + vTransform.Init(); + return; + } + + if ( nFlags & constrainOnlyHorz ) + { + vOut.y = 0; + } + + if ( nFlags & constrainOnlyVert ) + { + vOut.x = 0; + } + + if ( nFlags & constrainSnap ) + { + if ( nFlags & constrainIntSnap ) + { + // just snap to next integer + vOut.x = V_rint(vOut.x); + vOut.y = V_rint(vOut.y); + } + else + { + // snap to user grid + float flGridSpacing = m_pDocument->GetGridSpacing(); + + if ( nFlags & constrainHalfSnap ) + { + flGridSpacing *= 0.5f; + } + + vOut.y = V_rint(vOut.y / flGridSpacing) * flGridSpacing; + vOut.x = V_rint(vOut.x / flGridSpacing) * flGridSpacing; + } + } + + vTransform = m_vPlaneOrigin + vOut.x * m_vPlaneHorz + vOut.y * m_vPlaneVert; + } +} + +void Tool3D::ProjectTranslation( CMapView *pView, const Vector2D &vPoint, Vector &vTransform, int nFlags ) +{ + Vector vStart, vEnd; + + pView->BuildRay( vPoint, vStart, vEnd ); + + Vector vLine = vEnd-vStart; + + if ( !nFlags ) + { + // simple plane & line intersection + float d1 = DotProduct( m_vPlaneNormal, m_vPlaneOrigin-vStart ); + float d2 = DotProduct( m_vPlaneNormal, vLine ); + + if ( d2 == 0 ) + { + // line & plane are parallel ! + vTransform.Init(); + return; + } + + vTransform = vStart + (d1/d2) *vLine; + return; + } + + Vector v0 = vStart - m_vPlaneOrigin; + Vector vOut; + + if ( !SolveLinearEquation( v0, m_vPlaneHorz, m_vPlaneVert, -vLine, vOut) ) + { + vTransform.Init(); + return; + } + + if ( nFlags & constrainOnlyHorz ) + { + vOut.y = 0; + } + + if ( nFlags & constrainOnlyVert ) + { + vOut.x = 0; + } + + if ( nFlags & constrainSnap ) + { + if ( nFlags & constrainIntSnap ) + { + // just snap to next integer + vOut.x = V_rint(vOut.x); + vOut.y = V_rint(vOut.y); + } + else + { + // snap to user grid + float flGridSpacing = m_pDocument->GetGridSpacing(); + + if ( nFlags & constrainHalfSnap ) + { + flGridSpacing *= 0.5f; + } + + vOut.y = V_rint(vOut.y / flGridSpacing) * flGridSpacing; + vOut.x = V_rint(vOut.x / flGridSpacing) * flGridSpacing; + } + } + + vTransform = m_vPlaneOrigin + vOut.x * m_vPlaneHorz + vOut.y * m_vPlaneVert; +} + +bool Tool3D::OnLMouseDown2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_bMouseDown[MOUSE_LEFT] = true; + m_bMouseDragged[MOUSE_LEFT] = false; + m_vMousePos = m_vMouseStart[MOUSE_LEFT] = vPoint; + pView->SetCapture(); + return true; +} + +bool Tool3D::OnLMouseUp2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_vMousePos = vPoint; + m_bMouseDown[MOUSE_LEFT] = false; + m_bMouseDragged[MOUSE_LEFT] = false; + ReleaseCapture(); + return true; +} + +bool Tool3D::OnRMouseDown2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_bMouseDown[MOUSE_RIGHT] = true; + m_bMouseDragged[MOUSE_RIGHT] = false; + m_vMousePos = m_vMouseStart[MOUSE_RIGHT] = vPoint; + pView->SetCapture(); + return true; +} + +bool Tool3D::OnRMouseUp2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_vMousePos = vPoint; + m_bMouseDown[MOUSE_RIGHT] = false; + m_bMouseDragged[MOUSE_RIGHT] = false; + ReleaseCapture(); + return true; +} + +bool Tool3D::OnMouseMove2D( CMapView2D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_vMousePos = vPoint; + + for ( int i=0;i<2;i++) + { + if ( m_bMouseDown[i] ) + { + if ( !m_bMouseDragged[i] ) + { + // check if mouse was dragged if button is pressed down + Vector2D sizeDragged = vPoint - m_vMouseStart[i]; + + if ((abs(sizeDragged.x) > DRAG_THRESHHOLD) || (abs(sizeDragged.y) > DRAG_THRESHHOLD)) + { + // If here, means we've dragged the mouse + m_bMouseDragged[i] = true; + } + } + + // Make sure the point is visible. + pView->ToolScrollToPoint( vPoint ); + } + } + + return true; +} + +bool Tool3D::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_bMouseDown[MOUSE_LEFT] = true; + m_bMouseDragged[MOUSE_LEFT] = false; + m_vMousePos = m_vMouseStart[MOUSE_LEFT] = vPoint; + return true; +} + +bool Tool3D::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_vMousePos = vPoint; + m_bMouseDown[MOUSE_LEFT] = false; + m_bMouseDragged[MOUSE_LEFT] = false; + ::ReleaseCapture(); + return true; +} + +bool Tool3D::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_bMouseDown[MOUSE_RIGHT] = true; + m_bMouseDragged[MOUSE_RIGHT] = false; + m_vMousePos = m_vMouseStart[MOUSE_RIGHT] = vPoint; + return true; +} + +bool Tool3D::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_vMousePos = vPoint; + m_bMouseDown[MOUSE_RIGHT] = false; + m_bMouseDragged[MOUSE_RIGHT] = false; + ::ReleaseCapture(); + return true; +} + +bool Tool3D::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint ) +{ + m_vMousePos = vPoint; + for ( int i=0;i<2;i++) + { + if ( m_bMouseDown[i] ) + { + if ( !m_bMouseDragged[i] ) + { + // check if mouse was dragged if button is pressed down + Vector2D sizeDragged = vPoint - m_vMouseStart[i]; + + if ((abs(sizeDragged.x) > DRAG_THRESHHOLD) || (abs(sizeDragged.y) > DRAG_THRESHHOLD)) + { + // If here, means we've dragged the mouse + m_bMouseDragged[i] = true; + } + } + + // Make sure the point is visible. + // pView->ToolScrollToPoint( vPoint ); + } + } + + pView->SetCursor( vgui::dc_arrow ); + + return true; +} + +void Tool3D::RenderTranslationPlane(CRender *pRender) +{ + pRender->PushRenderMode( RENDER_MODE_WIREFRAME ); + pRender->SetDrawColor( Color(128,128,128) ); + + Vector viewPoint,vOffset; + + ProjectTranslation( pRender->GetView(), m_vMousePos, viewPoint, constrainSnap ); + + float fGrid = m_pDocument->GetGridSpacing(); + int nSteps = 16; + + vOffset = m_vPlaneVert * (fGrid * nSteps); + for (int h=-nSteps;h<=nSteps;h++) + { + Vector pos = viewPoint + ( m_vPlaneHorz * ( fGrid*h ) ); + pRender->DrawLine( pos+vOffset, pos-vOffset ); + } + + vOffset = m_vPlaneHorz * (fGrid * nSteps); + for (int v=-nSteps;v<=nSteps;v++) + { + Vector pos = viewPoint + ( m_vPlaneVert * ( fGrid*v ) ); + pRender->DrawLine( pos+vOffset, pos-vOffset ); + } + + pRender->PopRenderMode(); +}
\ No newline at end of file |