blob: 202a12d733a0a070debfa515ff324f7fd0dfee03 [file] [log] [blame]
/*
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "starboard/shared/uwp/analog_thumbstick_input.h"
#include <Windows.Gaming.Input.h>
#include <algorithm>
#include "starboard/log.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/types.h"
#pragma comment(lib, "xinput9_1_0.lib")
using Windows::Foundation::Collections::IVectorView;
using Windows::Gaming::Input::Gamepad;
using Windows::Gaming::Input::GamepadReading;
using Windows::Gaming::Input::RawGameController;
namespace starboard {
namespace shared {
namespace uwp {
namespace {
const int kMaxPlayerCounter = 4;
const float kDeadZoneThreshold = .24f;
float ApplyLinearDeadZone(float value, float maxValue, float deadZoneSize) {
if (value < -deadZoneSize) {
// Increase negative values to remove the deadzone discontinuity.
value += deadZoneSize;
} else if (value > deadZoneSize) {
// Decrease positive values to remove the deadzone discontinuity.
value -= deadZoneSize;
} else {
// Values inside the deadzone come out zero.
return 0;
}
// Scale into 0-1 range.
float scaledValue = value / (maxValue - deadZoneSize);
return std::max(-1.f, std::min(scaledValue, 1.f));
}
void ApplyStickDeadZone(float x,
float y,
float max_value,
float dead_zone_size,
float* result_x,
float* result_y) {
*result_x = ApplyLinearDeadZone(x, max_value, dead_zone_size);
*result_y = ApplyLinearDeadZone(y, max_value, dead_zone_size);
}
ThumbSticks ReadThumbStick(Gamepad ^ controller) {
ThumbSticks output;
GamepadReading reading = controller->GetCurrentReading();
ApplyStickDeadZone(static_cast<float>(reading.LeftThumbstickX),
static_cast<float>(reading.LeftThumbstickY), 1.f,
kDeadZoneThreshold, &output.left_x, &output.left_y);
ApplyStickDeadZone(static_cast<float>(reading.RightThumbstickX),
static_cast<float>(reading.RightThumbstickY), 1.f,
kDeadZoneThreshold, &output.right_x, &output.right_y);
return output;
}
} // namespace
void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination) {
destination->erase(destination->begin(), destination->end());
// This profiled to an average time of 33us to execute.
IVectorView<Gamepad ^> ^ gamepads = Gamepad::Gamepads;
// This profiled to take on average 9us of time to read controller state.
const uint32_t n = gamepads->Size;
for (uint32_t i = 0; i < n; ++i) {
Gamepad ^ gamepad = gamepads->GetAt(i);
ThumbSticks thumb_stick = ReadThumbStick(gamepad);
destination->push_back(thumb_stick);
}
}
} // namespace uwp
} // namespace shared
} // namespace starboard