summaryrefslogtreecommitdiff
path: root/hammer/mapview2d.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/mapview2d.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'hammer/mapview2d.cpp')
-rw-r--r--hammer/mapview2d.cpp690
1 files changed, 690 insertions, 0 deletions
diff --git a/hammer/mapview2d.cpp b/hammer/mapview2d.cpp
new file mode 100644
index 0000000..e304b34
--- /dev/null
+++ b/hammer/mapview2d.cpp
@@ -0,0 +1,690 @@
+//========= Copyright 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"
+
+// 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(pChildren->Element(pos));
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : rectUpdate -
+//-----------------------------------------------------------------------------
+void CMapView2D::Render()
+{
+
+ CMapDoc *pDoc = GetMapDoc();
+ CMapWorld *pWorld = pDoc->GetMapWorld();
+ CManifest *pManifest = pDoc->GetManifest();
+
+ if ( pManifest )
+ {
+ pWorld = pManifest->GetManifestWorld();
+ }
+
+ GetRender()->StartRenderFrame();
+
+ 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();
+
+ //
+ // 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;
+ 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(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;
+ GetMapDoc()->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 = 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 = 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 );
+ }
+ }
+}
+
+