CAddonButtonMap::DriverMap CAddonButtonMap::CreateLookupTable(const FeatureMap& features) { using namespace JOYSTICK; DriverMap driverMap; for (FeatureMap::const_iterator it = features.begin(); it != features.end(); ++it) { const ADDON::JoystickFeature& feature = it->second; switch (feature.Type()) { case JOYSTICK_FEATURE_TYPE_SCALAR: { driverMap[CPeripheralAddonTranslator::TranslatePrimitive(feature.Primitive(JOYSTICK_SCALAR_PRIMITIVE))] = it->first; break; } case JOYSTICK_FEATURE_TYPE_ANALOG_STICK: { std::vector<JOYSTICK_FEATURE_PRIMITIVE> primitives = { JOYSTICK_ANALOG_STICK_UP, JOYSTICK_ANALOG_STICK_DOWN, JOYSTICK_ANALOG_STICK_RIGHT, JOYSTICK_ANALOG_STICK_LEFT, }; for (auto primitive : primitives) driverMap[CPeripheralAddonTranslator::TranslatePrimitive(feature.Primitive(primitive))] = it->first; break; } case JOYSTICK_FEATURE_TYPE_ACCELEROMETER: { std::vector<JOYSTICK_FEATURE_PRIMITIVE> primitives = { JOYSTICK_ACCELEROMETER_POSITIVE_X, JOYSTICK_ACCELEROMETER_POSITIVE_Y, JOYSTICK_ACCELEROMETER_POSITIVE_Z, }; for (auto primitive : primitives) { CDriverPrimitive translatedPrimitive = CPeripheralAddonTranslator::TranslatePrimitive(feature.Primitive(primitive)); driverMap[translatedPrimitive] = it->first; // Map opposite semiaxis CDriverPrimitive oppositePrimitive = CDriverPrimitive(translatedPrimitive.Index(), 0, translatedPrimitive.SemiAxisDirection() * -1, 1); driverMap[oppositePrimitive] = it->first; } break; } default: break; } } return driverMap; }
kodi::addon::DriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const CDriverPrimitive& primitive) { kodi::addon::DriverPrimitive retVal; switch (primitive.Type()) { case PRIMITIVE_TYPE::BUTTON: { retVal = kodi::addon::DriverPrimitive::CreateButton(primitive.Index()); break; } case PRIMITIVE_TYPE::HAT: { retVal = kodi::addon::DriverPrimitive(primitive.Index(), TranslateHatDirection(primitive.HatDirection())); break; } case PRIMITIVE_TYPE::SEMIAXIS: { retVal = kodi::addon::DriverPrimitive(primitive.Index(), primitive.Center(), TranslateSemiAxisDirection(primitive.SemiAxisDirection()), primitive.Range()); break; } case PRIMITIVE_TYPE::MOTOR: { retVal = kodi::addon::DriverPrimitive::CreateMotor(primitive.Index()); break; } case PRIMITIVE_TYPE::KEY: { std::string keysym = GAME::CControllerTranslator::TranslateKeycode(primitive.Keycode()); retVal = kodi::addon::DriverPrimitive(keysym); break; } case PRIMITIVE_TYPE::MOUSE_BUTTON: { retVal = kodi::addon::DriverPrimitive::CreateMouseButton(TranslateMouseButton(primitive.MouseButton())); break; } case PRIMITIVE_TYPE::RELATIVE_POINTER: { retVal = kodi::addon::DriverPrimitive(TranslateRelPointerDirection(primitive.PointerDirection())); break; } default: break; } return retVal; }
bool CAddonButtonMap::AddScalar(const FeatureName& feature, const CDriverPrimitive& primitive) { if (!primitive.IsValid()) { FeatureMap::iterator it = m_features.find(feature); if (it != m_features.end()) m_features.erase(it); } else { UnmapPrimitive(primitive); ADDON::JoystickFeature scalar(feature, JOYSTICK_FEATURE_TYPE_SCALAR); scalar.SetPrimitive(CPeripheralAddonTranslator::TranslatePrimitive(primitive)); m_features[feature] = scalar; } m_driverMap = CreateLookupTable(m_features); if (auto addon = m_addon.lock()) return addon->MapFeatures(m_device, m_strControllerId, m_features); return false; }
bool CPrimitiveDetector::MapPrimitive(const CDriverPrimitive &primitive) { if (primitive.IsValid()) return m_buttonMapping->MapPrimitive(primitive); return false; }
std::string CJoystickTranslator::GetPrimitiveName(const CDriverPrimitive& primitive) { std::string primitiveTemplate; switch (primitive.Type()) { case PRIMITIVE_TYPE::BUTTON: primitiveTemplate = g_localizeStrings.Get(35015); // "Button %d" break; case PRIMITIVE_TYPE::SEMIAXIS: primitiveTemplate = g_localizeStrings.Get(35016); // "Axis %d" break; default: break; } return StringUtils::Format(primitiveTemplate.c_str(), primitive.Index()); }
ADDON::DriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const CDriverPrimitive& primitive) { ADDON::DriverPrimitive retVal; switch (primitive.Type()) { case BUTTON: { retVal = ADDON::DriverPrimitive::CreateButton(primitive.Index()); break; } case HAT: { retVal = ADDON::DriverPrimitive(primitive.Index(), TranslateHatDirection(primitive.HatDirection())); break; } case SEMIAXIS: { retVal = ADDON::DriverPrimitive(primitive.Index(), primitive.Center(), TranslateSemiAxisDirection(primitive.SemiAxisDirection()), primitive.Range()); break; } case MOTOR: { retVal = ADDON::DriverPrimitive::CreateMotor(primitive.Index()); break; } default: break; } return retVal; }
void CAddonButtonMap::AddScalar(const FeatureName& feature, const CDriverPrimitive& primitive) { const bool bMotor = (primitive.Type() == PRIMITIVE_TYPE::MOTOR); ADDON::JoystickFeature scalar(feature, bMotor ? JOYSTICK_FEATURE_TYPE_MOTOR : JOYSTICK_FEATURE_TYPE_SCALAR); scalar.SetPrimitive(JOYSTICK_SCALAR_PRIMITIVE, CPeripheralAddonTranslator::TranslatePrimitive(primitive)); if (auto addon = m_addon.lock()) addon->MapFeature(m_device, m_strControllerId, scalar); }
ADDON::DriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const CDriverPrimitive& primitive) { ADDON::DriverPrimitive retVal; switch (primitive.Type()) { case CDriverPrimitive::BUTTON: { retVal = ADDON::DriverPrimitive(primitive.Index()); break; } case CDriverPrimitive::HAT: { retVal = ADDON::DriverPrimitive(primitive.Index(), TranslateHatDirection(primitive.HatDirection())); break; } case CDriverPrimitive::SEMIAXIS: { retVal = ADDON::DriverPrimitive(primitive.Index(), TranslateSemiAxisDirection(primitive.SemiAxisDirection())); break; } default: break; } return retVal; }
bool CAddonButtonMap::AddAnalogStick(const FeatureName& feature, const CDriverPrimitive& up, const CDriverPrimitive& down, const CDriverPrimitive& right, const CDriverPrimitive& left) { if (!up.IsValid() && !down.IsValid() && !right.IsValid() && !left.IsValid()) { FeatureMap::iterator it = m_features.find(feature); if (it != m_features.end()) m_features.erase(it); } else { ADDON::JoystickFeature analogStick(feature, JOYSTICK_FEATURE_TYPE_ANALOG_STICK); if (up.IsValid()) { UnmapPrimitive(up); analogStick.SetUp(CPeripheralAddonTranslator::TranslatePrimitive(up)); } if (down.IsValid()) { UnmapPrimitive(down); analogStick.SetDown(CPeripheralAddonTranslator::TranslatePrimitive(down)); } if (right.IsValid()) { UnmapPrimitive(right); analogStick.SetRight(CPeripheralAddonTranslator::TranslatePrimitive(right)); } if (left.IsValid()) { UnmapPrimitive(left); analogStick.SetLeft(CPeripheralAddonTranslator::TranslatePrimitive(left)); } m_features[feature] = analogStick; } m_driverMap = CreateLookupTable(m_features); if (auto addon = m_addon.lock()) return addon->MapFeatures(m_device, m_strControllerId, m_features); return false; }
bool CDeadzoneFilter::GetDeadzone(unsigned int axisIndex, float& deadzone, const char* featureName, const char* settingName) { std::vector<ANALOG_STICK_DIRECTION> dirs = { ANALOG_STICK_DIRECTION::UP, ANALOG_STICK_DIRECTION::RIGHT, ANALOG_STICK_DIRECTION::DOWN, ANALOG_STICK_DIRECTION::LEFT, }; CDriverPrimitive primitive; for (auto dir : dirs) { if (m_buttonMap->GetAnalogStick(featureName, dir, primitive)) { if (primitive.Type() == PRIMITIVE_TYPE::SEMIAXIS && primitive.Index() == axisIndex) { deadzone = m_peripheral->GetSettingFloat(settingName); return true; } } } return false; }
CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMap, IKeymap* keymap) : m_buttonMapper(buttonMapper), m_buttonMap(buttonMap), m_keymap(keymap), m_lastAction(0), m_frameCount(0) { assert(m_buttonMapper != nullptr); assert(m_buttonMap != nullptr); // Make sure axes mapped to Select are centered before they can be mapped. // This ensures that they are not immediately mapped to the first button. if (m_keymap) { using namespace GAME; CControllerManager& controllerManager = CServiceBroker::GetGameControllerManager(); ControllerPtr controller = controllerManager.GetController(m_keymap->ControllerID()); const auto& features = controller->Features(); for (const auto& feature : features) { bool bIsSelectAction = false; const auto &actions = m_keymap->GetActions(CJoystickUtils::MakeKeyName(feature.Name())).actions; if (!actions.empty() && actions.begin()->actionId == ACTION_SELECT_ITEM) bIsSelectAction = true; if (!bIsSelectAction) continue; CDriverPrimitive primitive; if (!m_buttonMap->GetScalar(feature.Name(), primitive)) continue; if (primitive.Type() != PRIMITIVE_TYPE::SEMIAXIS) continue; // Set initial config, as detection will fail because axis is already activated AxisConfiguration axisConfig; axisConfig.bKnown = true; axisConfig.center = primitive.Center(); axisConfig.range = primitive.Range(); GetAxis(primitive.Index(), static_cast<float>(primitive.Center()), axisConfig).SetEmitted(primitive); } } }
bool CAddonButtonMap::AddAccelerometer(const FeatureName& feature, const CDriverPrimitive& positiveX, const CDriverPrimitive& positiveY, const CDriverPrimitive& positiveZ) { if (positiveX.IsValid() && positiveY.IsValid() && positiveZ.IsValid()) { FeatureMap::iterator it = m_features.find(feature); if (it != m_features.end()) m_features.erase(it); } else { ADDON::JoystickFeature accelerometer(feature, JOYSTICK_FEATURE_TYPE_ACCELEROMETER); if (positiveX.IsValid()) { UnmapPrimitive(positiveX); accelerometer.SetPositiveX(CPeripheralAddonTranslator::TranslatePrimitive(positiveX)); } if (positiveY.IsValid()) { UnmapPrimitive(positiveY); accelerometer.SetPositiveY(CPeripheralAddonTranslator::TranslatePrimitive(positiveY)); } if (positiveZ.IsValid()) { UnmapPrimitive(positiveZ); accelerometer.SetPositiveZ(CPeripheralAddonTranslator::TranslatePrimitive(positiveZ)); } // TODO: Unmap complementary semiaxes m_features[feature] = accelerometer; } m_driverMap = CreateLookupTable(m_features); if (auto addon = m_addon.lock()) return addon->MapFeatures(m_device, m_strControllerId, m_features); return false; }
CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMap, IActionMap* actionMap) : m_buttonMapper(buttonMapper), m_buttonMap(buttonMap), m_actionMap(actionMap), m_lastAction(0), m_frameCount(0) { assert(m_buttonMapper != nullptr); assert(m_buttonMap != nullptr); // Make sure axes mapped to Select are centered before they can be mapped. // This ensures that they are not immediately mapped to the first button. if (m_actionMap && m_actionMap->ControllerID() == m_buttonMap->ControllerID()) { using namespace GAME; CGameServices& gameServices = CServiceBroker::GetGameServices(); ControllerPtr controller = gameServices.GetController(m_actionMap->ControllerID()); const auto& features = controller->Layout().Features(); for (const auto& feature : features) { if (m_actionMap->GetActionID(feature.Name()) != ACTION_SELECT_ITEM) continue; CDriverPrimitive primitive; if (!m_buttonMap->GetScalar(feature.Name(), primitive)) continue; if (primitive.Type() != PRIMITIVE_TYPE::SEMIAXIS) continue; // Set initial config, as detection will fail because axis is already activated AxisConfiguration axisConfig; axisConfig.bKnown = true; axisConfig.center = primitive.Center(); axisConfig.range = primitive.Range(); GetAxis(primitive.Index(), primitive.Center(), axisConfig).SetEmitted(primitive); } } }