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.
763 lines
19 KiB
763 lines
19 KiB
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose: Rendering and mouse handling in the 2D view.
|
|
//
|
|
//===========================================================================//
|
|
|
|
#include "stdafx.h"
|
|
#include "hammer.h"
|
|
#include "MapView2D.h"
|
|
#include "MapView3D.h"
|
|
#include "MapDoc.h"
|
|
#include "Render2D.h"
|
|
#include "ToolManager.h"
|
|
#include "History.h"
|
|
#include "TitleWnd.h"
|
|
#include "mainfrm.h"
|
|
#include "MapSolid.h"
|
|
#include "ToolMorph.h" // FIXME: remove
|
|
#include "MapWorld.h"
|
|
#include "camera.h"
|
|
#include "Manifest.h"
|
|
#include "MapInstance.h"
|
|
#include "Options.h"
|
|
#include "..\FoW\FoW.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
|
|
extern bool g_bUpdateBones2D;
|
|
|
|
static DrawType_t __eNextViewType = VIEW2D_XY;
|
|
|
|
|
|
IMPLEMENT_DYNCREATE(CMapView2D, CMapView2DBase)
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CMapView2D, CMapView2DBase)
|
|
//{{AFX_MSG_MAP(CMapView2D)
|
|
ON_WM_KEYDOWN()
|
|
ON_COMMAND(ID_VIEW_2DXY, OnView2dxy)
|
|
ON_COMMAND(ID_VIEW_2DYZ, OnView2dyz)
|
|
ON_COMMAND(ID_VIEW_2DXZ, OnView2dxz)
|
|
ON_COMMAND_EX(ID_TOOLS_ALIGNTOP, OnToolsAlign)
|
|
ON_COMMAND_EX(ID_TOOLS_ALIGNBOTTOM, OnToolsAlign)
|
|
ON_COMMAND_EX(ID_TOOLS_ALIGNLEFT, OnToolsAlign)
|
|
ON_COMMAND_EX(ID_TOOLS_ALIGNRIGHT, OnToolsAlign)
|
|
ON_COMMAND_EX(ID_FLIP_HORIZONTAL, OnFlip)
|
|
ON_COMMAND_EX(ID_FLIP_VERTICAL, OnFlip)
|
|
ON_UPDATE_COMMAND_UI(ID_FLIP_HORIZONTAL, OnUpdateEditSelection)
|
|
ON_UPDATE_COMMAND_UI(ID_FLIP_VERTICAL, OnUpdateEditSelection)
|
|
ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNTOP, OnUpdateEditSelection)
|
|
ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNBOTTOM, OnUpdateEditSelection)
|
|
ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNLEFT, OnUpdateEditSelection)
|
|
ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNRIGHT, OnUpdateEditSelection)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Allows for iteration of draw types in order.
|
|
// Input : eDrawType - Current draw type.
|
|
// Output : Returns the next draw type in the list: XY, YZ, XZ. List wraps.
|
|
//-----------------------------------------------------------------------------
|
|
static DrawType_t NextDrawType(DrawType_t eDrawType)
|
|
{
|
|
if (eDrawType == VIEW2D_XY)
|
|
{
|
|
return(VIEW2D_YZ);
|
|
}
|
|
|
|
if (eDrawType == VIEW2D_YZ)
|
|
{
|
|
return(VIEW2D_XZ);
|
|
}
|
|
|
|
return(VIEW2D_XY);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Allows for iteration of draw types in reverse order.
|
|
// Input : eDrawType - Current draw type.
|
|
// Output : Returns the previous draw type in the list: XY, YZ, XZ. List wraps.
|
|
//-----------------------------------------------------------------------------
|
|
static DrawType_t PrevDrawType(DrawType_t eDrawType)
|
|
{
|
|
if (eDrawType == VIEW2D_XY)
|
|
{
|
|
return(VIEW2D_XZ);
|
|
}
|
|
|
|
if (eDrawType == VIEW2D_YZ)
|
|
{
|
|
return(VIEW2D_XY);
|
|
}
|
|
|
|
return(VIEW2D_YZ);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Constructor. Initializes data members.
|
|
// ---------------------------------------------------------------------------
|
|
CMapView2D::CMapView2D(void)
|
|
{
|
|
//
|
|
// Create next 2d view type.
|
|
//
|
|
__eNextViewType = NextDrawType(__eNextViewType);
|
|
SetDrawType(__eNextViewType);
|
|
|
|
m_bUpdateRenderObjects = true;
|
|
m_bLastActiveView = false;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Destructor. Frees dynamically allocated resources.
|
|
//-----------------------------------------------------------------------------
|
|
CMapView2D::~CMapView2D(void)
|
|
{
|
|
if ( GetMapDoc() )
|
|
{
|
|
GetMapDoc()->RemoveMRU(this);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: First-time initialization of this view.
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::OnInitialUpdate(void)
|
|
{
|
|
// NOTE: This must occur becore OnInitialUpdate
|
|
// Creates the title window
|
|
CreateTitleWindow();
|
|
|
|
// NOTE: This must occur becore OnInitialUpdate
|
|
// Other initialization.
|
|
|
|
|
|
|
|
SetDrawType( GetDrawType() );
|
|
|
|
CMapView2DBase::OnInitialUpdate();
|
|
|
|
// Add to doc's MRU list
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
pDoc->SetMRU(this);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : *pRender -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::DrawPointFile( CRender2D *pRender )
|
|
{
|
|
pRender->SetDrawColor( 255,0,0 );
|
|
|
|
int nPFPoints = GetMapDoc()->m_PFPoints.Count();
|
|
Vector* pPFPoints = GetMapDoc()->m_PFPoints.Base();
|
|
|
|
pRender->MoveTo( pPFPoints[0] );
|
|
|
|
for(int i = 1; i < nPFPoints; i++)
|
|
{
|
|
pRender->DrawLineTo( pPFPoints[i] );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Called when the base class wants the render lists to be recomputed
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::OnRenderListDirty()
|
|
{
|
|
m_bUpdateRenderObjects = true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Sorts the object to be rendered into one of two groups: normal objects
|
|
// and selected objects, so that selected objects can be rendered last.
|
|
// Input : pObject -
|
|
// pRenderList -
|
|
// Output : Returns TRUE on success, FALSE on failure.
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::AddToRenderLists(CMapClass *pObject)
|
|
{
|
|
if ( !pObject->IsVisible() )
|
|
return;
|
|
|
|
// Don't render groups, render their children instead.
|
|
if ( !pObject->IsGroup() )
|
|
{
|
|
if ( !pObject->IsVisible2D() )
|
|
return;
|
|
|
|
Vector vecMins, vecMaxs;
|
|
pObject->GetCullBox( vecMins, vecMaxs );
|
|
|
|
if ( IsValidBox( vecMins, vecMaxs ) )
|
|
{
|
|
// Make sure the object is in the update region.
|
|
if ( !IsInClientView(vecMins, vecMaxs) )
|
|
return;
|
|
}
|
|
|
|
m_RenderList.AddToTail(pObject);
|
|
}
|
|
|
|
// Recurse into children and add them.
|
|
const CMapObjectList *pChildren = pObject->GetChildren();
|
|
FOR_EACH_OBJ( *pChildren, pos )
|
|
{
|
|
AddToRenderLists((CUtlReference< CMapClass >)pChildren->Element(pos));
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: horribly inefficient rendering mechanism for FoW. Demonstration purposes only!
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::RenderFoW( void )
|
|
{
|
|
CRender2D *pRender = GetRender();
|
|
CFoW *pFoW = GetMapDoc()->GetFoW();
|
|
Vector MinCoord, MaxCoord, MinDrawCoord, MaxDrawCoord;
|
|
Vector2D DrawMins, DrawMaxs;
|
|
int GridSize = pFoW->GetHorizontalGridSize();
|
|
int MidPoint = GridSize / 2;
|
|
Color color;
|
|
|
|
pFoW->GetSize( MinCoord, MaxCoord );
|
|
|
|
MinDrawCoord.z = MaxDrawCoord.z = 0;
|
|
// pFoW->SnapCoordsToGrid( m_ViewMin, MinCoord, true );
|
|
// pFoW->SnapCoordsToGrid( m_ViewMax, MaxCoord, false );
|
|
|
|
pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ );
|
|
bool bPopMode = pRender->BeginClientSpace();
|
|
|
|
for( int x = MinCoord.x; x < MaxCoord.x; x += GridSize )
|
|
{
|
|
MinDrawCoord.x = x;
|
|
MaxDrawCoord.x = x + GridSize - 1;
|
|
|
|
for( int y = MinCoord.y; y < MaxCoord.y; y += GridSize )
|
|
{
|
|
float Degree = pFoW->LookupVisibilityDegree( x + MidPoint, y + MidPoint, 0 );
|
|
Degree = ( ( Degree * 0.25f ) + 0.0f ) * 255;
|
|
|
|
if ( Degree >= 0.95f )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
color.SetColor( 255, 0, 255, Degree );
|
|
|
|
pRender->SetDrawColor( color );
|
|
|
|
MaxDrawCoord.y = y;
|
|
MinDrawCoord.y = y + GridSize - 1;
|
|
|
|
pRender->TransformPoint( DrawMins, MinDrawCoord );
|
|
pRender->TransformPoint( DrawMaxs, MaxDrawCoord );
|
|
|
|
pRender->DrawFilledRect( DrawMins, DrawMaxs, ( byte * )&color, false );
|
|
}
|
|
}
|
|
|
|
color.SetColor( 255, 255, 255, 255 );
|
|
pRender->SetDrawColor( color );
|
|
|
|
if ( bPopMode )
|
|
{
|
|
pRender->EndClientSpace();
|
|
}
|
|
pRender->PopRenderMode();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : rectUpdate -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::Render()
|
|
{
|
|
// When in Foundry mode, the engine's vgui loop can cause Hammer's vgui windows to want to be drawn and we don't want that.
|
|
// In any case, don't draw unless we're inside CVGuiWnd::DrawVGuiPanel or else windows and viewports will be all wrong.
|
|
if ( !m_bIsDrawing )
|
|
return;
|
|
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
CMapWorld *pWorld = pDoc->GetMapWorld();
|
|
CManifest *pManifest = pDoc->GetManifest();
|
|
|
|
GetRender()->StartRenderFrame( false );
|
|
|
|
if ( pManifest )
|
|
{
|
|
pWorld = pManifest->GetManifestWorld();
|
|
}
|
|
|
|
|
|
if ( Options.general.bRadiusCulling )
|
|
{
|
|
DrawCullingCircleHelper2D( GetRender() );
|
|
}
|
|
|
|
// Draw grid if enabled.
|
|
if (pDoc->m_bShowGrid)
|
|
{
|
|
DrawGrid( GetRender(), axHorz, axVert, 0 );
|
|
}
|
|
|
|
//
|
|
// Draw the world if we have one.
|
|
//
|
|
if (pWorld == NULL)
|
|
return;
|
|
|
|
// Traverse the entire world, sorting visible elements into two arrays:
|
|
// Normal objects and selected objects, so that we can render the selected
|
|
// objects last.
|
|
//
|
|
|
|
if ( m_bUpdateRenderObjects )
|
|
{
|
|
m_RenderList.RemoveAll();
|
|
|
|
// fill render lists with visible objects
|
|
AddToRenderLists( pWorld );
|
|
|
|
g_bUpdateBones2D = true;
|
|
}
|
|
|
|
//
|
|
// Render normal (nonselected) objects first
|
|
//
|
|
|
|
GetRender()->PrepareInstanceStencil();
|
|
|
|
CUtlVector<CMapClass *> selectedObjects;
|
|
CUtlVector<CMapClass *> helperObjects;
|
|
|
|
for (int i = 0; i < m_RenderList.Count(); i++)
|
|
{
|
|
CMapClass *pObject = m_RenderList[i];
|
|
|
|
if ( pObject->IsSelected() )
|
|
{
|
|
// render later
|
|
if ( pObject->GetToolObject(0,false) )
|
|
{
|
|
helperObjects.AddToTail( pObject );
|
|
}
|
|
else
|
|
{
|
|
selectedObjects.AddToTail( pObject );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// render now
|
|
pObject->Render2D( GetRender() );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Render selected objects in second batch, so they overdraw normal object
|
|
//
|
|
for (int i = 0; i < selectedObjects.Count(); i++)
|
|
{
|
|
selectedObjects[i]->Render2D( GetRender() );
|
|
}
|
|
|
|
GetRender()->DrawInstanceStencil();
|
|
|
|
if ( pDoc->GetFoW() && m_eDrawType == VIEW2D_XY )
|
|
{ // only render the fog of war on the 2d top down view
|
|
RenderFoW();
|
|
}
|
|
|
|
//
|
|
// Draw pointfile if enabled.
|
|
//
|
|
if (pDoc->m_PFPoints.Count())
|
|
{
|
|
DrawPointFile( GetRender() );
|
|
}
|
|
|
|
pDoc->RenderDocument( GetRender() );
|
|
|
|
m_bUpdateRenderObjects = false;
|
|
g_bUpdateBones2D = false;
|
|
|
|
// render all tools
|
|
CBaseTool *pCurTool = m_pToolManager->GetActiveTool();
|
|
|
|
// render active tool
|
|
if ( pCurTool )
|
|
{
|
|
pCurTool->RenderTool2D( GetRender() );
|
|
}
|
|
|
|
// render map helpers at last
|
|
for (int i = 0; i < helperObjects.Count(); i++)
|
|
{
|
|
helperObjects[i]->Render2D( GetRender() );
|
|
}
|
|
|
|
GetRender()->EndRenderFrame();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: this function will render an instance map at the specific offset and rotation
|
|
// Input : pInstanceClass - the map class of the func_instance
|
|
// pMapClass - the map class of the world spawn of the instance
|
|
// InstanceOrigin - the translation offset
|
|
// InstanceAngles - the axis rotation
|
|
// Output : none
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::RenderInstance( CMapInstance *pInstanceClass, CMapClass *pMapClass, Vector &InstanceOrigin, QAngle &InstanceAngles )
|
|
{
|
|
if ( !pInstanceClass->IsInstanceVisible() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetRender()->PushInstanceData( pInstanceClass, InstanceOrigin, InstanceAngles );
|
|
|
|
RenderInstanceMapClass_r( pMapClass );
|
|
|
|
GetRender()->PopInstanceData();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: this function will recursively render an instance and all of its children
|
|
// Input : pObject - the object to be rendered
|
|
// Output : none
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::RenderInstanceMapClass_r( CMapClass *pObject )
|
|
{
|
|
if ( !pObject->IsVisible() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Don't render groups, render their children instead.
|
|
if ( !pObject->IsGroup() )
|
|
{
|
|
if ( !pObject->IsVisible2D() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Vector vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs, vecOrigin;
|
|
pObject->GetCullBox( vecMins, vecMaxs );
|
|
GetRender()->TransformInstanceAABB( vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs );
|
|
|
|
if ( IsValidBox( vecExpandedMins, vecExpandedMaxs ) )
|
|
{
|
|
// Make sure the object is in the update region.
|
|
if ( !IsInClientView( vecExpandedMins, vecExpandedMaxs ) )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
pObject->Render2D( GetRender() );
|
|
}
|
|
|
|
// Recurse into children and add them.
|
|
const CMapObjectList *pChildren = pObject->GetChildren();
|
|
FOR_EACH_OBJ( *pChildren, pos )
|
|
{
|
|
RenderInstanceMapClass_r((CUtlReference< CMapClass >)pChildren->Element(pos));
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : m_DrawType -
|
|
// bForceUpdate -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::SetDrawType(DrawType_t drawType)
|
|
{
|
|
Vector vOldView;
|
|
|
|
// reset old third axis to selection center level
|
|
m_pCamera->GetViewPoint( vOldView );
|
|
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
|
|
if ( pDoc && !pDoc->GetSelection()->IsEmpty() )
|
|
{
|
|
Vector vCenter;
|
|
pDoc->GetSelection()->GetBoundsCenter( vCenter );
|
|
vOldView[axThird] = vCenter[axThird];
|
|
}
|
|
else
|
|
{
|
|
vOldView[axThird] = 0;
|
|
}
|
|
|
|
switch (drawType)
|
|
{
|
|
case VIEW2D_XY:
|
|
SetAxes(AXIS_X, FALSE, AXIS_Y, TRUE);
|
|
if ( HasTitleWnd() )
|
|
{
|
|
GetTitleWnd()->SetTitle("top (x/y)");
|
|
}
|
|
break;
|
|
|
|
case VIEW2D_YZ:
|
|
SetAxes(AXIS_Y, FALSE, AXIS_Z, TRUE);
|
|
if ( HasTitleWnd() )
|
|
{
|
|
GetTitleWnd()->SetTitle("front (y/z)");
|
|
}
|
|
break;
|
|
|
|
case VIEW2D_XZ:
|
|
SetAxes(AXIS_X, FALSE, AXIS_Z, TRUE);
|
|
if ( HasTitleWnd() )
|
|
{
|
|
GetTitleWnd()->SetTitle("side (x/z)");
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
m_eDrawType = drawType;
|
|
|
|
m_pCamera->SetViewPoint( vOldView );
|
|
|
|
UpdateClientView();
|
|
|
|
if (m_bLastActiveView && GetMapDoc())
|
|
{
|
|
GetMapDoc()->UpdateTitle(this);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::OnView2dxy(void)
|
|
{
|
|
SetDrawType(VIEW2D_XY);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::OnView2dyz(void)
|
|
{
|
|
SetDrawType(VIEW2D_YZ);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::OnView2dxz(void)
|
|
{
|
|
SetDrawType(VIEW2D_XZ);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : bActivate -
|
|
// pActivateView -
|
|
// pDeactiveView -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::ActivateView(bool bActivate)
|
|
{
|
|
CMapView2DBase::ActivateView( bActivate );
|
|
|
|
if ( bActivate )
|
|
{
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
pDoc->SetMRU(this);
|
|
|
|
// tell doc to update title
|
|
m_bLastActiveView = true;
|
|
}
|
|
else
|
|
{
|
|
m_bLastActiveView = false;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : nID -
|
|
// Output : Returns TRUE on success, FALSE on failure.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CMapView2D::OnToolsAlign(UINT nID)
|
|
{
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
CSelection *pSelection = pDoc->GetSelection();
|
|
const CMapObjectList *pSelList = pSelection->GetList();
|
|
|
|
GetHistory()->MarkUndoPosition(pSelList, "Align");
|
|
GetHistory()->Keep(pSelList);
|
|
|
|
// convert nID into the appropriate ID_TOOLS_ALIGNxxx define
|
|
// taking into consideration the orientation of the axes
|
|
if(nID == ID_TOOLS_ALIGNTOP && bInvertVert)
|
|
nID = ID_TOOLS_ALIGNBOTTOM;
|
|
else if(nID == ID_TOOLS_ALIGNBOTTOM && bInvertVert)
|
|
nID = ID_TOOLS_ALIGNTOP;
|
|
else if(nID == ID_TOOLS_ALIGNLEFT && bInvertHorz)
|
|
nID = ID_TOOLS_ALIGNRIGHT;
|
|
else if(nID == ID_TOOLS_ALIGNRIGHT && bInvertHorz)
|
|
nID = ID_TOOLS_ALIGNLEFT;
|
|
|
|
// use boundbox of selection - move all objects to match extreme
|
|
// side of all the objects
|
|
BoundBox box;
|
|
pSelection->GetBounds(box.bmins, box.bmaxs);
|
|
|
|
Vector ptMove( 0, 0, 0 );
|
|
|
|
for (int i = 0; i < pSelList->Count(); i++)
|
|
{
|
|
CMapClass *pObject = (CUtlReference< CMapClass >)pSelList->Element(i);
|
|
|
|
Vector vecMins;
|
|
Vector vecMaxs;
|
|
pObject->GetRender2DBox(vecMins, vecMaxs);
|
|
|
|
// align top
|
|
if (nID == ID_TOOLS_ALIGNTOP)
|
|
{
|
|
ptMove[axVert] = box.bmins[axVert] - vecMins[axVert];
|
|
}
|
|
else if (nID == ID_TOOLS_ALIGNBOTTOM)
|
|
{
|
|
ptMove[axVert] = box.bmaxs[axVert] - vecMaxs[axVert];
|
|
}
|
|
else if (nID == ID_TOOLS_ALIGNLEFT)
|
|
{
|
|
ptMove[axHorz] = box.bmins[axHorz] - vecMins[axHorz];
|
|
}
|
|
else if (nID == ID_TOOLS_ALIGNRIGHT)
|
|
{
|
|
ptMove[axHorz] = box.bmaxs[axHorz] - vecMaxs[axHorz];
|
|
}
|
|
pObject->TransMove(ptMove);
|
|
}
|
|
|
|
pDoc->SetModifiedFlag();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Flips the selection horizontally or vertically (with respect to the
|
|
// view orientation.
|
|
// Input : nID -
|
|
// Output : Returns TRUE on success, FALSE on failure.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CMapView2D::OnFlip(UINT nID)
|
|
{
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
CSelection *pSelection = pDoc->GetSelection();
|
|
const CMapObjectList *pSelList = pSelection->GetList();
|
|
|
|
if ( pSelection->IsEmpty() )
|
|
{
|
|
return TRUE; // no selection
|
|
}
|
|
|
|
// flip objects from center of selection
|
|
Vector ptRef, vScale(1,1,1);
|
|
pSelection->GetBoundsCenter(ptRef);
|
|
|
|
// never about this axis:
|
|
if (nID == ID_FLIP_HORIZONTAL)
|
|
{
|
|
vScale[axHorz] = -1;
|
|
}
|
|
else if (nID == ID_FLIP_VERTICAL)
|
|
{
|
|
vScale[axVert] = -1;
|
|
}
|
|
|
|
GetHistory()->MarkUndoPosition( pSelList, "Flip Objects");
|
|
GetHistory()->Keep(pSelList);
|
|
|
|
// do flip
|
|
for (int i = 0; i < pSelList->Count(); i++)
|
|
{
|
|
CMapClass *pObject = (CUtlReference< CMapClass >)pSelList->Element(i);
|
|
pObject->TransScale(ptRef,vScale);
|
|
}
|
|
|
|
pDoc->SetModifiedFlag();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Manages the state of the Copy menu item.
|
|
//-----------------------------------------------------------------------------
|
|
void CMapView2D::OnUpdateEditSelection(CCmdUI *pCmdUI)
|
|
{
|
|
pCmdUI->Enable((!GetMapDoc()->GetSelection()->IsEmpty()) &&
|
|
(m_pToolManager->GetActiveToolID() != TOOL_FACEEDIT_MATERIAL) &&
|
|
!GetMainWnd()->IsShellSessionActive());
|
|
}
|
|
|
|
void CMapView2D::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_TAB)
|
|
{
|
|
// swicth to next draw type
|
|
SetDrawType( NextDrawType( m_eDrawType ) );
|
|
return;
|
|
}
|
|
|
|
CMapView2DBase::OnKeyDown( nChar, nRepCnt, nFlags );
|
|
}
|
|
|
|
void CMapView2D::DrawCullingCircleHelper2D( CRender2D *pRender )
|
|
{
|
|
CMapDoc *pDoc = GetMapDoc();
|
|
|
|
POSITION viewpos = pDoc->GetFirstViewPosition();
|
|
|
|
while ( viewpos )
|
|
{
|
|
CMapView3D *pView = dynamic_cast<CMapView3D*>( pDoc->GetNextView( viewpos ) );
|
|
if ( pView )
|
|
{
|
|
CCamera *pCamera = pView->GetCamera();
|
|
|
|
Vector cameraPos;
|
|
pCamera->GetViewPoint( cameraPos );
|
|
int iClipDist = (int)pCamera->GetFarClip();
|
|
|
|
pRender->SetDrawColor( 255, 0, 0 );
|
|
pRender->DrawCircle( cameraPos, iClipDist );
|
|
}
|
|
}
|
|
}
|
|
|
|
|