//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Base decorator class to make a DME renderable // //===========================================================================// #ifndef DMERENDERABLE_H #define DMERENDERABLE_H #ifdef _WIN32 #pragma once #endif #include "iclientunknown.h" #include "iclientrenderable.h" #include "datamodel/dmelement.h" #include "datamodel/dmattributevar.h" #include "mathlib/mathlib.h" #include "basehandle.h" #include "toolutils/enginetools_int.h" #include "engine/iclientleafsystem.h" #include "datamodel/dmelementfactoryhelper.h" //----------------------------------------------------------------------------- // Deals with the base implementation for turning a Dme into a renderable //----------------------------------------------------------------------------- template < class T > class CDmeRenderable : public T, public IClientUnknown, public IClientRenderable { DEFINE_UNINSTANCEABLE_ELEMENT( CDmeRenderable, T ); protected: virtual void OnAttributeChanged( CDmAttribute *pAttribute ); // IClientUnknown implementation. public: virtual void SetRefEHandle( const CBaseHandle &handle ); virtual const CBaseHandle& GetRefEHandle() const; virtual IClientUnknown* GetIClientUnknown() { return this; } virtual ICollideable* GetCollideable() { return 0; } virtual IClientRenderable* GetClientRenderable() { return this; } virtual IClientNetworkable* GetClientNetworkable() { return 0; } virtual IClientEntity* GetIClientEntity() { return 0; } virtual C_BaseEntity* GetBaseEntity() { return 0; } virtual IClientThinkable* GetClientThinkable() { return 0; } // virtual const Vector & GetRenderOrigin( void ) { return vec3_origin; } // virtual const QAngle & GetRenderAngles( void ) { return vec3_angle; } virtual bool ShouldDraw( void ) { return false; } virtual bool IsTransparent( void ) { return false; } virtual bool IsTwoPass( void ) { return false; } virtual void OnThreadedDrawSetup() {} virtual bool UsesPowerOfTwoFrameBufferTexture() { return false; } virtual bool UsesFullFrameBufferTexture() { return false; } virtual ClientShadowHandle_t GetShadowHandle() const; virtual ClientRenderHandle_t& RenderHandle(); virtual int GetBody() { return 0; } virtual int GetSkin() { return 0; } virtual const model_t* GetModel( ) const { return NULL; } // virtual int DrawModel( int flags ); virtual void ComputeFxBlend( ) { return; } virtual int GetFxBlend( ) { return 255; } virtual bool LODTest() { return true; } virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime ) { return true; } virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights ) {} virtual bool UsesFlexDelayedWeights() { return false; } virtual void DoAnimationEvents( void ) {} virtual IPVSNotify* GetPVSNotifyInterface() { return NULL; } virtual void GetRenderBoundsWorldspace( Vector& absMins, Vector& absMaxs ); virtual void GetColorModulation( float* color ); // virtual void GetRenderBounds( Vector& mins, Vector& maxs ); virtual bool ShouldReceiveProjectedTextures( int flags ) { return false; } virtual bool GetShadowCastDistance( float *pDist, ShadowType_t shadowType ) const { return false; } virtual bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const { return false; } virtual void GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType ); virtual bool IsShadowDirty( ) { return false; } virtual void MarkShadowDirty( bool bDirty ) {} virtual IClientRenderable *GetShadowParent() { return NULL; } virtual IClientRenderable *FirstShadowChild(){ return NULL; } virtual IClientRenderable *NextShadowPeer() { return NULL; } virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; } virtual void CreateModelInstance() {} virtual ModelInstanceHandle_t GetModelInstance() { return MODEL_INSTANCE_INVALID; } virtual const matrix3x4_t &RenderableToWorldTransform(); virtual int LookupAttachment( const char *pAttachmentName ) { return -1; } virtual bool GetAttachment( int number, Vector &origin, QAngle &angles ); virtual bool GetAttachment( int number, matrix3x4_t &matrix ); virtual float *GetRenderClipPlane() { return NULL; } virtual void RecordToolMessage() {} virtual bool IgnoresZBuffer( void ) const { return false; } // Add/remove to engine from drawing void DrawInEngine( bool bDrawInEngine ); bool IsDrawingInEngine() const; protected: virtual CDmAttribute* GetVisibilityAttribute() { return NULL; } virtual CDmAttribute* GetDrawnInEngineAttribute() { return m_bWantsToBeDrawnInEngine.GetAttribute(); } Vector m_vecRenderOrigin; QAngle m_angRenderAngles; protected: CDmaVar m_bWantsToBeDrawnInEngine; bool m_bIsDrawingInEngine; CBaseHandle m_RefEHandle; // Reference ehandle. Used to generate ehandles off this entity. ClientRenderHandle_t m_hRenderHandle; }; //----------------------------------------------------------------------------- // Construction, destruction //----------------------------------------------------------------------------- template < class T > void CDmeRenderable::OnConstruction() { m_hRenderHandle = INVALID_CLIENT_RENDER_HANDLE; m_bWantsToBeDrawnInEngine.InitAndSet( this, "wantsToBeDrawnInEngine", false, FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK ); m_bIsDrawingInEngine = false; } template < class T > void CDmeRenderable::OnDestruction() { if ( m_bIsDrawingInEngine ) { if ( clienttools ) { clienttools->RemoveClientRenderable( this ); } m_bIsDrawingInEngine = false; } } //----------------------------------------------------------------------------- // EHandles //----------------------------------------------------------------------------- template < class T > void CDmeRenderable::SetRefEHandle( const CBaseHandle &handle ) { m_RefEHandle = handle; } template < class T > const CBaseHandle& CDmeRenderable::GetRefEHandle() const { return m_RefEHandle; } //----------------------------------------------------------------------------- // Add/remove to engine from drawing //----------------------------------------------------------------------------- template < class T > void CDmeRenderable::DrawInEngine( bool bDrawInEngine ) { m_bWantsToBeDrawnInEngine = bDrawInEngine; } template < class T > bool CDmeRenderable::IsDrawingInEngine() const { return m_bIsDrawingInEngine; } //----------------------------------------------------------------------------- // Called when attributes changed //----------------------------------------------------------------------------- template < class T > void CDmeRenderable::OnAttributeChanged( CDmAttribute *pAttribute ) { T::OnAttributeChanged( pAttribute ); CDmAttribute *pVisibilityAttribute = GetVisibilityAttribute(); if ( pAttribute == pVisibilityAttribute || pAttribute == m_bWantsToBeDrawnInEngine.GetAttribute() ) { bool bIsVisible = pVisibilityAttribute ? pVisibilityAttribute->GetValue() : true; bool bShouldDrawInEngine = m_bWantsToBeDrawnInEngine && bIsVisible; if ( m_bIsDrawingInEngine != bShouldDrawInEngine ) { m_bIsDrawingInEngine = bShouldDrawInEngine; if ( clienttools ) { if ( m_bIsDrawingInEngine ) { clienttools->AddClientRenderable( this, IsTransparent() ? RENDER_GROUP_TRANSLUCENT_ENTITY : RENDER_GROUP_OPAQUE_ENTITY ); } else { clienttools->RemoveClientRenderable( this ); } } } } } //----------------------------------------------------------------------------- // Color modulation //----------------------------------------------------------------------------- template < class T > void CDmeRenderable::GetColorModulation( float* color ) { Assert(color); color[0] = color[1] = color[2] = 1.0f; } //----------------------------------------------------------------------------- // Attachments //----------------------------------------------------------------------------- template < class T > bool CDmeRenderable::GetAttachment( int number, Vector &origin, QAngle &angles ) { origin = GetRenderOrigin(); angles = GetRenderAngles(); return true; } template < class T > bool CDmeRenderable::GetAttachment( int number, matrix3x4_t &matrix ) { MatrixCopy( RenderableToWorldTransform(), matrix ); return true; } //----------------------------------------------------------------------------- // Other methods //----------------------------------------------------------------------------- template < class T > void CDmeRenderable::GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType ) { GetRenderBounds( mins, maxs ); } template < class T > inline ClientShadowHandle_t CDmeRenderable::GetShadowHandle() const { return CLIENTSHADOW_INVALID_HANDLE; } template < class T > inline ClientRenderHandle_t& CDmeRenderable::RenderHandle() { return m_hRenderHandle; } template < class T > void CDmeRenderable::GetRenderBoundsWorldspace( Vector& absMins, Vector& absMaxs ) { Vector mins, maxs; GetRenderBounds( mins, maxs ); // FIXME: Should I just use a sphere here? // Another option is to pass the OBB down the tree; makes for a better fit // Generate a world-aligned AABB const QAngle& angles = GetRenderAngles(); const Vector& origin = GetRenderOrigin(); if ( angles == vec3_angle ) { VectorAdd( mins, origin, absMins ); VectorAdd( maxs, origin, absMaxs ); } else { matrix3x4_t boxToWorld; AngleMatrix( angles, origin, boxToWorld ); TransformAABB( boxToWorld, mins, maxs, absMins, absMaxs ); } Assert( absMins.IsValid() && absMaxs.IsValid() ); } template < class T > const matrix3x4_t &CDmeRenderable::RenderableToWorldTransform() { static matrix3x4_t mat; AngleMatrix( GetRenderAngles(), GetRenderOrigin(), mat ); return mat; } //----------------------------------------------------------------------------- // Adds a 'visibility' attribute onto renderables that need it //----------------------------------------------------------------------------- template < class T > class CDmeVisibilityControl : public T { DEFINE_UNINSTANCEABLE_ELEMENT( CDmeVisibilityControl, T ); public: // Control visibility bool IsVisible() const; void SetVisible( bool bVisible ); private: virtual CDmAttribute* GetVisibilityAttribute() { return m_bIsVisible.GetAttribute(); } CDmaVar< bool > m_bIsVisible; }; //----------------------------------------------------------------------------- // Construction, destruction //----------------------------------------------------------------------------- template < class T > void CDmeVisibilityControl::OnConstruction() { m_bIsVisible.InitAndSet( this, "visible", true, FATTRIB_HAS_CALLBACK ); } template < class T > void CDmeVisibilityControl::OnDestruction() { } //----------------------------------------------------------------------------- // Deal with visibility //----------------------------------------------------------------------------- template < class T > void CDmeVisibilityControl::SetVisible( bool bVisible ) { if ( bVisible != m_bIsVisible ) { m_bIsVisible = bVisible; } } template < class T > bool CDmeVisibilityControl::IsVisible() const { return m_bIsVisible; } #endif // DMERENDERABLE_H