#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< 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 void HFXDefaultAllocateEffect(IHFXEffect *&ptr){ptr = new T;}; template 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 inline HFXEffectID HFXDefaultRegisterEffect(IHFXSystem &hfxSystem, const char *tag, HFXNEED needs, IHFXParamGroup *defaults, HFXCreate_t specialCreate = HFXDefaultAllocateEffect, HFXDestroy_t specialDestroy = HFXDefaultDeallocateEffect ) { 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 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(hfxSystem, tag, needs, pGroup, specialCreate, specialDestroy); } delete pGroup; return retval; }; #endif