Skip to content

Commit

Permalink
Game API v1.0.40: Add feature names to controller layouts
Browse files Browse the repository at this point in the history
This change expands the existing controller layout with vectors of
names for the various types of features on each controller.

The API has been modified to report controller layouts using a dedicated
function, which is called after the input topology is loaded. Other API
calls have been simplified to just pass controller ID instead of the full
layout.
  • Loading branch information
garbear committed Sep 10, 2018
1 parent dab4d5f commit 9a2ee05
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 64 deletions.
24 changes: 18 additions & 6 deletions xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,32 +152,43 @@ game_input_topology* GetTopology();
*/
void FreeTopology(game_input_topology* topology);

/*!
* \brief Set the layouts for known controllers
*
* \param controllers The controller layouts
* \param controller_count The number of items in the array
*
* After loading the input topology, the frontend will call this with
* controller layouts for all controllers discovered in the topology.
*/
void SetControllerLayouts(const game_controller_layout* controllers, unsigned int controller_count);

/*!
* \brief Enable/disable keyboard input using the specified controller
*
* \param enable True to enable input, false otherwise
* \param controller The controller info if enabling, or unused if disabling
* \param controller_id The controller ID if enabling, or unused if disabling
*
* \return True if keyboard input was enabled, false otherwise
*/
bool EnableKeyboard(bool enable, const game_controller* controller);
bool EnableKeyboard(bool enable, const char* controller_id);

/*!
* \brief Enable/disable mouse input using the specified controller
*
* \param enable True to enable input, false otherwise
* \param controller The controller info if enabling, or unused if disabling
* \param controller_id The controller ID if enabling, or unused if disabling
*
* \return True if mouse input was enabled, false otherwise
*/
bool EnableMouse(bool enable, const game_controller* controller);
bool EnableMouse(bool enable, const char* controller_id);

/*!
* \brief Connect/disconnect a controller to a port on the virtual game console
*
* \param connect True to connect a controller, false to disconnect
* \param address The address of the port
* \param controller The controller info if connecting, or unused if disconnecting
* \param controller_id The controller ID if connecting, or unused if disconnecting
*
* The address is a string that allows traversal of the controller topology.
* It is formed by alternating port IDs and controller IDs separated by "/".
Expand Down Expand Up @@ -212,7 +223,7 @@ bool EnableMouse(bool enable, const game_controller* controller);
* Any attempts to connect a controller to a port on a disconnected multitap
* will return false.
*/
bool ConnectController(bool connect, const char* port_address, const game_controller* controller);
bool ConnectController(bool connect, const char* port_address, const char* controller_id);

