summaryrefslogtreecommitdiff
path: root/common/ihfx/IHFX.h
blob: 227d699ab1ecb713d0273bd8f662eb1badd65106 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
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 &params, HFXParamID var, const char *string, unsigned int element=HFX_NON_ELEMENT) =0;
	virtual bool SetParameterGroupVar(IHFXParamGroup &params, 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