summaryrefslogtreecommitdiff
path: root/common/ihfx/ihfxeffect.h
blob: 002b2cae870869c32e52c92fff4a403f82d1a33d (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
 
#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