示例#1
0
void WindowsGamepadService::CheckXInputChanges(Gamepad& gamepad,
                                               XINPUT_STATE& state) {
  // Handle digital buttons first
  for (size_t b = 0; b < kNumMappings; b++) {
    if (state.Gamepad.wButtons & kXIButtonMap[b].button &&
        !(gamepad.state.Gamepad.wButtons & kXIButtonMap[b].button)) {
      // Button pressed
      NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, true);
    } else if (!(state.Gamepad.wButtons & kXIButtonMap[b].button) &&
               gamepad.state.Gamepad.wButtons & kXIButtonMap[b].button) {
      // Button released
      NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, false);
    }
  }

  // Then triggers
  if (state.Gamepad.bLeftTrigger != gamepad.state.Gamepad.bLeftTrigger) {
    bool pressed =
      state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
    NewButtonEvent(gamepad.id, kButtonLeftTrigger,
                   pressed, state.Gamepad.bLeftTrigger / 255.0);
  }
  if (state.Gamepad.bRightTrigger != gamepad.state.Gamepad.bRightTrigger) {
    bool pressed =
      state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
    NewButtonEvent(gamepad.id, kButtonRightTrigger,
                   pressed, state.Gamepad.bRightTrigger / 255.0);
  }

  // Finally deal with analog sticks
  // TODO: bug 1001955 - Support deadzones.
  if (state.Gamepad.sThumbLX != gamepad.state.Gamepad.sThumbLX) {
    NewAxisMoveEvent(gamepad.id, kLeftStickXAxis,
                     state.Gamepad.sThumbLX / 32767.0);
  }
  if (state.Gamepad.sThumbLY != gamepad.state.Gamepad.sThumbLY) {
    NewAxisMoveEvent(gamepad.id, kLeftStickYAxis,
                     -1.0 * state.Gamepad.sThumbLY / 32767.0);
  }
  if (state.Gamepad.sThumbRX != gamepad.state.Gamepad.sThumbRX) {
    NewAxisMoveEvent(gamepad.id, kRightStickXAxis,
                     state.Gamepad.sThumbRX / 32767.0);
  }
  if (state.Gamepad.sThumbRY != gamepad.state.Gamepad.sThumbRY) {
    NewAxisMoveEvent(gamepad.id, kRightStickYAxis,
                     -1.0 * state.Gamepad.sThumbRY / 32767.0);
  }
  gamepad.state = state;
}
示例#2
0
void
GamepadService::Update(const GamepadChangeEvent& aEvent)
{
  if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
    const GamepadAdded& a = aEvent.get_GamepadAdded();
    AddGamepad(a.index(), a.id(),
               static_cast<GamepadMappingType>(a.mapping()),
               a.num_buttons(), a.num_axes());
  } else if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
    const GamepadRemoved& a = aEvent.get_GamepadRemoved();
    RemoveGamepad(a.index());
  } else if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
    const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
    NewButtonEvent(a.index(), a.button(), a.pressed(), a.value());
  } else if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
    const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation();
    NewAxisMoveEvent(a.index(), a.axis(), a.value());
  } else {
    MOZ_CRASH("We shouldn't be here!");
  }
}
示例#3
0
bool
WindowsGamepadService::HandleRawInput(HRAWINPUT handle)
{
  if (!mHID) {
    return false;
  }

  // First, get data from the handle
  UINT size;
  GetRawInputData(handle, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER));
  nsTArray<uint8_t> data(size);
  data.SetLength(size);
  if (GetRawInputData(handle, RID_INPUT, data.Elements(), &size,
                      sizeof(RAWINPUTHEADER)) == kRawInputError) {
    return false;
  }
  PRAWINPUT raw = reinterpret_cast<PRAWINPUT>(data.Elements());

  Gamepad* gamepad = nullptr;
  for (unsigned i = 0; i < mGamepads.Length(); i++) {
    if (mGamepads[i].type == kRawInputGamepad
        && mGamepads[i].handle == raw->header.hDevice) {
      gamepad = &mGamepads[i];
      break;
    }
  }
  if (gamepad == nullptr) {
    return false;
  }

  // Second, get the preparsed data
  nsTArray<uint8_t> parsedbytes;
  if (!GetPreparsedData(raw->header.hDevice, parsedbytes)) {
    return false;
  }
  PHIDP_PREPARSED_DATA parsed =
    reinterpret_cast<PHIDP_PREPARSED_DATA>(parsedbytes.Elements());

  // Get all the pressed buttons.
  nsTArray<USAGE> usages(gamepad->numButtons);
  usages.SetLength(gamepad->numButtons);
  ULONG usageLength = gamepad->numButtons;
  if (mHID.mHidP_GetUsages(HidP_Input, kButtonUsagePage, 0, usages.Elements(),
                     &usageLength, parsed, (PCHAR)raw->data.hid.bRawData,
                     raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) {
    return false;
  }

  bool buttons[kMaxButtons] = { false };
  usageLength = std::min<ULONG>(usageLength, kMaxButtons);
  for (unsigned i = 0; i < usageLength; i++) {
    buttons[usages[i] - 1] = true;
  }

  if (gamepad->hasDpad) {
    // Get d-pad position as 4 buttons.
    ULONG value;
    if (mHID.mHidP_GetUsageValue(HidP_Input, gamepad->dpadCaps.UsagePage, 0, gamepad->dpadCaps.Range.UsageMin, &value, parsed, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid) == HIDP_STATUS_SUCCESS) {
      UnpackDpad(static_cast<LONG>(value), gamepad, buttons);
    }
  }

  for (unsigned i = 0; i < gamepad->numButtons; i++) {
    if (gamepad->buttons[i] != buttons[i]) {
      NewButtonEvent(gamepad->id, i, buttons[i]);
      gamepad->buttons[i] = buttons[i];
    }
  }

  // Get all axis values.
  for (unsigned i = 0; i < gamepad->numAxes; i++) {
    double new_value;
    if (gamepad->axes[i].caps.LogicalMin < 0) {
LONG value;
      if (mHID.mHidP_GetScaledUsageValue(HidP_Input, gamepad->axes[i].caps.UsagePage,
                                   0, gamepad->axes[i].caps.Range.UsageMin,
                                   &value, parsed,
                                   (PCHAR)raw->data.hid.bRawData,
                                   raw->data.hid.dwSizeHid)
          != HIDP_STATUS_SUCCESS) {
        continue;
      }
      new_value = ScaleAxis(value, gamepad->axes[i].caps.LogicalMin,
                            gamepad->axes[i].caps.LogicalMax);
    }
    else {
      ULONG value;
      if (mHID.mHidP_GetUsageValue(HidP_Input, gamepad->axes[i].caps.UsagePage, 0,
                             gamepad->axes[i].caps.Range.UsageMin, &value,
                             parsed, (PCHAR)raw->data.hid.bRawData,
                             raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) {
        continue;
      }

      new_value = ScaleAxis(value, gamepad->axes[i].caps.LogicalMin,
                            gamepad->axes[i].caps.LogicalMax);
    }
    if (gamepad->axes[i].value != new_value) {
      NewAxisMoveEvent(gamepad->id, i, new_value);
      gamepad->axes[i].value = new_value;
    }
  }

  return true;
}