123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404 |
- #include "pch.h"
- #include "dinput.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- // DDWrapers
- //
- //////////////////////////////////////////////////////////////////////////////
- class DIDeviceCaps : public TZeroFillWithSize<DIDEVCAPS> {
- public:
- };
- class DIDeviceInstance : public TZeroFillWithSize<DIDEVICEINSTANCE> {
- public:
- };
- class DIDataFormat : public TZeroFillWithSize<DIDATAFORMAT> {
- public:
- };
- class DIObjectDataFormat : public TZeroFill<DIOBJECTDATAFORMAT> {
- public:
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- const DIDATAFORMAT* g_pdfDIMouse;
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- class DDInputObject : public IObject {
- private:
- ZString m_strName;
- DWORD m_dwType;
- GUID m_guidType;
- public:
- DDInputObject(const ZString& strName, DWORD dwType, const GUID& guidType) :
- m_strName(strName),
- m_dwType(dwType),
- m_guidType(guidType)
- {
- }
- const ZString& GetName() const
- {
- return m_strName;
- }
- DWORD GetDWType() const
- {
- return m_dwType;
- }
- const GUID& GetGUID() const
- {
- return m_guidType;
- }
- };
- class ValueDDInputObject : public DDInputObject {
- private:
- TRef<ModifiableNumber> m_pnumber;
- public:
- ValueDDInputObject(const ZString& strName, DWORD dwID, const GUID& guidType) :
- DDInputObject(strName, dwID, guidType),
- m_pnumber(new ModifiableNumber(0))
- {
- }
- ModifiableNumber* GetValue() const
- {
- return m_pnumber;
- }
- };
- class ButtonDDInputObject : public DDInputObject {
- private:
- TRef<ModifiableBoolean> m_pbool;
- public:
- ButtonDDInputObject(const ZString& strName, DWORD dwID, const GUID& guidType) :
- DDInputObject(strName, dwID, guidType),
- m_pbool(new ModifiableBoolean(false))
- {
- }
- ModifiableBoolean* GetValue() const
- {
- return m_pbool;
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- class MouseInputStreamImpl : public MouseInputStream {
- private:
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
-
- BOOL EnumObjectsCallback(
- LPCDIDEVICEOBJECTINSTANCE pddoi
- ) {
- if (
- pddoi->dwType & DIDFT_AXIS
- || pddoi->dwType & DIDFT_POV
- ) {
- int index;
- if (pddoi->guidType == GUID_XAxis) {
- index = 0;
- } else if (pddoi->guidType == GUID_YAxis) {
- index = 1;
- } else if (pddoi->guidType == GUID_ZAxis) {
- index = 2;
- } else {
- index = -1;
- }
- ValueDDInputObject* pobject =
- new ValueDDInputObject(
- pddoi->tszName,
- pddoi->dwType,
- pddoi->guidType
- );
- if (index == -1) {
- m_vvalueObject.PushEnd(pobject);
- } else {
- m_vvalueObject.Set(index, pobject);
- }
- } else if (pddoi->dwType & DIDFT_PSHBUTTON) {
- ButtonDDInputObject* pobject =
- new ButtonDDInputObject(
- pddoi->tszName,
- pddoi->dwType,
- pddoi->guidType
- );
- m_vbuttonObject.PushEnd(pobject);
- }
- return DIENUM_CONTINUE;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
-
- static BOOL CALLBACK StaticEnumObjectsCallback(
- LPCDIDEVICEOBJECTINSTANCE lpddoi,
- LPVOID pvRef
- ) {
- MouseInputStreamImpl* pthis = (MouseInputStreamImpl*)pvRef;
- return pthis->EnumObjectsCallback(lpddoi);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // members
- //
- //////////////////////////////////////////////////////////////////////////////
-
- TRef<IDirectInputDevice2> m_pdid;
- TRef<ButtonEvent::SourceImpl> m_pbuttonEventSource;
- DIDeviceCaps m_didc;
- DIDeviceInstance m_didi;
- TVector<TRef<ValueDDInputObject > > m_vvalueObject;
- TVector<TRef<ButtonDDInputObject> > m_vbuttonObject;
- Rect m_rect;
- Point m_point;
- float m_z;
- bool m_bBuffered;
- bool m_bEnabled;
- int m_threshold1;
- int m_threshold2;
- int m_acceleration;
- float m_sensitivity;
- public:
- //////////////////////////////////////////////////////////////////////////////
- //
- // Constructor
- //
- //////////////////////////////////////////////////////////////////////////////
-
- MouseInputStreamImpl(IDirectInputDevice2* pdid, HWND hwnd) :
- m_pdid(pdid),
- m_rect(0, 0, 0, 0),
- m_point(0, 0),
- m_vvalueObject(3),
- m_bEnabled(false),
- m_bBuffered(true),
- m_pbuttonEventSource(ButtonEvent::Source::Create())
- {
- //
- // Are we running on NT
- //
- /*!!!
- OSVERSIONINFO osvi = { sizeof(osvi) };
- ZVerify(GetVersionEx(&osvi));
- if ((VER_PLATFORM_WIN32_NT & osvi.dwPlatformId) != 0) {
- m_bBuffered = false;
- }
- */
- //
- // Enumerate the buttons and values
- //
- DDCall(m_pdid->EnumObjects(StaticEnumObjectsCallback, this, DIDFT_ALL));
- //
- // Setup the device
- //
- SetupDevice();
- //
- // We only need mouse input when we are in the foreground
- //
- DDCall(m_pdid->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
- //
- // Get the mouse acceleration values
- //
- int pvalue[3];
- ZVerify(SystemParametersInfo(SPI_GETMOUSE, 0, pvalue, 0));
- m_threshold1 = pvalue[0];
- m_threshold2 = pvalue[1];
- m_acceleration = pvalue[2];
- m_sensitivity = 1.0f;
- /* !!! this only works on NT50
- int speed;
- ZVerify(SystemParametersInfo(SPI_GETMOUSESPEED, 0, &speed, 0));
- if (speed <= 2) {
- m_sensitivity = float(speed) / 32.0f;
- } else if(speed >= 3 && speed <= 10 ) {
- m_sensitivity = float(speed-2) / 8.0f;
- } else {
- m_sensitivity = float(speed-6) / 4.0f;
- }
- */
- }
- void SetupDevice()
- {
- //
- // Set the data format
- //
- DDCall(m_pdid->SetDataFormat(g_pdfDIMouse));
- //
- // Make some buffer space
- //
- if (m_bBuffered) {
- DIPROPDWORD dipdw;
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dipdw.diph.dwObj = 0;
- dipdw.diph.dwHow = DIPH_DEVICE;
- dipdw.dwData = 32;
- DDCall(m_pdid->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph));
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Methods
- //
- //////////////////////////////////////////////////////////////////////////////
-
- void DoClip()
- {
- if (
- m_rect.XMax() > m_rect.XMin()
- && m_rect.YMax() > m_rect.YMin()
- ) {
- if (m_point.X() < m_rect.XMin()) {
- m_point.SetX(m_rect.XMin());
- }
- if (m_point.X() >= m_rect.XMax()) {
- m_point.SetX(m_rect.XMax() - 1);
- }
- if (m_point.Y() < m_rect.YMin()) {
- m_point.SetY(m_rect.YMin());
- }
- if (m_point.Y() >= m_rect.YMax()) {
- m_point.SetY(m_rect.YMax() - 1);
- }
- }
- }
- float CalculateDelta(int delta)
- {
- if (abs(delta) > m_threshold1 && m_acceleration >= 1) {
- if (abs(delta) > m_threshold2 && m_acceleration >= 2) {
- return float(delta) * 4.0f * m_sensitivity;
- } else {
- return float(delta) * 2.0f * m_sensitivity;
- }
- }
- return float(delta) * m_sensitivity;
- }
- void DeltaPosition(int& dx, int& dy)
- {
- if (dx != 0 || dy != 0) {
- //ZDebugOutput("MouseMove: (" + ZString(dx) + ", " + ZString(dy) + ")\n");
- m_point.SetX(m_point.X() + CalculateDelta(dx));
- m_point.SetY(m_point.Y() - CalculateDelta(dy));
- dx = 0;
- dy = 0;
- //
- // Clip to the screen rect if required
- //
- DoClip();
- //
- // Update outputs
- //
- m_vvalueObject[0]->GetValue()->SetValue(m_point.X());
- m_vvalueObject[1]->GetValue()->SetValue(m_point.Y());
- }
- }
- void DeltaWheel(int dz)
- {
- if (dz != 0 ) {
- //ZDebugOutput("MouseDZ: " + ZString(dz) + "\n");
- m_z += float(dz);
- if (m_vvalueObject.GetCount() >= 3) {
- m_vvalueObject[0]->GetValue()->SetValue(m_z);
- }
- }
- }
- void ButtonChanged(int index, bool bDown)
- {
- //ZDebugOutput("MouseButton: " + ZString(index) + (bDown ? " down" : " up") + "\n");
- m_vbuttonObject[index]->GetValue()->SetValue(bDown);
- m_pbuttonEventSource->Trigger(ButtonEventData(index, bDown));
- }
- void UpdateBuffered()
- {
- //
- // Get the data
- //
- DIDEVICEOBJECTDATA didod;
- DWORD count = 1;
- int dx = 0;
- int dy = 0;
- while (count == 1) {
- HRESULT hr = m_pdid->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &didod, &count, 0);
- if (FAILED(hr)) {
- return;
- }
- if (count == 1) {
- //
- // Unpack the data
- //
- switch (didod.dwOfs) {
- case DIMOFS_BUTTON0:
- DeltaPosition(dx, dy);
- ButtonChanged(0, ((didod.dwData & 0x80) != 0));
- break;
- case DIMOFS_BUTTON1:
- ButtonChanged(1, ((didod.dwData & 0x80) != 0));
- break;
- case DIMOFS_BUTTON2:
- ButtonChanged(2, ((didod.dwData & 0x80) != 0));
- break;
- case DIMOFS_BUTTON3:
- ButtonChanged(3, ((didod.dwData & 0x80) != 0));
- break;
- case DIMOFS_X:
- dx += int(didod.dwData);
- break;
- case DIMOFS_Y:
- dy += int(didod.dwData);
- break;
- case DIMOFS_Z:
- DeltaWheel(int(didod.dwData));
- break;
- }
- }
- //
- // do the mouse change
- //
- DeltaPosition(dx, dy);
- }
- }
- void UpdatePolled()
- {
- //
- // Poll the device
- //
- m_pdid->Poll();
- //
- // Get the data
- //
- DIMOUSESTATE dims;
- DDCall(m_pdid->GetDeviceState(sizeof(dims), &dims));
- //
- // Unpack the data
- //
- int dx = int(dims.lX);
- int dy = int(dims.lY);
- int dz = int(dims.lZ);
- DeltaPosition(dx, dy);
- DeltaWheel(dz);
- int count = m_vbuttonObject.GetCount();
- for (int index = 0; index < count; index++) {
- bool bDown = ((dims.rgbButtons[index] & 0x80) != 0);
- ModifiableBoolean* pbool = m_vbuttonObject[index]->GetValue();
- if (bDown != pbool->GetValue()) {
- pbool->SetValue(bDown);
- ButtonChanged(index, bDown);
- }
- }
- }
- void Update()
- {
- //ZDebugOutput("Mouse Update\n");
- if (m_bEnabled) {
- //ZDebugOutput("Mouse Enabled\n");
- HRESULT hr = m_pdid->Acquire();
- //
- // We have to handle the case where another app has captured the
- // mouse, since we may have been switched out.
- //
- if (hr != DIERR_OTHERAPPHASPRIO) {
- DDCall(hr);
- if (m_bBuffered) {
- UpdateBuffered();
- } else {
- UpdatePolled();
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // MouseInputStream
- //
- //////////////////////////////////////////////////////////////////////////////
-
- void SetClipRect(const Rect& rect)
- {
- m_rect = rect;
- DoClip();
- }
- void SetPosition(const Point& point)
- {
- m_point = point;
- DoClip();
- }
- void SetWheelPosition(float pos)
- {
- m_z = pos;
- }
- const Point& GetPosition()
- {
- return m_point;
- }
- void SetEnabled(bool bEnabled)
- {
- if (m_bEnabled != bEnabled) {
- m_bEnabled = bEnabled;
- if (m_bEnabled) {
- //DDCall(m_pdid->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND));
- } else {
- //DDCall(m_pdid->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND));
- DDCall(m_pdid->Unacquire());
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // InputStream
- //
- //////////////////////////////////////////////////////////////////////////////
-
- int GetValueCount()
- {
- return m_vvalueObject.GetCount();
- }
- int GetButtonCount()
- {
- return m_vbuttonObject.GetCount();
- }
- Boolean* IsDown(int id)
- {
- if (id < m_vbuttonObject.GetCount()) {
- return m_vbuttonObject[id]->GetValue();
- } else {
- return NULL;
- }
- }
- Number* GetValue(int id)
- {
- if (id < m_vvalueObject.GetCount()) {
- return m_vvalueObject[id]->GetValue();
- } else {
- return NULL;
- }
- }
- ButtonEvent::Source* GetEventSource()
- {
- return m_pbuttonEventSource;
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- class JoystickInputStreamImpl : public JoystickInputStream {
- private:
- TRef<IDirectInputDevice2> m_pdid;
- DIDeviceCaps m_didc;
- DIDeviceInstance m_didi;
- TVector<TRef<ValueDDInputObject > > m_vvalueObject;
- TVector<TRef<ButtonDDInputObject> > m_vbuttonObject;
- BYTE* m_pbyteData;
- DWORD m_sizeData;
- bool m_bFocus;
- TRef<IDirectInputEffect> m_peffectBounce;
- TRef<IDirectInputEffect> m_peffectFire;
- TRef<IDirectInputEffect> m_peffectExplode;
- public:
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
-
- BOOL EnumObjectsCallback(
- LPCDIDEVICEOBJECTINSTANCE pddoi
- ) {
- if (
- pddoi->dwType & DIDFT_AXIS
- || pddoi->dwType & DIDFT_POV
- ) {
- int index;
- if (pddoi->guidType == GUID_XAxis ) {
- index = 0;
- } else if (pddoi->guidType == GUID_YAxis ) {
- index = 1;
- } else if (pddoi->guidType == GUID_Slider) {
- index = 2;
- } else if (pddoi->guidType == GUID_RzAxis) {
- index = 3;
- } else if (pddoi->guidType == GUID_POV ) {
- index = 4;
- } else {
- index = -1;
- }
- ValueDDInputObject* pobject =
- new ValueDDInputObject(
- pddoi->tszName,
- pddoi->dwType,
- pddoi->guidType
- );
- if (index == -1) {
- m_vvalueObject.PushEnd(pobject);
- } else {
- m_vvalueObject.Set(index, pobject);
- }
- } else if (pddoi->dwType & DIDFT_PSHBUTTON) {
- ButtonDDInputObject* pobject =
- new ButtonDDInputObject(
- pddoi->tszName,
- pddoi->dwType,
- pddoi->guidType
- );
- m_vbuttonObject.PushEnd(pobject);
- }
- return DIENUM_CONTINUE;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
-
- static BOOL CALLBACK StaticEnumObjectsCallback(
- LPCDIDEVICEOBJECTINSTANCE lpddoi,
- LPVOID pvRef
- ) {
- JoystickInputStreamImpl* pthis = (JoystickInputStreamImpl*)pvRef;
- return pthis->EnumObjectsCallback(lpddoi);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // Constructor
- //
- //////////////////////////////////////////////////////////////////////////////
- JoystickInputStreamImpl(IDirectInputDevice2* pdid, HWND hwnd) :
- m_pdid(pdid),
- m_bFocus(false),
- m_vvalueObject(5)
- {
- DDCall(m_pdid->GetCapabilities(&m_didc));
- DDCall(m_pdid->GetDeviceInfo(&m_didi));
- //
- // Enumerate the buttons and values
- //
- DDCall(m_pdid->EnumObjects(StaticEnumObjectsCallback, this, DIDFT_ALL));
- //
- // Remove any holes in the value vector
- //
- int index;
- int countValues = m_vvalueObject.GetCount();
- index = 0;
- while (index < countValues) {
- if (m_vvalueObject[index] == NULL) {
- if (index != countValues - 1) {
- m_vvalueObject.Set(index, m_vvalueObject[countValues - 1]);
- }
- countValues--;
- m_vvalueObject.SetCount(countValues);
- } else {
- index++;
- }
- }
- //
- // Build the data format
- //
- int countButtons = m_vbuttonObject.GetCount();
- m_sizeData = NextMultipleOf(4, countValues * 4 + countButtons * 1);
- DIDataFormat didf;
- didf.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
- didf.dwFlags = 0;
- didf.dwDataSize = m_sizeData;
- didf.dwNumObjs = countValues + countButtons;
- DIObjectDataFormat* pdiodf = new DIObjectDataFormat[didf.dwNumObjs];
- didf.rgodf = pdiodf;
- for (index = 0; index < countValues; index++) {
- ValueDDInputObject* pobject = m_vvalueObject[index];
- DIOBJECTDATAFORMAT& diodf = didf.rgodf[index];
- diodf.pguid = (GUID*)&(pobject->GetGUID());
- diodf.dwOfs = index * 4;
- diodf.dwType = pobject->GetDWType();
- diodf.dwFlags = DIDOI_ASPECTPOSITION;
- }
- for (index = 0; index < countButtons; index++) {
- ButtonDDInputObject* pobject = m_vbuttonObject[index];
- DIOBJECTDATAFORMAT& diodf = didf.rgodf[countValues + index];
- diodf.pguid = (GUID*)&(pobject->GetGUID());
- diodf.dwOfs = countValues * 4 + index;
- diodf.dwType = pobject->GetDWType();
- diodf.dwFlags = DIDOI_ASPECTPOSITION;
- }
- DDCall(m_pdid->SetDataFormat(&didf));
- delete pdiodf;
- //
- // Allocate a data receptical
- //
- m_pbyteData = new BYTE[m_sizeData];
- //
- // We only need joystick input when we are in the foreground
- //
- DDCall(m_pdid->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND));
- //
- // Set ranges
- //
- SetRanges();
- }
- ~JoystickInputStreamImpl()
- {
- delete m_pbyteData;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Implementation methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void SetRanges()
- {
- m_pdid->Unacquire();
- int countValues = m_vvalueObject.GetCount();
- for (int index = 0; index < countValues; index++) {
- if (m_vvalueObject[index] != NULL) {
- if ((m_vvalueObject[index]->GetDWType() & DIDFT_POV) == 0) {
- DIPROPRANGE dipr;
- dipr.diph.dwSize = sizeof(dipr);
- dipr.diph.dwHeaderSize = sizeof(dipr.diph);
- dipr.diph.dwHow = DIPH_BYID;
- dipr.diph.dwObj = m_vvalueObject[index]->GetDWType();
- dipr.lMin = -100000;
- dipr.lMax = 100000;
- DDCall(m_pdid->SetProperty(DIPROP_RANGE, &dipr.diph));
- }
- //
- //
- //
- DIPROPDWORD dipdw;
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dipdw.diph.dwObj = 0;
- dipdw.diph.dwHow = DIPH_DEVICE;
- DDCall(m_pdid->GetProperty(DIPROP_BUFFERSIZE, &dipdw.diph));
- }
- }
- }
- void Update()
- {
- HRESULT hr = m_pdid->Acquire();
- //
- // We have to handle the case where another app has captured the
- // joystick, since we may be switched out.
- // Or the joystick may have been unplugged.
- //
- if (SUCCEEDED(hr)) {
- //
- // Poll the device
- //
- m_pdid->Poll();
- //
- // The MS Gamepad will return error from this funtion if the mode button is pressed
- // Don't assert in that case. Just don't unpack the data.
- //
- hr = m_pdid->GetDeviceState(m_sizeData, m_pbyteData);
- if (SUCCEEDED(hr)) {
- //
- // Unpack the data
- //
- int countValues = m_vvalueObject.GetCount();
- int countButtons = m_vbuttonObject.GetCount();
- for (int index = 0; index < countValues; index++) {
- if ((m_vvalueObject[index]->GetDWType() & DIDFT_POV) != 0) {
- int ivalue = ((int*)m_pbyteData)[index];
- float value;
-
- if (ivalue == -1) {
- value = -2;
- } else if (ivalue > 18000) {
- value = float(ivalue - 36000) / 18000;
- } else {
- value = float(ivalue) / 18000;
- }
- //ZDebugOutput("RawHat: " + ZString(ivalue) + ", " + ZString(value) + "\n");
- m_vvalueObject[index]->GetValue()->SetValue(value);
- } else {
- float value = float(((int*)m_pbyteData)[index]) / 100000;
- value = bound(value, -1.0f, 1.0f);
- m_vvalueObject[index]->GetValue()->SetValue(value);
- }
- }
- for (index = 0; index < countButtons; index++) {
- m_vbuttonObject[index]->GetValue()->SetValue(
- m_pbyteData[countValues * 4 + index] != 0
- );
- }
- }
- }
- }
- void SetFocus(bool bFocus)
- {
- if (m_bFocus != bFocus) {
- m_bFocus = bFocus;
- if (m_bFocus) {
- //
- // Aquire the joystick
- //
-
- // !!! this doesn't work. I guess that at the time when this gets called
- // DInput doesn't think we are foreground yet.
- // DDCall(m_pdid->Acquire());
- } else {
- // !!! this gets called automatically
- // DDCall(m_pdid->Unacquire());
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Force Feedback
- //
- //////////////////////////////////////////////////////////////////////////////
- static BOOL CALLBACK EnumEffectTypeProc(LPCDIEFFECTINFO pei, LPVOID pv)
- {
- GUID *pguidEffect = NULL;
- // report back the guid of the effect we enumerated
- if (pv) {
- pguidEffect = (GUID *)pv;
- *pguidEffect = pei->guid;
- }
- // BUGBUG - look at this some more....
- return DIENUM_STOP;
- }
- void CreateEffects()
- {
- GUID guidEffect;
- DIEFFECT diEffect;
- DIENVELOPE diEnvelope;
- DWORD rgdwAxes[2];
- LONG rglDirections[2];
- DICONSTANTFORCE dicf;
- DIPERIODIC dipf;
- //
- // initialize DIEFFECT and DIENVELOPE structures
- //
- ZeroMemory(&diEffect, sizeof(DIEFFECT));
- ZeroMemory(&diEnvelope, sizeof(DIENVELOPE));
- //
- // these fields are the same for all effects we will be creating
- //
- diEffect.dwSize = sizeof(DIEFFECT);
- diEffect.dwSamplePeriod = 0; // use default sample period
- diEffect.dwTriggerButton = DIEB_NOTRIGGER;
- diEffect.dwTriggerRepeatInterval = 0;
- diEffect.rgdwAxes = rgdwAxes;
- diEffect.rglDirection = rglDirections;
- diEffect.dwGain = 7500; // todo: gain selected by user
- //
- // both the "bounce" and "fire" effects will be based on the first
- // constant force effect enumerated
- //
- //
- // don't check for errors. DInput sometimes return error, but then works anyway.
- //
- //DDCall(
- m_pdid->EnumEffects(
- (LPDIENUMEFFECTSCALLBACK)EnumEffectTypeProc,
- &guidEffect,
- DIEFT_CONSTANTFORCE
- //)
- );
- //
- // Create the bounce effect
- //
- dicf.lMagnitude = 10000;
- rgdwAxes[0] = DIJOFS_X;
- rgdwAxes[1] = DIJOFS_Y;
- rglDirections[0] = 0;
- rglDirections[1] = 0;
- diEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
- diEffect.dwDuration = 200000;
- diEffect.cAxes = 2;
- diEffect.lpEnvelope = NULL;
- diEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
- diEffect.lpvTypeSpecificParams = &dicf;
- //DDCall(
- m_pdid->CreateEffect(
- guidEffect,
- &diEffect,
- &m_peffectBounce,
- NULL
- //)
- );
- //
- // Create the fire effect
- //
- dicf.lMagnitude = 10000;
- rgdwAxes[0] = DIJOFS_Y;
- rglDirections[0] = 1;
- diEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_CARTESIAN;
- diEffect.dwDuration = 20000;
- diEffect.cAxes = 1;
- diEffect.lpEnvelope = NULL;
- diEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
- diEffect.lpvTypeSpecificParams = &dicf;
- //DDCall(
- m_pdid->CreateEffect(
- guidEffect,
- &diEffect,
- &m_peffectFire,
- NULL
- //)
- );
- //
- // the "explode" effect will be based on the first
- // periodic effect enumerated
- //
- //DDCall(
- m_pdid->EnumEffects(
- (LPDIENUMEFFECTSCALLBACK)EnumEffectTypeProc,
- &guidEffect,
- DIEFT_PERIODIC
- //)
- );
- //
- // Create the explode effect.
- // We want to shape the explode effect so that it starts
- // at it's peak and then fades out
- //
- diEnvelope.dwSize = sizeof(DIENVELOPE);
- diEnvelope.dwAttackLevel = 0;
- diEnvelope.dwAttackTime = 0;
- diEnvelope.dwFadeLevel = 0;
- diEnvelope.dwFadeTime = 1000000;
- dipf.dwMagnitude = 10000;
- dipf.lOffset = 0;
- dipf.dwPhase = 0;
- dipf.dwPeriod = 100000;
- rgdwAxes[0] = DIJOFS_X;
- rglDirections[0] = 0;
- diEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_CARTESIAN;
- diEffect.dwDuration = 1000000;
- diEffect.cAxes = 1;
- diEffect.lpEnvelope = &diEnvelope;
- diEffect.cbTypeSpecificParams = sizeof(DIPERIODIC);
- diEffect.lpvTypeSpecificParams = &dipf;
- //DDCall(
- m_pdid->CreateEffect(
- guidEffect,
- &diEffect,
- &m_peffectExplode,
- NULL
- //)
- );
- }
- void PlayFFEffect(short effectID, LONG lDirection)
- {
- //
- // !!! Don't check for errors here. Sometimes these functions will return error
- //
- switch (effectID) {
- case 0:
- if (m_peffectFire) {
- m_peffectFire->Start(1, 0);
- }
- break;
- case 1:
- if (m_peffectBounce) {
- DIEFFECT diEffect;
- LONG rglDirections[2] = { 0, 0 };
- ZeroMemory(&diEffect, sizeof(DIEFFECT));
- diEffect.dwSize = sizeof(DIEFFECT);
- rglDirections[0] = lDirection * 100;
- diEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
- diEffect.cAxes = 2;
- diEffect.rglDirection = rglDirections;
- m_peffectBounce->SetParameters(&diEffect, DIEP_DIRECTION);
- m_peffectBounce->Start(1, 0);
- }
- break;
- case 2:
- if (m_peffectExplode) {
- m_peffectExplode->Start(1, 0);
- }
- break;
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // JoystickInputStream methods
- //
- //////////////////////////////////////////////////////////////////////////////
- bool HasForceFeedback()
- {
- return (m_didc.dwFlags & DIDC_FORCEFEEDBACK) != 0;
- }
- ZString GetShortDescription(int index)
- {
- return "Joy " + ZString(index);
- }
- ZString GetDescription()
- {
- return m_didi.tszInstanceName;
- }
- ZString GetValueDescription(int id)
- {
- return m_vvalueObject[id]->GetName();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // InputStream methods
- //
- //////////////////////////////////////////////////////////////////////////////
- int GetValueCount()
- {
- return m_vvalueObject.GetCount();
- }
- int GetButtonCount()
- {
- return m_vbuttonObject.GetCount();
- }
- Boolean* IsDown(int id)
- {
- if (id < m_vbuttonObject.GetCount()) {
- return m_vbuttonObject[id]->GetValue();
- } else {
- return NULL;
- }
- }
- Number* GetValue(int id)
- {
- if (id < m_vvalueObject.GetCount()) {
- return m_vvalueObject[id]->GetValue();
- } else {
- return NULL;
- }
- }
- ButtonEvent::Source* GetEventSource()
- {
- ZUnimplemented();
- return NULL;
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- class InputEngineImpl : public InputEngine {
- private:
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- bool EnumDeviceCallback(LPDIDEVICEINSTANCE pdidi)
- {
- TRef<IDirectInputDevice> pdid;
- TRef<IDirectInputDevice2> pdid2;
- DDCall(m_pdi->CreateDevice( pdidi->guidInstance, &pdid, NULL));
- DDCall(pdid->QueryInterface(IID_IDirectInputDevice2, (void**)&pdid2));
- switch (pdidi->dwDevType & 0xff) {
- case DIDEVTYPE_MOUSE:
- {
- if (m_pmouseInputStream == NULL) {
- m_pmouseInputStream = new MouseInputStreamImpl(pdid2, m_hwnd);
- }
- }
- break;
- case DIDEVTYPE_JOYSTICK:
- {
- TRef<JoystickInputStreamImpl> pjoystickInputStream =
- new JoystickInputStreamImpl(pdid2, m_hwnd);
- m_vjoystickInputStream.PushEnd(pjoystickInputStream);
- }
- break;
- }
- return DIENUM_CONTINUE;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- static BOOL CALLBACK StaticEnumDeviceCallback(LPDIDEVICEINSTANCE pdidi, LPVOID pv)
- {
- InputEngineImpl* pthis = (InputEngineImpl*)pv;
- return pthis->EnumDeviceCallback(pdidi);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // data members
- //
- //////////////////////////////////////////////////////////////////////////////
- HWND m_hwnd;
- bool m_bFocus;
- TRef<IDirectInput> m_pdi;
- TVector<TRef<JoystickInputStreamImpl> > m_vjoystickInputStream;
- TRef<MouseInputStreamImpl> m_pmouseInputStream;
- HINSTANCE m_hdinput;
- public:
- //////////////////////////////////////////////////////////////////////////////
- //
- // Constructor
- //
- //////////////////////////////////////////////////////////////////////////////
- typedef HRESULT (WINAPI *PFNDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
- InputEngineImpl(HWND hwnd) :
- m_hwnd(hwnd),
- m_bFocus(false)
- {
- //
- // Create the direct input object
- //
- #ifdef Dynamic_DInput
- m_hdinput = ::LoadLibrary("dinput.dll");
- ZAssert(m_hdinput != NULL);
- PFNDirectInputCreate pfn = (PFNDirectInputCreate)::GetProcAddress(m_hdinput, "DirectInputCreateA");
- ZAssert(pfn != NULL);
- DDCall(pfn(
- GetModuleHandle(NULL),
- DIRECTINPUT_VERSION,
- &m_pdi,
- NULL
- ));
- //
- // grab the address of a few dinput globals
- //
- g_pdfDIMouse = (DIDATAFORMAT*)::GetProcAddress(m_hdinput, "c_dfDIMouse");
- ZAssert(g_pdfDIMouse != NULL);
- #else
- DDCall(DirectInputCreate(
- GetModuleHandle(NULL),
- DIRECTINPUT_VERSION,
- &m_pdi,
- NULL
- ));
- g_pdfDIMouse = &c_dfDIMouse;
- #endif
- //
- // If we failed then exit the app
- //
- if (m_pdi == NULL) {
- ::MessageBox(NULL, "Error initializing DirectInput. Check your installation", "Error", MB_OK);
- _exit(0);
- }
- //
- // Enumerate the devices
- //
- EnumerateJoysticks();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // InputEngine methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void EnumerateJoysticks()
- {
- //
- // Free up the old devices
- //
- m_vjoystickInputStream.SetEmpty();
- //
- // Enumerate all of the devices
- //
- DDCall(m_pdi->EnumDevices(
- 0,//DIDEVTYPE_JOYSTICK,
- (LPDIENUMDEVICESCALLBACK)StaticEnumDeviceCallback,
- this,
- DIEDFL_ATTACHEDONLY
- ));
- }
- int GetJoystickCount()
- {
- return m_vjoystickInputStream.GetCount();
- }
- JoystickInputStream* GetJoystick(int index)
- {
- if (
- index >= 0
- && index < m_vjoystickInputStream.GetCount()
- ) {
- return m_vjoystickInputStream[index];
- } else {
- return NULL;
- }
- }
- MouseInputStream* GetMouse()
- {
- return m_pmouseInputStream;
- }
- void Update()
- {
- if (m_bFocus) {
- m_pmouseInputStream->Update();
- int count = m_vjoystickInputStream.GetCount();
- for(int index = 0; index < count; index++) {
- m_vjoystickInputStream[index]->Update();
- }
- }
- }
- void SetFocus(bool bFocus)
- {
- if (m_bFocus != bFocus) {
- m_bFocus = bFocus;
- int count = m_vjoystickInputStream.GetCount();
- for(int index = 0; index < count; index++) {
- m_vjoystickInputStream[index]->SetFocus(m_bFocus);
- }
- }
- }
- };
- TRef<InputEngine> CreateInputEngine(HWND hwnd)
- {
- return new InputEngineImpl(hwnd);
- }
|