Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deadzone settings #10309

Merged
merged 7 commits into from Aug 26, 2016
@@ -255,6 +255,8 @@
5EF801001A97892A0035AA4D /* ReplayGain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF800FE1A97892A0035AA4D /* ReplayGain.cpp */; };
6815C1411CC7BADB000DB91A /* RumbleGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6815C13F1CC7BADB000DB91A /* RumbleGenerator.cpp */; };
6815C1421CC7BADB000DB91A /* RumbleGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6815C13F1CC7BADB000DB91A /* RumbleGenerator.cpp */; };
6838CF811D6665510057F17B /* DeadzoneFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6838CF7F1D6665510057F17B /* DeadzoneFilter.cpp */; };
6838CF821D6665510057F17B /* DeadzoneFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6838CF7F1D6665510057F17B /* DeadzoneFilter.cpp */; };
6861B9EA1CC248EE00F62655 /* DriverReceiving.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */; };
6861B9EB1CC248EE00F62655 /* DriverReceiving.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */; };
68AE5BA51C92412900C4D527 /* AddonCallbacksPeripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5BA31C92412900C4D527 /* AddonCallbacksPeripheral.cpp */; };
@@ -2758,6 +2760,8 @@
5EF800FF1A97892A0035AA4D /* ReplayGain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReplayGain.h; sourceTree = "<group>"; };
6815C13F1CC7BADB000DB91A /* RumbleGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RumbleGenerator.cpp; path = joysticks/RumbleGenerator.cpp; sourceTree = "<group>"; };
6815C1401CC7BADB000DB91A /* RumbleGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RumbleGenerator.h; path = joysticks/RumbleGenerator.h; sourceTree = "<group>"; };
6838CF7F1D6665510057F17B /* DeadzoneFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeadzoneFilter.cpp; path = joysticks/DeadzoneFilter.cpp; sourceTree = "<group>"; };
6838CF801D6665510057F17B /* DeadzoneFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeadzoneFilter.h; path = joysticks/DeadzoneFilter.h; sourceTree = "<group>"; };
6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DriverReceiving.cpp; path = joysticks/generic/DriverReceiving.cpp; sourceTree = "<group>"; };
6861B9E91CC248EE00F62655 /* DriverReceiving.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DriverReceiving.h; path = joysticks/generic/DriverReceiving.h; sourceTree = "<group>"; };
6861B9EC1CC248F600F62655 /* IDriverReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IDriverReceiver.h; path = joysticks/IDriverReceiver.h; sourceTree = "<group>"; };
@@ -6143,6 +6147,8 @@
isa = PBXGroup;
children = (
68AE5BC71C9241E200C4D527 /* generic */,
6838CF7F1D6665510057F17B /* DeadzoneFilter.cpp */,
6838CF801D6665510057F17B /* DeadzoneFilter.h */,
68AE5BAC1C9241DF00C4D527 /* DefaultJoystick.cpp */,
68AE5BAD1C9241DF00C4D527 /* DefaultJoystick.h */,
68AE5BAE1C9241DF00C4D527 /* DriverPrimitive.cpp */,
@@ -9905,6 +9911,7 @@
E38E20AC0D25F9FD00618676 /* GUIViewStateVideo.cpp in Sources */,
E38E20AE0D25F9FD00618676 /* GUIWindowFileManager.cpp in Sources */,
E38E20AF0D25F9FD00618676 /* GUIWindowFullScreen.cpp in Sources */,
6838CF811D6665510057F17B /* DeadzoneFilter.cpp in Sources */,
E38E20B10D25F9FD00618676 /* GUIWindowHome.cpp in Sources */,
E38E20B20D25F9FD00618676 /* GUIWindowLoginScreen.cpp in Sources */,
E38E20B30D25F9FD00618676 /* GUIWindowMusicBase.cpp in Sources */,
@@ -10964,6 +10971,7 @@
DF396ED21C42A25F00214C1A /* DarwinNSUserDefaults.mm in Sources */,
E49911DF174E5D3700741B6D /* DVDInputStreamFFmpeg.cpp in Sources */,
E49911E0174E5D3700741B6D /* DVDInputStreamFile.cpp in Sources */,
6838CF821D6665510057F17B /* DeadzoneFilter.cpp in Sources */,
E49911E3174E5D3700741B6D /* DVDInputStreamMemory.cpp in Sources */,
F597B05C18A804E0005AADAE /* DVDVideoCodec.cpp in Sources */,
E49911E4174E5D3700741B6D /* DVDInputStreamNavigator.cpp in Sources */,
@@ -16083,7 +16083,19 @@ msgctxt "#35077"
msgid "Analog sticks"
msgstr ""

