mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,987 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GlobalFunctions.h"
|
||||
#include "History.h"
|
||||
#include "MapDefs.h"
|
||||
#include "MapDoc.h"
|
||||
#include "MapFace.h"
|
||||
#include "MapSolid.h"
|
||||
#include "MapView2D.h"
|
||||
#include "MapWorld.h"
|
||||
#include "Options.h"
|
||||
#include "Render2D.h"
|
||||
#include "Render3D.h"
|
||||
#include "RenderUtils.h"
|
||||
#include "StatusBarIDs.h" // dvs: remove
|
||||
#include "ToolClipper.h"
|
||||
#include "ToolManager.h"
|
||||
#include "vgui/Cursor.h"
|
||||
#include "Selection.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
#pragma warning( disable:4244 )
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Friend Function (for MapClass->EnumChildren Callback)
|
||||
//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function creates a new clip group with the given solid as
|
||||
// the original solid.
|
||||
// Input: pSolid - the original solid to put in the clip list
|
||||
// pClipper - the clipper tool
|
||||
// Output: successful?? (true/false)
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL AddToClipList( CMapSolid *pSolid, Clipper3D *pClipper )
|
||||
{
|
||||
CClipGroup *pClipGroup = new CClipGroup;
|
||||
if( !pClipGroup )
|
||||
return false;
|
||||
|
||||
pClipGroup->SetOrigSolid( pSolid );
|
||||
pClipper->m_ClipResults.AddToTail( pClipGroup );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CClipGroup
|
||||
//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor. Gets rid of the unnecessary clip solids.
|
||||
//-----------------------------------------------------------------------------
|
||||
CClipGroup::~CClipGroup()
|
||||
{
|
||||
delete m_pClipSolids[0];
|
||||
delete m_pClipSolids[1];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor - initialize the clipper variables
|
||||
//-----------------------------------------------------------------------------
|
||||
Clipper3D::Clipper3D(void)
|
||||
{
|
||||
m_Mode = FRONT;
|
||||
|
||||
m_ClipPlane.normal.Init();
|
||||
m_ClipPlane.dist = 0.0f;
|
||||
m_ClipPoints[0].Init();
|
||||
m_ClipPoints[1].Init();
|
||||
m_ClipPointHit = -1;
|
||||
|
||||
m_pOrigObjects = NULL;
|
||||
|
||||
m_bDrawMeasurements = false;
|
||||
SetEmpty();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: deconstructor
|
||||
//-----------------------------------------------------------------------------
|
||||
Clipper3D::~Clipper3D(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when the tool is activated.
|
||||
// Input : eOldTool - The ID of the previously active tool.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::OnActivate()
|
||||
{
|
||||
if (IsActiveTool())
|
||||
{
|
||||
//
|
||||
// Already the active tool - toggle the mode.
|
||||
//
|
||||
IterateClipMode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when the tool is deactivated.
|
||||
// Input : eNewTool - The ID of the tool that is being activated.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::OnDeactivate()
|
||||
{
|
||||
SetEmpty();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: (virtual imp) This function handles the "dragging" of the mouse
|
||||
// while the left mouse button is depressed. It updates the position
|
||||
// of the clippoing plane point selected in the StartTranslation
|
||||
// function. This function rebuilds the clipping plane and updates
|
||||
// the clipping solids when necessary.
|
||||
// Input: pt - current location of the mouse in the 2DView
|
||||
// uFlags - constrained clipping plane point movement
|
||||
// *dragSize - not used in the virtual implementation
|
||||
// Output: success of translation (TRUE/FALSE)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Clipper3D::UpdateTranslation( const Vector &vUpdate, UINT uFlags )
|
||||
{
|
||||
// sanity check
|
||||
if( IsEmpty() )
|
||||
return false;
|
||||
|
||||
Vector vNewPos = m_vOrgPos + vUpdate;
|
||||
|
||||
// snap point if need be
|
||||
if ( uFlags & constrainSnap )
|
||||
m_pDocument->Snap( vNewPos, uFlags );
|
||||
|
||||
//
|
||||
// update clipping point positions
|
||||
//
|
||||
if ( m_ClipPoints[m_ClipPointHit] == vNewPos )
|
||||
return false;
|
||||
|
||||
|
||||
if( uFlags & constrainMoveAll )
|
||||
{
|
||||
//
|
||||
// calculate the point and delta - to move both clip points simultaneously
|
||||
//
|
||||
|
||||
Vector delta = vNewPos - m_ClipPoints[m_ClipPointHit];
|
||||
m_ClipPoints[(m_ClipPointHit+1)%2] += delta;
|
||||
}
|
||||
|
||||
m_ClipPoints[m_ClipPointHit] = vNewPos;
|
||||
|
||||
// build the new clip plane and update clip results
|
||||
BuildClipPlane();
|
||||
|
||||
GetClipResults();
|
||||
|
||||
m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: (virtual imp) This function defines all finishing functionality
|
||||
// necessary at the end of a clipping action. Nothing really!!!
|
||||
// Input : bSave - passed along the the Tool finish translation call
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::FinishTranslation( bool bSave )
|
||||
{
|
||||
// get the clip results -- in case the update is a click and not a drag
|
||||
GetClipResults();
|
||||
|
||||
Tool3D::FinishTranslation( bSave );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: iterate through the types of clipping modes, update after an
|
||||
// iteration takes place to visualize the new clip results
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::IterateClipMode( void )
|
||||
{
|
||||
//
|
||||
// increment the clipping mode (wrap when necessary)
|
||||
//
|
||||
m_Mode++;
|
||||
|
||||
if( m_Mode > BOTH )
|
||||
{
|
||||
m_Mode = FRONT;
|
||||
}
|
||||
|
||||
// update the clipped objects based on the mode
|
||||
GetClipResults();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This resets the solids to clip (the original list) and calls the
|
||||
// CalcClipResults function to generate new "clip" solids
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::GetClipResults( void )
|
||||
{
|
||||
// reset the clip list to the original solid lsit
|
||||
SetClipObjects( m_pOrigObjects );
|
||||
|
||||
// calculate the clipped objects based on the current "clip plane"
|
||||
CalcClipResults();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function allows one to specifically set the clipping plane
|
||||
// information, as opposed to building a clip plane during "translation"
|
||||
// Input: pPlane - the plane information used to create the clip plane
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::SetClipPlane( PLANE *pPlane )
|
||||
{
|
||||
//
|
||||
// copy the clipping plane info
|
||||
//
|
||||
m_ClipPlane.normal = pPlane->normal;
|
||||
m_ClipPlane.dist = pPlane->dist;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function builds a clipping plane based on the clip point
|
||||
// locations manipulated in the "translation" functions and the 2DView
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::BuildClipPlane( void )
|
||||
{
|
||||
// calculate the up vector
|
||||
Vector upVect = m_vPlaneNormal;
|
||||
|
||||
// calculate the right vector
|
||||
Vector rightVect;
|
||||
VectorSubtract( m_ClipPoints[1], m_ClipPoints[0], rightVect );
|
||||
|
||||
// calculate the forward (normal) vector
|
||||
Vector forwardVect;
|
||||
CrossProduct( upVect, rightVect, forwardVect );
|
||||
VectorNormalize( forwardVect );
|
||||
|
||||
//
|
||||
// save the clip plane info
|
||||
//
|
||||
m_ClipPlane.normal = forwardVect;
|
||||
m_ClipPlane.dist = DotProduct( m_ClipPoints[0], forwardVect );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This functions sets up the list of objects to be clipped.
|
||||
// Initially the list is passed in (typically a Selection set). On
|
||||
// subsequent "translation" updates the list is refreshed from the
|
||||
// m_pOrigObjects list.
|
||||
// Input: pList - the list of objects (solids) to be clipped
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::SetClipObjects( const CMapObjectList *pList )
|
||||
{
|
||||
// check for an empty list
|
||||
if( !pList )
|
||||
return;
|
||||
|
||||
// save the original list
|
||||
m_pOrigObjects = pList;
|
||||
|
||||
// clear the clip results list
|
||||
ResetClipResults();
|
||||
|
||||
//
|
||||
// copy solids into the clip list
|
||||
//
|
||||
FOR_EACH_OBJ( *m_pOrigObjects, pos )
|
||||
{
|
||||
CMapClass *pObject = m_pOrigObjects->Element( pos );
|
||||
if( !pObject )
|
||||
continue;
|
||||
|
||||
if( pObject->IsMapClass( MAPCLASS_TYPE( CMapSolid ) ) )
|
||||
{
|
||||
AddToClipList( ( CMapSolid* )pObject, this );
|
||||
}
|
||||
|
||||
pObject->EnumChildren( ENUMMAPCHILDRENPROC( AddToClipList ), DWORD( this ), MAPCLASS_TYPE( CMapSolid ) );
|
||||
}
|
||||
|
||||
// the clipping list is not empty anymore
|
||||
m_bEmpty = false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function calculates based on the defined or given clipping
|
||||
// plane and clipping mode the new clip solids.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::CalcClipResults( void )
|
||||
{
|
||||
// sanity check
|
||||
if( IsEmpty() )
|
||||
return;
|
||||
|
||||
//
|
||||
// iterate through and clip all of the solids in the clip list
|
||||
//
|
||||
FOR_EACH_OBJ( m_ClipResults, pos )
|
||||
{
|
||||
CClipGroup *pClipGroup = m_ClipResults.Element( pos );
|
||||
CMapSolid *pOrigSolid = pClipGroup->GetOrigSolid();
|
||||
if( !pOrigSolid )
|
||||
continue;
|
||||
|
||||
//
|
||||
// check the modes for which solids to generate
|
||||
//
|
||||
CMapSolid *pFront = NULL;
|
||||
CMapSolid *pBack = NULL;
|
||||
if( m_Mode == FRONT )
|
||||
{
|
||||
pOrigSolid->Split( &m_ClipPlane, &pFront, NULL );
|
||||
}
|
||||
else if( m_Mode == BACK )
|
||||
{
|
||||
pOrigSolid->Split( &m_ClipPlane, NULL, &pBack );
|
||||
}
|
||||
else if( m_Mode == BOTH )
|
||||
{
|
||||
pOrigSolid->Split( &m_ClipPlane, &pFront, &pBack );
|
||||
}
|
||||
|
||||
if( pFront )
|
||||
{
|
||||
pFront->SetTemporary(true);
|
||||
pClipGroup->SetClipSolid( pFront, FRONT );
|
||||
}
|
||||
|
||||
if( pBack )
|
||||
{
|
||||
pBack->SetTemporary(true);
|
||||
pClipGroup->SetClipSolid( pBack, BACK );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function handles the removal of the "original" solid when it
|
||||
// has been clipped into new solid(s) or removed from the world (group
|
||||
// or entity) entirely. It handles this in an undo safe fashion.
|
||||
// Input: pOrigSolid - the solid to remove
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::RemoveOrigSolid( CMapSolid *pOrigSolid )
|
||||
{
|
||||
m_pDocument->DeleteObject(pOrigSolid);
|
||||
|
||||
//
|
||||
// remove the solid from the selection set if in the seleciton set and
|
||||
// its parent is the world, or set the selection state to none parent is group
|
||||
// or entity in the selection set
|
||||
//
|
||||
|
||||
CSelection *pSelection = m_pDocument->GetSelection();
|
||||
|
||||
if ( pSelection->IsSelected( pOrigSolid ) )
|
||||
{
|
||||
pSelection->SelectObject( pOrigSolid, scUnselect );
|
||||
}
|
||||
else
|
||||
{
|
||||
pOrigSolid->SetSelectionState( SELECT_NONE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function handles the saving of newly clipped solids (derived
|
||||
// from an "original" solid). It handles them in an undo safe fashion.
|
||||
// Input: pSolid - the newly clipped solid
|
||||
// pOrigSolid - the "original" solid or solid the clipped solid was
|
||||
// derived from
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::SaveClipSolid( CMapSolid *pSolid, CMapSolid *pOrigSolid )
|
||||
{
|
||||
//
|
||||
// no longer a temporary solid
|
||||
//
|
||||
pSolid->SetTemporary( FALSE );
|
||||
|
||||
//
|
||||
// Add the new solid to the original solid's parent (group, entity, world, etc.).
|
||||
//
|
||||
m_pDocument->AddObjectToWorld(pSolid, pOrigSolid->GetParent());
|
||||
|
||||
//
|
||||
// handle linking solid into selection -- via selection set when parent is the world
|
||||
// and selected, or set the selection state if parent is group or entity in selection set
|
||||
//
|
||||
if( m_pDocument->GetSelection()->IsSelected( pOrigSolid ) )
|
||||
{
|
||||
m_pDocument->SelectObject( pSolid, scSelect );
|
||||
}
|
||||
else
|
||||
{
|
||||
pSolid->SetSelectionState( SELECT_NORMAL );
|
||||
}
|
||||
|
||||
GetHistory()->KeepNew( pSolid );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function saves all the clipped solid information. If new solids
|
||||
// were generated from the original, they are saved and the original is
|
||||
// set for desctruciton. Otherwise, the original solid is kept.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::SaveClipResults( void )
|
||||
{
|
||||
// sanity check!
|
||||
if( IsEmpty() )
|
||||
return;
|
||||
|
||||
// mark this place in the history
|
||||
GetHistory()->MarkUndoPosition( NULL, "Clip Objects" );
|
||||
|
||||
//
|
||||
// save all new objects into the selection list
|
||||
//
|
||||
FOR_EACH_OBJ( m_ClipResults, pos )
|
||||
{
|
||||
CClipGroup *pClipGroup = m_ClipResults.Element( pos );
|
||||
if( !pClipGroup )
|
||||
continue;
|
||||
|
||||
CMapSolid *pOrigSolid = pClipGroup->GetOrigSolid();
|
||||
CMapSolid *pBackSolid = pClipGroup->GetClipSolid( CClipGroup::BACK );
|
||||
CMapSolid *pFrontSolid = pClipGroup->GetClipSolid( CClipGroup::FRONT );
|
||||
|
||||
//
|
||||
// save the front clip solid and clear the clip results list of itself
|
||||
//
|
||||
if( pFrontSolid )
|
||||
{
|
||||
SaveClipSolid( pFrontSolid, pOrigSolid );
|
||||
pClipGroup->SetClipSolid( NULL, CClipGroup::FRONT );
|
||||
}
|
||||
|
||||
//
|
||||
// save the front clip solid and clear the clip results list of itself
|
||||
//
|
||||
if( pBackSolid )
|
||||
{
|
||||
SaveClipSolid( pBackSolid, pOrigSolid );
|
||||
pClipGroup->SetClipSolid( NULL, CClipGroup::BACK );
|
||||
}
|
||||
|
||||
// Send the notification that this solid as been clipped.
|
||||
pOrigSolid->PostUpdate( Notify_Clipped );
|
||||
|
||||
// remove the original solid
|
||||
RemoveOrigSolid( pOrigSolid );
|
||||
}
|
||||
|
||||
// set the the clipping results list as empty
|
||||
ResetClipResults();
|
||||
|
||||
// update world and views
|
||||
|
||||
m_pDocument->SetModifiedFlag();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws the measurements of a brush in the 2D view.
|
||||
// Input : pRender -
|
||||
// pSolid -
|
||||
// nFlags -
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::DrawBrushExtents( CRender2D *pRender, CMapSolid *pSolid, int nFlags )
|
||||
{
|
||||
//
|
||||
// get the bounds of the solid
|
||||
//
|
||||
Vector Mins, Maxs;
|
||||
pSolid->GetRender2DBox( Mins, Maxs );
|
||||
|
||||
//
|
||||
// Determine which side of the clipping plane this solid is on in screen
|
||||
// space. This tells us where to draw the extents.
|
||||
//
|
||||
if( ( m_ClipPlane.normal[0] == 0 ) && ( m_ClipPlane.normal[1] == 0 ) && ( m_ClipPlane.normal[2] == 0 ) )
|
||||
return;
|
||||
|
||||
Vector normal = m_ClipPlane.normal;
|
||||
|
||||
if( nFlags & DBT_BACK )
|
||||
{
|
||||
VectorNegate( normal );
|
||||
}
|
||||
|
||||
Vector2D planeNormal;
|
||||
|
||||
pRender->TransformNormal( planeNormal, normal );
|
||||
|
||||
if( planeNormal.x <= 0 )
|
||||
{
|
||||
nFlags &= ~DBT_RIGHT;
|
||||
nFlags |= DBT_LEFT;
|
||||
}
|
||||
else if( planeNormal.x > 0 )
|
||||
{
|
||||
nFlags &= ~DBT_LEFT;
|
||||
nFlags |= DBT_RIGHT;
|
||||
}
|
||||
|
||||
if( planeNormal.y <= 0 )
|
||||
{
|
||||
nFlags &= ~DBT_BOTTOM;
|
||||
nFlags |= DBT_TOP;
|
||||
}
|
||||
else if( planeNormal.y > 0 )
|
||||
{
|
||||
nFlags &= ~DBT_TOP;
|
||||
nFlags |= DBT_BOTTOM;
|
||||
}
|
||||
|
||||
DrawBoundsText(pRender, Mins, Maxs, nFlags);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pRender -
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::RenderTool2D(CRender2D *pRender)
|
||||
{
|
||||
if ( IsEmpty() )
|
||||
return;
|
||||
|
||||
// check flag for rendering vertices
|
||||
bool bDrawVerts = ( bool )( Options.view2d.bDrawVertices == TRUE );
|
||||
|
||||
// setup the line to use
|
||||
|
||||
pRender->SetDrawColor( 255, 255, 255 );
|
||||
|
||||
//
|
||||
// render the clipped solids
|
||||
//
|
||||
FOR_EACH_OBJ( m_ClipResults, pos )
|
||||
{
|
||||
CClipGroup *pClipGroup = m_ClipResults.Element( pos );
|
||||
CMapSolid *pClipBack = pClipGroup->GetClipSolid( CClipGroup::BACK );
|
||||
CMapSolid *pClipFront = pClipGroup->GetClipSolid( CClipGroup::FRONT );
|
||||
if( !pClipBack && !pClipFront )
|
||||
continue;
|
||||
|
||||
//
|
||||
// draw clip solids with the extents
|
||||
//
|
||||
if( pClipBack )
|
||||
{
|
||||
int faceCount = pClipBack->GetFaceCount();
|
||||
for( int i = 0; i < faceCount; i++ )
|
||||
{
|
||||
CMapFace *pFace = pClipBack->GetFace( i );
|
||||
|
||||
// size 4
|
||||
pRender->DrawPolyLine( pFace->nPoints, pFace->Points );
|
||||
|
||||
if ( bDrawVerts )
|
||||
{
|
||||
pRender->DrawHandles( pFace->nPoints, pFace->Points );
|
||||
}
|
||||
|
||||
if( m_bDrawMeasurements )
|
||||
{
|
||||
DrawBrushExtents( pRender, pClipBack, DBT_TOP | DBT_LEFT | DBT_BACK );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pClipFront )
|
||||
{
|
||||
int faceCount = pClipFront->GetFaceCount();
|
||||
for( int i = 0; i < faceCount; i++ )
|
||||
{
|
||||
CMapFace *pFace = pClipFront->GetFace( i );
|
||||
|
||||
pRender->DrawPolyLine( pFace->nPoints, pFace->Points );
|
||||
|
||||
if ( bDrawVerts )
|
||||
{
|
||||
pRender->DrawHandles( pFace->nPoints, pFace->Points );
|
||||
}
|
||||
|
||||
if( m_bDrawMeasurements )
|
||||
{
|
||||
DrawBrushExtents( pRender, pClipFront, DBT_BOTTOM | DBT_RIGHT );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// draw the clip-plane
|
||||
//
|
||||
pRender->SetDrawColor( 0, 255, 255 );
|
||||
pRender->DrawLine( m_ClipPoints[0], m_ClipPoints[1] );
|
||||
|
||||
//
|
||||
// draw the clip-plane endpoints
|
||||
//
|
||||
|
||||
pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_SQUARE );
|
||||
pRender->SetHandleColor( 255, 255, 255 );
|
||||
|
||||
pRender->DrawHandle( m_ClipPoints[0] );
|
||||
pRender->DrawHandle( m_ClipPoints[1] );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Renders the brushes that will be left by the clipper in white
|
||||
// wireframe.
|
||||
// Input : pRender - Rendering interface.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::RenderTool3D( CRender3D *pRender )
|
||||
{
|
||||
// is there anything to render?
|
||||
if( m_bEmpty )
|
||||
return;
|
||||
|
||||
//
|
||||
// setup the renderer
|
||||
//
|
||||
pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
|
||||
|
||||
FOR_EACH_OBJ( m_ClipResults, pos )
|
||||
{
|
||||
CClipGroup *pClipGroup = m_ClipResults.Element( pos );
|
||||
|
||||
CMapSolid *pFrontSolid = pClipGroup->GetClipSolid( CClipGroup::FRONT );
|
||||
if( pFrontSolid )
|
||||
{
|
||||
color32 rgbColor = pFrontSolid->GetRenderColor();
|
||||
pFrontSolid->SetRenderColor(255, 255, 255);
|
||||
pFrontSolid->Render3D(pRender);
|
||||
pFrontSolid->SetRenderColor(rgbColor);
|
||||
}
|
||||
|
||||
CMapSolid *pBackSolid = pClipGroup->GetClipSolid( CClipGroup::BACK );
|
||||
if( pBackSolid )
|
||||
{
|
||||
color32 rgbColor = pBackSolid->GetRenderColor();
|
||||
pBackSolid->SetRenderColor(255, 255, 255);
|
||||
pBackSolid->Render3D(pRender);
|
||||
pBackSolid->SetRenderColor(rgbColor);
|
||||
}
|
||||
}
|
||||
|
||||
pRender->PopRenderMode();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: (virtual imp)
|
||||
// Input : pt -
|
||||
// BOOL -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int Clipper3D::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles)
|
||||
{
|
||||
// check points
|
||||
|
||||
for ( int i=0; i<2;i++ )
|
||||
{
|
||||
if ( HitRect(pView, ptClient, m_ClipPoints[i], HANDLE_RADIUS) )
|
||||
{
|
||||
return i+1; // return clip point index + 1
|
||||
}
|
||||
}
|
||||
|
||||
// neither point hit
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reset (clear) the clip results.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::ResetClipResults( void )
|
||||
{
|
||||
//
|
||||
// delete the clip solids held in the list -- originals are just pointers
|
||||
// to pre-existing objects
|
||||
//
|
||||
FOR_EACH_OBJ( m_ClipResults, pos )
|
||||
{
|
||||
CClipGroup *pClipGroup = m_ClipResults.Element(pos);
|
||||
|
||||
if( pClipGroup )
|
||||
{
|
||||
delete pClipGroup;
|
||||
}
|
||||
}
|
||||
|
||||
m_ClipResults.RemoveAll();
|
||||
|
||||
// the clipping list is empty
|
||||
SetEmpty();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : nChar -
|
||||
// nRepCnt -
|
||||
// nFlags -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Clipper3D::OnKeyDown2D(CMapView2D *pView, UINT nChar, UINT nRepCnt, UINT nFlags)
|
||||
{
|
||||
switch (nChar)
|
||||
{
|
||||
case 'O':
|
||||
{
|
||||
//
|
||||
// Toggle the rendering of measurements.
|
||||
//
|
||||
ToggleMeasurements();
|
||||
return true;
|
||||
}
|
||||
|
||||
case VK_RETURN:
|
||||
{
|
||||
//
|
||||
// Do the clip.
|
||||
//
|
||||
if (!IsEmpty() )
|
||||
{
|
||||
SaveClipResults();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case VK_ESCAPE:
|
||||
{
|
||||
OnEscape();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles left mouse button down events in the 2D view.
|
||||
// Input : Per CWnd::OnLButtonDown.
|
||||
// Output : Returns true if the message was handled, false if not.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Clipper3D::OnLMouseDown2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
|
||||
{
|
||||
Tool3D::OnLMouseDown2D(pView, nFlags, vPoint);
|
||||
|
||||
unsigned int uConstraints = GetConstraints( nFlags );
|
||||
|
||||
//
|
||||
// Convert point to world coords.
|
||||
//
|
||||
Vector vecWorld;
|
||||
pView->ClientToWorld(vecWorld, vPoint);
|
||||
vecWorld[pView->axThird] = COORD_NOTINIT;
|
||||
|
||||
// getvisiblepoint fills in any coord that's still set to COORD_NOTINIT:
|
||||
m_pDocument->GetBestVisiblePoint(vecWorld);
|
||||
|
||||
// snap starting position to grid
|
||||
if ( uConstraints & constrainSnap )
|
||||
m_pDocument->Snap(vecWorld, uConstraints);
|
||||
|
||||
|
||||
bool bStarting = false;
|
||||
|
||||
// if the tool is not empty, and shift is not held down (to
|
||||
// start a new camera), don't do anything.
|
||||
if(!IsEmpty())
|
||||
{
|
||||
// test for clip point hit (result = {0, 1, 2}
|
||||
int hitPoint = HitTest( pView, vPoint );
|
||||
|
||||
if ( hitPoint > 0 )
|
||||
{
|
||||
// test for clip point hit (result = {0, 1, -1})
|
||||
m_ClipPointHit = hitPoint-1; // convert back to index
|
||||
m_vOrgPos = m_ClipPoints[m_ClipPointHit];
|
||||
StartTranslation( pView, vPoint );
|
||||
}
|
||||
else if ( m_vPlaneNormal != pView->GetViewAxis() )
|
||||
{
|
||||
SetEmpty();
|
||||
bStarting = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nFlags & MK_SHIFT)
|
||||
{
|
||||
SetEmpty();
|
||||
bStarting = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true; // do nothing;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bStarting = true;
|
||||
}
|
||||
|
||||
SetClipObjects(m_pDocument->GetSelection()->GetList());
|
||||
|
||||
if (bStarting)
|
||||
{
|
||||
// start the tools translation functionality
|
||||
StartTranslation( pView, vPoint );
|
||||
|
||||
// set the initial clip points
|
||||
m_ClipPointHit = 0;
|
||||
m_ClipPoints[0] = vecWorld;
|
||||
m_ClipPoints[1] = vecWorld;
|
||||
m_vOrgPos = vecWorld;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles left mouse button up events in the 2D view.
|
||||
// Input : Per CWnd::OnLButtonUp.
|
||||
// Output : Returns true if the message was handled, false if not.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Clipper3D::OnLMouseUp2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
|
||||
{
|
||||
Tool3D::OnLMouseUp2D(pView, nFlags, vPoint);
|
||||
|
||||
if ( IsTranslating() )
|
||||
{
|
||||
FinishTranslation(true);
|
||||
}
|
||||
|
||||
m_pDocument->UpdateStatusbar();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int Clipper3D::GetConstraints(unsigned int nKeyFlags)
|
||||
{
|
||||
unsigned int uConstraints = Tool3D::GetConstraints( nKeyFlags );
|
||||
|
||||
if(nKeyFlags & MK_CONTROL)
|
||||
{
|
||||
uConstraints |= constrainMoveAll;
|
||||
}
|
||||
|
||||
return uConstraints;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles mouse move events in the 2D view.
|
||||
// Input : Per CWnd::OnMouseMove.
|
||||
// Output : Returns true if the message was handled, false if not.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Clipper3D::OnMouseMove2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
|
||||
{
|
||||
vgui::HCursor hCursor = vgui::dc_arrow;
|
||||
unsigned int uConstraints = GetConstraints( nFlags );
|
||||
|
||||
Tool3D::OnMouseMove2D(pView, nFlags, vPoint);
|
||||
|
||||
//
|
||||
// Convert to world coords.
|
||||
//
|
||||
Vector vecWorld;
|
||||
pView->ClientToWorld(vecWorld, vPoint);
|
||||
|
||||
//
|
||||
// Update status bar position display.
|
||||
//
|
||||
char szBuf[128];
|
||||
|
||||
if ( uConstraints & constrainSnap )
|
||||
m_pDocument->Snap(vecWorld,uConstraints);
|
||||
|
||||
sprintf(szBuf, " @%.0f, %.0f ", vecWorld[pView->axHorz], vecWorld[pView->axVert]);
|
||||
SetStatusText(SBI_COORDS, szBuf);
|
||||
|
||||
if (IsTranslating())
|
||||
{
|
||||
// cursor is cross here
|
||||
Tool3D::UpdateTranslation( pView, vPoint, uConstraints);
|
||||
|
||||
hCursor = vgui::dc_none;
|
||||
}
|
||||
else if (!IsEmpty())
|
||||
{
|
||||
//
|
||||
// If the cursor is on a handle, set it to a cross.
|
||||
//
|
||||
if (HitTest( pView, vPoint, true))
|
||||
{
|
||||
hCursor = vgui::dc_crosshair;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hCursor != vgui::dc_none )
|
||||
pView->SetCursor( hCursor );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles character events.
|
||||
// Input : Per CWnd::OnKeyDown.
|
||||
// Output : Returns true if the message was handled, false if not.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Clipper3D::OnKeyDown3D(CMapView3D *pView, UINT nChar, UINT nRepCnt, UINT nFlags)
|
||||
{
|
||||
switch (nChar)
|
||||
{
|
||||
case VK_RETURN:
|
||||
{
|
||||
if (!IsEmpty()) // dvs: what does isempty mean for the clipper?
|
||||
{
|
||||
SaveClipResults();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case VK_ESCAPE:
|
||||
{
|
||||
OnEscape();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles the escape key in the 2D or 3D views.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Clipper3D::OnEscape(void)
|
||||
{
|
||||
// If we're clipping, clear it
|
||||
if (!IsEmpty())
|
||||
{
|
||||
SetEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDocument->GetTools()->SetTool(TOOL_POINTER);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user