diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/mapview2d.cpp | |
| download | archived-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.cpp | 690 |
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 ); + } + } +} + + |