|
|
#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
|