Merge branch 'master' into 'achievements_support'

# Conflicts:
#   dll/steam_remote_storage.h
This commit is contained in:
Nemirtingas 2019-10-05 19:48:41 +00:00
commit 8d22fb72ae
23 changed files with 2177 additions and 114 deletions

View file

@ -110,8 +110,12 @@ struct Steam_Call_Result {
return check_timedout(created, STEAM_CALLRESULT_TIMEOUT);
}
bool call_completed() {
return (!reserved) && check_timedout(created, run_in);
}
bool can_execute() {
return (!reserved) && (!to_delete) && check_timedout(created, run_in);
return (!to_delete) && call_completed();
}
bool has_cb() {
@ -169,14 +173,14 @@ public:
bool exists(SteamAPICall_t api_call) {
auto cr = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
if (cr == callresults.end()) return false;
if (cr->reserved) return false;
if (!cr->call_completed()) return false;
return true;
}
bool callback_result(SteamAPICall_t api_call, void *copy_to, unsigned int size) {
auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
if (cb_result != callresults.end()) {
if (cb_result->reserved) return false;
if (!cb_result->call_completed()) return false;
if (cb_result->result.size() > size) return false;
memcpy(copy_to, &(cb_result->result[0]), cb_result->result.size());

View file

@ -471,7 +471,7 @@ STEAMAPI_API ISteamHTMLSurface *SteamHTMLSurface() { PRINT_DEBUG("SteamHTMLSu
STEAMAPI_API ISteamInventory *SteamInventory() { PRINT_DEBUG("SteamInventory()\n");return get_steam_client_old()->GetISteamInventory(SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), old_inventory); }
STEAMAPI_API ISteamVideo *SteamVideo() { PRINT_DEBUG("SteamVideo()\n");return get_steam_client_old()->GetISteamVideo(SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), old_video); }
STEAMAPI_API ISteamParentalSettings *SteamParentalSettings() { PRINT_DEBUG("SteamParentalSettings()\n");return get_steam_client_old()->GetISteamParentalSettings(SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), ""); }
STEAMAPI_API ISteamUnifiedMessages *SteamUnifiedMessages() { PRINT_DEBUG("SteamUnifiedMessages()\n");return get_steam_client_old()->GetISteamUnifiedMessages(SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), old_unified_messages); }
//Gameserver stuff

View file

@ -71,16 +71,15 @@ static void get_broadcast_info(uint16 port)
IP_ADAPTER_INFO *pAdapter = pAdapterInfo;
while (pAdapter) {
unsigned long gateway = 0, subnet_mask = 0;
unsigned long iface_ip = 0, subnet_mask = 0;
if (inet_pton(AF_INET, pAdapter->IpAddressList.IpMask.String, &subnet_mask) == 1
&& inet_pton(AF_INET, pAdapter->GatewayList.IpAddress.String, &gateway) == 1) {
&& inet_pton(AF_INET, pAdapter->IpAddressList.IpAddress.String, &iface_ip) == 1) {
IP_PORT *ip_port = &broadcasts[number_broadcasts];
//ip_port->ip.family = AF_INET;
uint32 gateway_ip = ntohl(gateway), subnet_ip = ntohl(subnet_mask);
uint32 broadcast_ip = gateway_ip + ~subnet_ip - 1;
ip_port->ip = htonl(broadcast_ip);
uint32 broadcast_ip = iface_ip | ~subnet_mask;
ip_port->ip = broadcast_ip;
ip_port->port = port;
number_broadcasts++;
@ -707,18 +706,26 @@ bool Networking::handle_low_level_udp(Common_Message *msg, IP_PORT ip_port)
#define NUM_TCP_WAITING 128
Networking::Networking(CSteamID id, uint32 appid, uint16 port, std::set<uint32_t> *custom_broadcasts)
Networking::Networking(CSteamID id, uint32 appid, uint16 port, std::set<uint32_t> *custom_broadcasts, bool disable_sockets)
{
run_at_startup();
tcp_port = udp_port = port;
own_ip = 0x7F000001;
alive = true;
last_run = std::chrono::high_resolution_clock::now();
this->appid = appid;
if (disable_sockets) {
enabled = false;
udp_socket = -1;
tcp_socket = -1;
return;
}
if (custom_broadcasts) {
std::transform(custom_broadcasts->begin(), custom_broadcasts->end(), std::back_inserter(this->custom_broadcasts), [](uint32 ip) {return htonl(ip);});
}
run_at_startup();
sock_t sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
PRINT_DEBUG("UDP socket: %u\n", sock);
if (is_socket_valid(sock) && set_socket_nonblocking(sock)) {
@ -1055,6 +1062,7 @@ void Networking::Run()
void Networking::addListenId(CSteamID id)
{
if (!enabled) return;
auto i = std::find(ids.begin(), ids.end(), id);
if (i != ids.end()) {
return;
@ -1088,6 +1096,8 @@ bool Networking::sendToIPPort(Common_Message *msg, uint32 ip, uint16 port, bool
bool Networking::sendTo(Common_Message *msg, bool reliable, Connection *conn)
{
if (!enabled) return false;
bool ret = false;
CSteamID dest_id((uint64)msg->dest_id());
if (std::find(ids.begin(), ids.end(), dest_id) != ids.end()) {

View file

@ -124,7 +124,7 @@ public:
//NOTE: for all functions ips/ports are passed/returned in host byte order
//ex: 127.0.0.1 should be passed as 0x7F000001
static std::set<uint32> resolve_ip(std::string dns);
Networking(CSteamID id, uint32 appid, uint16 port, std::set<uint32_t> *custom_broadcasts);
Networking(CSteamID id, uint32 appid, uint16 port, std::set<uint32_t> *custom_broadcasts, bool disable_sockets);
void addListenId(CSteamID id);
void setAppID(uint32 appid);
void Run();

View file

@ -202,4 +202,15 @@ void Settings::setLeaderboard(std::string leaderboard, enum ELeaderboardSortMeth
leader.display_type = display_type;
leaderboards[leaderboard] = leader;
}
}
int Settings::add_image(std::string data, uint32 width, uint32 height)
{
int last = images.size() + 1;
struct Image_Data dt;
dt.width = width;
dt.height = height;
dt.data = data;
images[last] = dt;
return last;
}

View file

@ -52,6 +52,18 @@ struct Stat_config {
};
};
struct Image_Data {
uint32 width;
uint32 height;
std::string data;
};
struct Controller_Settings {
std::map<std::string, std::map<std::string, std::pair<std::set<std::string>, std::string>>> action_sets;
std::map<std::string, std::string> action_set_layer_parents;
std::map<std::string, std::map<std::string, std::pair<std::set<std::string>, std::string>>> action_set_layers;
};
class Settings {
CSteamID steam_id;
CGameID game_id;
@ -116,6 +128,16 @@ public:
//stats
std::map<std::string, Stat_config> getStats() { return stats; }
void setStatDefiniton(std::string name, struct Stat_config stat_config) {stats[name] = stat_config; }
//images
std::map<int, struct Image_Data> images;
int add_image(std::string data, uint32 width, uint32 height);
//controller
struct Controller_Settings controller_settings;
//networking
bool disable_networking = false;
};
#endif

View file

@ -18,6 +18,8 @@
#include "settings_parser.h"
#include <fstream>
#include <cctype>
#include <sstream>
#include <iterator>
static void load_custom_broadcasts(std::string broadcasts_filepath, std::set<uint32> &custom_broadcasts)
{
@ -32,6 +34,77 @@ static void load_custom_broadcasts(std::string broadcasts_filepath, std::set<uin
}
}
template<typename Out>
static void split_string(const std::string &s, char delim, Out result) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
static void load_gamecontroller_settings(Settings *settings)
{
std::string path = Local_Storage::get_game_settings_path() + "controller";
std::vector<std::string> paths = Local_Storage::get_filenames_path(path);
for (auto & p: paths) {
size_t length = p.length();
if (length < 4) continue;
if ( std::toupper(p.back()) != 'T') continue;
if ( std::toupper(p[length - 2]) != 'X') continue;
if ( std::toupper(p[length - 3]) != 'T') continue;
if (p[length - 4] != '.') continue;
PRINT_DEBUG("controller config %s\n", p.c_str());
std::string action_set_name = p.substr(0, length - 4);
std::transform(action_set_name.begin(), action_set_name.end(), action_set_name.begin(),[](unsigned char c){ return std::toupper(c); });
std::string controller_config_path = path + PATH_SEPARATOR + p;
std::ifstream input( controller_config_path );
if (input.is_open()) {
std::map<std::string, std::pair<std::set<std::string>, std::string>> button_pairs;
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
}
if (!line.empty() && line[line.length()-1] == '\r') {
line.pop_back();
}
std::string action_name;
std::string button_name;
std::string source_mode;
std::size_t deliminator = line.find("=");
if (deliminator != 0 && deliminator != std::string::npos && deliminator != line.size()) {
action_name = line.substr(0, deliminator);
std::size_t deliminator2 = line.find("=", deliminator + 1);
if (deliminator2 != std::string::npos && deliminator2 != line.size()) {
button_name = line.substr(deliminator + 1, deliminator2 - (deliminator + 1));
source_mode = line.substr(deliminator2 + 1);
} else {
button_name = line.substr(deliminator + 1);
source_mode = "";
}
}
std::transform(action_name.begin(), action_name.end(), action_name.begin(),[](unsigned char c){ return std::toupper(c); });
std::transform(button_name.begin(), button_name.end(), button_name.begin(),[](unsigned char c){ return std::toupper(c); });
std::pair<std::set<std::string>, std::string> button_config = {{}, source_mode};
split_string(button_name, ',', std::inserter(button_config.first, button_config.first.begin()));
button_pairs[action_name] = button_config;
PRINT_DEBUG("Added %s %s %s\n", action_name.c_str(), button_name.c_str(), source_mode.c_str());
}
settings->controller_settings.action_sets[action_set_name] = button_pairs;
PRINT_DEBUG("Added %u action names to %s\n", button_pairs.size(), action_set_name.c_str());
}
}
}
uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out)
{
@ -174,6 +247,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
}
bool steam_offline_mode = false;
bool disable_networking = false;
{
std::string steam_settings_path = Local_Storage::get_game_settings_path();
@ -182,6 +256,8 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
PRINT_DEBUG("steam settings path %s\n", p.c_str());
if (p == "offline.txt") {
steam_offline_mode = true;
} else if (p == "disable_networking.txt") {
disable_networking = true;
}
}
}
@ -192,6 +268,8 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
settings_server->set_port(port);
settings_client->custom_broadcasts = custom_broadcasts;
settings_server->custom_broadcasts = custom_broadcasts;
settings_client->disable_networking = disable_networking;
settings_server->disable_networking = disable_networking;
{
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt";
@ -386,6 +464,8 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
}
}
load_gamecontroller_settings(settings_client);
*settings_client_out = settings_client;
*settings_server_out = settings_server;
*local_storage_out = local_storage;

View file

@ -44,7 +44,7 @@ Steam_Client::Steam_Client()
uint32 appid = create_localstorage_settings(&settings_client, &settings_server, &local_storage);
network = new Networking(settings_server->get_local_steam_id(), appid, settings_server->get_port(), &(settings_server->custom_broadcasts));
network = new Networking(settings_server->get_local_steam_id(), appid, settings_server->get_port(), &(settings_server->custom_broadcasts), settings_server->disable_networking);
callback_results_client = new SteamCallResults();
callback_results_server = new SteamCallResults();
@ -65,7 +65,7 @@ Steam_Client::Steam_Client()
steam_remote_storage = new Steam_Remote_Storage(settings_client, local_storage, callback_results_client);
steam_screenshots = new Steam_Screenshots();
steam_http = new Steam_HTTP(settings_client, network, callback_results_client, callbacks_client);
steam_controller = new Steam_Controller();
steam_controller = new Steam_Controller(settings_client, callback_results_client, callbacks_client, run_every_runcb);
steam_ugc = new Steam_UGC(settings_client, callback_results_client, callbacks_client);
steam_applist = new Steam_Applist();
steam_music = new Steam_Music(callbacks_client);

View file

@ -27,7 +27,11 @@
#include "steam_remote_storage.h"
#include "steam_screenshots.h"
#include "steam_http.h"
#ifdef CONTROLLER_SUPPORT
#include "steam_controller.h"
#else
#include "steam_controller_disabled.h"
#endif
#include "steam_ugc.h"
#include "steam_applist.h"
#include "steam_music.h"

View file

@ -16,6 +16,57 @@
<http://www.gnu.org/licenses/>. */
#include "base.h"
#include "../controller/gamepad.h"
#include <cctype>
struct Controller_Map {
std::map<ControllerDigitalActionHandle_t, std::set<int>> active_digital;
std::map<ControllerAnalogActionHandle_t, std::pair<std::set<int>, enum EInputSourceMode>> active_analog;
};
struct Controller_Action {
ControllerHandle_t controller_handle;
struct Controller_Map active_map;
ControllerDigitalActionHandle_t active_set;
Controller_Action(ControllerHandle_t controller_handle) {
this->controller_handle = controller_handle;
}
void activate_action_set(ControllerDigitalActionHandle_t active_set, std::map<ControllerActionSetHandle_t, struct Controller_Map> &controller_maps) {
auto map = controller_maps.find(active_set);
if (map == controller_maps.end()) return;
this->active_set = active_set;
this->active_map = map->second;
}
std::set<int> button_id(ControllerDigitalActionHandle_t handle) {
auto a = active_map.active_digital.find(handle);
if (a == active_map.active_digital.end()) return {};
return a->second;
}
std::pair<std::set<int>, enum EInputSourceMode> analog_id(ControllerAnalogActionHandle_t handle) {
auto a = active_map.active_analog.find(handle);
if (a == active_map.active_analog.end()) return std::pair<std::set<int>, enum EInputSourceMode>({}, k_EInputSourceMode_None);
return a->second;
}
};
enum EXTRA_GAMEPAD_BUTTONS {
BUTTON_LTRIGGER = BUTTON_COUNT + 1,
BUTTON_RTRIGGER = BUTTON_COUNT + 2,
BUTTON_STICK_LEFT_UP = BUTTON_COUNT + 3,
BUTTON_STICK_LEFT_DOWN = BUTTON_COUNT + 4,
BUTTON_STICK_LEFT_LEFT = BUTTON_COUNT + 5,
BUTTON_STICK_LEFT_RIGHT = BUTTON_COUNT + 6,
BUTTON_STICK_RIGHT_UP = BUTTON_COUNT + 7,
BUTTON_STICK_RIGHT_DOWN = BUTTON_COUNT + 8,
BUTTON_STICK_RIGHT_LEFT = BUTTON_COUNT + 9,
BUTTON_STICK_RIGHT_RIGHT = BUTTON_COUNT + 10,
};
#define JOY_ID_START 10
class Steam_Controller :
public ISteamController001,
@ -26,12 +77,171 @@ public ISteamController006,
public ISteamController,
public ISteamInput
{
class Settings *settings;
class SteamCallResults *callback_results;
class SteamCallBacks *callbacks;
class RunEveryRunCB *run_every_runcb;
std::map<std::string, int> button_strings = {
{"DUP", BUTTON_DPAD_UP},
{"DDOWN", BUTTON_DPAD_DOWN},
{"DLEFT", BUTTON_DPAD_LEFT},
{"DRIGHT", BUTTON_DPAD_RIGHT},
{"START", BUTTON_START},
{"BACK", BUTTON_BACK},
{"LSTICK", BUTTON_LEFT_THUMB},
{"RSTICK", BUTTON_RIGHT_THUMB},
{"LBUMPER", BUTTON_LEFT_SHOULDER},
{"RBUMPER", BUTTON_RIGHT_SHOULDER},
{"A", BUTTON_A},
{"B", BUTTON_B},
{"X", BUTTON_X},
{"Y", BUTTON_Y},
{"DLTRIGGER", BUTTON_LTRIGGER},
{"DRTRIGGER", BUTTON_RTRIGGER},
{"DLJOYUP", BUTTON_STICK_LEFT_UP},
{"DLJOYDOWN", BUTTON_STICK_LEFT_DOWN},
{"DLJOYLEFT", BUTTON_STICK_LEFT_LEFT},
{"DLJOYRIGHT", BUTTON_STICK_LEFT_RIGHT},
{"DRJOYUP", BUTTON_STICK_RIGHT_UP},
{"DRJOYDOWN", BUTTON_STICK_RIGHT_DOWN},
{"DRJOYLEFT", BUTTON_STICK_RIGHT_LEFT},
{"DRJOYRIGHT", BUTTON_STICK_RIGHT_RIGHT},
};
std::map<std::string, int> analog_strings = {
{"LTRIGGER", TRIGGER_LEFT},
{"RTRIGGER", TRIGGER_RIGHT},
{"LJOY", STICK_LEFT + JOY_ID_START},
{"RJOY", STICK_RIGHT + JOY_ID_START},
};
std::map<std::string, enum EInputSourceMode> analog_input_modes = {
{"joystick_move", k_EInputSourceMode_JoystickMove},
{"joystick_camera", k_EInputSourceMode_JoystickCamera},
{"trigger", k_EInputSourceMode_Trigger},
};
std::map<std::string, ControllerActionSetHandle_t> action_handles;
std::map<std::string, ControllerDigitalActionHandle_t> digital_action_handles;
std::map<std::string, ControllerAnalogActionHandle_t> analog_action_handles;
std::map<ControllerActionSetHandle_t, struct Controller_Map> controller_maps;
std::map<ControllerHandle_t, struct Controller_Action> controllers;
bool disabled;
void set_handles(std::map<std::string, std::map<std::string, std::pair<std::set<std::string>, std::string>>> action_sets) {
uint64 handle_num = 1;
for (auto & set : action_sets) {
ControllerActionSetHandle_t action_handle_num = handle_num;
++handle_num;
action_handles[set.first] = action_handle_num;
for (auto & config_key : set.second) {
uint64 current_handle_num = handle_num;
++handle_num;
for (auto & button_string : config_key.second.first) {
auto digital = button_strings.find(button_string);
if (digital != button_strings.end()) {
ControllerDigitalActionHandle_t digital_handle_num = current_handle_num;
if (digital_action_handles.find(config_key.first) == digital_action_handles.end()) {
digital_action_handles[config_key.first] = digital_handle_num;
} else {
digital_handle_num = digital_action_handles[config_key.first];
}
controller_maps[action_handle_num].active_digital[digital_handle_num].insert(digital->second);
} else {
auto analog = analog_strings.find(button_string);
if (analog != analog_strings.end()) {
ControllerAnalogActionHandle_t analog_handle_num = current_handle_num;
enum EInputSourceMode source_mode;
if (analog->second == TRIGGER_LEFT || analog->second == TRIGGER_RIGHT) {
source_mode = k_EInputSourceMode_Trigger;
} else {
source_mode = k_EInputSourceMode_JoystickMove;
}
auto input_mode = analog_input_modes.find(config_key.second.second);
if (input_mode != analog_input_modes.end()) {
source_mode = input_mode->second;
}
if (analog_action_handles.find(config_key.first) == analog_action_handles.end()) {
analog_action_handles[config_key.first] = analog_handle_num;
} else {
analog_handle_num = analog_action_handles[config_key.first];
}
controller_maps[action_handle_num].active_analog[analog_handle_num].first.insert(analog->second);
controller_maps[action_handle_num].active_analog[analog_handle_num].second = source_mode;
} else {
PRINT_DEBUG("Did not recognize controller button %s\n", button_string.c_str());
continue;
}
}
}
}
}
}
public:
static void steam_run_every_runcb(void *object)
{
PRINT_DEBUG("steam_controller_run_every_runcb\n");
Steam_Controller *steam_controller = (Steam_Controller *)object;
steam_controller->RunCallbacks();
}
Steam_Controller(class Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb)
{
this->settings = settings;
this->run_every_runcb = run_every_runcb;
this->run_every_runcb->add(&Steam_Controller::steam_run_every_runcb, this);
this->callback_results = callback_results;
this->callbacks = callbacks;
set_handles(settings->controller_settings.action_sets);
disabled = !action_handles.size();
}
~Steam_Controller()
{
//TODO rm network callbacks
this->run_every_runcb->remove(&Steam_Controller::steam_run_every_runcb, this);
}
// Init and Shutdown must be called when starting/ending use of this interface
bool Init()
{
PRINT_DEBUG("Steam_Controller::Init()\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (disabled) {
return true;
}
GamepadInit();
GamepadUpdate();
for (int i = 1; i < 5; ++i) {
struct Controller_Action cont_action(i);
//Activate the action set if there is only one present.
//TODO: I don't know if one gets activated by default when there's more than one
if (action_handles.size() == 1) {
cont_action.activate_action_set(action_handles.begin()->second, controller_maps);
}
controllers.insert(std::pair<ControllerHandle_t, struct Controller_Action>(i, cont_action));
}
return true;
}
@ -44,6 +254,12 @@ bool Init( const char *pchAbsolutePathToControllerConfigVDF )
bool Shutdown()
{
PRINT_DEBUG("Steam_Controller::Shutdown()\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (disabled) {
return true;
}
GamepadShutdown();
return true;
}
@ -58,6 +274,11 @@ void SetOverrideMode( const char *pchMode )
void RunFrame()
{
PRINT_DEBUG("Steam_Controller::RunFrame()\n");
if (disabled) {
return;
}
GamepadUpdate();
}
bool GetControllerState( uint32 unControllerIndex, SteamControllerState001_t *pState )
@ -71,8 +292,20 @@ bool GetControllerState( uint32 unControllerIndex, SteamControllerState001_t *pS
// Returns the number of handles written to handlesOut
int GetConnectedControllers( ControllerHandle_t *handlesOut )
{
PRINT_DEBUG("GetConnectedControllers\n");
return 0;
PRINT_DEBUG("Steam_Controller::GetConnectedControllers\n");
if (!handlesOut) return 0;
if (disabled) {
return 0;
}
int count = 0;
if (GamepadIsConnected(GAMEPAD_0)) {*handlesOut = GAMEPAD_0 + 1; ++handlesOut; ++count;};
if (GamepadIsConnected(GAMEPAD_1)) {*handlesOut = GAMEPAD_1 + 1; ++handlesOut; ++count;};
if (GamepadIsConnected(GAMEPAD_2)) {*handlesOut = GAMEPAD_2 + 1; ++handlesOut; ++count;};
if (GamepadIsConnected(GAMEPAD_3)) {*handlesOut = GAMEPAD_3 + 1; ++handlesOut; ++count;};
PRINT_DEBUG("returned %i connected controllers\n", count);
return count;
}
@ -80,7 +313,7 @@ int GetConnectedControllers( ControllerHandle_t *handlesOut )
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
bool ShowBindingPanel( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("ShowBindingPanel\n");
PRINT_DEBUG("Steam_Controller::ShowBindingPanel\n");
return false;
}
@ -89,8 +322,15 @@ bool ShowBindingPanel( ControllerHandle_t controllerHandle )
// Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.
ControllerActionSetHandle_t GetActionSetHandle( const char *pszActionSetName )
{
PRINT_DEBUG("GetActionSetHandle %s\n", pszActionSetName);
return 124;
PRINT_DEBUG("Steam_Controller::GetActionSetHandle %s\n", pszActionSetName);
if (!pszActionSetName) return 0;
std::string upper_action_name(pszActionSetName);
std::transform(upper_action_name.begin(), upper_action_name.end(), upper_action_name.begin(),[](unsigned char c){ return std::toupper(c); });
auto set_handle = action_handles.find(upper_action_name);
if (set_handle == action_handles.end()) return 0;
return set_handle->second;
}
@ -99,34 +339,47 @@ ControllerActionSetHandle_t GetActionSetHandle( const char *pszActionSetName )
// your state loops, instead of trying to place it in all of your state transitions.
void ActivateActionSet( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle )
{
PRINT_DEBUG("ActivateActionSet\n");
PRINT_DEBUG("Steam_Controller::ActivateActionSet %llu %llu\n", controllerHandle, actionSetHandle);
if (controllerHandle == STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS) {
for (auto & c: controllers) {
c.second.activate_action_set(actionSetHandle, controller_maps);
}
}
auto controller = controllers.find(controllerHandle);
if (controller == controllers.end()) return;
controller->second.activate_action_set(actionSetHandle, controller_maps);
}
ControllerActionSetHandle_t GetCurrentActionSet( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("GetCurrentActionSet\n");
return 124;
PRINT_DEBUG("Steam_Controller::GetCurrentActionSet %llu\n", controllerHandle);
auto controller = controllers.find(controllerHandle);
if (controller == controllers.end()) return 0;
return controller->second.active_set;
}
void ActivateActionSetLayer( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle )
{
PRINT_DEBUG("ActivateActionSetLayer\n");
PRINT_DEBUG("Steam_Controller::ActivateActionSetLayer\n");
}
void DeactivateActionSetLayer( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle )
{
PRINT_DEBUG("DeactivateActionSetLayer\n");
PRINT_DEBUG("Steam_Controller::DeactivateActionSetLayer\n");
}
void DeactivateAllActionSetLayers( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("DeactivateAllActionSetLayers\n");
PRINT_DEBUG("Steam_Controller::DeactivateAllActionSetLayers\n");
}
int GetActiveActionSetLayers( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t *handlesOut )
{
PRINT_DEBUG("GetActiveActionSetLayers\n");
PRINT_DEBUG("Steam_Controller::GetActiveActionSetLayers\n");
return 0;
}
@ -136,17 +389,72 @@ int GetActiveActionSetLayers( ControllerHandle_t controllerHandle, ControllerAct
// Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls.
ControllerDigitalActionHandle_t GetDigitalActionHandle( const char *pszActionName )
{
PRINT_DEBUG("GetDigitalActionHandle %s\n", pszActionName);
return 123;
PRINT_DEBUG("Steam_Controller::GetDigitalActionHandle %s\n", pszActionName);
if (!pszActionName) return 0;
std::string upper_action_name(pszActionName);
std::transform(upper_action_name.begin(), upper_action_name.end(), upper_action_name.begin(),[](unsigned char c){ return std::toupper(c); });
auto handle = digital_action_handles.find(upper_action_name);
if (handle == digital_action_handles.end()) return 0;
return handle->second;
}
// Returns the current state of the supplied digital game action
ControllerDigitalActionData_t GetDigitalActionData( ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle )
{
PRINT_DEBUG("GetDigitalActionData\n");
PRINT_DEBUG("Steam_Controller::GetDigitalActionData %llu %llu\n", controllerHandle, digitalActionHandle);
ControllerDigitalActionData_t digitalData;
digitalData.bActive = false;
digitalData.bState = false;
auto controller = controllers.find(controllerHandle);
if (controller == controllers.end()) return digitalData;
std::set<int> buttons = controller->second.button_id(digitalActionHandle);
if (!buttons.size()) return digitalData;
digitalData.bActive = true;
GAMEPAD_DEVICE device = (GAMEPAD_DEVICE)(controllerHandle - 1);
for (auto button : buttons) {
bool pressed = false;
if (button < BUTTON_COUNT) {
pressed = GamepadButtonDown(device, (GAMEPAD_BUTTON)button);
} else {
switch (button) {
case BUTTON_LTRIGGER:
pressed = GamepadTriggerLength(device, TRIGGER_LEFT) > 0.8;
break;
case BUTTON_RTRIGGER:
pressed = GamepadTriggerLength(device, TRIGGER_RIGHT) > 0.8;
break;
case BUTTON_STICK_LEFT_UP:
case BUTTON_STICK_LEFT_DOWN:
case BUTTON_STICK_LEFT_LEFT:
case BUTTON_STICK_LEFT_RIGHT:
pressed = GamepadStickLength(device, STICK_LEFT) > 0.1 &&
((int)GamepadStickDir(device, STICK_LEFT) == ((button - BUTTON_STICK_LEFT_UP) + 1));
break;
case BUTTON_STICK_RIGHT_UP:
case BUTTON_STICK_RIGHT_DOWN:
case BUTTON_STICK_RIGHT_LEFT:
case BUTTON_STICK_RIGHT_RIGHT:
pressed = GamepadStickLength(device, STICK_RIGHT) > 0.1 &&
((int)GamepadStickDir(device, STICK_RIGHT) == ((button - BUTTON_STICK_RIGHT_UP) + 1));
break;
default:
break;
}
}
if (pressed) {
digitalData.bState = true;
break;
}
}
return digitalData;
}
@ -155,32 +463,170 @@ ControllerDigitalActionData_t GetDigitalActionData( ControllerHandle_t controlle
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
int GetDigitalActionOrigins( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerDigitalActionHandle_t digitalActionHandle, EControllerActionOrigin *originsOut )
{
PRINT_DEBUG("GetDigitalActionOrigins\n");
return 0;
PRINT_DEBUG("Steam_Controller::GetDigitalActionOrigins\n");
EInputActionOrigin origins[STEAM_CONTROLLER_MAX_ORIGINS];
int ret = GetDigitalActionOrigins(controllerHandle, actionSetHandle, digitalActionHandle, origins );
for (int i = 0; i < ret; ++i) {
originsOut[i] = (EControllerActionOrigin)(origins[i] - (k_EInputActionOrigin_XBox360_A - k_EControllerActionOrigin_XBox360_A));
}
return ret;
}
int GetDigitalActionOrigins( InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, EInputActionOrigin *originsOut )
{
PRINT_DEBUG("GetDigitalActionOrigins steaminput\n");
return 0;
PRINT_DEBUG("Steam_Controller::GetDigitalActionOrigins steaminput\n");
auto controller = controllers.find(inputHandle);
if (controller == controllers.end()) return 0;
auto map = controller_maps.find(actionSetHandle);
if (map == controller_maps.end()) return 0;
auto a = map->second.active_digital.find(digitalActionHandle);
if (a == map->second.active_digital.end()) return 0;
int count = 0;
for (auto button: a->second) {
switch (button) {
case BUTTON_A:
originsOut[count] = k_EInputActionOrigin_XBox360_A;
break;
case BUTTON_B:
originsOut[count] = k_EInputActionOrigin_XBox360_B;
break;
case BUTTON_X:
originsOut[count] = k_EInputActionOrigin_XBox360_X;
break;
case BUTTON_Y:
originsOut[count] = k_EInputActionOrigin_XBox360_Y;
break;
case BUTTON_LEFT_SHOULDER:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftBumper;
break;
case BUTTON_RIGHT_SHOULDER:
originsOut[count] = k_EInputActionOrigin_XBox360_RightBumper;
break;
case BUTTON_START:
originsOut[count] = k_EInputActionOrigin_XBox360_Start;
break;
case BUTTON_BACK:
originsOut[count] = k_EInputActionOrigin_XBox360_Back;
break;
case BUTTON_LTRIGGER:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftTrigger_Click;
break;
case BUTTON_RTRIGGER:
originsOut[count] = k_EInputActionOrigin_XBox360_RightTrigger_Click;
break;
case BUTTON_LEFT_THUMB:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftStick_Click;
break;
case BUTTON_RIGHT_THUMB:
originsOut[count] = k_EInputActionOrigin_XBox360_RightStick_Click;
break;
case BUTTON_STICK_LEFT_UP:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftStick_DPadNorth;
break;
case BUTTON_STICK_LEFT_DOWN:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftStick_DPadSouth;
break;
case BUTTON_STICK_LEFT_LEFT:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftStick_DPadWest;
break;
case BUTTON_STICK_LEFT_RIGHT:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftStick_DPadEast;
break;
case BUTTON_STICK_RIGHT_UP:
originsOut[count] = k_EInputActionOrigin_XBox360_RightStick_DPadNorth;
break;
case BUTTON_STICK_RIGHT_DOWN:
originsOut[count] = k_EInputActionOrigin_XBox360_RightStick_DPadSouth;
break;
case BUTTON_STICK_RIGHT_LEFT:
originsOut[count] = k_EInputActionOrigin_XBox360_RightStick_DPadWest;
break;
case BUTTON_STICK_RIGHT_RIGHT:
originsOut[count] = k_EInputActionOrigin_XBox360_RightStick_DPadEast;
break;
case BUTTON_DPAD_UP:
originsOut[count] = k_EInputActionOrigin_XBox360_DPad_North;
break;
case BUTTON_DPAD_DOWN:
originsOut[count] = k_EInputActionOrigin_XBox360_DPad_South;
break;
case BUTTON_DPAD_LEFT:
originsOut[count] = k_EInputActionOrigin_XBox360_DPad_West;
break;
case BUTTON_DPAD_RIGHT:
originsOut[count] = k_EInputActionOrigin_XBox360_DPad_East;
break;
default:
originsOut[count] = k_EInputActionOrigin_None;
break;
}
++count;
if (count >= STEAM_INPUT_MAX_ORIGINS) {
break;
}
}
return count;
}
// Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls.
ControllerAnalogActionHandle_t GetAnalogActionHandle( const char *pszActionName )
{
PRINT_DEBUG("GetAnalogActionHandle %s\n", pszActionName);
return 125;
PRINT_DEBUG("Steam_Controller::GetAnalogActionHandle %s\n", pszActionName);
if (!pszActionName) return 0;
std::string upper_action_name(pszActionName);
std::transform(upper_action_name.begin(), upper_action_name.end(), upper_action_name.begin(),[](unsigned char c){ return std::toupper(c); });
auto handle = analog_action_handles.find(upper_action_name);
if (handle == analog_action_handles.end()) return 0;
return handle->second;
}
// Returns the current state of these supplied analog game action
ControllerAnalogActionData_t GetAnalogActionData( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle )
{
PRINT_DEBUG("GetAnalogActionData\n");
PRINT_DEBUG("Steam_Controller::GetAnalogActionData %llu %llu\n", controllerHandle, analogActionHandle);
ControllerAnalogActionData_t data;
data.eMode = k_EInputSourceMode_None;
data.x = data.y = 0;
data.bActive = false;
auto controller = controllers.find(controllerHandle);
if (controller == controllers.end()) return data;
auto analog = controller->second.analog_id(analogActionHandle);
if (!analog.first.size()) return data;
data.bActive = true;
data.eMode = analog.second;
for (auto a : analog.first) {
if (a >= JOY_ID_START) {
int joystick_id = a - JOY_ID_START;
GamepadStickNormXY((GAMEPAD_DEVICE)(controllerHandle - 1), (GAMEPAD_STICK) joystick_id, &data.x, &data.y);
float length = GamepadStickLength((GAMEPAD_DEVICE)(controllerHandle - 1), (GAMEPAD_STICK) joystick_id);
data.x = data.x * length;
data.y = data.y * length;
} else {
data.x = GamepadTriggerLength((GAMEPAD_DEVICE)(controllerHandle - 1), (GAMEPAD_TRIGGER) a);
}
if (data.x || data.y) {
break;
}
}
return data;
}
@ -189,32 +635,73 @@ ControllerAnalogActionData_t GetAnalogActionData( ControllerHandle_t controllerH
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
int GetAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerAnalogActionHandle_t analogActionHandle, EControllerActionOrigin *originsOut )
{
PRINT_DEBUG("GetAnalogActionOrigins\n");
return 0;
PRINT_DEBUG("Steam_Controller::GetAnalogActionOrigins\n");
EInputActionOrigin origins[STEAM_CONTROLLER_MAX_ORIGINS];
int ret = GetAnalogActionOrigins(controllerHandle, actionSetHandle, analogActionHandle, origins );
for (int i = 0; i < ret; ++i) {
originsOut[i] = (EControllerActionOrigin)(origins[i] - (k_EInputActionOrigin_XBox360_A - k_EControllerActionOrigin_XBox360_A));
}
return ret;
}
int GetAnalogActionOrigins( InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, EInputActionOrigin *originsOut )
{
PRINT_DEBUG("GetAnalogActionOrigins steaminput\n");
return 0;
PRINT_DEBUG("Steam_Controller::GetAnalogActionOrigins steaminput\n");
auto controller = controllers.find(inputHandle);
if (controller == controllers.end()) return 0;
auto map = controller_maps.find(actionSetHandle);
if (map == controller_maps.end()) return 0;
auto a = map->second.active_analog.find(analogActionHandle);
if (a == map->second.active_analog.end()) return 0;
int count = 0;
for (auto a: a->second.first) {
switch (a) {
case TRIGGER_LEFT:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftTrigger_Pull;
break;
case TRIGGER_RIGHT:
originsOut[count] = k_EInputActionOrigin_XBox360_RightTrigger_Pull;
break;
case STICK_LEFT + JOY_ID_START:
originsOut[count] = k_EInputActionOrigin_XBox360_LeftStick_Move;
break;
case STICK_RIGHT + JOY_ID_START:
originsOut[count] = k_EInputActionOrigin_XBox360_RightStick_Move;
break;
default:
originsOut[count] = k_EInputActionOrigin_None;
break;
}
++count;
if (count >= STEAM_INPUT_MAX_ORIGINS) {
break;
}
}
return count;
}
void StopAnalogActionMomentum( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t eAction )
{
PRINT_DEBUG("StopAnalogActionMomentum\n");
PRINT_DEBUG("Steam_Controller::StopAnalogActionMomentum\n");
}
// Trigger a haptic pulse on a controller
void TriggerHapticPulse( ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec )
{
PRINT_DEBUG("TriggerHapticPulse\n");
PRINT_DEBUG("Steam_Controller::TriggerHapticPulse\n");
}
void TriggerHapticPulse( uint32 unControllerIndex, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec )
{
PRINT_DEBUG("TriggerHapticPulse old\n");
PRINT_DEBUG("Steam_Controller::TriggerHapticPulse old\n");
TriggerHapticPulse(unControllerIndex, eTargetPad, usDurationMicroSec );
}
@ -222,28 +709,32 @@ void TriggerHapticPulse( uint32 unControllerIndex, ESteamControllerPad eTargetPa
// nFlags is currently unused and reserved for future use.
void TriggerRepeatedHapticPulse( ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec, unsigned short usOffMicroSec, unsigned short unRepeat, unsigned int nFlags )
{
PRINT_DEBUG("TriggerRepeatedHapticPulse\n");
PRINT_DEBUG("Steam_Controller::TriggerRepeatedHapticPulse\n");
}
// Tigger a vibration event on supported controllers.
void TriggerVibration( ControllerHandle_t controllerHandle, unsigned short usLeftSpeed, unsigned short usRightSpeed )
{
PRINT_DEBUG("TriggerVibration\n");
PRINT_DEBUG("Steam_Controller::TriggerVibration %hu %hu\n", usLeftSpeed, usRightSpeed);
auto controller = controllers.find(controllerHandle);
if (controller == controllers.end()) return;
GamepadSetRumble((GAMEPAD_DEVICE)(controllerHandle - 1), ((double)usLeftSpeed) / 65535.0, ((double)usRightSpeed) / 65535.0);
}
// Set the controller LED color on supported controllers.
void SetLEDColor( ControllerHandle_t controllerHandle, uint8 nColorR, uint8 nColorG, uint8 nColorB, unsigned int nFlags )
{
PRINT_DEBUG("SetLEDColor\n");
PRINT_DEBUG("Steam_Controller::SetLEDColor\n");
}
// Returns the associated gamepad index for the specified controller, if emulating a gamepad
int GetGamepadIndexForController( ControllerHandle_t ulControllerHandle )
{
PRINT_DEBUG("GetGamepadIndexForController\n");
PRINT_DEBUG("Steam_Controller::GetGamepadIndexForController\n");
return 0;
}
@ -251,7 +742,7 @@ int GetGamepadIndexForController( ControllerHandle_t ulControllerHandle )
// Returns the associated controller handle for the specified emulated gamepad
ControllerHandle_t GetControllerForGamepadIndex( int nIndex )
{
PRINT_DEBUG("GetControllerForGamepadIndex\n");
PRINT_DEBUG("Steam_Controller::GetControllerForGamepadIndex\n");
return 0;
}
@ -259,7 +750,7 @@ ControllerHandle_t GetControllerForGamepadIndex( int nIndex )
// Returns raw motion data from the specified controller
ControllerMotionData_t GetMotionData( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("GetMotionData\n");
PRINT_DEBUG("Steam_Controller::GetMotionData\n");
ControllerMotionData_t data = {};
return data;
}
@ -269,13 +760,13 @@ ControllerMotionData_t GetMotionData( ControllerHandle_t controllerHandle )
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
bool ShowDigitalActionOrigins( ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle, float flScale, float flXPosition, float flYPosition )
{
PRINT_DEBUG("ShowDigitalActionOrigins\n");
PRINT_DEBUG("Steam_Controller::ShowDigitalActionOrigins\n");
return true;
}
bool ShowAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle, float flScale, float flXPosition, float flYPosition )
{
PRINT_DEBUG("ShowAnalogActionOrigins\n");
PRINT_DEBUG("Steam_Controller::ShowAnalogActionOrigins\n");
return true;
}
@ -283,13 +774,13 @@ bool ShowAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerAna
// Returns a localized string (from Steam's language setting) for the specified origin
const char *GetStringForActionOrigin( EControllerActionOrigin eOrigin )
{
PRINT_DEBUG("GetStringForActionOrigin\n");
PRINT_DEBUG("Steam_Controller::GetStringForActionOrigin\n");
return "Button String";
}
const char *GetStringForActionOrigin( EInputActionOrigin eOrigin )
{
PRINT_DEBUG("GetStringForActionOrigin steaminput\n");
PRINT_DEBUG("Steam_Controller::GetStringForActionOrigin steaminput\n");
return "Button String";
}
@ -297,75 +788,82 @@ const char *GetStringForActionOrigin( EInputActionOrigin eOrigin )
// Get a local path to art for on-screen glyph for a particular origin
const char *GetGlyphForActionOrigin( EControllerActionOrigin eOrigin )
{
PRINT_DEBUG("GetGlyphForActionOrigin\n");
PRINT_DEBUG("Steam_Controller::GetGlyphForActionOrigin\n");
return "";
}
const char *GetGlyphForActionOrigin( EInputActionOrigin eOrigin )
{
PRINT_DEBUG("GetGlyphForActionOrigin steaminput\n");
PRINT_DEBUG("Steam_Controller::GetGlyphForActionOrigin steaminput\n");
return "";
}
// Returns the input type for a particular handle
ESteamInputType GetInputTypeForHandle( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("GetInputTypeForHandle\n");
return k_ESteamInputType_Unknown;
PRINT_DEBUG("Steam_Controller::GetInputTypeForHandle\n");
auto controller = controllers.find(controllerHandle);
if (controller == controllers.end()) return k_ESteamInputType_Unknown;
return k_ESteamInputType_XBox360Controller;
}
const char *GetStringForXboxOrigin( EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetStringForXboxOrigin\n");
PRINT_DEBUG("Steam_Controller::GetStringForXboxOrigin\n");
return "";
}
const char *GetGlyphForXboxOrigin( EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetGlyphForXboxOrigin\n");
PRINT_DEBUG("Steam_Controller::GetGlyphForXboxOrigin\n");
return "";
}
EControllerActionOrigin GetActionOriginFromXboxOrigin_( ControllerHandle_t controllerHandle, EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetActionOriginFromXboxOrigin\n");
PRINT_DEBUG("Steam_Controller::GetActionOriginFromXboxOrigin\n");
return k_EControllerActionOrigin_None;
}
EInputActionOrigin GetActionOriginFromXboxOrigin( InputHandle_t inputHandle, EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetActionOriginFromXboxOrigin steaminput\n");
PRINT_DEBUG("Steam_Controller::GetActionOriginFromXboxOrigin steaminput\n");
return k_EInputActionOrigin_None;
}
EControllerActionOrigin TranslateActionOrigin( ESteamInputType eDestinationInputType, EControllerActionOrigin eSourceOrigin )
{
PRINT_DEBUG("TranslateActionOrigin\n");
PRINT_DEBUG("Steam_Controller::TranslateActionOrigin\n");
return k_EControllerActionOrigin_None;
}
EInputActionOrigin TranslateActionOrigin( ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin )
{
PRINT_DEBUG("TranslateActionOrigin steaminput\n");
PRINT_DEBUG("Steam_Controller::TranslateActionOrigin steaminput\n");
return k_EInputActionOrigin_None;
}
bool GetControllerBindingRevision( ControllerHandle_t controllerHandle, int *pMajor, int *pMinor )
{
PRINT_DEBUG("GetControllerBindingRevision\n");
PRINT_DEBUG("Steam_Controller::GetControllerBindingRevision\n");
return false;
}
bool GetDeviceBindingRevision( InputHandle_t inputHandle, int *pMajor, int *pMinor )
{
PRINT_DEBUG("GetDeviceBindingRevision\n");
PRINT_DEBUG("Steam_Controller::GetDeviceBindingRevision\n");
return false;
}
uint32 GetRemotePlaySessionID( InputHandle_t inputHandle )
{
PRINT_DEBUG("GetRemotePlaySessionID\n");
PRINT_DEBUG("Steam_Controller::GetRemotePlaySessionID\n");
return 0;
}
void RunCallbacks()
{
RunFrame();
}
};

View file

@ -0,0 +1,375 @@
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
The Goldberg Emulator 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator; if not, see
<http://www.gnu.org/licenses/>. */
#include "base.h"
class Steam_Controller :
public ISteamController001,
public ISteamController003,
public ISteamController004,
public ISteamController005,
public ISteamController006,
public ISteamController,
public ISteamInput
{
public:
Steam_Controller(class Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb)
{
}
// Init and Shutdown must be called when starting/ending use of this interface
bool Init()
{
PRINT_DEBUG("Steam_Controller::Init()\n");
return true;
}
bool Init( const char *pchAbsolutePathToControllerConfigVDF )
{
PRINT_DEBUG("Steam_Controller::Init() old\n");
return Init();
}
bool Shutdown()
{
PRINT_DEBUG("Steam_Controller::Shutdown()\n");
return true;
}
void SetOverrideMode( const char *pchMode )
{
PRINT_DEBUG("Steam_Controller::SetOverrideMode\n");
}
// Synchronize API state with the latest Steam Controller inputs available. This
// is performed automatically by SteamAPI_RunCallbacks, but for the absolute lowest
// possible latency, you call this directly before reading controller state.
void RunFrame()
{
PRINT_DEBUG("Steam_Controller::RunFrame()\n");
}
bool GetControllerState( uint32 unControllerIndex, SteamControllerState001_t *pState )
{
PRINT_DEBUG("Steam_Controller::GetControllerState()\n");
return false;
}
// Enumerate currently connected controllers
// handlesOut should point to a STEAM_CONTROLLER_MAX_COUNT sized array of ControllerHandle_t handles
// Returns the number of handles written to handlesOut
int GetConnectedControllers( ControllerHandle_t *handlesOut )
{
PRINT_DEBUG("GetConnectedControllers\n");
return 0;
}
// Invokes the Steam overlay and brings up the binding screen
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
bool ShowBindingPanel( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("ShowBindingPanel\n");
return false;
}
// ACTION SETS
// Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.
ControllerActionSetHandle_t GetActionSetHandle( const char *pszActionSetName )
{
PRINT_DEBUG("GetActionSetHandle %s\n", pszActionSetName);
return 124;
}
// Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive')
// This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in
// your state loops, instead of trying to place it in all of your state transitions.
void ActivateActionSet( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle )
{
PRINT_DEBUG("ActivateActionSet\n");
}
ControllerActionSetHandle_t GetCurrentActionSet( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("GetCurrentActionSet\n");
return 124;
}
void ActivateActionSetLayer( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle )
{
PRINT_DEBUG("ActivateActionSetLayer\n");
}
void DeactivateActionSetLayer( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle )
{
PRINT_DEBUG("DeactivateActionSetLayer\n");
}
void DeactivateAllActionSetLayers( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("DeactivateAllActionSetLayers\n");
}
int GetActiveActionSetLayers( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t *handlesOut )
{
PRINT_DEBUG("GetActiveActionSetLayers\n");
return 0;
}
// ACTIONS
// Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls.
ControllerDigitalActionHandle_t GetDigitalActionHandle( const char *pszActionName )
{
PRINT_DEBUG("GetDigitalActionHandle %s\n", pszActionName);
return 123;
}
// Returns the current state of the supplied digital game action
ControllerDigitalActionData_t GetDigitalActionData( ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle )
{
PRINT_DEBUG("GetDigitalActionData\n");
ControllerDigitalActionData_t digitalData;
digitalData.bActive = false;
return digitalData;
}
// Get the origin(s) for a digital action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
int GetDigitalActionOrigins( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerDigitalActionHandle_t digitalActionHandle, EControllerActionOrigin *originsOut )
{
PRINT_DEBUG("GetDigitalActionOrigins\n");
return 0;
}
int GetDigitalActionOrigins( InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, EInputActionOrigin *originsOut )
{
PRINT_DEBUG("GetDigitalActionOrigins steaminput\n");
return 0;
}
// Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls.
ControllerAnalogActionHandle_t GetAnalogActionHandle( const char *pszActionName )
{
PRINT_DEBUG("GetAnalogActionHandle %s\n", pszActionName);
return 125;
}
// Returns the current state of these supplied analog game action
ControllerAnalogActionData_t GetAnalogActionData( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle )
{
PRINT_DEBUG("GetAnalogActionData\n");
ControllerAnalogActionData_t data;
data.eMode = k_EInputSourceMode_None;
data.x = data.y = 0;
data.bActive = false;
return data;
}
// Get the origin(s) for an analog action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
int GetAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerAnalogActionHandle_t analogActionHandle, EControllerActionOrigin *originsOut )
{
PRINT_DEBUG("GetAnalogActionOrigins\n");
return 0;
}
int GetAnalogActionOrigins( InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, EInputActionOrigin *originsOut )
{
PRINT_DEBUG("GetAnalogActionOrigins steaminput\n");
return 0;
}
void StopAnalogActionMomentum( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t eAction )
{
PRINT_DEBUG("StopAnalogActionMomentum\n");
}
// Trigger a haptic pulse on a controller
void TriggerHapticPulse( ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec )
{
PRINT_DEBUG("TriggerHapticPulse\n");
}
void TriggerHapticPulse( uint32 unControllerIndex, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec )
{
PRINT_DEBUG("TriggerHapticPulse old\n");
TriggerHapticPulse(unControllerIndex, eTargetPad, usDurationMicroSec );
}
// Trigger a pulse with a duty cycle of usDurationMicroSec / usOffMicroSec, unRepeat times.
// nFlags is currently unused and reserved for future use.
void TriggerRepeatedHapticPulse( ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec, unsigned short usOffMicroSec, unsigned short unRepeat, unsigned int nFlags )
{
PRINT_DEBUG("TriggerRepeatedHapticPulse\n");
}
// Tigger a vibration event on supported controllers.
void TriggerVibration( ControllerHandle_t controllerHandle, unsigned short usLeftSpeed, unsigned short usRightSpeed )
{
PRINT_DEBUG("TriggerVibration\n");
}
// Set the controller LED color on supported controllers.
void SetLEDColor( ControllerHandle_t controllerHandle, uint8 nColorR, uint8 nColorG, uint8 nColorB, unsigned int nFlags )
{
PRINT_DEBUG("SetLEDColor\n");
}
// Returns the associated gamepad index for the specified controller, if emulating a gamepad
int GetGamepadIndexForController( ControllerHandle_t ulControllerHandle )
{
PRINT_DEBUG("GetGamepadIndexForController\n");
return 0;
}
// Returns the associated controller handle for the specified emulated gamepad
ControllerHandle_t GetControllerForGamepadIndex( int nIndex )
{
PRINT_DEBUG("GetControllerForGamepadIndex\n");
return 0;
}
// Returns raw motion data from the specified controller
ControllerMotionData_t GetMotionData( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("GetMotionData\n");
ControllerMotionData_t data = {};
return data;
}
// Attempt to display origins of given action in the controller HUD, for the currently active action set
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
bool ShowDigitalActionOrigins( ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle, float flScale, float flXPosition, float flYPosition )
{
PRINT_DEBUG("ShowDigitalActionOrigins\n");
return true;
}
bool ShowAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle, float flScale, float flXPosition, float flYPosition )
{
PRINT_DEBUG("ShowAnalogActionOrigins\n");
return true;
}
// Returns a localized string (from Steam's language setting) for the specified origin
const char *GetStringForActionOrigin( EControllerActionOrigin eOrigin )
{
PRINT_DEBUG("GetStringForActionOrigin\n");
return "Button String";
}
const char *GetStringForActionOrigin( EInputActionOrigin eOrigin )
{
PRINT_DEBUG("GetStringForActionOrigin steaminput\n");
return "Button String";
}
// Get a local path to art for on-screen glyph for a particular origin
const char *GetGlyphForActionOrigin( EControllerActionOrigin eOrigin )
{
PRINT_DEBUG("GetGlyphForActionOrigin\n");
return "";
}
const char *GetGlyphForActionOrigin( EInputActionOrigin eOrigin )
{
PRINT_DEBUG("GetGlyphForActionOrigin steaminput\n");
return "";
}
// Returns the input type for a particular handle
ESteamInputType GetInputTypeForHandle( ControllerHandle_t controllerHandle )
{
PRINT_DEBUG("GetInputTypeForHandle\n");
return k_ESteamInputType_Unknown;
}
const char *GetStringForXboxOrigin( EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetStringForXboxOrigin\n");
return "";
}
const char *GetGlyphForXboxOrigin( EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetGlyphForXboxOrigin\n");
return "";
}
EControllerActionOrigin GetActionOriginFromXboxOrigin_( ControllerHandle_t controllerHandle, EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetActionOriginFromXboxOrigin\n");
return k_EControllerActionOrigin_None;
}
EInputActionOrigin GetActionOriginFromXboxOrigin( InputHandle_t inputHandle, EXboxOrigin eOrigin )
{
PRINT_DEBUG("GetActionOriginFromXboxOrigin steaminput\n");
return k_EInputActionOrigin_None;
}
EControllerActionOrigin TranslateActionOrigin( ESteamInputType eDestinationInputType, EControllerActionOrigin eSourceOrigin )
{
PRINT_DEBUG("TranslateActionOrigin\n");
return k_EControllerActionOrigin_None;
}
EInputActionOrigin TranslateActionOrigin( ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin )
{
PRINT_DEBUG("TranslateActionOrigin steaminput\n");
return k_EInputActionOrigin_None;
}
bool GetControllerBindingRevision( ControllerHandle_t controllerHandle, int *pMajor, int *pMinor )
{
PRINT_DEBUG("GetControllerBindingRevision\n");
return false;
}
bool GetDeviceBindingRevision( InputHandle_t inputHandle, int *pMajor, int *pMinor )
{
PRINT_DEBUG("GetDeviceBindingRevision\n");
return false;
}
uint32 GetRemotePlaySessionID( InputHandle_t inputHandle )
{
PRINT_DEBUG("GetRemotePlaySessionID\n");
return 0;
}
};

View file

@ -19,6 +19,12 @@
#define SEND_FRIEND_RATE 4.0
struct Avatar_Numbers {
int smallest;
int medium;
int large;
};
class Steam_Friends :
public ISteamFriends004,
public ISteamFriends005,
@ -45,7 +51,7 @@ public ISteamFriends
bool modified;
std::vector<Friend> friends;
unsigned img_count;
std::map<uint64, struct Avatar_Numbers> avatars;
CSteamID lobby_id;
std::chrono::high_resolution_clock::time_point last_sent_friends;
@ -82,6 +88,29 @@ bool isAppIdCompatible(Friend *f)
return settings->get_local_game_id().AppID() == f->appid();
}
struct Avatar_Numbers add_friend_avatars(CSteamID id)
{
uint64 steam_id = id.ConvertToUint64();
auto avatar_ids = avatars.find(steam_id);
if (avatar_ids != avatars.end()) {
return avatar_ids->second;
}
//TODO: get real image data from self/other peers
struct Avatar_Numbers avatar_numbers;
char zero_array[184 * 184 * 4] = {};
std::string small_avatar(zero_array, 32 * 32 * 4);
std::string medium_avatar(zero_array, 64 * 64 * 4);
std::string large_avatar(zero_array, 184 * 184 * 4);
avatar_numbers.smallest = settings->add_image(small_avatar, 32, 32);
avatar_numbers.medium = settings->add_image(medium_avatar, 64, 64);
avatar_numbers.large = settings->add_image(large_avatar, 184, 184);
avatars[steam_id] = avatar_numbers;
return avatar_numbers;
}
public:
static void steam_friends_callback(void *object, Common_Message *msg)
{
@ -552,8 +581,10 @@ void ActivateGameOverlayInviteDialog( CSteamID steamIDLobby )
int GetSmallFriendAvatar( CSteamID steamIDFriend )
{
PRINT_DEBUG("Steam_Friends::GetSmallFriendAvatar\n");
++img_count;
return (img_count * 3) + 1;
//IMPORTANT NOTE: don't change friend avatar numbers for the same friend or else some games endlessly allocate stuff.
std::lock_guard<std::recursive_mutex> lock(global_mutex);
struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend);
return numbers.smallest;
}
@ -561,8 +592,9 @@ int GetSmallFriendAvatar( CSteamID steamIDFriend )
int GetMediumFriendAvatar( CSteamID steamIDFriend )
{
PRINT_DEBUG("Steam_Friends::GetMediumFriendAvatar\n");
++img_count;
return (img_count * 3) + 2;
std::lock_guard<std::recursive_mutex> lock(global_mutex);
struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend);
return numbers.medium;
}
@ -571,8 +603,9 @@ int GetMediumFriendAvatar( CSteamID steamIDFriend )
int GetLargeFriendAvatar( CSteamID steamIDFriend )
{
PRINT_DEBUG("Steam_Friends::GetLargeFriendAvatar\n");
++img_count;
return (img_count * 3) + 0;
std::lock_guard<std::recursive_mutex> lock(global_mutex);
struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend);
return numbers.large;
}
int GetFriendAvatar( CSteamID steamIDFriend, int eAvatarSize )
@ -671,19 +704,19 @@ bool SetRichPresence( const char *pchKey, const char *pchValue )
PRINT_DEBUG("Steam_Friends::SetRichPresence %s %s\n", pchKey, pchValue ? pchValue : "NULL");
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (pchValue) {
#ifdef SHOW_DIALOG_RICH_CONNECT
if (std::string(pchKey) == std::string("connect"))
MessageBox(0, pchValue, pchKey, MB_OK);
#endif
(*us.mutable_rich_presence())[pchKey] = pchValue;
auto prev_value = (*us.mutable_rich_presence()).find(pchKey);
if (prev_value == (*us.mutable_rich_presence()).end() || prev_value->second != pchValue) {
(*us.mutable_rich_presence())[pchKey] = pchValue;
modified = true;
}
} else {
auto to_remove = us.mutable_rich_presence()->find(pchKey);
if (to_remove != us.mutable_rich_presence()->end()) {
us.mutable_rich_presence()->erase(to_remove);
modified = true;
}
}
modified = true;
return true;
}

