diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /common/ihfx/IHFX.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'common/ihfx/IHFX.h')
| -rw-r--r-- | common/ihfx/IHFX.h | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/common/ihfx/IHFX.h b/common/ihfx/IHFX.h new file mode 100644 index 0000000..227d699 --- /dev/null +++ b/common/ihfx/IHFX.h @@ -0,0 +1,707 @@ +#ifndef I_NOVINT_HFX +#define I_NOVINT_HFX + +#define HFX_VERSION_MAJOR 0 +#define HFX_VERSION_MAJOR_SZ "0" +#define HFX_VERSION_MINOR 5 +#define HFX_VERSION_MINOR_SZ "5" +#define HFX_VERSION_FLOAT 0.5 +#include "util/HFXInterfaceHelper.h" + +//( NovintHFX ) +#include "HFXConfig.h" +//( HFXClasses ) +namespace std{ + template<class _Ty> + class allocator; + template <class _Ty, + class _Ax > class vector; +}; + +#if _MSC_VER < 1400 +#define VECTOR_TYPE(type) std::vector<type> +#endif + +#if _MSC_VER >= 1400 +#define VECTOR_TYPE(type) ::std::vector<type, ::std::allocator<type> > +#endif + +#pragma warning( disable : 4251 ) +class EffectTag; + +//ensure these are not int he NovintHFX namespace. +#include "IHFXParam.h" +#include "IHFXEffect.h" + +typedef int _declspec(dllimport) (*LinkHFX_Fn)( const char * password, const char *cmdline, void **effects, void **system ); +//temporarily disable warning regarding to data classes +// needing external classes +#pragma warning(disable:4661) +//forward decl. +class IDevice; +class IStack; +struct IBaseEffectParams; +class IBaseEffect; +//( HapticsMath ) +#include "Types/hfxVec3.h" +//( HapticsSystem ) +struct IHapticEffectParamGroup; +typedef IHapticEffectParamGroup IHFXParamGroup; +typedef int DeviceIndex; +typedef unsigned long hfxPreciseTime; +typedef bool (*EnableMouseFn)( void ); + +enum eMouseMove +{ + eHFXMM_Delta=0, + eHFXMM_Absolute=0, +}; + +enum eMouseButton +{ + eHFXMM_1232=0,//1=left 2=right 3=middle 4=right + eHFXMM_1111,//1=left 2=left 3=left 4=left + eHFXMM_1342,//1=left 2=middle 3=4th 4=right + eHFXMM_None, +}; +enum eMouseMethod +{ + eHFXMouseMeth_OSInput=0, + eHFXMouseMeth_fMouse, + eHFXMouseMeth_useCallback, + eHFXMouseMeth_smartDelta, + eHFXMouseMeth_delta, + eHFXMouseMeth_COUNT, +}; +enum eMouseClick +{ + eHFXMC_Left=0, + eHFXMC_Right, + eHFXMC_Middle, + eHFXMC_Fourth, + eHFXMC_COUNT, +}; +typedef bool (*MouseEmulationFn)( const double &devicex_pos, + const double &devicey_pos, + const double &devicez_pos, + const double &devicex_delta, + const double &devicey_delta, + const double &devicez_delta, + const int &buttons_down, + const int &buttons_pressed, + const int &buttons_released, + bool moved, + /* adjust if you would liek to send a mouse button */ + bool buttonsDown[eHFXMC_COUNT] + ); + +struct ApplicationData +{ +}; +typedef void (*RollCallIndexSetCallBack)(IDevice *pDevice, const int devices_left); +class HFX_PURE_INTERFACE IHapticsSystem +{ +public: + + // call this method prior to shutting down the game. + virtual void ShutDown(bool hard=false) =0; + // THIS FUNCTION MUST BE CALLED BY YOUR APPLICATION AND RETURN TRUE PRIOR TO CREATING A DEVICE! + // window = the HWND of the program. + // returns weather or not the applicationdata was sufficent. + virtual bool AttachApplication(ApplicationData &app) =0; + virtual bool AttachApplicationByProcessName(ApplicationData &app, const char *szProcessName) =0; + + // If you want to use more than 1 device set this before. NOTE: for multiple devices you must use device lock + //HFX_VIRTUAL bool SetOptionalDeviceCount( unsigned int nDevices ); + + // Use this function to create a device. (note: when making multiple devices they must be connected in numerical order.) + virtual bool RunDevice(IDevice **ppDevice, const char *deviceName=0, const char *configDir=0) =0; + + // When using multiple devices you _MUST_ lock devices after device connection attempts are made. + virtual void LockDevices() =0; + + // When using mutliple devices you _MUST_ unlock devices once they are locked to connect more devices and then lock again afterwards. + virtual void UnlockDevices() =0; + + // Note: this will return the max number of devices specified in the constructor of HapticsSystem. + virtual unsigned int GetTargetDeviceCount() const =0; + + // connects multiple devices at once. returns number of devices connected. + // if targetNumber==-1 then all connected devices will be ran. + virtual int RunMultipleDevices(const int targetNumber=-1) =0; + + // returns true if device was stopped. + virtual bool StopRunningDevice(IDevice **ppDevice) =0; + + // returns true if all instances were stopped. + virtual bool StopAllRunningDevices() =0; + + //this will ask the user to press a button on each device. the order in which they + // press a button on each connected device will order their device id from zero to the number + // of falcons the user has minus one. + // note: without roll call devices are ordered by their serial number. + // returns false if only one falcon is connected. + virtual bool RollCallDevices(RollCallIndexSetCallBack CallBackFn=0,bool bCreateThread=false) =0; + + // will return true untill roll call is over. + virtual bool IsInRollCall() const =0; + + // updates roll call data. only call this if your in a roll call and the roll call was not started + // with bCreateThread set to true. + // returns true if still in roll call. + virtual bool RollCallUpdate() =0; + + // cancles roll call in progress. if ApplyMadeChanges is true the devices who responded + // to the roll call will be set in and the unset will be moved to the end of the index list. + virtual bool StopRollCall(bool ApplyMadeChanges=false) =0; + + //only call this ONCE per game input tick. + // returns number of devices updated. + virtual int InputUpdate(); + + //void SetMouseMode(HWND window,eHFXMouseMove MoveMode=eHFXMM_Delta,eHFXMouseButton ButtonMode=eHFXMM_1232); + virtual void SetMouseMode(eMouseMove MoveMode=eHFXMM_Delta,eMouseButton ButtonMode=eHFXMM_1232) =0; + virtual void StartMouse(IDevice *pDev) =0; + virtual void StartMouse(const DeviceIndex device) =0; + virtual void StartMouse() =0; + virtual void MouseUpdate() =0; + virtual void StopMouse() =0; + + // returns if we are in cursor emulation. If pDevice is null it will return weather any device is in mouse emulation. + virtual bool IsMouseMode(const IDevice *pDevice=0) =0; + + //returns true if forces are allowed. + virtual bool ForcesAllowed() =0; + + //returns true if input is allowed. + virtual bool InputAllowed() =0; + + //returns true if forces are enabled. + // Note: this could be true and forces may not be allowed. + // MouseMode RollCall window focus and possibly other things will not allow forces. + virtual bool ForcesEnabled() =0; + + //HFX_VIRTUAL void DisableForces() HFX_PURE; + //HFX_VIRTUAL void EnableForces() HFX_PURE; + //returns device of index nDevice + virtual IDevice *GetRunningDeviceByIndex(const DeviceIndex nDevice) const =0; + + //returns device on hardware index. + virtual IDevice *GetRunningDeviceByHardwareIndex(const int nSerialOrder) const =0; + + //returns number of running devices. + virtual int RunningDeviceCount() const =0; + + //returns number of devices connected to the users computer. + virtual int ConnectedDeviceCount() const =0; + + // this will re count available devices. + // use ConnectedDeviceCount() to get the count. + virtual void RecountConnectedDevices() =0; + + virtual bool AllocateEffectParameter(IHFXParamGroup *&pIEffectParam, HFXEffectID associatedClass, const char *copyCachedSettings=0, const char *storageName=0) =0; + HFX_INLINE bool AllocateEffectParameter(IHFXParamGroup *&pIEffectParam, const char *copyCachedSettings=(const char*)0, const char *storageName=0 ){return AllocateEffectParameter(pIEffectParam, 0, copyCachedSettings, storageName);} + virtual bool DeallocateEffectParameter(IHFXParamGroup *&ppIEffectParam) =0; + + virtual unsigned int GetCachedParameterCount() const =0; + virtual IHFXParamGroup *GetCachedParameter(const char *name) =0; + virtual IHFXParamGroup *GetCachedParameter(const unsigned int name) =0; + virtual const char *GetCachedParameterName(const unsigned int id) const =0; + + // Note: any format ( besides Bitfile ) where it cannot find the file specified will try to + // load a encoded bitfile if it does not exist. A bit file will be generated when you load any + // format. When release time comes around just delete the iniFile and include the bitfile output + + // each format has a way to turn this functionality off. if you + virtual bool CacheEffectParametersINI( const char *iniFile ) =0; + + virtual bool CacheEffectParametersBitfile( const char *bitFile ) =0; + // will add .nvnt extension + virtual bool SaveCache( const char *file ) =0; + + //HFX_VIRTUAL bool LoadHFXModule( const char *moduleName, const char *modulePassword=0 ) HFX_PURE; + virtual hfxPreciseTime GetBaseTime() const =0; + virtual hfxPreciseTime GetRunTime() const =0; + virtual double GetRunTimeSeconds() const =0; + virtual double GetBaseTimeSeconds() const =0; + + virtual bool CreateNewEffectStack(const char *uniqueName, IStack**ppStack, unsigned int inputDevices=0) =0; + virtual bool DeleteEffectStack(IStack**ppStack) =0; + virtual IStack* FindEffectStack(const char *name) =0; + + //command support + //HFX_VIRTUAL int RunCommand( const char *cmd ) HFX_PURE; + + //HFX_VIRTUAL bool InitFromXML(ApplicationData &appdata,unsigned int &devices, const char *xmlLoc) HFX_PURE; + + virtual int LogMessage(const int type, const char *fmt, ...); + virtual int LogMessage(const char *fmt, ...); + + virtual bool SetMouseEmulation( eMouseMethod method ) =0; + virtual bool SetMouseEmulationFunction( MouseEmulationFn method_function ) =0; + #ifndef HFX_INTERNAL + inline bool SetMouseEmulation( MouseEmulationFn method_function ){if(!method_function) return false; return ( SetMouseEmulation(eHFXMouseMeth_useCallback) && SetMouseEmulationFunction(method_function)); } + #endif + virtual bool ScaleDeviceCoordsForCursor( double &x, double &y, double width=-1, double height=-1, double offsetx=-1, double offsety=-1 ) =0; + // try and put device to sleep. if null all devices will try to sleep. devices will sleep untill touched. + virtual void AttemptSlumber(IDevice *device=0) =0; + + virtual void ActivateDynamicWindowHandler(const char *windowClassName, const char *windowText, unsigned int msHeartInterval=70) =0; + virtual void DeactivateDynamicWindowHandler() =0; + virtual bool IsDynamicWindowHandlerRunning() const =0; + + virtual HFXEffectID RegisterEffectClass(const char *tag, HFXCreate_t alloc, HFXDestroy_t dealloc, HFXNEED needs, IHFXParamGroup *defaults=0) =0; +#define HFX_NON_ELEMENT 0xFFFFF0 + virtual bool SetParameterGroupVar(IHFXParamGroup ¶ms, HFXParamID var, const char *string, unsigned int element=HFX_NON_ELEMENT) =0; + virtual bool SetParameterGroupVar(IHFXParamGroup ¶ms, const char *varString, const char *string, unsigned int element=HFX_NON_ELEMENT) =0; + virtual HFXEffectID LookupEffectIDByName(const char *name) const =0; + virtual const char *LookupEffectNameByID(HFXEffectID id) const =0; + + // only call if explicit stack syncs are enabled + virtual void SyncEffectStacks() =0; + + virtual HFXParamID EnumerateEffectParameters( HFXEffectID id, HFXParamID LastParamID ) =0; + virtual bool CacheEffectParameterGroupCopy(const char *cachename, IHFXParamGroup *params) =0; + virtual bool SaveEffectParameterCache(const char *filename, const char *type = "ini") =0; + virtual void DoReport() =0; +}; + +//( HapticsDevice ) +//HFX BUTTON DEFINES : Based on HDL Button Defines. +#define HFX_BUTTON_1 0x00000001 /**< Mask for button 1 */ +#define HFX_BUTTON_2 0x00000002 /**< Mask for button 2 */ +#define HFX_BUTTON_3 0x00000004 /**< Mask for button 3 */ +#define HFX_BUTTON_4 0x00000008 /**< Mask for button 4 */ +#define HFX_BUTTON_ANY 0xffffffff /**< Mask for any button */ + +//Internal class. +struct HFX_PURE_INTERFACE IDeviceData +{ +}; + +namespace NovintHFX{ + class Device; + class Stack; + namespace Effects{ + struct command_info; + int ProcessCommand( IBaseEffect *pEffect, const char *argv[], const unsigned int argc ); + } +}; +// This function callback type will be used with SetServoLoopCallbackFunction. +// The main difference between hdlServoOp and this is that you get the device. +typedef int (*OldServoLoopFn) (void *pParam, class IDevice *pDevice, double outforces[3]); +class HFX_PURE_INTERFACE IDevice +{ +public: + //Is this device able to output forces? + virtual bool AcceptingForces() const =0; + + //The device is connected. + virtual bool IsConnected() const =0; + + //Sets pos to the tool Position. + virtual void GetToolPosition(double pos[3]) const =0; + virtual void GetToolPositionWorkspace(double pos[3]) const =0; + virtual void GetButtonData(int *down=0, int *pressed=0, int *released=0) const =0; + virtual void GetCurrentForce(double force[3]) const =0; + virtual bool IsButtonDown( int nButton ) const =0; + virtual IStack *GetEffectStack() =0; + virtual const DeviceIndex GetIndex() const =0; + virtual int GetHardwareIndex() const =0; + virtual void InputUpdate() =0; + + virtual bool ConnectStack( IStack *stack ) =0; + virtual bool DisconnectStack( IStack *stack ) =0; + + // This function is here for quick integration into games which already have a few custom + // effects of their own. Taking the old ServoOp function and adding in pDevice + virtual void SetServoLoopCallbackFunction( OldServoLoopFn old_fn, void *pParam ) =0; + + // you should never call this unless your in a callback running on servo. + virtual void _GetServoData(double toolpos[3], int &buttons) =0; + + virtual __int64 GetSerialNumber() const =0; + + virtual BoundingBox3 GetWorkspace() const =0; + + virtual void SetEngineData(void *data) =0; + virtual void *GetEngineData() const =0; + + virtual bool HasRested( unsigned int msDur=1 ) const =0; + virtual bool IsSleeping(bool justForces=false) const =0; + virtual bool TriggerFade(unsigned int msMuteTime, unsigned int msDuration, bool forceOverride=false) =0; + virtual void ForceSlumber() =0; + virtual void SetForceScale(const double &scale) =0; + virtual double GetForceScale() const =0; +}; + +//( HapticsStack ) +class Processor; +//EFFECT STACK +//note one stack per device handle only. +class HFX_PURE_INTERFACE IStack +{ +public: + + // Returns true if effect was created. + // -- + // NOTE: NOT ALL EFFECTS ( SUCH AS SELF DELETING ) + // WILL ALLOW YOU TO HAVE A HANDLE TO IT. + // CHECKING POINTER VALIDITY OF THE HANDLE IN THE + // CREATE NEW EFFECT WILL ONLY LET YOU KNOW IF + // ANYTHING WAS SET TO IT, NOT NECCISARILLY IF + // THE EFFECT WAS CREATED. + // -- + virtual bool CreateCachedEffect(IHFXEffect *&pHandle, const char *entry, const char *instancename=0 ); + + template<typename T> + HFX_INLINE bool CreateCachedEffect(T *&pTypedHandle, const char *entry, const char *instanceName=0) + { + return CreateCachedEffect((IHFXEffect*&)pTypedHandle, entry, instanceName); + } + HFX_INLINE bool CreateCachedEffect(const char *entry){ return CreateCachedEffect(hfxNoHandle, entry); } + + virtual bool CreateNewEffect(IHFXEffect *&ppHandle, HFXEffectID effectName, IHFXParamGroup *params, const char *instanceName=0); + + template<typename T> + HFX_INLINE bool CreateNewEffect(T *&pTypedHandle, HFXEffectID effectName, IHFXParamGroup *params, const char *instanceName=0) + { + return CreateNewEffect((IHFXEffect*&)pTypedHandle, effectName, params, instanceName); + } + + HFX_INLINE bool CreateNewEffect(HFXEffectID effectName, IHFXParamGroup *params){ return CreateNewEffect(hfxNoHandle, effectName, params, 0); }; + // Returns NULL if there was no effect using that name. + // -- + // NOTE: YOU SHOULD ONLY HAVE ONE HANDLE OF A EFFECT + // IN AS A MEMBER VARIABLE ( NON LOCAL ). OTHERWISE + // YOU RISK INVALID POINTERS IF YOU DELETE THE EFFECT. + // WITH A SECOND REFERENCE. + virtual IHFXEffect *FindRunningEffect(const char *instanceName) const =0; + // Returns true if effect was deleted + // -- + // NOTE: THIS IS ONLY FOR EFFECTS WHICH NEED TO BE + // DELETED MANUALLY. MANY EFFECTS WILL DELETE + // THEMSELFS AND THOSE EFFECTS YOU SHOULD NOT + // EVER RECEIVE HANDLES FOR. + // -- + virtual bool DeleteRunningEffect(IHFXEffect *&effect) =0; + + template<typename T> + HFX_INLINE bool DeleteRunningEffect(T *&pTypedEffect) + { + return DeleteRunningEffect((IHFXEffect*&)pTypedEffect); + } + + virtual void GetLastForce(double force[3])const =0; + + virtual void SetDeviceLock(bool state) =0; + virtual bool IsDeviceListLocked() const =0; + + // returns true if device was added or is already a member. if slot is -1 it will just enter the device + // as the next available slot. + virtual bool AddDevice(IDevice*pDevice, int slot=-1) =0; + + // returns the device in slot + virtual IDevice *GetDeviceInSlot(unsigned int id=0) const =0; + + virtual void GetCalclatedForces(double force[3]) =0; + virtual const char *Name() const =0; + + //command support + //HFX_VIRTUAL int RunCommand( const char *cmd ) HFX_PURE; + + virtual void *GetUserData() const =0; + virtual void SetUserData(void*data) =0; + + virtual void SetVolume( const double &scale ) =0; + virtual double GetVolume() const =0; + + virtual unsigned int GetTargetDeviceCount() const =0; + + virtual void SetEngineData(void *data) =0; + virtual void *GetEngineData() const =0; + + virtual void SetEffectUserData(IHFXEffect *pEffect, void *pData) =0; + virtual void *GetEffectUserData(IHFXEffect *pEffect) =0; +}; + +//( HapticsEffect ) +struct HFX_PURE_INTERFACE IRegister +{ +public: + virtual void AllocateEffect(IHFXEffect *&pEffectPtr) =0; + virtual void DeallocateEffect(IHFXEffect *&pEffectPtr) =0; + virtual void AllocateParameterGroup(IHFXParamGroup *&pEffectPtr) =0; + virtual void DeallocateParameterGroup(IHFXParamGroup *&pEffectPtr) =0; + virtual const char *GetTagName() const =0; +}; + +#define HFX_PROCESSOR_PARAM_FORCESCALE 4294967293 +#define HFX_PROCESSOR_PARAM_TIMESCALE 4294967294 + +class HFX_PURE_INTERFACE IProcessor +{ +public: + + // call this to mute and unmute this effect. (note: effect will still be updated, just will not output force.) + // note : this setting will not be applied untill the next sync op ( InputUpdate ) called by the application. + virtual void SetMuted(bool mute) =0; + virtual void SetPaused(bool pause) =0; + + // see if the effect is muted. + HFX_INLINE bool IsMuted() const { return ((GetEffectState() & HFXSTATE_MUTE)!=0); } + + // see if the effect is explicitly paused. + HFX_INLINE bool IsPaused() const { return ((GetEffectState() & HFXSTATE_PAUSE)!=0); } + + // scale this force (NOTE: THIS IS SEPERATE FROM PARAMETER SCALE!) + virtual void SetForceScale( double scale ) =0; + virtual double GetForceScale( ) const =0; + + virtual const char *GetEffectTypeName() const =0; + + // override this function to return the number of falcons this + // effect requires. + HFX_INLINE unsigned int RequiredDeviceCount() const + { + HFXNEED needs= GetEffectNeeds(); + return HFXNEED_UTIL_COUNT_DEVICES(needs); + } + + // returns true if the effect is running. + HFX_INLINE bool IsRunning() const {return ( (GetEffectState() & (HFXSTATE_RUNNING)) != 0 );} + + // if your effect is not self deleting and requires runtime data you should override this to true. + HFX_INLINE bool CanBeHandled() const { return (GetEffectNeeds() & HFXNEED_ENCAPSULATED)==0; } + + // this lets the haptic effect stack know you are done with this effect and it is waiting to be deleted. + // CANNOT BE OVERRIDDEN ( see OnFlaggedForRemoval() ) + virtual void FlagForRemoval() =0; + + //Stack functions! + friend class NovintHFX::Stack; + friend int NovintHFX::Effects::ProcessCommand( IBaseEffect *pEffect, const char *argv[], const unsigned int argc ); + + // do not use. + //HFX_VIRTUAL bool Stop() HFX_PURE; + + // DO NOT OVERRIDE! + HFX_INLINE bool NeedsRemoval() const + { return ( ( GetEffectNeeds() & HFXNEED_REMOVE ) ? ( ( ( GetEffectState() & HFXSTATE_RUNNING ) ) ? false : true ) : false ); } + + // DO NOT OVERRIDE! + HFX_INLINE bool WantsSyncOp() const + { + return (((GetEffectNeeds() & HFXNEED_SYNC)!=0) && ((GetEffectState() & HFXSTATE_WANT_SYNC)!=0)); + } + // DO NOT OVERRIDE! + virtual bool WantsUpdate() const {return (((GetEffectNeeds() & HFXNEED_PROCESS)!=0) && ((GetEffectState() & HFXSTATE_WANT_UPDATE)!=0) && ((GetEffectState() & HFXSTATE_RUNNING)!=0));} + + virtual HFXSTATE GetEffectState() const =0; + virtual const HFXNEED &GetEffectNeeds() const =0; + + virtual void *_output() const =0; + + virtual const double &Runtime() const =0; + virtual const double &Frametime() const =0; + + virtual IStack *GetStack() =0; + virtual IHFXSystem *GetSystem() =0; + virtual void *GetUserData() =0; + virtual void SetUserData(void *userData) =0; + HFX_INLINE hfxVec3 &Output() { return *(reinterpret_cast<hfxVec3*>(_output())); } + HFX_INLINE const hfxVec3 &Output() const{return *(reinterpret_cast<const hfxVec3*>(_output()));} + HFX_INLINE double &operator[](int i){ return (Output().m[i]); }; + HFX_INLINE const double &operator[](int i)const{ return (Output()[i]); }; + HFX_INLINE bool IsOutputValid() const { return !IsOutputNaN();} + HFX_INLINE bool IsOutputNaN() const { const double *o=Output(); return(o[0]!=o[0]||o[1]!=o[1]||o[2]!=o[2]);} + HFX_INLINE hfxVec3 &operator =(const hfxVec3 &vect){hfxVec3 &out = Output(); out = vect; return out;} +}; +typedef IProcessor IHFXProcessor; +typedef char HFX_VarType; + +#define HFX_Double 'd' +#define HFX_Float 'f' +#define HFX_Int 'i' +#define HFX_Bool 'b' +#define HFX_Other 'o' +#define HFX_Pointer 'p' +#define HFX_Null 0 + + +#pragma warning( default : 4251 ) + +#ifdef HFX_MODULE_LAYER +#include HFX_MODULE_LAYER +#endif + +#define ConnectNovintHFX YOU_MUST_INCLUDE_WINDOWS_PRIOR_TO_INCLUDING_INovintHFX_h +#endif + +// to connect windows.h must be included +#if ( !defined(I_NOVINT_HFX_WINDOWS) && ( defined(_INC_WINDOWS) || defined(LoadLibrary) && defined(HMODULE) ) ) && !defined(STATIC_IHFX) +#define I_NOVINT_HFX_WINDOWS + +#ifdef ConnectNovintHFX +#undef ConnectNovintHFX +#endif + +extern HMODULE dllNovintHFX_; +extern IHapticsSystem *_hfx; + +//quick helper class to ensure novint hfx unloads properly. +struct NovintHFXCloseHelper +{ + NovintHFXCloseHelper() : forceSkipQuit(false) + { + static bool ONE_INSTANCE_ONLY=true; + if(!ONE_INSTANCE_ONLY) + { +#ifdef _DEBUG + // look at the call stack and please remove whatever is calling this constructor. + // there should be only one HFX_INIT_VARS. + DebugBreak(); +#endif + ExitProcess(100); + } + ONE_INSTANCE_ONLY = false; + }; + bool forceSkipQuit; + ~NovintHFXCloseHelper() + { + if(!forceSkipQuit&&_hfx) + { + _hfx->ShutDown(true); + } + }; +}; +extern NovintHFXCloseHelper _hfx_close; + +#define HFX_INIT_VARS() \ + HMODULE dllNovintHFX_=0; \ + IHapticsSystem *_hfx =0; \ + NovintHFXCloseHelper _hfx_close; + +// if windows is included heres a inline function to get the interface! +inline bool ConnectNovintHFX( IHapticsSystem **ppSystem, void *window, const char *cmd, void*pCursorEnableFn=0, unsigned int TargetDevices=1) +{ + if(ppSystem==0) + return false; + + char szNovintDir[ MAX_PATH ]; + char szNovintDll[ MAX_PATH ]; + if ( GetEnvironmentVariableA( "NOVINT_DEVICE_SUPPORT", szNovintDir, sizeof( szNovintDir ) ) == 0 || !V_IsAbsolutePath( szNovintDir ) ) + { + return false; + } + + unsigned int tries = 0; + while(dllNovintHFX_==0) + { + const char *dllName = HFX_DYNAMIC_LIBRARY_NAME(tries); + if(!dllName) + break; + V_sprintf_safe( szNovintDll, "%s\\bin\\%s", szNovintDir, dllName ); + dllNovintHFX_ = LoadLibraryA( szNovintDll ); + if(!dllNovintHFX_) + tries++; + } + + NovintHFX_ExposeInterfaceFn connectFn = 0; + if(dllNovintHFX_) + { + connectFn = (NovintHFX_ExposeInterfaceFn)GetProcAddress(dllNovintHFX_, HFX_CONNECT_FUNCTION_NAME()); + } + if(!connectFn){ + // if direct load failed.. + if(dllNovintHFX_) + { + FreeLibrary(dllNovintHFX_); + } + V_sprintf_safe( szNovintDll, "%s\\bin\\%s", szNovintDir, "hfx.dll" ); + dllNovintHFX_ = LoadLibraryA( szNovintDll ); + if(dllNovintHFX_) + { + connectFn = (NovintHFX_ExposeInterfaceFn)GetProcAddress(dllNovintHFX_, "CreateHFX"); + } + } + if(connectFn&&connectFn((void **)ppSystem, window, cmd, HFX_VERSION_MAJOR, HFX_VERSION_MINOR, pCursorEnableFn, TargetDevices )==0) + { + _hfx = (*ppSystem); + return true; + } + + return false; +} +#ifndef HFX_STRIPPED +inline bool ConnectNovintHFX_XML( IHapticsSystem **ppSystem, void *window, const char *xml, void*pCursorEnableFn=0, unsigned int TargetDevices=1) +{ + if(ppSystem==0) + return false; + + char szNovintDir[ MAX_PATH ]; + char szNovintDll[ MAX_PATH ]; + if ( GetEnvironmentVariable( "NOVINT_DEVICE_SUPPORT", szNovintDir, sizeof( szNovintDir ) ) == 0 || !V_IsAbsolutePath( szNovintDir ) ) + { + return false; + } + + unsigned int tries = 0; + while(dllNovintHFX_==0) + { + const char *dllName = HFX_DYNAMIC_LIBRARY_NAME(tries); + if(!dllName) + break; + V_sprintf_safe( szNovintDll, "%s\\bin\\%s", szNovintDir, dllName ); + dllNovintHFX_ = LoadLibraryA( szNovintDll ); + if(!dllNovintHFX_) + tries++; + } + NovintHFX_ExposeInterfaceFn connectFn = 0; + if(dllNovintHFX_) + { + connectFn = (NovintHFX_ExposeInterfaceFn)GetProcAddress(dllNovintHFX_, HFX_CONNECT_FUNCTION_NAME_XML()); + } + if(!connectFn){ + if(dllNovintHFX_) + { + FreeLibrary(dllNovintHFX_); + dllNovintHFX_=0; + } + V_sprintf_safe( szNovintDll, "%s\\bin\\%s", szNovintDir, "hfx.dll" ); + dllNovintHFX_ = LoadLibraryA( szNovintDll ); + if(dllNovintHFX_) + { + connectFn = (NovintHFX_ExposeInterfaceFn)GetProcAddress(dllNovintHFX_, "CreateHFX_XML"); + } + + } + if(connectFn&&connectFn((void **)ppSystem, window, xml, HFX_VERSION_MAJOR, HFX_VERSION_MINOR, pCursorEnableFn, TargetDevices )==0) + { + _hfx = (*ppSystem); + return true; + } + return false; +} +#endif +inline bool ConnectNovintHFX( IHapticsSystem **ppSystem, HWND hwnd, const char *cmd, void*pCursorEnableFn=0, unsigned int TargetDevices=1 ){ return ConnectNovintHFX( ppSystem, (void*)hwnd, cmd, pCursorEnableFn, TargetDevices); } +inline void DisconnectNovintHFX(IHapticsSystem **ppSystem=0) +{ + if(dllNovintHFX_&&_hfx) + { + IHapticsSystem *pTemp = _hfx; + _hfx = 0; + _hfx_close.forceSkipQuit=true; + if(ppSystem) + { + *ppSystem = 0; + } + pTemp->ShutDown(); + if(FreeLibrary(dllNovintHFX_)) + { + dllNovintHFX_ = 0; + } + } +} +#endif + |