//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "stdafx.h" #include "Box3D.h" #include "GlobalFunctions.h" #include "MainFrm.h" // dvs: hack for tools migration code #include "MapDoc.h" #include "MapView2D.h" #include "Options.h" #include "Render2D.h" #include "Render3D.h" #include "RenderUtils.h" #include "resource.h" #include "StatusBarIDs.h" #include "hammer_mathlib.h" #include "vgui/Cursor.h" #include "HammerVGui.h" #include #include "camera.h" // memdbgon must be the last include file in a .cpp file!!! #include #pragma warning(disable:4244) extern float g_MAX_MAP_COORD; // dvs: move these into Globals.h!! extern float g_MIN_MAP_COORD; // dvs: move these into Globals.h!! WorldUnits_t Box3D::m_eWorldUnits = Units_None; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Box3D::Box3D(void) { SetEmpty(); SetDrawFlags(0); m_TranslateMode = modeScale; m_vTranslationFixPoint.Init(); m_TranslateHandle.Init(); m_bEnableHandles = true; SetDrawColors(Options.colors.clrToolHandle, Options.colors.clrToolBlock); } void Box3D::SetEmpty() { Tool3D::SetEmpty(); ResetBounds(); if ( m_pDocument ) { m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); } } //----------------------------------------------------------------------------- // Purpose: // Input : pView - // pt - Point in client coordinates. // bValidOnly - // Output : //----------------------------------------------------------------------------- int Box3D::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles) { bool bHit = false; if ( pView->HitTest( ptClient, bmins, bmaxs ) ) { // The point is inside the main rect. m_LastHitTestHandle.Init(); bHit = true; } if ( !m_bEnableHandles || !bTestHandles ) { // Handles are turned off, so we don't need to do any more testing. // Return whether we hit the main rect or not. return bHit; } // check if we hit a handle Vector handles[3*3*3]; int numHandles = GetVisibleHandles( handles, pView, m_TranslateMode ); Vector vOffset(HANDLE_OFFSET,HANDLE_OFFSET,HANDLE_OFFSET); if ( pView->IsOrthographic() ) { vOffset /= pView->GetCamera()->GetZoom(); } else { vOffset.Init(); } Vector vCenter = (bmins+bmaxs)/2; Vector vDelta = (bmaxs + vOffset) - vCenter; for ( int i = 0; iCreateCursorFromFile("Resource/rotate.cur"); // cursor icon depends on handle and map view : Vector2D ptOrigin; pView->WorldToClient( ptOrigin, Vector(0,0,0) ); Vector2D ptHit; pView->WorldToClient( ptHit, vHandleHit ); Vector2D pt; pt.x = ptHit.x - ptOrigin.x; pt.y = ptHit.y - ptOrigin.y; if (eTransformMode == modeScale) { if ( pt.x > 0 ) { if ( pt.y > 0 ) return vgui::dc_sizenwse; else if ( pt.y < 0 ) return vgui::dc_sizenesw; else return vgui::dc_sizewe; } else if ( pt.x < 0 ) { if ( pt.y > 0 ) return vgui::dc_sizenesw; else if ( pt.y < 0 ) return vgui::dc_sizenwse; else return vgui::dc_sizewe; } else // pt.x == 0 { if ( pt.y != 0 ) return vgui::dc_sizens; else return vgui::dc_sizeall; } } else if (eTransformMode == modeShear) { if ( pt.x == 0 ) return vgui::dc_sizewe; else return vgui::dc_sizens; } return vgui::dc_none; } //----------------------------------------------------------------------------- // Purpose: // Input : bEnable - //----------------------------------------------------------------------------- void Box3D::EnableHandles(bool bEnable) { m_bEnableHandles = bEnable; } //----------------------------------------------------------------------------- // Purpose: Finds the corner nearest to a given point in world coordinates. // Output : Returns the corner in world coordinates (axThird is always 0). //----------------------------------------------------------------------------- const Vector Box3D::NearestCorner( const Vector2D &vPoint, CMapView *pView, const Vector *pCustomHandleBox ) { Vector vHandles[3*3*3]; float fBestDist = 999999.9f; Vector vBestCorner(0,0,0); int nFace = -1; Vector start,end,pos; pView->BuildRay( vPoint, start,end ); float dist = IntersectionLineAABBox( bmins, bmaxs, start, end, nFace ); if ( dist < 0 ) return vBestCorner; // get point where we hit the bbox pos = end-start; VectorNormalize( pos ); pos = start + pos*dist; // mode rotate has only corner handles int nNumHandles = GetVisibleHandles( vHandles, pView, modeRotate ); for ( int i=0; i 0 ) { m_vTranslationFixPoint[i] = bmins[i]; } else if ( handle < 0 ) { m_vTranslationFixPoint[i] = bmaxs[i]; } } } } // get axis normals from picked face Vector v1,v2,v3,vOrigin; // if no valid translation handle, cull against BBox if ( m_TranslateMode == modeMove ) { int nFace; pView->BuildRay( vPoint, v1, v2 ); IntersectionLineAABBox( bmins, bmaxs, v1, v2, nFace ); if ( nFace >= 0 ) { // get axis & normals of face we hit GetAxisFromFace( nFace, v1, v2, v3 ); } else { pView->GetBestTransformPlane( v1,v2,v3 ); } vOrigin = m_vTranslationFixPoint; } else { pView->GetBestTransformPlane( v1,v2,v3 ); HandleToWorld( vOrigin, m_TranslateHandle ); } // set temp transformation plane SetTransformationPlane(vOrigin, v1, v2, v3 ); // align translation plane to world origin ProjectOnTranslationPlane( vec3_origin, vOrigin, 0 ); // set transformation plane SetTransformationPlane(vOrigin, v1, v2, v3 ); Tool3D::StartTranslation( pView, vPoint, false ); m_TransformMatrix.Identity(); } //----------------------------------------------------------------------------- // Purpose: // Input : pszBuf - //----------------------------------------------------------------------------- void Box3D::GetStatusString(char *pszBuf) { *pszBuf = '\0'; Vector mins(0,0,0); Vector maxs(0,0,0); if ( IsValidBox() ) { mins = bmins; maxs = bmaxs; } if ( IsTranslating() ) { TranslateBox( mins, maxs ); } Vector size = maxs - mins; Vector center = ( maxs + mins ) * 0.5f; if ( !IsTranslating() || m_TranslateMode == modeScale || m_TranslateMode == modeMove ) { if (!IsEmpty()) { if ( IsTranslating() && m_TranslateMode == modeMove ) { center = m_vTranslationFixPoint; TranslatePoint( center ); } switch (m_eWorldUnits) { case Units_None: { sprintf(pszBuf, " %dw %dl %dh @(%.0f %.0f %.0f)", (int)fabs(size.x), (int)fabs(size.y), (int)fabs(size.z), center.x,center.y,center.z ); break; } case Units_Inches: { sprintf(pszBuf, " %d\"w %d\"l %d\"h", (int)fabs(size.x), (int)fabs(size.y), (int)fabs(size.z)); break; } case Units_Feet_Inches: { int nFeetWide = (int)fabs(size.x) / 12; int nInchesWide = (int)fabs(size.x) % 12; int nFeetLong = (int)fabs(size.y) / 12; int nInchesLong = (int)fabs(size.y) % 12; int nFeetHigh = (int)fabs(size.z) / 12; int nInchesHigh = (int)fabs(size.z) % 12; sprintf(pszBuf, " %d' %d\"w %d' %d\"l %d' %d\"h", nFeetWide, nInchesWide, nFeetLong, nInchesLong, nFeetHigh, nInchesHigh); break; } } } } else if ( m_TranslateMode == modeShear ) { sprintf(pszBuf, " shear: %d %d %d ", (int)m_vTranslation.x, (int)m_vTranslation.y, (int)m_vTranslation.z ); } else if ( m_TranslateMode == modeRotate ) { int rotAxis = GetTransformationAxis(); if ( rotAxis != -1 ) { sprintf(pszBuf, " %.2f%c", m_vTranslation[abs(rotAxis+2)%3], 0xF8); } else { sprintf(pszBuf, " %.2f %.2f %.2f%c", m_vTranslation.x, m_vTranslation.y, m_vTranslation.z, 0xF8); } } else { Assert( 0 ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Box3D::UpdateStatusBar() { char szBuf[MAX_PATH]; GetStatusString(szBuf); SetStatusText(SBI_SIZE, szBuf); } int Box3D::GetVisibleHandles( Vector *handles, CMapView *pView, int nMode ) { bool bCorners, bEdges, bFaces; bool bIs2D = pView->IsOrthographic(); Vector vViewAxis = pView->GetViewAxis(); Vector vViewPoint; pView->GetCamera()->GetViewPoint( vViewPoint ); if ( bIs2D ) { bCorners = false; bEdges = nMode == modeRotate || nMode == modeScale; bFaces = nMode == modeShear || nMode == modeScale; } else { bCorners = nMode == modeRotate || nMode == modeScale; bEdges = nMode == modeScale; bFaces = nMode == modeShear; } if ( !bCorners && !bEdges && !bFaces ) return 0; int count = 0; for ( int x = -1; x < 2; x++ ) { if ( bIs2D && (x != 0) && (fabs(vViewAxis.x) == 1) ) continue; for ( int y = -1; y < 2; y++ ) { if ( bIs2D && (y != 0) && (fabs(vViewAxis.y) == 1) ) continue; for ( int z = -1; z<2; z++) { if ( bIs2D && (z != 0) && (fabs(vViewAxis.z) == 1) ) continue; int n = abs(x) + abs(y) + abs(z); if ( n == 0 ) { // don't add center as handle continue; } else if ( n == 1 ) { if ( !bFaces ) continue; } else if ( n == 2 ) { if ( !bEdges ) continue; } else { if ( !bCorners ) continue; } if ( !bIs2D ) { Vector vHandle; HandleToWorld( vHandle, Vector(x,y,z) ); Vector vDelta = vHandle - vViewPoint; float fDistance = VectorLength( vDelta ); int nFace; vDelta /= fDistance; // normalize if ( DotProduct(vDelta,vViewAxis) < 0 ) continue; float fIntersection = IntersectionLineAABBox( bmins, bmaxs, vViewPoint, vViewPoint+vDelta*99999, nFace ); if ( fIntersection >= 0 && fIntersection*1.01 < fDistance ) continue; } // add handle as visible handles[count] = Vector(x,y,z); count++; } } } return count; } //----------------------------------------------------------------------------- // Purpose: // Input : ptWorld - point to update with in world coordinates // uConstraints - // dragSize - // Output : //----------------------------------------------------------------------------- bool Box3D::UpdateTranslation(const Vector &vUpdate, UINT uConstraints) { if (m_TranslateMode == modeNone) { return false; } else if ( m_TranslateMode == modeRotate ) { Vector vCenter; ProjectOnTranslationPlane( m_vTranslationFixPoint, vCenter ); Vector vStart; HandleToWorld( vStart, m_TranslateHandle ); Vector v1 = vStart-vCenter; VectorNormalize( v1 ); Vector v2 = (vStart+vUpdate)-vCenter; VectorNormalize( v2 ); float volume = DotProduct( m_vPlaneNormal, CrossProduct( v1, v2) ); float angle = RAD2DEG( acos( DotProduct( v1,v2) ) ); if (uConstraints & constrainSnap) { angle += 7.5; angle -= fmod(double(angle), double(15.0)); } else { angle += 0.25; angle -= fmod(double(angle), double(.5)); } if ( volume < 0 ) angle = -angle; if ( fabs(m_vPlaneNormal.x) == 1 ) m_vTranslation.z = (m_vPlaneNormal.x>0)?angle:-angle; else if ( fabs(m_vPlaneNormal.y) == 1 ) m_vTranslation.x = (m_vPlaneNormal.y>0)?angle:-angle; else if ( fabs(m_vPlaneNormal.z) == 1 ) m_vTranslation.y = (m_vPlaneNormal.z>0)?angle:-angle; } else { if ( vUpdate == m_vTranslation ) return false; // no change m_vTranslation = vUpdate; // restrict translation, snap to grid, prevent overlap etc // make sure reference point snaps if enabled if ( uConstraints ) { // project back on projection plane Vector pos; if ( m_TranslateMode == modeMove ) { // when moving opbject make sure reference point is on grid pos = m_vTranslationFixPoint; } else { // otherwise translated handle should be on grid HandleToWorld( pos, m_TranslateHandle); } ProjectOnTranslationPlane( pos + m_vTranslation, m_vTranslation, uConstraints ); m_vTranslation -= pos; } if ( m_TranslateMode == modeScale ) { for ( int i=0; i<3; i++ ) { float handle = m_TranslateHandle[i]; if ( handle > 0 ) { float newMaxs = bmaxs[i] + m_vTranslation[i]; if( m_bPreventOverlap && newMaxs <= bmins[i] ) { m_vTranslation[i] = bmins[i] - bmaxs[i] + 1; } } else if ( handle < 0 ) { float newMins = bmins[i] + m_vTranslation[i]; if( m_bPreventOverlap && newMins >= bmaxs[i] ) { m_vTranslation[i] = bmaxs[i] - bmins[i] - 1; } } } } } UpdateTransformMatrix(); m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); return true; } //----------------------------------------------------------------------------- // Purpose: // Input : dwHandleColor - // dwBoxColor - //----------------------------------------------------------------------------- void Box3D::SetDrawColors(COLORREF dwHandleColor, COLORREF dwBoxColor) { if (dwHandleColor != 0xffffffff) { m_clrHandle = dwHandleColor; } if (dwBoxColor != 0xffffffff) { m_clrBox = dwBoxColor; } } //----------------------------------------------------------------------------- // Purpose: // Input : *pt - //----------------------------------------------------------------------------- void Box3D::TranslatePoint(Vector& pt) { TransformPoint( m_TransformMatrix, pt ); } const VMatrix& Box3D::GetTransformMatrix() { return m_TransformMatrix; } void Box3D::UpdateTransformMatrix() { m_TransformMatrix.Identity(); if ( m_TranslateMode == modeNone ) { return; } else if ( m_TranslateMode == modeMove ) { m_TransformMatrix.SetTranslation( m_vTranslation ); return; } else if ( m_TranslateMode == modeScale ) { Vector vScale( 1,1,1); Vector vMove(0,0,0); Vector vSize = bmaxs-bmins; for ( int i=0; i<3; i++ ) { float handle = m_TranslateHandle[i]; if ( vSize[i] == 0 ) continue; if ( handle > 0 ) { vScale[i] = (m_vTranslation[i]+vSize[i]) / vSize[i]; vMove[i] = m_vTranslation[i] / 2; } else if ( handle < 0 ) { vScale[i] = (-m_vTranslation[i]+vSize[i]) / vSize[i]; vMove[i] = m_vTranslation[i] / 2; } } m_TransformMatrix = m_TransformMatrix.Scale( vScale ); m_TransformMatrix.SetTranslation( vMove ); } else if ( m_TranslateMode == modeShear ) { Vector vSize = bmaxs-bmins; int axisS = -1; // shear axis that wont change int axisA = -1; // first shear axis int axisB = -1; // second shear axis for ( int i=0; i<3; i++ ) { float handle = m_TranslateHandle[i]; if ( handle > 0 ) { Assert( axisS == -1); axisS = i; } else if ( handle < 0 ) { Assert( axisS == -1); axisS = i; vSize *= -1; } else { if ( axisA == -1 ) axisA = i; else axisB = i; } } Assert( (axisA!=-1) && (axisB!=-1) && (axisS!=-1) ); m_TransformMatrix.m[axisA][axisS] = (m_vTranslation[axisA])/(vSize[axisS]); m_TransformMatrix.m[axisB][axisS] = (m_vTranslation[axisB])/(vSize[axisS]); } else if ( m_TranslateMode == modeRotate ) { QAngle angle = *(QAngle*)&m_vTranslation; // buuuhhh m_TransformMatrix.SetupMatrixOrgAngles( vec3_origin, angle ); } // apply m_vTranslationFixPoint offset Vector offset; m_TransformMatrix.V3Mul( m_vTranslationFixPoint, offset ); offset = m_vTranslationFixPoint - offset; m_TransformMatrix.m[0][3] += offset[0]; m_TransformMatrix.m[1][3] += offset[1]; m_TransformMatrix.m[2][3] += offset[2]; } void Box3D::TranslateBox(Vector& mins, Vector& maxs) { if ( m_TranslateMode == modeNone ) { return; } if ( m_TranslateMode == modeMove ) { mins += m_vTranslation; maxs += m_vTranslation; } else if ( m_TranslateMode == modeScale ) { for ( int i=0; i<3; i++ ) { float handle = m_TranslateHandle[i]; if ( handle > 0 ) { maxs[i] += m_vTranslation[i]; } else if ( handle < 0 ) { mins[i] += m_vTranslation[i]; } } } else if ( m_TranslateMode == modeShear ) { TranslatePoint( mins ); TranslatePoint( maxs ); } else if ( m_TranslateMode == modeRotate ) { TranslatePoint( mins ); TranslatePoint( maxs ); } NormalizeBox( mins, maxs ); } //----------------------------------------------------------------------------- // Purpose: // Input : bSave - //----------------------------------------------------------------------------- void Box3D::FinishTranslation(bool bSave) { if( bSave ) { Vector newMins = bmins; Vector newMaxs = bmaxs; TranslateBox( newMins, newMaxs ); LimitBox( newMins, newMaxs, g_MAX_MAP_COORD ); SetBounds( newMins, newMaxs ); m_bEmpty = false; } // if we are finished with moving the selection, switch back to the // original translation mode if ( m_TranslateMode == modeMove ) { m_TranslateMode = m_LastTranslateMode; } Tool3D::FinishTranslation(bSave); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Box3D::ToggleTranslateMode(void) { if( m_TranslateMode == modeMove ) { m_TranslateMode = modeScale; } else if( m_TranslateMode == modeScale ) { m_TranslateMode = modeRotate; } else if( m_TranslateMode == modeRotate ) { m_TranslateMode = modeShear; } else if( m_TranslateMode == modeShear ) { m_TranslateMode = modeScale; // don't go back to move mode } } //----------------------------------------------------------------------------- // Purpose: // Input : dwFlags - //----------------------------------------------------------------------------- void Box3D::SetDrawFlags(DWORD dwFlags) { m_dwDrawFlags = dwFlags; } void Box3D::RenderHandles2D(CRender2D *pRender, const Vector &mins, const Vector &maxs) { Vector handles[3*3*3]; int numHandles = GetVisibleHandles( handles, pRender->GetView(), m_TranslateMode ); if ( numHandles == 0 ) return; pRender->SetHandleColor( GetRValue(m_clrHandle), GetGValue(m_clrHandle), GetBValue(m_clrHandle) ); if ( m_TranslateMode == modeRotate ) { pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CIRCLE ); } else { pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_SQUARE ); } Vector vCenter = (mins+maxs)/2; Vector vDelta = maxs - vCenter; Vector2D vOffset; bool bPopMode = pRender->BeginClientSpace(); for ( int i=0; iTransformNormal( vOffset, handles[i] ); vOffset.x = fsign(vOffset.x); vOffset.y = fsign(vOffset.y); vOffset*=HANDLE_OFFSET; Vector pos = vCenter + vDelta * handles[i]; pRender->DrawHandle( pos, &vOffset ); } if ( bPopMode ) pRender->EndClientSpace(); } void Box3D::RenderHandles3D(CRender3D *pRender, const Vector &mins, const Vector &maxs) { Vector handles[3*3*3]; int numHandles = GetVisibleHandles( handles, pRender->GetView(), m_TranslateMode ); if ( numHandles == 0 ) return; Vector vCenter = (mins+maxs)/2; Vector vDelta = maxs - vCenter; if ( m_TranslateMode == modeRotate ) { pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CIRCLE ); } else { pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_SQUARE ); } pRender->SetHandleColor( GetRValue(m_clrHandle), GetGValue(m_clrHandle), GetBValue(m_clrHandle) ); pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ ); bool bPopMode = pRender->BeginClientSpace(); for ( int i=0; iDrawHandle( pos ); } if ( bPopMode ) pRender->EndClientSpace(); pRender->PopRenderMode(); } void Box3D::HandleToWorld( Vector &vWorld, const Vector &vHandle, const Vector *pCustomHandleBox) { Vector vCenter, vDelta; if ( pCustomHandleBox ) { vCenter = (pCustomHandleBox[0] + pCustomHandleBox[1]) / 2; vDelta = pCustomHandleBox[1] - vCenter; } else { vCenter = (bmins+bmaxs)/2; vDelta = bmaxs - vCenter; } vWorld = vCenter + (vDelta * vHandle); } //----------------------------------------------------------------------------- // Purpose: // Input : *pDC - // bounds - //----------------------------------------------------------------------------- void Box3D::RenderTool2D(CRender2D *pRender) { Vector mins = bmins; Vector maxs = bmaxs; CMapView2D *pView = (CMapView2D*)pRender->GetView(); Assert( pRender ); if ( IsTranslating() ) { TranslateBox( mins, maxs ); } else if ( IsEmpty() ) { return; } if ( m_dwDrawFlags & boundstext) { DrawBoundsText(pRender, mins, maxs, DBT_TOP | DBT_LEFT); } if ( IsTranslating() ) { pRender->PushRenderMode( RENDER_MODE_DOTTED ); pRender->SetDrawColor( GetRValue(Options.colors.clrToolDrag), GetGValue(Options.colors.clrToolDrag), GetBValue(Options.colors.clrToolDrag) ); } else if (!(m_dwDrawFlags & thicklines)) { pRender->PushRenderMode( RENDER_MODE_DOTTED ); pRender->SetDrawColor( GetRValue(m_clrBox), GetGValue(m_clrBox), GetBValue(m_clrBox) ); } else { pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ ); pRender->SetDrawColor( GetRValue(m_clrBox), GetGValue(m_clrBox), GetBValue(m_clrBox) ); } // render bounds if ( !IsTranslating() || m_TranslateMode == modeScale || m_TranslateMode == modeMove ) { // draw simple rectangle pRender->DrawRectangle( mins, maxs, false, 0 ); } else { // during rotation or shearing, draw transformed bounding box Vector v[4]; // init all points to center v[0] = v[1] = v[2] = v[3] = (bmins+bmaxs) / 2; int axis = pView->axHorz; v[0][axis] = v[1][axis] = bmins[axis]; v[2][axis] = v[3][axis] = bmaxs[axis]; axis = pView->axVert; v[1][axis] = v[2][axis] = bmins[axis]; v[0][axis] = v[3][axis] = bmaxs[axis]; for ( int i=0; i<4; i++) { TranslatePoint( v[i] ); } pRender->DrawLine( v[0], v[1] ); pRender->DrawLine( v[1], v[2] ); pRender->DrawLine( v[2], v[3] ); pRender->DrawLine( v[3], v[0] ); } pRender->PopRenderMode(); // draw a cross for translation origin in move or rotation mode if ( IsTranslating() ) { if ( m_TranslateMode == modeMove || m_TranslateMode == modeRotate ) { Vector vec = m_vTranslationFixPoint; if ( m_TranslateMode == modeMove ) { TranslatePoint( vec ); } // draw 'X' pRender->SetHandleStyle( 7, CRender::HANDLE_CROSS ); pRender->SetHandleColor( GetRValue(Options.colors.clrToolDrag), GetGValue(Options.colors.clrToolDrag), GetBValue(Options.colors.clrToolDrag) ); pRender->DrawHandle( vec ); } } else if ( m_bEnableHandles ) { RenderHandles2D( pRender, mins, maxs ); } } //----------------------------------------------------------------------------- // Purpose: Renders this region as a wireframe box. // Input : pRender - 3D Renderer. //----------------------------------------------------------------------------- void Box3D::RenderTool3D(CRender3D *pRender) { if ( IsTranslating() ) { VMatrix matrix = GetTransformMatrix(); pRender->BeginLocalTransfrom( matrix ); } else if (IsEmpty()) { return; } pRender->PushRenderMode( RENDER_MODE_FLAT ); pRender->SetDrawColor( GetRValue(m_clrBox), GetGValue(m_clrBox), GetBValue(m_clrBox) ); pRender->DrawBox( bmins, bmaxs ); pRender->PopRenderMode(); if ( IsTranslating() ) { pRender->EndLocalTransfrom(); if ( m_TranslateMode == modeMove || m_TranslateMode == modeRotate ) { Vector vec = m_vTranslationFixPoint; if ( m_TranslateMode == modeMove ) { TranslatePoint( vec ); } // draw 'X' pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ ); pRender->SetHandleStyle( 7, CRender::HANDLE_CROSS ); pRender->SetHandleColor( GetRValue(Options.colors.clrToolDrag), GetGValue(Options.colors.clrToolDrag), GetBValue(Options.colors.clrToolDrag) ); pRender->DrawHandle( vec ); pRender->PopRenderMode(); } } else if ( m_bEnableHandles ) { RenderHandles3D( pRender, bmins, bmaxs ); }; } //----------------------------------------------------------------------------- // Purpose: // Input : *vecStart - // *mins - // *maxs - //----------------------------------------------------------------------------- void Box3D::StartNew( CMapView *pView, const Vector2D &vPoint, const Vector &vecStart, const Vector &vecSize ) { //Setup our info m_TranslateMode = modeScale; m_TranslateHandle = Vector( 1, 1, 1 ); bmins = vecStart; bmaxs = vecStart+vecSize; NormalizeBox( bmins, bmaxs ); StartTranslation( pView, vPoint, Vector( 1, 1, 1 ) ); m_bPreventOverlap = false; m_bEmpty = false; }