//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef MAPOVERLAY_H #define MAPOVERLAY_H #pragma once #include #include "utlvector.h" #include "MapSideList.h" class CHelperInfo; class CMapFace; class CRender3D; class CMapView; class IEditorTexture; #define OVERLAY_HANDLES_COUNT 4 #define NUM_CLIPFACE_TEXCOORDS 2 #define OVERLAY_TYPE_GENERIC 0x01 #define OVERLAY_TYPE_SHORE 0x02 //============================================================================= // // Class Map Overlay // class CMapOverlay : public CMapSideList { public: DECLARE_MAPCLASS( CMapOverlay, CMapSideList ); // Construction/Deconstruction. CMapOverlay(); ~CMapOverlay(); // Factory for building from a list of string parameters. static CMapClass *CreateMapOverlay( CHelperInfo *pInfo, CMapEntity *pParent ); // Virtual/Interface Implementation. virtual void PostloadWorld( CMapWorld *pWorld ); virtual CMapClass *Copy( bool bUpdateDependencies ); virtual CMapClass *CopyFrom( CMapClass *pObject, bool bUpdateDependencies ); void CalcBounds( BOOL bFullUpdate = FALSE ); virtual void OnParentKeyChanged( const char* szKey, const char* szValue ); virtual void OnNotifyDependent( CMapClass *pObject, Notify_Dependent_t eNotifyType ); void DoTransform( const VMatrix &matrix ); void OnPaste( CMapClass *pCopy, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList); void OnClone( CMapClass *pClone, CMapWorld *pWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList ); void OnUndoRedo( void ); void Render3D( CRender3D *pRender ); // Overlay. void HandlesReset( void ); bool HandlesHitTest( CMapView *pView, const Vector2D &vPoint ); void HandlesDragTo( Vector &vecImpact, CMapFace *pFace ); void HandleMoveTo( int iHandle, Vector &vecPoint, CMapFace *pFace ); void SetTexCoords( Vector2D vecTexCoords[4] ); void GetHandlePos( int iHandle, Vector &vecPos ); bool IsSelected( void ) { return ( GetSelectionState() == SELECT_NORMAL ); } void DoClip( void ); void CenterEntity( void ); void GetPlane( cplane_t &plane ); int GetFaceCount( void ) { return m_Faces.Count(); } CMapFace *GetFace( int iFace ) { return m_Faces.Element( iFace ); } void SetMaterial( const char *szMaterialName ); void SetMaterial( IEditorTexture *pTexture ) { m_Material.m_pTexture = pTexture; } IEditorTexture* GetMaterial() { return m_Material.m_pTexture; } // Creation. void Basis_Init( CMapFace *pFace ); void Handles_Init( CMapFace *pFace ); void SideList_Init( CMapFace *pFace ); void SideList_AddFace( CMapFace *pFace ); void SetLoaded( bool bLoaded ) { m_bLoaded = bLoaded; } // Attributes. inline virtual bool IsVisualElement( void ) { return true; } inline virtual bool ShouldRenderLast( void ) { return true; } inline const char* GetDescription() { return ( "Overlay" ); } void SetOverlayType( unsigned short uiType ) { m_uiFlags |= uiType; } void ResetOverlayType( unsigned short uiType ) { m_uiFlags &= ~uiType; } unsigned short GetOverlayType( void ) { return m_uiFlags; } ChunkFileResult_t SaveDataToVMF( CChunkFile *pFile, CSaveInfo *pSaveInfo ); private: //========================================================================= // // Basis Data // struct Basis_t { CMapFace *m_pFace; // Index to the face the basis were derived from Vector m_vecOrigin; // Origin of basis vectors (in plane) Vector m_vecAxes[3]; // Basis vectors int m_nAxesFlip[3]; // u, v, n flip values (3 bits x,y,z) - saved off the z components of the first 3 uv points }; void Basis_Clear( void ); void Basis_SetFace( CMapFace *pFace ); void Basis_UpdateOrigin( void ); void Basis_BuildAxes( void ); void Basis_SetInitialUAxis( Vector const &vecNormal ); bool Basis_IsValid( void ); void Basis_Copy( Basis_t *pSrc, Basis_t *pDst ); void Basis_UpdateParentKey( void ); // Legacy support. void Basis_BuildFromSideList( void ); void Basis_ToggleAxesFlip( int iAxis, int iComponent ); bool Basis_IsFlipped( int iAxis, int iComponent ); //========================================================================= // // Handle Data // struct Handles_t { int m_iHit; // Index of the selected handle Vector2D m_vecBasisCoords[OVERLAY_HANDLES_COUNT]; // U,V coordinates of the 4 corners in the editable plane (use basis) Vector m_vec3D[OVERLAY_HANDLES_COUNT]; // World space handles for snap testing }; void Handles_Clear( void ); void Handles_Build3D(); void Handles_Render3D( CRender3D *pRender ); void Handles_SurfToOverlayPlane( CMapFace *pFace, Vector const &vSurf, Vector &vPoint ); void Handles_Copy( Handles_t *pSrc, Handles_t *pDst ); void Handles_UpdateParentKey( void ); void Handles_FixOrder(); //========================================================================= // // ClipFace Data // struct BlendData_t { void Init() { m_nType = 0; memset(m_iPoints, 0, sizeof(m_iPoints)); memset(m_flBlends, 0, sizeof(m_flBlends)); } int m_nType; // type of blend (point, edge, barycentric) short m_iPoints[3]; // displacement point indices float m_flBlends[3]; // blending values }; struct ClipFace_t { CMapFace *m_pBuildFace; int m_nPointCount; CUtlVector m_aPoints; CUtlVector m_aDispPointUVs; // z is always 0 (need to be this way to share functions!) CUtlVector m_aTexCoords[NUM_CLIPFACE_TEXCOORDS]; CUtlVector m_aBlends; ClipFace_t() { m_pBuildFace = NULL; m_nPointCount = 0; } ~ClipFace_t() { m_aPoints.Purge(); m_aDispPointUVs.Purge(); m_aBlends.Purge(); for ( int iCoord = 0; iCoord < NUM_CLIPFACE_TEXCOORDS; ++iCoord ) { m_aTexCoords[iCoord].Purge(); } } }; typedef CUtlVector ClipFaces_t; ClipFace_t *ClipFace_Create( int nSize ); void ClipFace_Destroy( ClipFace_t **ppClipFace ); ClipFace_t *ClipFace_Copy( ClipFace_t *pSrc ); void ClipFace_GetBounds( ClipFace_t *pClipFace, Vector &vecMin, Vector &vecMax ); void ClipFace_Clip( ClipFace_t *pClipFace, cplane_t *pClipPlane, float flEpsilon, ClipFace_t **ppFront, ClipFace_t **ppBack ); void ClipFace_ClipBarycentric( ClipFace_t *pClipFace, cplane_t *pClipPlane, float flEpsilon, int iClip, CMapDisp *pDisp, ClipFace_t **ppFront, ClipFace_t **ppBack ); void ClipFace_PreClipDisp( ClipFace_t *pClipFace, CMapDisp *pDisp ); void ClipFace_PostClipDisp( void ); void ClipFace_ResolveBarycentricClip( CMapDisp *pDisp, ClipFace_t *pClipFace, int iClipFacePoint, const Vector2D &vecPointUV, float *pCoefs, int *pTris, Vector2D *pVertsUV ); bool ClipFace_CalcBarycentricCooefs( CMapDisp *pDisp, Vector2D *pVertsUV, const Vector2D &vecPointUV, float *pCoefs ); int ClipFace_GetAxisType( cplane_t *pClipPlane ); void ClipFace_BuildBlend( ClipFace_t *pClipFace, CMapDisp *pDisp, cplane_t *pClipPlane, int iClip, const Vector &vecUV, const Vector &vecPoint ); void ClipFace_CopyBlendFrom( ClipFace_t *pClipFace, BlendData_t *pBlendFrom ); void ClipFace_BuildFacesFromBlendedData( ClipFace_t *pClipFace ); //========================================================================= // // Material Functions // struct Material_t { IEditorTexture *m_pTexture; // material Vector2D m_vecTextureU; // material starting and ending U Vector2D m_vecTextureV; // material starting and ending V }; void Material_Clear( void ); void Material_Copy( Material_t *pSrc, Material_t *pDst ); void Material_TexCoordInit( void ); void Material_UpdateParentKey( void ); //========================================================================= // // Clipping // void PreClip( void ); void PostClip( void ); void DoClipFace( CMapFace *pFace ); void DoClipDisp( CMapFace *pFace, ClipFace_t *pClippedFace ); void DoClipDispInV( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces ); void DoClipDispInU( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces ); void DoClipDispInUVFromTLToBR( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces ); void DoClipDispInUVFromBLToTR( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces ); void Disp_ClipFragments( CMapDisp *pDisp, ClipFaces_t &aDispFragments ); void Disp_DoClip( CMapDisp *pDisp, ClipFaces_t &aDispFragments, cplane_t &clipPlane, float clipDistStart, int nInterval, int nLoopStart, int nLoopEnd, int nLoopInc ); //========================================================================== // // Transform // // Utility void OverlayUVToOverlayPlane( const Vector2D &vecUV, Vector &vecPoint ); void OverlayPlaneToOverlayUV( const Vector &vecPoint, Vector2D &vecUV ); void WorldToOverlayPlane( const Vector &vecWorld, Vector &vecPoint ); void OverlayPlaneToWorld( CMapFace *pFace, const Vector &vecPlane, Vector &vecWorld ); void OverlayPlaneToSurfFromList( const Vector &vecOverlayPoint, Vector &vecSurfPoint ); bool EntityOnSurfFromListToBaseFacePlane( const Vector &vecWorldPoint, Vector &vecBasePoint ); bool BuildEdgePlanes( Vector const *pPoints, int pointCount, cplane_t *pEdgePlanes, int edgePlaneCount ); void UpdateDispBarycentric( void ); void PostModified( void ); void GetTriVerts( CMapDisp *pDisp, const Vector2D &vecSurfUV, int *pTris, Vector2D *pVertsUV ); private: Basis_t m_Basis; // Overlay Basis Data Handles_t m_Handles; // Overlay Handle Data Material_t m_Material; // Overlay Material ClipFace_t *m_pOverlayFace; // Primary Overlay ClipFaces_t m_aRenderFaces; // Clipped Face Cache (Render Faces) unsigned short m_uiFlags; // bool m_bLoaded; }; #endif // MAPOVERLAY_H