summaryrefslogtreecommitdiff
path: root/common/ihfx/ihfxeffect.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/ihfx/ihfxeffect.h')
-rw-r--r--common/ihfx/ihfxeffect.h327
1 files changed, 327 insertions, 0 deletions
diff --git a/common/ihfx/ihfxeffect.h b/common/ihfx/ihfxeffect.h
new file mode 100644
index 0000000..002b2ca
--- /dev/null
+++ b/common/ihfx/ihfxeffect.h
@@ -0,0 +1,327 @@
+
+#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
+ \ No newline at end of file