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.
327 lines
12 KiB
327 lines
12 KiB
|
|
#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 ©) : 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 |
|
|