/*!
* \brief Notify the add-on of an input event
Expand Down Expand Up @@ -309,6 +320,7 @@ void __declspec(dllexport) get_addon(void* ptr)
pClient->toAddon.HasFeature = HasFeature;
pClient->toAddon.GetTopology = GetTopology;
pClient->toAddon.FreeTopology = FreeTopology;
pClient->toAddon.SetControllerLayouts = SetControllerLayouts;
pClient->toAddon.EnableKeyboard = EnableKeyboard;
pClient->toAddon.EnableMouse = EnableMouse;
pClient->toAddon.ConnectController = ConnectController;
Expand Down
21 changes: 15 additions & 6 deletions xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,19 +446,27 @@ typedef enum GAME_PORT_TYPE
GAME_PORT_CONTROLLER,
} GAME_PORT_TYPE;

typedef struct game_controller
typedef struct game_controller_layout
{
const char* controller_id;
char* controller_id;
bool provides_input; // False for multitaps
char** digital_buttons;
unsigned int digital_button_count;
char** analog_buttons;
unsigned int analog_button_count;
char** analog_sticks;
unsigned int analog_stick_count;
char** accelerometers;
unsigned int accelerometer_count;
char** keys;
unsigned int key_count;
char** rel_pointers;
unsigned int rel_pointer_count;
char** abs_pointers;
unsigned int abs_pointer_count;
char** motors;
unsigned int motor_count;
} ATTRIBUTE_PACKED game_controller;
} ATTRIBUTE_PACKED game_controller_layout;

struct game_input_port;

Expand Down Expand Up @@ -680,9 +688,10 @@ typedef struct KodiToAddonFuncTable_Game
bool (__cdecl* HasFeature)(const char*, const char*);
game_input_topology* (__cdecl* GetTopology)();
void (__cdecl* FreeTopology)(game_input_topology*);
bool (__cdecl* EnableKeyboard)(bool, const game_controller*);
bool (__cdecl* EnableMouse)(bool, const game_controller*);
bool (__cdecl* ConnectController)(bool, const char*, const game_controller*);
void (__cdecl* SetControllerLayouts)(const game_controller_layout*, unsigned int);
bool (__cdecl* EnableKeyboard)(bool, const char*);
bool (__cdecl* EnableMouse)(bool, const char*);
bool (__cdecl* ConnectController)(bool, const char*, const char*);
bool (__cdecl* InputEvent)(const game_input_event*);
size_t (__cdecl* SerializeSize)(void);
GAME_ERROR (__cdecl* Serialize)(uint8_t*, size_t);
Expand Down
4 changes: 2 additions & 2 deletions xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
#define ADDON_INSTANCE_VERSION_AUDIOENCODER_XML_ID "kodi.binary.instance.audioencoder"
#define ADDON_INSTANCE_VERSION_AUDIOENCODER_DEPENDS "addon-instance/AudioEncoder.h"

#define ADDON_INSTANCE_VERSION_GAME "1.0.39"
#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.39"
#define ADDON_INSTANCE_VERSION_GAME "1.0.40"
#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.40"
#define ADDON_INSTANCE_VERSION_GAME_XML_ID "kodi.binary.instance.game"
#define ADDON_INSTANCE_VERSION_GAME_DEPENDS "kodi_game_dll.h" \
"kodi_game_types.h" \
Expand Down
6 changes: 4 additions & 2 deletions xbmc/games/addons/input/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
set(SOURCES GameClientDevice.cpp
set(SOURCES GameClientController.cpp
GameClientDevice.cpp
GameClientHardware.cpp
GameClientInput.cpp
GameClientJoystick.cpp
Expand All @@ -8,7 +9,8 @@ set(SOURCES GameClientDevice.cpp
GameClientTopology.cpp
)

set(HEADERS GameClientDevice.h
set(HEADERS GameClientController.h
GameClientDevice.h
GameClientHardware.h
GameClientInput.h
GameClientJoystick.h
Expand Down
139 changes: 139 additions & 0 deletions xbmc/games/addons/input/GameClientController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2018 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 "GameClientController.h"
#include "GameClientInput.h"
#include "games/controllers/Controller.h"
#include "games/controllers/ControllerFeature.h"
#include "games/controllers/ControllerLayout.h"
#include "games/controllers/ControllerTopology.h"

#include <algorithm>
#include <vector>

using namespace KODI;
using namespace GAME;

CGameClientController::CGameClientController(CGameClientInput &input, ControllerPtr controller) :
m_input(input),
m_controller(std::move(controller)),
m_controllerId(m_controller->ID())
{
// Generate arrays of features
for (const CControllerFeature &feature : m_controller->Features())
{
// Skip feature if not supported by the game client
if (!m_input.HasFeature(m_controller->ID(), feature.Name()))
continue;

// Add feature to array of the appropriate type
switch (feature.Type())
{
case FEATURE_TYPE::SCALAR:
{
switch (feature.InputType())
{
case JOYSTICK::INPUT_TYPE::DIGITAL:
m_digitalButtons.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
case JOYSTICK::INPUT_TYPE::ANALOG:
m_analogButtons.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
default:
break;
}
break;
}
case FEATURE_TYPE::ANALOG_STICK:
m_analogSticks.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
case FEATURE_TYPE::ACCELEROMETER:
m_accelerometers.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
case FEATURE_TYPE::KEY:
m_keys.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
case FEATURE_TYPE::RELPOINTER:
m_relPointers.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
case FEATURE_TYPE::ABSPOINTER:
m_absPointers.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
case FEATURE_TYPE::MOTOR:
m_motors.emplace_back(const_cast<char*>(feature.Name().c_str()));
break;
default:
break;
}
}

//! @todo Sort vectors
}

game_controller_layout CGameClientController::TranslateController() const
{
game_controller_layout controllerStruct{};

controllerStruct.controller_id = const_cast<char*>(m_controllerId.c_str());
controllerStruct.provides_input = m_controller->Layout().Topology().ProvidesInput();

if (!m_digitalButtons.empty())
{
controllerStruct.digital_buttons = const_cast<char**>(m_digitalButtons.data());
controllerStruct.digital_button_count = m_digitalButtons.size();
}
if (!m_analogButtons.empty())
{
controllerStruct.analog_buttons = const_cast<char**>(m_analogButtons.data());
controllerStruct.analog_button_count = m_analogButtons.size();
}
if (!m_analogSticks.empty())
{
controllerStruct.analog_sticks = const_cast<char**>(m_analogSticks.data());
controllerStruct.analog_stick_count = m_analogSticks.size();
}
if (!m_accelerometers.empty())
{
controllerStruct.accelerometers = const_cast<char**>(m_accelerometers.data());
controllerStruct.accelerometer_count = m_accelerometers.size();
}
if (!m_keys.empty())
{
controllerStruct.keys = const_cast<char**>(m_keys.data());
controllerStruct.key_count = m_keys.size();
}
if (!m_relPointers.empty())
{
controllerStruct.rel_pointers = const_cast<char**>(m_relPointers.data());
controllerStruct.rel_pointer_count = m_relPointers.size();
}
if (!m_absPointers.empty())
{
controllerStruct.abs_pointers = const_cast<char**>(m_absPointers.data());
controllerStruct.abs_pointer_count = m_absPointers.size();
}
if (!m_motors.empty())
{
controllerStruct.motors = const_cast<char**>(m_motors.data());
controllerStruct.motor_count = m_motors.size();
}

return controllerStruct;
}
70 changes: 70 additions & 0 deletions xbmc/games/addons/input/GameClientController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2018 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

#include "addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h"
#include "games/controllers/ControllerTypes.h"

#include <vector>

namespace KODI
{
namespace GAME
{
class CGameClientInput;

/*!
* \brief A container for the layout of a controller connected to a game
* client input port
*/
class CGameClientController
{
public:
/*!
* \brief Construct a controller layout
*
* \brief controller The controller add-on
*/
CGameClientController(CGameClientInput &input, ControllerPtr controller);

/*!
* \brief Get a controller layout for the Game API
*/
game_controller_layout TranslateController() const;

private:
// Construction parameters
CGameClientInput &m_input;
const ControllerPtr m_controller;

// Buffer parameters
std::string m_controllerId;
std::vector<char*> m_digitalButtons;
std::vector<char*> m_analogButtons;
std::vector<char*> m_analogSticks;
std::vector<char*> m_accelerometers;
std::vector<char*> m_keys;
std::vector<char*> m_relPointers;
std::vector<char*> m_absPointers;
std::vector<char*> m_motors;
};
} // namespace GAME
} // namespace KODI
Loading

0 comments on commit 9a2ee05

Please sign in to comment.