View file

@ -1152,16 +1152,21 @@ void RunCallbacks()
}
}
} else {
int compare_to = stoi(value->second, 0, 0);
PRINT_DEBUG("Compare Values %i %i\n", compare_to, f.value_int);
if (f.eComparisonType == k_ELobbyComparisonEqual) {
if (compare_to == f.value_int) {
PRINT_DEBUG("Equal\n");
//use = use;
} else {
PRINT_DEBUG("Not Equal\n");
use = false;
try {
int compare_to = std::stoi(value->second, 0, 0);
PRINT_DEBUG("Compare Values %i %i\n", compare_to, f.value_int);
if (f.eComparisonType == k_ELobbyComparisonEqual) {
if (compare_to == f.value_int) {
PRINT_DEBUG("Equal\n");
//use = use;
} else {
PRINT_DEBUG("Not Equal\n");
use = false;
}
}
} catch (...) {
//Same case as if the key is not in the lobby?
use = false;
}
//TODO: add more comparisons
}

View file

@ -83,6 +83,10 @@ Steam_Remote_Storage(class Settings *settings, Local_Storage *local_storage, cla
bool FileWrite( const char *pchFile, const void *pvData, int32 cubData )
{
PRINT_DEBUG("Steam_Remote_Storage::FileWrite %s %u\n", pchFile, cubData);
if (!pchFile || cubData <= 0 || cubData > k_unMaxCloudFileChunkSize) {
return false;
}
std::lock_guard<std::recursive_mutex> lock(global_mutex);
int data_stored = local_storage->store_data(Local_Storage::remote_storage_folder, pchFile, (char* )pvData, cubData);
PRINT_DEBUG("Steam_Remote_Storage::Stored %i, %u\n", data_stored, data_stored == cubData);
@ -103,12 +107,16 @@ STEAM_CALL_RESULT( RemoteStorageFileWriteAsyncComplete_t )
SteamAPICall_t FileWriteAsync( const char *pchFile, const void *pvData, uint32 cubData )
{
PRINT_DEBUG("Steam_Remote_Storage::FileWriteAsync\n");
if (!pchFile || cubData > k_unMaxCloudFileChunkSize || cubData == 0) {
return k_uAPICallInvalid;
}
std::lock_guard<std::recursive_mutex> lock(global_mutex);
bool success = local_storage->store_data(Local_Storage::remote_storage_folder, pchFile, (char* )pvData, cubData) == cubData;
RemoteStorageFileWriteAsyncComplete_t data;
data.m_eResult = k_EResultOK;
data.m_eResult = success ? k_EResultOK : k_EResultFail;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.01);
}

View file

@ -82,39 +82,39 @@ const char *GetIPCountry()
return "US";
}
static uint32 width_image(int iImage)
{
if ((iImage % 3) == 1) return 32;
if ((iImage % 3) == 2) return 64;
return 184;
}
// returns true if the image exists, and valid sizes were filled out
bool GetImageSize( int iImage, uint32 *pnWidth, uint32 *pnHeight )
{
PRINT_DEBUG("GetImageSize\n");
PRINT_DEBUG("GetImageSize %i\n", iImage);
if (!iImage || !pnWidth || !pnHeight) return false;
std::lock_guard<std::recursive_mutex> lock(global_mutex);
*pnWidth = width_image(iImage);
*pnHeight = width_image(iImage);;
auto image = settings->images.find(iImage);
if (image == settings->images.end()) return false;
*pnWidth = image->second.width;
*pnHeight = image->second.height;
return true;
}
// returns true if the image exists, and the buffer was successfully filled out
// results are returned in RGBA format
// the destination buffer size should be 4 * height * width * sizeof(char)
bool GetImageRGBA( int iImage, uint8 *pubDest, int nDestBufferSize )
{
PRINT_DEBUG("GetImageRGBA\n");
PRINT_DEBUG("GetImageRGBA %i\n", iImage);
if (!iImage || !pubDest || !nDestBufferSize) return false;
unsigned size = width_image(iImage) * width_image(iImage) * 4;
std::lock_guard<std::recursive_mutex> lock(global_mutex);
auto image = settings->images.find(iImage);
if (image == settings->images.end()) return false;
unsigned size = image->second.data.size();
if (nDestBufferSize < size) size = nDestBufferSize;
memset(pubDest, 0xFF, size);
image->second.data.copy((char *)pubDest, nDestBufferSize);
return true;
}
// returns the IP of the reporting server for valve - currently only used in Source engine games
bool GetCSERIPPort( uint32 *unIP, uint16 *usPort )
{