source-engine/common/ihfx/ihfxeffect.h

327 lines
12 KiB
C
Raw Normal View History

2020-04-22 16:56:21 +00:00
#ifndef IHFXEFFECT_H_
#define IHFXEFFECT_H_
#include ".\\HFXConfig.h"
#include ".\\IHFXParam.h"
struct IHapticEffectParamGroup;
typedef IHapticEffectParamGroup IHFXParamGroup;
class IProcessor;
typedef IProcessor IHFXProcessor;
class IStack;
typedef IStack IHFXStack;
enum HFXStateBits
{
// when a state variable is made it uses the below value
HFXSTATE_INITIAL =0,
// explicite pause
HFXSTATE_PAUSE =(1<<0),
// explicite mute
HFXSTATE_MUTE =(1<<1),
// the effect has gone into its exit phase.
HFXSTATE_EXITING =(1<<2),
HFXSTATE_WANT_SYNC =(1<<3),
HFXSTATE_CLIENT_ONLY =4,
//everything below will be uncontrolled by servo
HFXSTATE_WANT_UPDATE =(1<<HFXSTATE_CLIENT_ONLY),
HFXSTATE_RUNNING =(1<<(HFXSTATE_CLIENT_ONLY+1)),
HFXSTATE_HAULT =(1<<(HFXSTATE_CLIENT_ONLY+2)),
HFXSTATE_HOLDING_EFFECT =(1<<(HFXSTATE_CLIENT_ONLY+3)),
HFXSTATE_COUNT =8,
// number of state bits before non servo controlled bits
};
typedef unsigned __int8 HFXSTATE;
typedef HFXSTATE HFXStateStorage;
#if WIN64
typedef const HFXStateStorage &HFXStateTransfer;
#else
typedef const HFXStateStorage HFXStateTransfer;
#endif
// utility union, takes up same memory as a flagset but gives you
// inline operators and helper functions for state flags
union HFX_ALIGN(8) HFXStateFlags
{
public:
//default constructor
HFX_INLINE HFXStateFlags(){};
//copy constructor
HFX_INLINE HFXStateFlags(const HFXStateFlags &copy) : Storage(copy.Storage){};
HFX_INLINE HFXStateFlags(HFXStateStorage flags) : Storage(flags){};
HFX_INLINE HFXStateFlags(
bool bRunning, bool bPaused, bool bMuted, bool bHaulted, bool bExiting
) : Storage((bRunning ? HFXSTATE_RUNNING : 0)|
(bPaused ? HFXSTATE_PAUSE : 0)|
(bMuted ? HFXSTATE_MUTE : 0)|
(bHaulted ? HFXSTATE_HAULT : 0)|
(bExiting ? HFXSTATE_EXITING : 0) )
{};
// actual flags. (shared memory)
HFXStateStorage Storage;
// flags in boolean form. (shared memory)
struct {
bool Running:1;
bool Paused:1;
bool Muted:1;
bool Haulted:1;
bool Exiting:1;
};
// flags in bool group ( for -> operator )
struct HFXStateFlagGroup{
bool Running:1;
bool Paused:1;
bool Muted:1;
bool Haulted:1;
bool Exiting:1;
}Flags;
// type cast operators to flagstorage type
HFX_INLINE operator HFXStateStorage &(){return Storage;}
HFX_INLINE operator const HFXStateStorage &()const{return Storage;}
HFX_INLINE operator HFXStateStorage (){return Storage;}
HFX_INLINE operator const HFXStateStorage ()const{return Storage;}
// at operator to get reference of storage.
HFX_INLINE HFXStateStorage &operator *(){return Storage;};
HFX_INLINE const HFXStateStorage &operator *()const{return Storage;};
// bool operator, to see if there are any flags set.
HFX_INLINE bool operator()(int bit){return (Storage & bit)!=0;};
// -> operator to get boolean access flags quickly.
HFX_INLINE HFXStateFlagGroup *operator ->(){return &Flags;};
HFX_INLINE const HFXStateFlagGroup *operator ->()const{return &Flags;};
HFX_INLINE HFXStateStorage *operator &(){return &Storage;};
HFX_INLINE const HFXStateStorage *operator &()const{return &Storage;};
HFX_INLINE HFXStateStorage &operator =(HFXStateTransfer state){Storage = state; return Storage;}
HFX_INLINE HFXStateStorage &operator |=(HFXStateTransfer state){Storage |= state; return Storage;}
HFX_INLINE HFXStateStorage &operator &=(HFXStateTransfer state){Storage &= state; return Storage;}
HFX_INLINE HFXStateStorage &operator ^=(HFXStateTransfer state){Storage |= state; return Storage;}
HFX_INLINE HFXStateStorage operator ~()const{return ~Storage;}
HFX_INLINE HFXStateStorage operator |(HFXStateTransfer state){return (Storage|state);}
HFX_INLINE HFXStateStorage operator &(HFXStateTransfer state){return (Storage&state);}
HFX_INLINE HFXStateStorage operator ^(HFXStateTransfer state){return (Storage^state);}
HFX_INLINE bool operator ==(HFXStateTransfer state){return (Storage==state);}
HFX_INLINE bool operator !=(HFXStateTransfer state){return (Storage!=state);}
HFX_INLINE bool operator !(){return (Storage==0);}
HFX_INLINE operator bool(){return (Storage!=0);}
HFX_INLINE HFXStateFlags *UtilPointer(){return this;};
HFX_INLINE const HFXStateFlags *UtilPointer()const{return this;};
HFX_INLINE HFXStateFlags &Util(){return *this;};
HFX_INLINE const HFXStateFlags &Util()const{return *this;};
};
enum HFXNeeds
{
//effect has a application thread time sync
HFXNEED_SYNC =(1 << 0),
//effect has a servo thread time update
HFXNEED_PROCESS =(1 << 1),
//effect takes parameters
HFXNEED_SET =(1 << 2),
//effect needs stack access
HFXNEED_STACK =(1 << 3),
//device slots. if you need a device you need a stack.
HFXNEED_DEVICE1 =(1 << 4),
HFXNEED_DEVICE2 =(1 << 5),
HFXNEED_DEVICE3 =(1 << 6),
HFXNEED_DEVICE4 =(1 << 7),
HFXNEED_DEVICE5 =(1 << 8),
HFXNEED_DEVICE6 =(1 << 9),
HFXNEED_DEVICE7 =(1 << 10),
HFXNEED_DEVICE8 =(1 << 11),
//ability to create/destroy sub effects
HFXNEED_MANAGE =(1 << 12),
//effect needs to know how long its been running.
HFXNEED_RUNTIME =(1 << 13),
//effect needs to know how long its been since the last time its processed a function.
HFXNEED_FRAMETIME =(1 << 14),
//effect needs a fixed time sent to its framtime
HFXNEED_FIXEDTIME =(1 << 15),
//effect has a init function
HFXNEED_INSTANCE =(1 << 16),
//effect needs owning stack's parent access
HFXNEED_PARENT =(1 << 17),
//effect is self deleting
HFXNEED_REMOVE =(1 << 18),
//effect does not give handles. these effects need to be self deleting
HFXNEED_ENCAPSULATED =(1 << 19),
HFXNEED_EXIT =(1 << 20),
//state change inform flags
HFXNEED_STATE_INFORM =(1 << 21),
HFXNEED_RUNNING_INFORM =(1 << 22),
HFXNEED_PAUSE_INFORM =(1 << 23),
HFXNEED_HAULT_INFORM =(1 << 24),
HFXNEED_MUTE_INFORM =(1 << 25),
HFXNEED_EXITING_INFORM =(1 << 26),
// USE THE BELOW FLAGS TO DECLARE FEATURES TO A EFFECT CLASS WHEN REGISTERING
HFXNEED_DECL_SYNC =(HFXNEED_SYNC),
HFXNEED_DECL_PROCESS =(HFXNEED_PROCESS),
HFXNEED_DECL_STACK =(HFXNEED_STACK),
HFXNEED_DECL_DEVICE1 =(HFXNEED_DEVICE1|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE2 =(HFXNEED_DEVICE2|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE3 =(HFXNEED_DEVICE3|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE4 =(HFXNEED_DEVICE4|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE5 =(HFXNEED_DEVICE5|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE6 =(HFXNEED_DEVICE6|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE7 =(HFXNEED_DEVICE7|HFXNEED_DECL_STACK),
HFXNEED_DECL_DEVICE8 =(HFXNEED_DEVICE8|HFXNEED_DECL_STACK),
HFXNEED_DECL_RUNTIME =(HFXNEED_RUNTIME),
HFXNEED_DECL_FRAMETIME =(HFXNEED_FRAMETIME),
// there is no decl for HFXNEED_FIXEDTIME as it is pointless without
// a runtime or frametime decl.
HFXNEED_DECL_FIXEDFRAME =(HFXNEED_FRAMETIME|HFXNEED_FIXEDTIME),
HFXNEED_DECL_FIXEDRUNTIME =(HFXNEED_DECL_RUNTIME|HFXNEED_FIXEDTIME),
HFXNEED_DECL_MANAGE =(HFXNEED_DECL_FRAMETIME|HFXNEED_DECL_STACK),
HFXNEED_DECL_REMOVE =(HFXNEED_REMOVE),
HFXNEED_DECL_ENCAPSULATED =(HFXNEED_ENCAPSULATED|HFXNEED_DECL_REMOVE),
HFXNEED_DECL_PARENT =(HFXNEED_PARENT),
HFXNEED_DECL_INSTANCE =(HFXNEED_INSTANCE),
HFXNEED_DECL_SET =(HFXNEED_SET),
// there is no HFXNEED_STATE_INFORM declare as it would be pointless without a
// declaration of specific informs
HFXNEED_DECL_RUNNING_INFORM =(HFXNEED_RUNNING_INFORM|HFXNEED_STATE_INFORM),
HFXNEED_DECL_PAUSE_INFORM =(HFXNEED_PAUSE_INFORM|HFXNEED_STATE_INFORM),
HFXNEED_DECL_MUTE_INFORM =(HFXNEED_MUTE_INFORM|HFXNEED_STATE_INFORM),
HFXNEED_DECL_EXITING_INFORM =(HFXNEED_EXITING_INFORM|HFXNEED_STATE_INFORM),
HFXNEED_DECL_HAULT_INFORM =(HFXNEED_HAULT_INFORM|HFXNEED_STATE_INFORM),
// only use this if you will actually be using all informs!
HFXNEED_DECL_TOTAL_INFORM =( HFXNEED_RUNNING_INFORM|HFXNEED_PAUSE_INFORM|
HFXNEED_MUTE_INFORM|HFXNEED_EXITING_INFORM|
HFXNEED_STATE_INFORM),
// INFORMATION FLAGS
HFXNEED_INFO_DEVICE =( HFXNEED_DEVICE1|HFXNEED_DEVICE2|
HFXNEED_DEVICE3|HFXNEED_DEVICE4|
HFXNEED_DEVICE5|HFXNEED_DEVICE6|
HFXNEED_DEVICE7|HFXNEED_DEVICE8),
};
#define HFXNEED_UTIL_COUNT_DEVICES(flags) \
( ( ( (flags) & HFXNEED_INFO_DEVICE ) != 0) ? ( \
( ( ( (flags) & HFXNEED_DEVICE1 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE2 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE3 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE4 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE5 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE6 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE7 ) != 0) ? 1 : 0 ) + \
( ( ( (flags) & HFXNEED_DEVICE8 ) != 0) ? 1 : 0 ) ) \
: 0 )
typedef unsigned __int32 HFXNEED;
#define HFX_XCHANGE 16
#define HFX_YCHANGE 17
#define HFX_ZCHANGE 18
enum HFXResult
{
HFXRESULT_ERROR =-2,
HFXRESULT_FINISHED =-1,
HFXRESULT_CONTINUE =0,
// x axis was set
HFXRESULT_XCHANGED =(1 << HFX_XCHANGE),
// y axis was set
HFXRESULT_YCHANGED =(1 << HFX_YCHANGE),
// z axis was set
HFXRESULT_ZCHANGED =(1 << HFX_ZCHANGE),
// x and y axis was set
HFXRESULT_XYCHANGED =(HFXRESULT_XCHANGED|HFXRESULT_YCHANGED),
// x and z axis was set
HFXRESULT_XZCHANGED =(HFXRESULT_XCHANGED|HFXRESULT_ZCHANGED),
// y and z axis was set
HFXRESULT_YZCHANGED =(HFXRESULT_YCHANGED|HFXRESULT_ZCHANGED),
// x and y axis was set
HFXRESULT_YXCHANGED =HFXRESULT_XYCHANGED,
// x and z axis was set
HFXRESULT_ZXCHANGED =HFXRESULT_XZCHANGED,
// y and z axis was set
HFXRESULT_ZYCHANGED =HFXRESULT_YZCHANGED,
// x, y and z axis set
HFXRESULT_XYZCHANGED =(HFXRESULT_XCHANGED|HFXRESULT_YCHANGED|HFXRESULT_ZCHANGED),
HFXRESULT_CHANGED =HFXRESULT_XYZCHANGED,
};
typedef int HFXRESULT;
class HFX_PURE_INTERFACE IHapticEffect
{
public:
// return false if you decide the processor given to you is not sufficient
// or any other reason the effect should not be made.
// !called one time only. before any other funciton calls.
// IF YOU WANT THIS TO BE CALLED YOU MUST REGISTER YOUR EFFECT WITH HFXNEED_DECL_INSTANCE
virtual bool Initialize(IHFXProcessor &processor)=0;
// called by the game thread and blocks the haptics thread so the game and haptics loop are safe inside.
// IF YOU WANT THIS TO BE CALLED YOU MUST REGISTER YOUR EFFECT WITH HFXNEED_DECL_SYNC
virtual HFXRESULT SyncOp(IHFXProcessor &processor)=0;
//called at haptic rate. should set the output parameter to the target output force.
// calculation should optimized and precise in here.
// IF YOU WANT THIS TO BE CALLED YOU MUST REGISTER YOUR EFFECT WITH HFXNEED_DECL_PROCESS
virtual HFXRESULT Update(IHFXProcessor &processor)=0;
//return true if parameters sent to you are sufficient.
virtual bool Set(IHFXProcessor &processor, IHFXParamGroup *parameter)=0;
//notification of state change.
// WILL ONLY BE CALLED IF YOU DECLARE YOUR EFFECT REGISTER WITH A _INFORM decl and will ONLY be called with those.
// note: state will be only one bit. for every bit changed on sync this function will be called.
virtual void OnStateChange(IHFXProcessor &processor, HFXSTATE state, bool flagged)=0;
};
typedef IHapticEffect IHFXEffect;
typedef void (*hfxFilterFunction)(double outvect[3]);
typedef void (*HFXCreate_t)(IHFXEffect*&ptr);
typedef void (*HFXDestroy_t)(IHFXEffect*&ptr);
template<typename T>
void HFXDefaultAllocateEffect(IHFXEffect *&ptr){ptr = new T;};
template<typename T>
void HFXDefaultDeallocateEffect(IHFXEffect *&ptr){if(!ptr)return; delete ((T*)ptr); ptr=0;};
class IHapticsSystem;
typedef IHapticsSystem IHFXSystem;
class IDevice;
typedef IDevice IHFXDevice;
class IStack;
typedef IStack IHFXStack;
// T == effect class
template<typename T>
inline HFXEffectID HFXDefaultRegisterEffect(IHFXSystem &hfxSystem, const char *tag, HFXNEED needs, IHFXParamGroup *defaults, HFXCreate_t specialCreate = HFXDefaultAllocateEffect<T>, HFXDestroy_t specialDestroy = HFXDefaultDeallocateEffect<T> )
{
hfxSystem.LogMessage((const int)1,"EFFECT REGISTERING! %s Size = %i \n", tag, sizeof(T));
return hfxSystem.RegisterEffectClass(
tag,
specialCreate,
specialDestroy,
needs,
defaults);
};
// T == effect class
// P == parametergroup class
template<typename T, typename P>
inline HFXEffectID HFXDefaultRegisterEffect(IHFXSystem &hfxSystem, const char *tag, HFXNEED needs, HFXCreate_t specialCreate = 0, HFXDestroy_t specialDestroy = 0)
{
P *pGroup = new P;
HFXEffectID retval=0;
if(pGroup->CopyDefaults(pGroup))
{
retval = HFXDefaultRegisterEffect<T>(hfxSystem, tag, needs, pGroup, specialCreate, specialDestroy);
}
delete pGroup;
return retval;
};
#endif