void updateButtons(bool collectEvents) { DIDEVICEOBJECTDATA data[inputBufferSize]; DWORD inOut; HRESULT hr; RECT rect; ::GetClientRect(window, &rect); bool ignoreClicks = mouseX < 0 || mouseX > rect.right || mouseY < 0 || mouseY > rect.bottom; inOut = inputBufferSize; hr = mouse->GetDeviceData(sizeof data[0], data, &inOut, 0); switch(hr) { case DI_OK: case DI_BUFFEROVERFLOW: { // Everything's ok: Update buttons and fire events. for (unsigned i = 0; i < inOut; ++i) { bool down = (data[i].dwData & 0x80) != 0 && !ignoreClicks; switch (data[i].dwOfs) { case DIMOFS_BUTTON0: { unsigned id = swapMouse ? msRight : msLeft; setButton(id, down, collectEvents); break; } case DIMOFS_BUTTON1: { unsigned id = swapMouse ? msLeft : msRight; setButton(id, down, collectEvents); break; } case DIMOFS_BUTTON2: { setButton(msMiddle, down, collectEvents); break; } case DIMOFS_Z: { if (!collectEvents || data[i].dwData == 0) break; EventInfo event; event.action = EventInfo::buttonDown; if (int(data[i].dwData) < 0) event.id = msWheelDown; else event.id = msWheelUp; events.push_back(event); event.action = EventInfo::buttonUp; events.push_back(event); break; } } } break; } case DIERR_NOTACQUIRED: case DIERR_INPUTLOST: { // Cannot fetch new events: Release all buttons. for (unsigned id = msRangeBegin; id < msRangeEnd; ++id) setButton(id, false, collectEvents); mouse->Acquire(); break; } } keyboard: inOut = inputBufferSize; hr = keyboard->GetDeviceData(sizeof data[0], data, &inOut, 0); switch (hr) { case DI_OK: case DI_BUFFEROVERFLOW: { for (unsigned i = 0; i < inOut; ++i) forceButton(data[i].dwOfs, (data[i].dwData & 0x80) != 0, collectEvents); break; } case DIERR_NOTACQUIRED: case DIERR_INPUTLOST: { for (unsigned id = kbRangeBegin; id < kbRangeEnd; ++id) setButton(id, false, collectEvents); keyboard->Acquire(); break; } } boost::array<bool, gpNum> gpBuffer; gpBuffer.assign(false); for (unsigned gp = 0; gp < gamepads.size(); ++gp) { gamepads[gp]->Poll(); DIJOYSTATE joy; hr = gamepads[gp]->GetDeviceState(sizeof joy, &joy); switch (hr) { case DI_OK: { if (joy.lX < -stickThreshold) gpBuffer[gpLeft - gpRangeBegin] = true; else if (joy.lX > stickThreshold) gpBuffer[gpRight - gpRangeBegin] = true; if (joy.lY < -stickThreshold) gpBuffer[gpUp - gpRangeBegin] = true; else if (joy.lY > stickThreshold) gpBuffer[gpDown - gpRangeBegin] = true; for (unsigned id = gpButton0; id < gpRangeEnd; ++id) if (joy.rgbButtons[id - gpButton0]) gpBuffer[id - gpRangeBegin] = true; break; } case DIERR_NOTACQUIRED: case DIERR_INPUTLOST: { gamepads[gp]->Acquire(); break; } } } for (unsigned id = gpRangeBegin; id < gpRangeEnd; ++id) setButton(id, gpBuffer[id - gpRangeBegin], collectEvents); }
// For polled devices, or when there's no data. void setButton(unsigned id, bool down, bool collectEvent) { if (buttons.at(id) != down) forceButton(id, down, collectEvent); }
void updateButtons(bool collectEvents) { DIDEVICEOBJECTDATA data[inputBufferSize]; DWORD inOut; HRESULT hr; RECT rect; ::GetClientRect(window, &rect); bool ignoreClicks = mouseX < 0 || mouseX > rect.right || mouseY < 0 || mouseY > rect.bottom; inOut = inputBufferSize; hr = mouse->GetDeviceData(sizeof data[0], data, &inOut, 0); switch(hr) { case DI_OK: case DI_BUFFEROVERFLOW: { // Everything's ok: Update buttons and fire events. for (unsigned i = 0; i < inOut; ++i) { bool down = (data[i].dwData & 0x80) != 0 && !ignoreClicks; // No switch statement here because it breaks compilation with MinGW. if (data[i].dwOfs == DIMOFS_BUTTON0) { unsigned id = swapMouse ? msRight : msLeft; setButton(id, down, collectEvents); } else if (data[i].dwOfs == DIMOFS_BUTTON1) { unsigned id = swapMouse ? msLeft : msRight; setButton(id, down, collectEvents); } else if (data[i].dwOfs == DIMOFS_BUTTON2) { setButton(msMiddle, down, collectEvents); } else if (data[i].dwOfs == DIMOFS_Z && collectEvents && data[i].dwData) { EventInfo event; event.action = EventInfo::buttonDown; if (int(data[i].dwData) < 0) event.id = msWheelDown; else event.id = msWheelUp; events.push_back(event); event.action = EventInfo::buttonUp; events.push_back(event); } } break; } case DIERR_NOTACQUIRED: case DIERR_INPUTLOST: { // Cannot fetch new events: Release all buttons. for (unsigned id = msRangeBegin; id <= msRangeEnd; ++id) setButton(id, false, collectEvents); mouse->Acquire(); break; } } inOut = inputBufferSize; hr = keyboard->GetDeviceData(sizeof data[0], data, &inOut, 0); switch (hr) { case DI_OK: case DI_BUFFEROVERFLOW: { for (unsigned i = 0; i < inOut; ++i) forceButton(data[i].dwOfs, (data[i].dwData & 0x80) != 0, collectEvents); break; } case DIERR_NOTACQUIRED: case DIERR_INPUTLOST: { for (unsigned id = kbRangeBegin; id <= kbRangeEnd; ++id) setButton(id, false, collectEvents); keyboard->Acquire(); break; } } std::tr1::array<bool, gpNum> gpBuffer = { false }; for (unsigned gp = 0; gp < gamepads.size() && gp < numGamepads; ++gp) { gamepads[gp]->Poll(); int rangeOffset = (gp + 1) * gpNumPerGamepad - gpRangeBegin; DIJOYSTATE joy; hr = gamepads[gp]->GetDeviceState(sizeof joy, &joy); switch (hr) { case DI_OK: { if (joy.lX < -stickThreshold) gpBuffer[gpLeft + rangeOffset] = true; else if (joy.lX > stickThreshold) gpBuffer[gpRight + rangeOffset] = true; if (joy.lY < -stickThreshold) gpBuffer[gpUp + rangeOffset] = true; else if (joy.lY > stickThreshold) gpBuffer[gpDown + rangeOffset] = true; for (unsigned id = gpButton0; id <= gpButton15; ++id) if (joy.rgbButtons[id - gpButton0]) gpBuffer[id + rangeOffset] = true; break; } case DIERR_NOTACQUIRED: case DIERR_INPUTLOST: { gamepads[gp]->Acquire(); break; } } // Merge these results into the area for "all gamepads OR'ed together" for (int index = 0; index < gpNumPerGamepad; ++index) gpBuffer[index] = (gpBuffer[index] || gpBuffer[index + (gp + 1) * gpNumPerGamepad]); } for (unsigned id = gpRangeBegin; id <= gpRangeEnd; ++id) setButton(id, gpBuffer[id - gpRangeBegin], collectEvents); }