You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
11 KiB
341 lines
11 KiB
5 years ago
|
//========= 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<bool> 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<T>::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<T>::OnDestruction()
|
||
|
{
|
||
|
if ( m_bIsDrawingInEngine )
|
||
|
{
|
||
|
if ( clienttools )
|
||
|
{
|
||
|
clienttools->RemoveClientRenderable( this );
|
||
|
}
|
||
|
m_bIsDrawingInEngine = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// EHandles
|
||
|
//-----------------------------------------------------------------------------
|
||
|
template < class T >
|
||
|
void CDmeRenderable<T>::SetRefEHandle( const CBaseHandle &handle )
|
||
|
{
|
||
|
m_RefEHandle = handle;
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
const CBaseHandle& CDmeRenderable<T>::GetRefEHandle() const
|
||
|
{
|
||
|
return m_RefEHandle;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Add/remove to engine from drawing
|
||
|
//-----------------------------------------------------------------------------
|
||
|
template < class T >
|
||
|
void CDmeRenderable<T>::DrawInEngine( bool bDrawInEngine )
|
||
|
{
|
||
|
m_bWantsToBeDrawnInEngine = bDrawInEngine;
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
bool CDmeRenderable<T>::IsDrawingInEngine() const
|
||
|
{
|
||
|
return m_bIsDrawingInEngine;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Called when attributes changed
|
||
|
//-----------------------------------------------------------------------------
|
||
|
template < class T >
|
||
|
void CDmeRenderable<T>::OnAttributeChanged( CDmAttribute *pAttribute )
|
||
|
{
|
||
|
T::OnAttributeChanged( pAttribute );
|
||
|
CDmAttribute *pVisibilityAttribute = GetVisibilityAttribute();
|
||
|
if ( pAttribute == pVisibilityAttribute || pAttribute == m_bWantsToBeDrawnInEngine.GetAttribute() )
|
||
|
{
|
||
|
bool bIsVisible = pVisibilityAttribute ? pVisibilityAttribute->GetValue<bool>() : 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<T>::GetColorModulation( float* color )
|
||
|
{
|
||
|
Assert(color);
|
||
|
color[0] = color[1] = color[2] = 1.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Attachments
|
||
|
//-----------------------------------------------------------------------------
|
||
|
template < class T >
|
||
|
bool CDmeRenderable<T>::GetAttachment( int number, Vector &origin, QAngle &angles )
|
||
|
{
|
||
|
origin = GetRenderOrigin();
|
||
|
angles = GetRenderAngles();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
bool CDmeRenderable<T>::GetAttachment( int number, matrix3x4_t &matrix )
|
||
|
{
|
||
|
MatrixCopy( RenderableToWorldTransform(), matrix );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Other methods
|
||
|
//-----------------------------------------------------------------------------
|
||
|
template < class T >
|
||
|
void CDmeRenderable<T>::GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType )
|
||
|
{
|
||
|
GetRenderBounds( mins, maxs );
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
inline ClientShadowHandle_t CDmeRenderable<T>::GetShadowHandle() const
|
||
|
{
|
||
|
return CLIENTSHADOW_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
inline ClientRenderHandle_t& CDmeRenderable<T>::RenderHandle()
|
||
|
{
|
||
|
return m_hRenderHandle;
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
void CDmeRenderable<T>::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<T>::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<T>::OnConstruction()
|
||
|
{
|
||
|
m_bIsVisible.InitAndSet( this, "visible", true, FATTRIB_HAS_CALLBACK );
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
void CDmeVisibilityControl<T>::OnDestruction()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Deal with visibility
|
||
|
//-----------------------------------------------------------------------------
|
||
|
template < class T >
|
||
|
void CDmeVisibilityControl<T>::SetVisible( bool bVisible )
|
||
|
{
|
||
|
if ( bVisible != m_bIsVisible )
|
||
|
{
|
||
|
m_bIsVisible = bVisible;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
bool CDmeVisibilityControl<T>::IsVisible() const
|
||
|
{
|
||
|
return m_bIsVisible;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#endif // DMERENDERABLE_H
|