#empty strings from id 35078 to 35087
#. Setting title for left analog stick deadzone
#: system/peripherals.xml
msgctxt "#35078"
msgid "Left stick deadzone"
msgstr ""

#. Setting title for right analog stick deadzone
#: system/peripherals.xml
msgctxt "#35079"
msgid "Right stick deadzone"
msgstr ""

#empty strings from id 35080 to 35087

#. Name of the setting that enables/disables powering off controllers on exit
#: system/settings/settings.xml
@@ -49,4 +49,10 @@
<setting key="do_not_use_custom_keymap" type="bool" value="0" label="35009" order="1" />
<setting key="keymap" value="wetek-play" label="35007" configurable="0" />
</peripheral>

<peripheral class="joystick" mapTo="joystick">
<setting key="left_stick_deadzone" type="float" label="35078" order="1" value="0.2" min="0.0" step="0.05" max="1.0" />
<setting key="right_stick_deadzone" type="float" label="35079" order="2" value="0.2" min="0.0" step="0.05" max="1.0" />
</peripheral>

</peripherals>
@@ -1,11 +1,13 @@
set(SOURCES DefaultJoystick.cpp
set(SOURCES DeadzoneFilter.cpp
DefaultJoystick.cpp
DriverPrimitive.cpp
JoystickMonitor.cpp
JoystickTranslator.cpp
KeymapHandler.cpp
RumbleGenerator.cpp)

set(HEADERS DefaultJoystick.h
set(HEADERS DeadzoneFilter.h
DefaultJoystick.h
DriverPrimitive.h
IButtonMap.h
IButtonMapper.h
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2016 Team Kodi
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this Program; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include "DeadzoneFilter.h"
#include "DefaultJoystick.h"
#include "IButtonMap.h"
#include "peripherals/devices/Peripheral.h"
#include "utils/log.h"

using namespace JOYSTICK;

// Settings for analog sticks
#define SETTING_LEFT_STICK_DEADZONE "left_stick_deadzone"
#define SETTING_RIGHT_STICK_DEADZONE "right_stick_deadzone"

CDeadzoneFilter::CDeadzoneFilter(IButtonMap* buttonMap, PERIPHERALS::CPeripheral* peripheral) :
m_buttonMap(buttonMap),
m_peripheral(peripheral)
{
if (m_buttonMap->ControllerID() != DEFAULT_CONTROLLER_ID)
CLog::Log(LOGERROR, "ERROR: Must use default controller profile instead of %s", m_buttonMap->ControllerID().c_str());
}

float CDeadzoneFilter::FilterAxis(unsigned int axisIndex, float axisValue)
{
float deadzone = 0.0f;

bool bSuccess = GetDeadzone(axisIndex, deadzone, DEFAULT_LEFT_STICK_NAME, SETTING_LEFT_STICK_DEADZONE) ||
GetDeadzone(axisIndex, deadzone, DEFAULT_RIGHT_STICK_NAME, SETTING_RIGHT_STICK_DEADZONE);

if (bSuccess)
return ApplyDeadzone(axisValue, deadzone);

return axisValue;
}

bool CDeadzoneFilter::GetDeadzone(unsigned int axisIndex, float& deadzone, const char* featureName, const char* settingName)
{
CDriverPrimitive up;
CDriverPrimitive down;
CDriverPrimitive right;
CDriverPrimitive left;

if (m_buttonMap->GetAnalogStick(featureName, up, down, right, left))
{
if (up.Index() == axisIndex ||
down.Index() == axisIndex ||
right.Index() == axisIndex ||
left.Index() == axisIndex)
{
deadzone = m_peripheral->GetSettingFloat(settingName);
return true;
}
}
return false;
}

float CDeadzoneFilter::ApplyDeadzone(float value, float deadzone)
{
if (deadzone < 0.0f || deadzone >= 1.0f)
return 0.0f;

if (value > deadzone)
return (value - deadzone) / (1.0f - deadzone);
else if (value < -deadzone)
return (value + deadzone) / (1.0f - deadzone);

return 0.0f;
}
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2016 Team Kodi
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this Program; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#pragma once

namespace PERIPHERALS
{
class CPeripheral;
}

namespace JOYSTICK
{
class IButtonMap;

/*!
* \brief Analog axis deadzone filtering
*
* Axis is scaled appropriately, so position is continuous
* from -1.0 to 1.0:
*
* | / 1.0
* | /
* __|__/
* / |
* / |--| Deadzone
* -1.0 / |
*
* After deadzone filtering, the value will be:
*
* - Negative in the interval [-1.0, -deadzone)
* - Zero in the interval [-deadzone, deadzone]
* - Positive in the interval (deadzone, 1.0)
*/
class CDeadzoneFilter
{
public:
CDeadzoneFilter(IButtonMap* buttonMap, PERIPHERALS::CPeripheral* peripheral);

/*!
* \brief Apply deadzone filtering to an axis
* \param axisIndex The axis index
* \param axisValud The axis value\
* \return The value after applying deadzone filtering
*/
float FilterAxis(unsigned int axisIndex, float axisValue);

private:
/*!
* \brief Get the deadzone value from the peripheral's settings
* \param axisIndex The axis index
* \param[out] result The deadzone value
* \param featureName The feature that axisIndex is mapped to
* \param settingName The setting corresponding to the given feature
* \return True if the feature is an analog stick and the peripheral has the setting
*/
bool GetDeadzone(unsigned int axisIndex, float& result, const char* featureName, const char* settingName);

/*!
* \brief Utility function to calculate the deadzone
* \param value The value
* \param deadzone The deadzone
* \return The scaled deadzone
*/
static float ApplyDeadzone(float value, float deadzone);

// Construction parameters
IButtonMap* const m_buttonMap;
PERIPHERALS::CPeripheral* const m_peripheral;
};
}
@@ -27,6 +27,10 @@

#define DEFAULT_CONTROLLER_ID "game.controller.default"

// Analog sticks on the default controller
#define DEFAULT_LEFT_STICK_NAME "leftstick"
#define DEFAULT_RIGHT_STICK_NAME "rightstick"

namespace JOYSTICK
{
class IKeymapHandler;
@@ -1,4 +1,5 @@
SRCS=DefaultJoystick.cpp \
SRCS=DeadzoneFilter.cpp \
DefaultJoystick.cpp \
DriverPrimitive.cpp \
JoystickMonitor.cpp \
JoystickTranslator.cpp \
@@ -402,7 +402,8 @@ bool CPeripherals::GetMappingForDevice(const CPeripheralBus &bus, PeripheralScan
PeripheralTypeTranslator::FormatHexString(result.m_iProductId, strProductId);
CLog::Log(LOGDEBUG, "%s - device (%s:%s) mapped to %s (type = %s)", __FUNCTION__, strVendorId.c_str(), strProductId.c_str(), mapping.m_strDeviceName.c_str(), PeripheralTypeTranslator::TypeToString(mapping.m_mappedTo));
result.m_mappedType = mapping.m_mappedTo;
result.m_strDeviceName = mapping.m_strDeviceName;
if (!mapping.m_strDeviceName.empty())
result.m_strDeviceName = mapping.m_strDeviceName;
return true;
}
}
@@ -762,29 +763,15 @@ void CPeripherals::ProcessEvents(void)
bus->ProcessEvents();
}

PeripheralAddonPtr CPeripherals::GetAddon(const CPeripheral* device)
PeripheralAddonPtr CPeripherals::GetAddonWithButtonMap(const CPeripheral* device)
{
PeripheralAddonPtr addon;

PeripheralBusAddonPtr addonBus = std::static_pointer_cast<CPeripheralBusAddon>(GetBusByType(PERIPHERAL_BUS_ADDON));
if (device && addonBus)
{
PeripheralBusType busType = device->GetBusType();

if (busType == PERIPHERAL_BUS_ADDON)
{
// If device is from an add-on, use that add-on
PeripheralAddonPtr peripheralAddon;
unsigned int index;
if (addonBus->SplitLocation(device->Location(), addon, index))
addon = std::move(peripheralAddon);
}
else
{
// Otherwise, have the add-on bus find a suitable add-on
addonBus->GetAddonWithButtonMap(device, addon);
}
}
PeripheralAddonPtr addon;

PeripheralAddonPtr addonWithButtonMap;
if (addonBus && addonBus->GetAddonWithButtonMap(device, addonWithButtonMap))
addon = std::move(addonWithButtonMap);

return addon;
}
@@ -239,7 +239,7 @@ namespace PERIPHERALS
// implementation of IEventScannerCallback
virtual void ProcessEvents(void) override;

virtual PeripheralAddonPtr GetAddon(const CPeripheral* device);
virtual PeripheralAddonPtr GetAddonWithButtonMap(const CPeripheral* device);

virtual void ResetButtonMaps(const std::string& controllerId);

@@ -29,7 +29,7 @@ using namespace PERIPHERALS;

CAddonButtonMapping::CAddonButtonMapping(CPeripheral* peripheral, IButtonMapper* mapper)
{
PeripheralAddonPtr addon = g_peripherals.GetAddon(peripheral);
PeripheralAddonPtr addon = g_peripherals.GetAddonWithButtonMap(peripheral);

if (!addon)
{
@@ -32,7 +32,7 @@ using namespace PERIPHERALS;

CAddonInputHandling::CAddonInputHandling(CPeripheral* peripheral, IInputHandler* handler, IDriverReceiver* receiver)
{
PeripheralAddonPtr addon = g_peripherals.GetAddon(peripheral);
PeripheralAddonPtr addon = g_peripherals.GetAddonWithButtonMap(peripheral);

if (!addon)
{
@@ -56,6 +56,11 @@ namespace PERIPHERALS
*/
bool NeedsPolling(void) const { CSingleLock lock(m_critSection); return m_bNeedsPolling; }

/*!
* \brief Initialize the properties of a peripheral with a known location
*/
virtual bool InitializeProperties(CPeripheral* peripheral) { return true; }

/*!
* @brief Get the instance of the peripheral at the given location.
* @param strLocation The location.
@@ -60,7 +60,7 @@ CPeripheralBusAndroid::~CPeripheralBusAndroid()
CXBMCApp::UnregisterInputDeviceCallbacks();
}

bool CPeripheralBusAndroid::InitializeProperties(CPeripheral* peripheral) const
bool CPeripheralBusAndroid::InitializeProperties(CPeripheral* peripheral)
{
if (peripheral == nullptr || peripheral->Type() != PERIPHERAL_JOYSTICK)
{
@@ -41,12 +41,8 @@ namespace PERIPHERALS
CPeripheralBusAndroid(CPeripherals *manager);
virtual ~CPeripheralBusAndroid();

/*!
* \brief Initialize the properties of a peripheral with a known location
*/
bool InitializeProperties(CPeripheral* peripheral) const;

// specialisation of CPeripheralBus
bool InitializeProperties(CPeripheral* peripheral) override;
void ProcessEvents() override;

// implementations of IInputDeviceCallbacks
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.