//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //===========================================================================// #ifndef C_FUNC_BREAKABLESURF_H #define C_FUNC_BREAKABLESURF_H #ifdef _WIN32 #pragma once #endif #include "iviewrender.h" #include "proxyentity.h" #define MAX_NUM_PANELS 16 #define NUM_EDGE_TYPES 4 #define NUM_EDGE_STYLES 3 extern IVDebugOverlay *debugoverlay; enum WinSide_t { WIN_SIDE_BOTTOM, WIN_SIDE_RIGHT, WIN_SIDE_TOP, WIN_SIDE_LEFT, }; enum WinEdge_t { EDGE_NOT = -1, // No edge EDGE_NONE, /* No edge on both sides /##\ */ EDGE_FULL, // Edge on both sides |##| EDGE_LEFT, /* Edge is on left only |##\ */ EDGE_RIGHT, // Edge is on right only /##| }; #define STYLE_HIGHLIGHT = -1; //----------------------------------------------------------------------------- // All the information associated with a particular handle //----------------------------------------------------------------------------- struct Panel_t { char m_nWidth; char m_nHeight; char m_nSide; char m_nEdgeType; char m_nStyle; }; struct EdgeTexture_t { int m_nRenderIndex; int m_nStyle; CMaterialReference m_pMaterialEdge; CTextureReference m_pMaterialEdgeTexture; }; class C_BreakableSurface : public C_BaseEntity, public IBrushRenderer { public: DECLARE_CLASS( C_BreakableSurface, C_BaseEntity ); DECLARE_DATADESC(); DECLARE_CLIENTCLASS(); int m_nNumWide; int m_nNumHigh; float m_flPanelWidth; float m_flPanelHeight; Vector m_vNormal; Vector m_vCorner; bool m_bIsBroken; int m_nSurfaceType; // This is the texture we're going to use to multiply by the cracked base texture ITexture* m_pCurrentDetailTexture; // Stores linked list of edges to render CUtlLinkedList< Panel_t, unsigned short > m_RenderList; C_BreakableSurface(); ~C_BreakableSurface(); public: void InitMaterial(WinEdge_t nEdgeType, int nEdgeStyle, char const* pMaterialName); virtual void OnDataChanged( DataUpdateType_t updateType ); virtual void OnPreDataChanged( DataUpdateType_t updateType ); RenderableTranslucencyType_t ComputeTranslucencyType( void ); bool HavePanel(int nWidth, int nHeight); bool RenderBrushModelSurface( IClientEntity* pBaseEntity, IBrushSurface* pBrushSurface ); int DrawModel( int flags, const RenderableInstance_t &instance ); void DrawSolidBlocks( IBrushSurface* pBrushSurface ); virtual void OnRestore(); virtual bool ShouldReceiveProjectedTextures( int flags ); private: // One bit per pane CNetworkArray( bool, m_RawPanelBitVec, MAX_NUM_PANELS * MAX_NUM_PANELS ); bool m_PrevRawPanelBitVec[ MAX_NUM_PANELS * MAX_NUM_PANELS ]; // 2 bits of flags and 2 bits of edge type byte m_nPanelBits[MAX_NUM_PANELS][MAX_NUM_PANELS]; //UNDONE: allocate this dynamically? CMaterialReference m_pMaterialBox; EdgeTexture_t m_pSolid; EdgeTexture_t m_pEdge[NUM_EDGE_TYPES][NUM_EDGE_STYLES]; inline bool InLegalRange(int nWidth, int nHeight); inline bool IsPanelSolid(int nWidth, int nHeight); inline bool IsPanelStale(int nWidth, int nHeight); inline void SetPanelSolid(int nWidth, int nHeight, bool value); inline void SetPanelStale(int nWidth, int nHeight, bool value); void DrawOneEdge( IBrushSurface* pBrushSurface, IMesh* pMesh, CMeshBuilder *pMeshBuilder, const Vector &vStartPos, const Vector &vWStep, const Vector &vHstep, WinSide_t nEdge); void DrawOneHighlight( IBrushSurface* pBrushSurface, IMesh* pMesh, CMeshBuilder *pMeshBuilder, const Vector &vStartPos, const Vector &vWStep, const Vector &vHstep, WinSide_t nEdge); void DrawOneBlock(IBrushSurface* pBrushSurface, IMesh* pMesh, CMeshBuilder *pMeshBuilder, const Vector &vPosition, const Vector &vWidth, const Vector &vHeight); void DrawRenderList( IBrushSurface* pBrushSurface); void DrawRenderListHighlights( IBrushSurface* pBrushSurface ); int FindRenderPanel(int nWidth, int nHeight, WinSide_t nSide); void AddToRenderList(int nWidth, int nHeight, WinSide_t nSide, WinEdge_t nEdgeType, int forceStyle); int FindFirstRenderTexture(WinEdge_t nEdgeType, int nStyle); inline void SetStyleType( int w, int h, int type ) { Assert( type < NUM_EDGE_STYLES ); Assert( type >= 0 ); // Clear old value m_nPanelBits[ w ][ h ] &= ( ~0x03 << 2 ); // Insert new value m_nPanelBits[ w ][ h ] |= ( type << 2 ); } inline int GetStyleType( int w, int h ) { int value = m_nPanelBits[ w ][ h ]; value = ( value >> 2 ) & 0x03; Assert( value < NUM_EDGE_STYLES ); return value; } // Gets at the cracked version of the material void FindCrackedMaterial(); CMaterialReference m_pCrackedMaterial; CTextureReference m_pMaterialBoxTexture; void UpdateEdgeType(int nWidth, int nHeight, int forceStyle = -1 ); }; class CBreakableSurfaceProxy : public CEntityMaterialProxy { public: CBreakableSurfaceProxy(); virtual ~CBreakableSurfaceProxy(); virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); virtual void OnBind( C_BaseEntity *pC_BaseEntity ); virtual IMaterial *GetMaterial(); private: // get at the material whose texture we're going to steal void AcquireSourceMaterial( C_BaseEntity* pEnt ); IMaterialVar* m_BaseTextureVar; }; #endif // C_FUNC_BREAKABLESURF_H