|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Clones a physics object by use of shadows
//
// $NoKeywords: $
//=============================================================================//
#ifndef PHYSICSSHADOWCLONE_H
#define PHYSICSSHADOWCLONE_H
#ifdef _WIN32
#pragma once
#endif
#include "vphysics_interface.h"
#include "BaseEntity.h"
#include "baseanimating.h"
class CPhysicsShadowClone;
struct PhysicsObjectCloneLink_t { IPhysicsObject *pSource; IPhysicsShadowController *pShadowController; IPhysicsObject *pClone; };
struct CPhysicsShadowCloneLL { CPhysicsShadowClone *pClone; CPhysicsShadowCloneLL *pNext; };
#define FVPHYSICS_IS_SHADOWCLONE 0x4000
class CPhysicsShadowClone : public CBaseAnimating { DECLARE_CLASS( CPhysicsShadowClone, CBaseAnimating );
private: EHANDLE m_hClonedEntity; //the entity we're supposed to be cloning the physics of
VMatrix m_matrixShadowTransform; //all cloned coordinates and angles will be run through this matrix before being applied
VMatrix m_matrixShadowTransform_Inverse; CUtlVector<PhysicsObjectCloneLink_t> m_CloneLinks; //keeps track of which of our physics objects are linked to the source's objects
bool m_bShadowTransformIsIdentity; //the shadow transform doesn't update often, so we can cache this
bool m_bImmovable; //cloning a track train or door, something that doesn't really work on a force-based level
bool m_bInAssumedSyncState;
void FullSyncClonedPhysicsObjects( bool bTeleport ); void SyncEntity( bool bPullChanges );
IPhysicsEnvironment *m_pOwnerPhysEnvironment; //clones exist because of multi-environment situations
public: CPhysicsShadowClone( void ); virtual ~CPhysicsShadowClone( void ); bool m_bShouldUpSync; DBG_CODE_NOSCOPE( const char *m_szDebugMarker; );
//do the thing with the stuff, you know, the one that goes WooooWooooWooooWooooWoooo
virtual void Spawn( void );
//crush, kill, DESTROY!!!!!
void Free( void );
//syncs to the source entity in every way possible, assumed sync does some rudimentary tests to see if the object is in sync, and if so, skips the update
void FullSync( bool bAllowAssumedSync = false );
//syncs just the physics objects, bPullChanges should be true when this clone should match it's source, false when it should force differences onto the source entity
void PartialSync( bool bPullChanges );
//virtual bool CreateVPhysics( void );
virtual void VPhysicsDestroyObject( void ); virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); virtual int ObjectCaps( void ); virtual void UpdateOnRemove( void );
//routing to the source entity for cloning goodness
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
//avoid blocking traces that are supposed to hit our source entity
virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
//is this clone occupying the exact same space as the object it's cloning?
inline bool IsUntransformedClone( void ) const { return m_bShadowTransformIsIdentity; }; void SetCloneTransformationMatrix( const matrix3x4_t &matTransform );
inline bool IsInAssumedSyncState( void ) const { return m_bInAssumedSyncState; } inline IPhysicsEnvironment *GetOwnerEnvironment( void ) const { return m_pOwnerPhysEnvironment; }
//what entity are we cloning?
void SetClonedEntity( EHANDLE hEntToClone ); EHANDLE GetClonedEntity( void );
virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent );
//damage relays to source entity if anything ever hits the clone
virtual bool PassesDamageFilter( const CTakeDamageInfo &info ); virtual bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker ); virtual int OnTakeDamage( const CTakeDamageInfo &info ); virtual int TakeHealth( float flHealth, int bitsDamageType ); virtual void Event_Killed( const CTakeDamageInfo &info );
static CPhysicsShadowClone *CreateShadowClone( IPhysicsEnvironment *pInPhysicsEnvironment, EHANDLE hEntToClone, const char *szDebugMarker, const matrix3x4_t *pTransformationMatrix = NULL );
//given a physics object that is part of this clone, tells you which physics object in the source
IPhysicsObject *TranslatePhysicsToClonedEnt( const IPhysicsObject *pPhysics );
static bool IsShadowClone( const CBaseEntity *pEntity ); static CPhysicsShadowCloneLL *GetClonesOfEntity( const CBaseEntity *pEntity ); static void FullSyncAllClones( void );
static CUtlVector<CPhysicsShadowClone *> const &g_ShadowCloneList;
friend void DrawDebugOverlayForShadowClone( CPhysicsShadowClone *pClone );
//only really necessary to call for entities that create custom collideables.
static void NotifyDestroy( IPhysicsObject *pDestroyingPhys, CBaseEntity *pOwningEntity = NULL ); //passing in the original owner entity just makes the search faster
static void NotifyDestroy( CPhysCollide *pDestroyingCollide, CBaseEntity *pOwningEntity = NULL ); //passing in the original owner entity just makes the search faster
private: void DestroyClonedPhys( IPhysicsObject *pPhys ); void DestroyClonedCollideable( CPhysCollide *pCollide ); };
class CTraceFilterTranslateClones : public CTraceFilter //give it another filter, and it'll translate shadow clones into their source entity for tests
{ ITraceFilter *m_pActualFilter; //the filter that tests should be forwarded to after translating clones
public: CTraceFilterTranslateClones( ITraceFilter *pOtherFilter ) : m_pActualFilter(pOtherFilter) {}; virtual bool ShouldHitEntity( IHandleEntity *pEntity, int contentsMask ); virtual TraceType_t GetTraceType() const; };
#endif //#ifndef PHYSICSSHADOWCLONE_H
|