From 7b6f307561067611985ddf207999b80df58a7b8b Mon Sep 17 00:00:00 2001 From: Hinsbart <liu.gam3@gmail.com> Date: Wed, 27 Apr 2016 18:12:02 +0200 Subject: [PATCH] Replace SUTjoystick with built-in gamepad support. Fixes #74 Mappings: Move - DPAD or Left Stick Bomb - A Restart - Select Next level - X Menu - Start Without SUTjoysticks "emulate_mouse" feature, the menus become unnavigatable with a gamepad (except for the restart/next lvl one, which has bindings). That's work for the future. --- engine.cfg | 19 +- main/gui.gd | 11 +- shared/SUTjoystick.gd | 759 -------------------------------------------------- 3 files changed, 12 insertions(+), 777 deletions(-) delete mode 100644 shared/SUTjoystick.gd diff --git a/engine.cfg b/engine.cfg index 94fc4a3..ff67194 100644 --- a/engine.cfg +++ b/engine.cfg @@ -24,7 +24,6 @@ ScreenManager="res://shared/screen_manager.gd" ScenesManager="*res://shared/scenes_manager.gd" SettingsManager="*res://shared/settings_manager.gd" FileManager="*res://shared/file_manager.gd" -SUTjoystick="res://shared/SUTjoystick.gd" [display] @@ -40,16 +39,16 @@ gen_mipmaps=true [input] +btn_right=[key(Right), key(D), jbutton(0, 15), jaxis(0, 1)] +btn_left=[key(Left), key(A), jbutton(0, 14), jaxis(0, 0)] +btn_down=[key(Down), key(S), jbutton(0, 13), jaxis(0, 3)] +btn_up=[key(Up), key(W), jbutton(0, 12), jaxis(0, 2)] +retry=[key(R), jbutton(0, 10)] +to_menu=[key(M), jbutton(0, 11)] +next_level=[key(N), jbutton(0, 2)] +btn_space=[key(Space), jbutton(0, 0)] +place_bomb=[key(Space), jbutton(0, 0)] step=[key(Period)] -btn_right=[key(Right), key(D)] -btn_left=[key(Left), key(A)] -btn_down=[key(Down), key(S)] -btn_up=[key(Up), key(W)] -btn_space=[key(Space)] -retry=[key(R)] -place_bomb=[key(Space)] -next_level=[key(N)] -to_menu=[key(M)] [render] diff --git a/main/gui.gd b/main/gui.gd index 5176bed..e060af9 100644 --- a/main/gui.gd +++ b/main/gui.gd @@ -10,7 +10,6 @@ onready var timer = get_node("timer") onready var popup = get_node("popup") onready var level_holder = get_node("../level_holder") onready var player = get_node("../player_holder/player") -onready var JS = get_node("/root/SUTjoystick") func _ready(): var nodes_left = get_node("popup/popup_node/body/container").get_children() @@ -41,19 +40,17 @@ func _ready(): get_node("touch_controls/buttons").set_hidden(input_mode != SettingsManager.INPUT_BUTTONS) get_node("touch_controls/buttons").set_ignore_mouse(input_mode != SettingsManager.INPUT_BUTTONS) - # Turn off mouse emulation in-game - JS.emulate_mouse(false) # Subscribe to various notifications level_holder.connect("counters_changed", self, "update_counters") set_process_input(true) func _input(event): - if JS.get_digital("back") || (event.is_action("retry") && event.is_pressed() && !event.is_echo()): + if event.is_action("retry") && event.is_pressed() && !event.is_echo(): popup_button_pressed("retry") - if JS.get_digital("action_3") || (event.is_action("next_level") && event.is_pressed() && !event.is_echo()): + if event.is_action("next_level") && event.is_pressed() && !event.is_echo(): popup_button_pressed("next") - if JS.get_digital("start") || (event.is_action("to_menu") && event.is_pressed() && !event.is_echo()): + if event.is_action("to_menu") && event.is_pressed() && !event.is_echo(): popup_button_pressed("menu") func update_counters(): @@ -101,7 +98,6 @@ func show_popup(title, text, wait): # Show a popup with title and text, after so _show_popup(title, text) func _show_popup(title, text): # Show a popup with title and text - JS.emulate_mouse(true) get_tree().set_pause(true) popup.get_node("popup_node/header/title").set_text(title) @@ -122,7 +118,6 @@ func popup_button_pressed(name): # Actions for different popup buttons elif name == "menu": ScenesManager.load_scene("res://menu/menu.tscn") - JS.emulate_mouse(false) hide_popup() func hide_popup(): # Hide the popup diff --git a/shared/SUTjoystick.gd b/shared/SUTjoystick.gd deleted file mode 100644 index bb8c12a..0000000 --- a/shared/SUTjoystick.gd +++ /dev/null @@ -1,759 +0,0 @@ -#==============================================================================# -# Shine Upon Thee Joysticks Module -#------------------------------------------------------------------------------# -# Written by Dana Olson <dana@shineuponthee.com> -# -# License: MIT (same as Godot Engine) -# -# Target Version: Godot Engine master branch -# -# Handles remapping gamepads automatically based on the device name reported -# by Godot. Also converts analog-digital and digital-analog so all pads support -# both (digital-analog conversions are limited to all-or-nothing values). -# Also supports automatic device registration and deregistration for up to 4 players. -# Also supports automatic device switching, eg: for single-player games. -# -# TO USE: add SUTjoystick.gd and the js_maps/ directory to your project. -# Add SUTjoystick.gd as an autoload. -# -# The functions you will be interested in are: -# get_digital(name, player) - pass the digital state name you wish to poll and player number (optional). Returns 1/True or 0/False. -# get_analog(name, player) - pass the analog state name you wish to poll and player number (optional). Returns float between 0 and 1. -# get_angle(name, player) - pass the input name (leftstick, rightstick, or dpad) you wish to poll and player number (optional). Returns angle in radians, or null if no angle. -# And to a lesser extent: -# set_deadzone(value, player) - pass the value (or null to disabe custom deadzones) and player number (optional) to set custom deadzones. -# get_device_name(player) - pass the player number (optional). Returns the name of the device assigned to the player. -# get_device_number(player) - pass the player number (optional). Returns the system device number assigned to the player. -# get_device_player(device) - pass the system device number. Returns the player number using the device. -# deregister_player(player) - pass the player number (optional). Clears the assigned device(s) from the player or all players. -# emulate_mouse(enabled, player) - pass a boolean and player number (optional). Allows controlling the mouse with the controller. -# -# Fully-detailed documentation is available in the README; also online here: -# https://gitlab.com/shine-upon-thee/joystick -# -# TODO: -# Show common_name when a profile is loaded, rather than raw name -# Indicate in jstest GUI when a mapping exists and has been loaded -# Enable the diagram on the mapper tool after editing a mapping, for testing purposes prior to submission -# Submit directly inside app, since Windows has problems passing long URL strings (low priority) -# Android / Ouya support (need Godot to provide device name first) -# OSX support (need Godot to have joystick support first) -# Detailed states and signals for digital inputs? -# Pick up profiles in SUTjoystick GUI appdata dir? (could be problematic if users have old configs, but they could just regenerate them... would give the benefit of a global file for all games using this module) -# Auto-detect max deadzone during junk collection? limit it to 50% or something, as that's pretty high -# Add more axis and buttons to Raw tab -# Somehow add a button to allow opening the map file directly in a text editor? -# Allow tweaking a mapping somehow, before submitting -# If no mapping is supported and fallback is disabled, passthru the raw values? May or may not be useful. -# Maybe just allow access to raw values via raw_*, where analog gets axes and digital gets buttons -# Remove null key/value pairs from dictionaries before converting to json? -# Profile versioning, to ignore out-of-date files? (should be unnecessary, as I think we're stable now) -# Digital tooltips on diagram (tooltips not possible on sprites, apparently - this is more trouble than it's worth) -#==============================================================================# -extends Node - -const supported_os = [ - "x11", - "windows" -] - -# set this flag to false to suppress debugging text output -var verbose = true -# this variable is used to disable falling back to the default mapping for unrecognized devices -var disable_fallback_map = false -# this variable will reassign a device to the first empty player slot in the event that an earlier player slot opens up (device is disconnected) -var reassign_active_devices = true - -# virtual mouse cursor variables -var virtual_mouse_enabled = false -var virtual_mouse_speed = 500 # pixels per second -var virtual_mouse_pos = Vector2() -var disable_mouse_warp = false # disable mouse pointer warping when enabling/disabling mouse emulation - -# this variable will hold the device id of whichever joystick is sending input -var player_device = [-1, -1, -1, -1] # 4-player support max (could be extended if need be) -# this variable holds the currently-active joystick mappings for each player -var active_map = [null,null,null,null] -# this is set at every input, allows to get input for any player -var active_player = 1 # from 1 to 4 -# custom deadzone overrides -var custom_deadzone = [-1, -1, -1, -1] -# scale analog input values so they range from 0-1 instead of the actual value of the stick, which will register 0 up until the deadzone -var scale_analog_values = true - -# these hold the axis and button states in analog and digital formats -var analog_state = [ - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,leftstick_hor=0,leftstick_ver=0,rightstick_hor=0,rightstick_ver=0,dpad_hor=0,dpad_ver=0}, - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,leftstick_hor=0,leftstick_ver=0,rightstick_hor=0,rightstick_ver=0,dpad_hor=0,dpad_ver=0}, - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,leftstick_hor=0,leftstick_ver=0,rightstick_hor=0,rightstick_ver=0,dpad_hor=0,dpad_ver=0}, - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,leftstick_hor=0,leftstick_ver=0,rightstick_hor=0,rightstick_ver=0,dpad_hor=0,dpad_ver=0} -] -var digital_state = [ - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,action_1=0,action_3=0,action_4=0,action_2=0,back=0,start=0,home=0,click_right=0,click_left=0,bump_left=0,bump_right=0}, - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,action_1=0,action_3=0,action_4=0,action_2=0,back=0,start=0,home=0,click_right=0,click_left=0,bump_left=0,bump_right=0}, - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,action_1=0,action_3=0,action_4=0,action_2=0,back=0,start=0,home=0,click_right=0,click_left=0,bump_left=0,bump_right=0}, - {leftstick_up=0,leftstick_down=0,leftstick_left=0,leftstick_right=0,rightstick_up=0,rightstick_down=0,rightstick_left=0,rightstick_right=0,dpad_up=0,dpad_down=0,dpad_left=0,dpad_right=0,trig_left=0,trig_right=0,action_1=0,action_3=0,action_4=0,action_2=0,back=0,start=0,home=0,click_right=0,click_left=0,bump_left=0,bump_right=0} -] - -# mappings will be loaded first from user://, then from res://js_maps/, then from this array. -# mappings are OS-specific, so they're loaded by the load_js_maps function. -var js_maps = [] - -const js_map_template = { - common_name = "", # product name as sold in stores - name = "", # name reported by driver to Godot - md5 = "", # md5 of name reported by Godot - os = null, # operating system profile applies to - special = false, - flight_stick = false, - guitar = false, - deadzone = 0.1, - axis = { - leftstick_up = null, - leftstick_down = null, - leftstick_left = null, - leftstick_right = null, - rightstick_up = null, - rightstick_down = null, - rightstick_left = null, - rightstick_right = null, - dpad_up = null, - dpad_down = null, - dpad_left = null, - dpad_right = null, - trig_left = null, - trig_right = null - }, - button = { - dpad_up = null, - dpad_down = null, - dpad_left = null, - dpad_right = null, - trig_left = null, - trig_right = null, - action_1 = null, # A / green / cross / 6 o'clock - action_2 = null, # B / red / circle / 3 o'clock - action_3 = null, # X / blue / square / 9 o'clock - action_4 = null, # Y / yellow / triangle / 12 o'clock - back = null, # back / select - start = null, # start - home = null, # labeled analog - bump_left = null, - bump_right = null, - click_left = null, - click_right = null - } -} - -# for mouse emulation, possibly other uses later -var semaphore = {} - - -################################################################################ -# START OF PUBLIC FUNCTIONS - -func get_digital(name, player=0): -# pass the button name and optional player number and get back true or false if it's pressed or not -# player will be 1-4, 0 will be any player - # aliases for face buttons - if name.match('action_*'): - name = name.replace("_a","_1") - name = name.replace("_south","_1") - name = name.replace("_s","_1") - name = name.replace("_down","_1") - name = name.replace("_green","_1") - name = name.replace("_cross","_1") - name = name.replace("_b","_2") - name = name.replace("_east","_2") - name = name.replace("_e","_2") - name = name.replace("_right","_2") - name = name.replace("_red","_2") - name = name.replace("_circle","_2") - name = name.replace("_x","_3") - name = name.replace("_west","_3") - name = name.replace("_w","_3") - name = name.replace("_left","_3") - name = name.replace("_blue","_3") - name = name.replace("_square","_3") - name = name.replace("_y","_4") - name = name.replace("_north","_4") - name = name.replace("_n","_4") - name = name.replace("_up","_4") - name = name.replace("_yellow","_4") - name = name.replace("_triangle","_4") - else: - # other aliases - name = name.replace("guide","home") - name = name.replace("ps","home") - name = name.replace("playstation","home") - name = name.replace("system","start") - name = name.replace("run","start") - name = name.replace("select","back") - name = name.replace("option","back") - name = name.replace("bumper_","bump_") - name = name.replace("shoulder_","bump_") - name = name.replace("trigger_","trig_") - name = name.replace("d-pad_","dpad_") - name = name.replace("d_pad_","dpad_") - name = name.replace("direction_","dpad_") - name = name.replace("directionpad_","dpad_") - name = name.replace("ls_","leftstick_") - name = name.replace("left_","leftstick_") - name = name.replace("lstick_","leftstick_") - name = name.replace("rs_","rightstick_") - name = name.replace("right_","rightstick_") - name = name.replace("rstick_","rightstick_") - if player == 0: - player = active_player - return digital_state[player-1][name] - -func get_angle(name, player=0): -# return the angle of the given input (leftstick, rightstick, dpad) in degrees, or null if no angle - var x = get_analog(name+"_hor", player) - var y = get_analog(name+"_ver", player) - if x == 0 and y == 0: - return - var angle = atan2(-x, -y) - return angle - -func get_analog(name, player=0): -# pass an axis name and optional player number and get back the value -# player will be 1-4, 0 will be any player - # a few aliases - name = name.replace("_vert","_ver") - name = name.replace("_vertical","_ver") - name = name.replace("_horiz","_hor") - name = name.replace("_horizontal","_hor") - name = name.replace("trigger_","trig_") - name = name.replace("d-pad_","dpad_") - name = name.replace("d_pad_","dpad_") - name = name.replace("direction_","dpad_") - name = name.replace("directionpad_","dpad_") - name = name.replace("ls_","leftstick_") - name = name.replace("left_","leftstick_") - name = name.replace("lstick_","leftstick_") - name = name.replace("rs_","rightstick_") - name = name.replace("right_","rightstick_") - name = name.replace("rstick_","rightstick_") - if not player: - player = active_player - return analog_state[player-1][name] - - -func get_device_number(player=0): -# returns the current device number for the given player -# player will be 1-4 - if player == 0: - player = active_player - return player_device[player-1] - - -func get_device_player(device): -# returns the player number for the given system device number -# player will be 1-4 - for player in range(player_device.size()): - if player_device[player] == device: - return player+1 - return 0 - - -func get_device_name(player=0): -# returns the device name for the given player -# returns empty string if no device connected -# player will be 1-4 - if player == 0: - player = active_player - if active_map[player-1] != null: - if active_map[player-1].has("common_name"): - return active_map[player-1]["common_name"] - elif active_map[player-1].has("name"): - return active_map[player-1]["name"] - else: - return "" - else: - return "No mapping found" - - -func deregister_player(player=0): - if player > 0: - debug_print("device " + str(player_device[player-1]) + " disconnected from player #" + str(player)) - player_device[player-1] = -1 - active_map[player-1] = null - else: - player_device= [-1,-1,-1,-1] - active_map = [null,null,null,null] - debug_print("deregistering all devices.") - - -func emulate_mouse(enable, player=0): -# toggle mouse emulation, with an optional player number - if enable: - virtual_mouse_enabled = true - set_process(true) - if !disable_mouse_warp: - virtual_mouse_pos = OS.get_window_size() / 2 # warp to middle of window - debug_print("mouse emulation enabled") - else: - virtual_mouse_enabled = false - set_process(false) - if !disable_mouse_warp: - Input.warp_mouse_pos(OS.get_window_size()) # warp cursor to bottom corner, out of view - debug_print("mouse emulation disabled") - - -func set_deadzone(value=-1, player=0): -# pass a value and player number to set a custom deadzone that will override what is configured in the mapping -# it goes by player number, rather than device, and can be changed at any point -# if a player number is not passed, it will apply to all players -# if value is >= 1, it will be interpreted as a percentage -# calling without a value (or a negative value) will remove the custom deadzone - var msg = "set to " + str(value) - if value == null or value < 0: - value = -1 - msg = "cleared" - elif value >= 1: - value *= .01 - msg = "set to " + str(value) - if player: - debug_print("custom deadzone " + msg + " for player " + str(player)) - custom_deadzone[player-1] = value - else: - debug_print("custom deadzone " + msg + " globally") - for player in range(0,4): - custom_deadzone[player] = value - - -# END OF PUBLIC FUNCTIONS -################################################################################ - - -func _init(): - if not OS.get_name().to_lower() in supported_os: - print("[SUTjoystick]: operating system not currently supported") - return - load_js_maps() - Input.connect("joy_connection_changed",self,"_device_connection") - set_process_input(true) - print("[SUTjoystick]: module loaded") - return - - -func load_js_maps(): -# this function loads platform-specific maps and fallbacks into the js_maps array -# it runs once, at init time -# if the fallback hasn't been disabled, the first entry in the array will be used. -# if you don't want the js_maps directory in your project, you can add more json mappings to this array. - if OS.get_name().to_lower() == 'x11': - js_maps = [ - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":3,"trig_right":6},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":9,"click_right":10,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":7,"trig_left":null,"trig_right":null},"common_name":"Fallback","deadzone":0.2,"flight_stick":false,"guitar":false,"md5":"882277bdf25efaeb8295e842ebcb3d11","name":"Fallback","os":"x11","special":false}, - # add new Linux mappings here - {"axis":{"dpad_down":7,"dpad_left":-6,"dpad_right":6,"dpad_up":-7,"leftstick_down":3,"leftstick_left":-4,"leftstick_right":4,"leftstick_up":-3,"rightstick_down":2,"rightstick_left":-1,"rightstick_right":1,"rightstick_up":-2,"trig_left":null,"trig_right":null},"button":{"action_1":5,"action_2":6,"action_3":4,"action_4":7,"back":10,"bump_left":1,"bump_right":0,"click_left":3,"click_right":2,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":11,"trig_left":9,"trig_right":8},"common_name":"Thrustmaster T-Flight Hotas X Flight Stick","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"028eb3d1145466520cda0304dd6850d5","name":"Thrustmaster T.Flight Hotas X","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":null,"leftstick_left":null,"leftstick_right":null,"leftstick_up":null,"rightstick_down":null,"rightstick_left":null,"rightstick_right":null,"rightstick_up":null,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":3,"action_4":0,"back":8,"blue":3,"bump_left":null,"bump_right":null,"click_left":null,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"green":1,"home":12,"orange":4,"red":2,"start":9,"trig_left":null,"trig_right":null,"yellow":0},"common_name":"Guitar Hero 3 PS3 Guitar","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"12d6d31f37826c613975b1a13500c4a1","name":"Licensed by Sony Computer Entertainment Guitar Hero3 for PlayStation (R) 3","os":"x11","special":true}, - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":3,"trig_right":6},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":9,"click_right":10,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":7,"trig_left":null,"trig_right":null},"common_name":"Logitech Gamepad F510","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"1494e42f2ef3a43aed70f3eb6bae44cb","name":"Logitech Gamepad F510","os":"x11","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":3,"trig_right":-6},"button":{"action_1":0,"action_2":3,"action_3":1,"action_4":2,"back":16,"bump_left":4,"bump_right":5,"click_left":6,"click_right":7,"dpad_down":9,"dpad_left":10,"dpad_right":11,"dpad_up":8,"home":15,"start":14,"trig_left":12,"trig_right":13},"common_name":"OUYA Wireless Controller","deadzone":0.15,"flight_stick":false,"guitar":false,"md5":"2282b5deb46ec99a8012a79483878334","name":"OUYA Game Controller","os":"x11","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":null,"leftstick_left":null,"leftstick_right":null,"leftstick_up":null,"rightstick_down":null,"rightstick_left":null,"rightstick_right":null,"rightstick_up":null,"trig_left":null,"trig_right":null},"button":{"action_1":null,"action_2":null,"action_3":null,"action_4":null,"back":null,"blue1":4,"blue2":9,"blue3":14,"blue4":19,"bump_left":null,"bump_right":null,"click_left":null,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"green1":2,"green2":7,"green3":12,"green4":17,"home":null,"orange1":3,"orange2":8,"orange3":13,"orange4":18,"red1":0,"red2":5,"red3":10,"red4":15,"start":null,"trig_left":null,"trig_right":null,"yellow1":1,"yellow2":6,"yellow3":11,"yellow4":16},"common_name":"Buzz PS3 Controllers","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"2abaa9765204c75aec53a81ad6435f65","name":"Namtai Wbuzz","os":"x11","special":true}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":null,"leftstick_left":null,"leftstick_right":null,"leftstick_up":null,"rightstick_down":null,"rightstick_left":null,"rightstick_right":null,"rightstick_up":null,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"blue":0,"bump_left":null,"bump_right":null,"click_left":null,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"green":1,"home":12,"lead_indicator":6,"orange":4,"red":2,"start":9,"trig_left":null,"trig_right":null,"yellow":3},"common_name":"Rock Band PS3 Guitar","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"4d60d1bda12f2d3e294838aa47d60d81","name":"Licensed by Sony Computer Entertainment America Harmonix Guitar for PlayStation3","os":"x11","special":true}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":3,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-3,"trig_left":null,"trig_right":null},"button":{"action_1":2,"action_2":3,"action_3":0,"action_4":1,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"ASUS XitePad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"51dcc211864b6ef2d8f5d4707966eb30","name":"GreenAsia Inc. USB Joystick ","os":"x11","special":false}, - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":6,"trig_right":5},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":9,"click_right":10,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":7,"trig_left":null,"trig_right":null},"common_name":"Microsoft Xbox 360 Controller (xboxdrv)","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"5d98694fae9bc456936c3141dc2df5d1","name":"Xbox Gamepad (userspace driver)","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":12,"start":9,"trig_left":6,"trig_right":7},"common_name":"Rock Candy Wireless Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"62cb440051003f81e5ebfabcb634d0a5","name":"Performance Designed Products Rock Candy Wireless Gamepad for PS3","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":null,"rightstick_left":null,"rightstick_right":null,"rightstick_up":null,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":null,"bump_right":null,"click_left":10,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":12,"start":9,"trig_left":6,"trig_right":7},"common_name":"Rapala Fishing Rod PS3 Controller","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"6d75b4dc963aa0b331fc4a24097ad168","name":"GuitarHero for Playstation (R) 3 GuitarHero for Playstation (R) 3","os":"x11","special":true}, - {"axis":{"dpad_down":7,"dpad_left":-6,"dpad_right":6,"dpad_up":-7,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":null,"trig_right":null},"button":{"action_1":2,"action_2":1,"action_3":3,"action_4":0,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"SPEEDLINK Strike Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"7405f31b70f8002536e8771479cb1931","name":"DragonRise Inc. Generic USB Joystick ","os":"x11","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":-2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":2,"rightstick_down":-4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":0,"action_3":3,"action_4":2,"back":10,"bump_left":6,"bump_right":7,"click_left":null,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":9,"trig_left":4,"trig_right":5},"common_name":"Nintendo Wii Classic Controller","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"8ea7def47e5e821805253745eb48e773","name":"Nintendo Wii Remote Classic Controller","os":"x11","special":false}, - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":3,"trig_right":6},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":9,"click_right":10,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":7,"trig_left":null,"trig_right":null},"common_name":"Logitech Gamepad F310","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"8fd846f25dd3d37bc02dde759023cc27","name":"Logitech Gamepad F310","os":"x11","special":false}, - {"axis":{"dpad_down":7,"dpad_left":-7,"dpad_right":6,"dpad_up":-7,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":null,"trig_right":null},"button":{"action_1":0,"action_2":1,"action_3":3,"action_4":4,"back":2,"bump_left":6,"bump_right":7,"click_left":null,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":5,"start":8,"trig_left":9,"trig_right":10},"common_name":"Logitech WingMan Cordless Gamepad","deadzone":0.15,"flight_stick":false,"guitar":false,"md5":"930f35c3a3545ba3df30d43dedff93d5","name":"Logitech WingMan Cordless Gamepad","os":"x11","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":null,"rightstick_left":null,"rightstick_right":null,"rightstick_up":null,"trig_left":null,"trig_right":null},"button":{"action_1":14,"action_2":13,"action_3":null,"action_4":null,"back":null,"bump_left":10,"bump_right":null,"click_left":1,"click_right":null,"dpad_down":6,"dpad_left":7,"dpad_right":5,"dpad_up":4,"home":16,"start":null,"trig_left":8,"trig_right":null},"common_name":"PlayStation Navigation Controller","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"983a7856b9a6b0e406cf347b374357b1","name":"Sony Navigation Controller","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":3,"action_2":4,"action_3":0,"action_4":1,"back":10,"bump_left":6,"bump_right":7,"click_left":2,"click_right":5,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":11,"trig_left":8,"trig_right":9},"common_name":"InterAct Hammerhead FX Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"98a74c9f896e219797038f079bbf3b72","name":"S.T.D. Interact Gaming Device","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"Logitech Cordless RumblePad 2","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"ad549640d1dc4475e99322ab97aad5bc","name":"Logitech Logitech Cordless RumblePad 2","os":"x11","special":false}, - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":6,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-6,"trig_left":4,"trig_right":5},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":12,"start":9,"trig_left":6,"trig_right":7},"common_name":"Sony DualShock 4 Controller","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"b3a3fcaa6e4b2ab4ef2652873401bb50","name":"Sony Computer Entertainment Wireless Controller","os":"x11","special":false}, - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":3,"trig_right":6},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":9,"click_right":10,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":7,"trig_left":null,"trig_right":null},"common_name":"Microsoft Xbox 360 Controller","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"cfa4a29ff20eda298e1e9aae963a0cfa","name":"Microsoft X-Box 360 pad","os":"x11","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":13,"trig_right":14},"button":{"action_1":14,"action_2":13,"action_3":15,"action_4":12,"back":0,"bump_left":10,"bump_right":11,"click_left":1,"click_right":2,"dpad_down":6,"dpad_left":7,"dpad_right":5,"dpad_up":4,"home":16,"start":3,"trig_left":8,"trig_right":9},"common_name":"Sony DualShock 3 Controller","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"d13b8d6f46331f0e7ce5bac321b9e548","name":"Sony PLAYSTATION(R)3 Controller","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":12,"start":9,"trig_left":6,"trig_right":7},"common_name":"Hori Gem Pad 3","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"e348a33709a2ed9b6ffa8e7055ef2e39","name":"HORI CO.,LTD PAD A","os":"x11","special":false}, - {"axis":{"dpad_down":2,"dpad_left":-1,"dpad_right":1,"dpad_up":-2,"leftstick_down":null,"leftstick_left":null,"leftstick_right":null,"leftstick_up":null,"rightstick_down":null,"rightstick_left":null,"rightstick_right":null,"rightstick_up":null,"trig_left":null,"trig_right":null},"button":{"action_1":0,"action_2":1,"action_3":3,"action_4":4,"back":null,"bump_left":6,"bump_right":7,"click_left":null,"click_right":null,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":8,"trig_left":5,"trig_right":2},"common_name":"SLS Sega Saturn USB Control Pad (Cypress)","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"e374509322a147b7564531b1dfe528a0","name":"CYPRESS USB Gamepad","os":"x11","special":false}, - {"axis":{"dpad_down":8,"dpad_left":-7,"dpad_right":7,"dpad_up":-8,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-5,"trig_left":3,"trig_right":6},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":9,"click_right":10,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":8,"start":7,"trig_left":null,"trig_right":null},"common_name":"Logitech Wireless Gamepad F710","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"eab2a984c7e3a7d63145da4b85e354f6","name":"Logitech Gamepad F710","os":"x11","special":false}, - {"axis":{"dpad_down":6,"dpad_left":-5,"dpad_right":5,"dpad_up":-6,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"Logitech Dual Action Gamepad","deadzone":0.05,"flight_stick":false,"guitar":false,"md5":"fb062fb595f4a8dc6514de3711715cfc","name":"Logitech Logitech Dual Action","os":"x11","special":false}, - ] - elif OS.get_name().to_lower() == 'windows': - js_maps = [ - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"Fallback","deadzone":0.2,"flight_stick":false,"guitar":false,"md5":"882277bdf25efaeb8295e842ebcb3d11","name":"Fallback","os":"windows","special":false}, - # add new Windows mappings here - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"SPEEDLINK XEOX Pro Analog Gamepad (Xinput)","deadzone":0.06,"flight_stick":false,"guitar":false,"md5":"13cd059d8e11f5fd835cd6ea8ca2d294","name":"Controller (XEOX Gamepad)","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"Logitech Dual Action Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"1cf550ea7d99812211fa396b7a6cd14d","name":"Logitech Dual Action USB","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-6,"rightstick_right":6,"rightstick_up":-5,"trig_left":3,"trig_right":4},"button":{"action_1":0,"action_2":3,"action_3":1,"action_4":2,"back":16,"bump_left":4,"bump_right":5,"click_left":6,"click_right":7,"dpad_down":9,"dpad_left":10,"dpad_right":11,"dpad_up":8,"home":15,"start":14,"trig_left":12,"trig_right":13},"common_name":"OUYA Wireless Controller","deadzone":0.15,"flight_stick":false,"guitar":false,"md5":"2282b5deb46ec99a8012a79483878334","name":"OUYA Game Controller","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":3,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-3,"trig_left":null,"trig_right":null},"button":{"action_1":2,"action_2":3,"action_3":0,"action_4":1,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"ASUS XitePad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"490432ba3130ba6c84ce48c93b41cae8","name":"PC TWIN SHOCK","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"Controller #XBOX 360 For Windows#","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"4ca24f9ab550e3bfd1cc810bd5407389","name":"Controller #XBOX 360 For Windows#","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"Logitech Gamepad F510","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"5a56109c103985cd58cb632aba7ab21a","name":"Controller (Gamepad F510)","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"Generic Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"6600671ba26e978aae43536af123b683","name":"Microsoft PC-joystick driver","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"SPEEDLINK XEOX Pro Analog Gamepad","deadzone":0.05,"flight_stick":false,"guitar":false,"md5":"6cff56117caa8635e7b902e8b9834b52","name":"XEOX Gamepad SL-6556-BK","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"Logitech Wireless Gamepad F710","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"ad7479fc125ad9464261f219b46ce088","name":"Controller (Gamepad F710)","os":"windows","special":false}, - {"axis":{"dpad_down":2,"dpad_left":null,"dpad_right":null,"dpad_up":-2,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-3,"rightstick_right":3,"rightstick_up":-4,"trig_left":null,"trig_right":null},"button":{"action_1":1,"action_2":2,"action_3":0,"action_4":3,"back":8,"bump_left":4,"bump_right":5,"click_left":10,"click_right":11,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":9,"trig_left":6,"trig_right":7},"common_name":"Logitech Dual Action Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"dc88655de00fe05f13e734ed885fa0f0","name":"Logitech Dual Action","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":4,"rightstick_left":-5,"rightstick_right":5,"rightstick_up":-4,"trig_left":3,"trig_right":-3},"button":{"action_1":0,"action_2":1,"action_3":2,"action_4":3,"back":6,"bump_left":4,"bump_right":5,"click_left":8,"click_right":9,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":null,"start":7,"trig_left":null,"trig_right":null},"common_name":"Logitech Gamepad F310","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"dd91fa3cdc97ee58bfe45f2f417a444f","name":"Controller (Gamepad F310)","os":"windows","special":false}, - {"axis":{"dpad_down":null,"dpad_left":null,"dpad_right":null,"dpad_up":null,"leftstick_down":2,"leftstick_left":-1,"leftstick_right":1,"leftstick_up":-2,"rightstick_down":5,"rightstick_left":-4,"rightstick_right":4,"rightstick_up":-3,"trig_left":null,"trig_right":null},"button":{"action_1":0,"action_2":1,"action_3":3,"action_4":4,"back":2,"bump_left":6,"bump_right":7,"click_left":null,"click_right":null,"dpad_down":13,"dpad_left":14,"dpad_right":15,"dpad_up":12,"home":5,"start":8,"trig_left":9,"trig_right":10},"common_name":"WingMan Cordless Gamepad","deadzone":0.1,"flight_stick":false,"guitar":false,"md5":"f916ad081ca6e2ae04a4aca3e571f8cb","name":"WingMan Cordless Gamepad","os":"windows","special":false}, - ] - return - - -func get_assign_player_device(evdev): -# pass the event device and a boolean if we should be assigning unclaimed devices to open player slots -# returns the player number (0-3) for the given event device id. - # loop through the 4 player devices and determine which this event is for - var slot = -1 # this will be the player number the current device is assigned to, or -1 - for player in range(player_device.size()): - var playerdev = player_device[player] - # is evdev already in use by another player? - var previous_player = get_device_player(evdev) - if playerdev == evdev: - # device was already assigned to a player, set slot to player number - slot = player - break - elif (playerdev == -1) and not previous_player: - # device hasn't been assigned yet, assign it to next player - player_device[player] = evdev - debug_print("assigned device #" + str(evdev) + " to player #" + str(player+1)) - slot = player - update_js_map(slot) - break - elif (playerdev == -1) and reassign_active_devices: - # player slot empty, reassign whatever device this is - active_map[player] = active_map[previous_player-1] - player_device[previous_player-1] = -1 - active_map[previous_player-1] = null - # now reassign the device to the empty player slot - player_device[player] = evdev - debug_print("reassigned device #" + str(evdev) + " from player #" + str(previous_player) + " to player #" + str(player+1)) - slot = player - break - elif player == player_device.size() - 1: - # if we have looped through all four slots in the player_device array - debug_print("four devices assigned, ignoring device " + str(evdev)) - return slot - - -func _input(ev): - var player = -1 # which assigned device are we using? - # buttons - if ev.type == InputEvent.JOYSTICK_BUTTON: - player = get_assign_player_device(ev.device) - if player == -1: - return - if active_map[player] == null: - return - for btn in active_map[player]["button"]: - if active_map[player]["button"][btn] == ev.button_index: - digital_state[player][btn] = ev.pressed - # handle mapping certain buttons to axes - if btn == "dpad_up" and active_map[player]["axis"]["dpad_up"] == null: - analog_state[player]["dpad_up"] = ev.pressed - analog_state[player]["dpad_ver"] = -ev.pressed - elif btn == "dpad_down" and active_map[player]["axis"]["dpad_down"] == null: - analog_state[player]["dpad_down"] = ev.pressed - analog_state[player]["dpad_ver"] = ev.pressed - elif btn == "dpad_left" and active_map[player]["axis"]["dpad_left"] == null: - analog_state[player]["dpad_left"] = ev.pressed - analog_state[player]["dpad_hor"] = -ev.pressed - elif btn == "dpad_right" and active_map[player]["axis"]["dpad_right"] == null: - analog_state[player]["dpad_right"] = ev.pressed - analog_state[player]["dpad_hor"] = ev.pressed - elif btn == "trig_left" and active_map[player]["axis"]["trig_left"] == null: - analog_state[player]["trig_left"] = ev.pressed - elif btn == "trig_right" and active_map[player]["axis"]["trig_right"] == null: - analog_state[player]["trig_right"] = ev.pressed - # update the active player number - active_player = player + 1 - # axes - elif ev.type == InputEvent.JOYSTICK_MOTION: - if ev.axis > 13: # should be a safe number... ignore all events from DualShock 3 motion-sensing - return - # if an axis moves greater than 75%, we can assume it's a valid input and do the assign - if abs(ev.value) > 0.75: - player = get_assign_player_device(ev.device) - else: - player = get_device_player(ev.device) - 1 - if player == -1: - return - if active_map[player] == null: - return - # variable which will prevent updating the active player variable when a noisy device is sending values under the deadzone - var skip_active_player_update = false - # loop through all axis names from the map until we match the one the event is for - for axis_name in active_map[player]["axis"]: - # axes start at 1 in the maps due to signage: -0 clashes with +0 - # add 1 to event axis so it matches - var evaxis = ev.axis + 1 - # if the event value is less than 0, check to match up negative axis in the maps - if ev.value < 0: - evaxis = -evaxis - #NOTE triggers are super finnicky and handled differently by driver/device/platform - # if I had my choice, the entire world would use a single gamepad, or at least a standard - # but sadly, this won't happen. so, I have to make a sacrifice. gamepads that use a full - # axis for each trigger will only register once they pass 0. they lose sensitivity, but this - # is simply the easiest way to get around a stupid problem. - # FIXME: what about triggers that share an axis? what happens if you pull both at the - # same time? ...ARRRRRRGHHHHHHHHH - # workaround for if left and right triggers do not share an axis - if active_map[player]["axis"]["trig_left"] and active_map[player]["axis"]["trig_right"]: - if abs(active_map[player]["axis"]["trig_left"]) != abs(active_map[player]["axis"]["trig_right"]): - # if absolute event axis matches absolute trigger axis, force the polarity match - if abs(evaxis) == abs(active_map[player]["axis"]["trig_left"]): - evaxis = active_map[player]["axis"]["trig_left"] - elif abs(evaxis) == abs(active_map[player]["axis"]["trig_right"]): - evaxis = active_map[player]["axis"]["trig_right"] - - # if we get a match from the map - if active_map[player]["axis"][axis_name] == evaxis: - # get the absolute event value - var val = abs(ev.value) - var mirror_axis = null # axis to zero, if any - var composite_axis = null # ver/hor/bal axis to simulate - var composite_val = 0 - # set the deadzone to use, either custom by the app, or what is in the profile - var deadzone = active_map[player]["deadzone"] - if custom_deadzone[player] >= 0: - deadzone = custom_deadzone[player] - # massage the raw value into what we want (deadzone, scaling, etc) - if val < deadzone: - val = 0 - # some devices never register a full 1 value, and it bothers me :P - elif val > 0.99: - val = 1 - # allow scaling analog values to use the full 0-1 range, even if there is a deadzone - elif scale_analog_values and deadzone > 0: - val = ((val - deadzone) / (1 - deadzone)) - # if it's a trigger, reverse the range to 0-1 - if axis_name == 'trig_left': - # hacky workaround for stupid triggers... - # if mapped axis polarity doesn't match event value, it was forced - if active_map[player]["axis"][axis_name] > 0 and ev.value < 0: - val = 0 - elif active_map[player]["axis"][axis_name] < 0 and ev.value > 0: - val = 0 - elif axis_name == 'trig_right': - # hacky workaround for stupid triggers... - # if mapped axis polarity doesn't match event value, it was forced - if active_map[player]["axis"][axis_name] > 0 and ev.value < 0: - val = 0 - elif active_map[player]["axis"][axis_name] < 0 and ev.value > 0: - val = 0 - # zero the opposite axis, except for triggers - elif axis_name.match('*_up'): - # if up is pressed, down must not be. zero it out. - mirror_axis = axis_name.replace("_up","_down") - # handle the vertical composite axis - composite_axis = axis_name.replace("_up","_ver") - composite_val = -val - elif axis_name.match('*_down'): - # if down is pressed, up must not be. zero it out. - mirror_axis = axis_name.replace("_down","_up") - # handle the vertical composite axis - composite_axis = axis_name.replace("_down","_ver") - composite_val = val - elif axis_name.match('*_left'): - # if left is pressed, right must not be. zero it out. - mirror_axis = axis_name.replace("_left","_right") - # handle the horizontal composite axis - composite_axis = axis_name.replace("_left","_hor") - composite_val = -val - elif axis_name.match('*_right'): - # if right is pressed, left must not be. zero it out. - mirror_axis = axis_name.replace("_right","_left") - # handle the horizontal composite axis - composite_axis = axis_name.replace("_right","_hor") - composite_val = val - # set the composite axis state/value - if composite_axis != null: - analog_state[player][composite_axis] = composite_val - # if the axis was already zero, let's not change the active player for noisy devices later on - if analog_state[player][axis_name] == 0: - skip_active_player_update = true - # set the analog state/value - analog_state[player][axis_name] = val - - # convert analog values to digital states - # mappings include a possible digital state for this axis - if active_map[player]["button"].has(axis_name): - # only set the digital state if this particular mapping doesn't have the button - if active_map[player]["button"][axis_name] == null: - digital_state[player][axis_name] = val > 0 - # mappings don't include a possible digital state for this axis - else: - digital_state[player][axis_name] = val > 0 - # now let's zero the flipped axis if need be - if mirror_axis != null: - analog_state[player][mirror_axis] = 0 - if active_map[player]["button"].has(axis_name): - if active_map[player]["button"][axis_name] == null: - digital_state[player][mirror_axis] = 0 - else: - digital_state[player][mirror_axis] = 0 - # now update the active player number - if not skip_active_player_update: - active_player = player + 1 - return - - -func _process(delta): - # handle mouse movement emulation, when enabled - # we need to maintain an internal position, because warp_mouse_pos doesn't update the real cursor position - if virtual_mouse_enabled: - # cursor position - var virtual_mouse_movement = Vector2() - virtual_mouse_movement.x = virtual_mouse_speed * delta * get_analog("leftstick_hor") - virtual_mouse_movement.y = virtual_mouse_speed * delta * get_analog("leftstick_ver") - if virtual_mouse_movement != Vector2(0,0): - virtual_mouse_pos += virtual_mouse_movement - var screen_size = OS.get_window_size() # leave this here, in case window size changes - virtual_mouse_pos.x = min(max(virtual_mouse_pos.x,0), screen_size.x) - virtual_mouse_pos.y = min(max(virtual_mouse_pos.y,0), screen_size.y) - Input.warp_mouse_pos(virtual_mouse_pos) - # left-click - if !semaphore.has("mouse1") and get_digital("action_1"): - semaphore["mouse1"] = true - var mouse_click = InputEvent() - mouse_click.type = InputEvent.MOUSE_BUTTON - mouse_click.pressed = true - mouse_click.pos = virtual_mouse_pos - mouse_click.button_index = 1 - get_tree().input_event(mouse_click) - mouse_click.pressed = false - get_tree().input_event(mouse_click) - elif semaphore.has("mouse1") and !get_digital("action_1"): - semaphore.erase("mouse1") - # right-click - if !semaphore.has("mouse2") and get_digital("action_2"): - semaphore["mouse2"] = true - var mouse_click = InputEvent() - mouse_click.type = InputEvent.MOUSE_BUTTON - mouse_click.pressed = true - mouse_click.pos = virtual_mouse_pos - mouse_click.button_index = 2 - get_tree().input_event(mouse_click) - mouse_click.pressed = false - get_tree().input_event(mouse_click) - elif semaphore.has("mouse2") and !get_digital("action_2"): - semaphore.erase("mouse2") - # middle-click - if !semaphore.has("mouse3") and get_digital("action_4"): - semaphore["mouse3"] = true - var mouse_click = InputEvent() - mouse_click.type = InputEvent.MOUSE_BUTTON - mouse_click.pressed = true - mouse_click.pos = virtual_mouse_pos - mouse_click.button_index = 3 - get_tree().input_event(mouse_click) - mouse_click.pressed = false - get_tree().input_event(mouse_click) - elif semaphore.has("mouse3") and !get_digital("action_4"): - semaphore.erase("mouse3") - # scroll wheel - if !semaphore.has("mousewheel") and (get_digital("dpad_up") or get_digital("rightstick_up")): - semaphore["mousewheel"] = true - var mouse_click = InputEvent() - mouse_click.type = InputEvent.MOUSE_BUTTON - mouse_click.pressed = true - mouse_click.pos = virtual_mouse_pos - mouse_click.button_index = 4 - get_tree().input_event(mouse_click) - mouse_click.pressed = false - get_tree().input_event(mouse_click) - elif !semaphore.has("mousewheel") and (get_digital("dpad_down") or get_digital("rightstick_down")): - semaphore["mousewheel"] = true - var mouse_click = InputEvent() - mouse_click.type = InputEvent.MOUSE_BUTTON - mouse_click.pressed = true - mouse_click.pos = virtual_mouse_pos - mouse_click.button_index = 5 - get_tree().input_event(mouse_click) - mouse_click.pressed = false - get_tree().input_event(mouse_click) - elif semaphore.has("mousewheel") and !get_digital("dpad_up") and !get_digital("rightstick_up"): - semaphore.erase("mousewheel") - - -func update_js_map(player): - if player < 0: - return - var name = Input.get_joy_name(player_device[player]) - # remove this check later on, after fixing the bug mentioned in _device_connection() - #if name == "": - # return - var joy_md5 = name.md5_text() - if active_map[player] != null and active_map[player]["md5"] == joy_md5: - # no mapping change needed - return - # read from file first - active_map[player] = load_mapping_file(joy_md5) - if typeof(active_map[player]) == TYPE_DICTIONARY: - if active_map[player].has("md5"): - if active_map[player].md5 == joy_md5: - debug_print("player " + str(player+1) + " is using " + active_map[player]["common_name"]) - return - # read hard-coded mappings - for map in js_maps: - if map["md5"] == joy_md5: - debug_print("using hard-coded mapping.") - active_map[player] = map - debug_print("player " + str(player+1) + " is using " + active_map[player]["common_name"]) - return - # couldn't find a map, handle fallback behavior - if disable_fallback_map: - debug_print("no mapping found, fallback disabled. " + joy_md5) - else: - debug_print("no mapping found, using fallback. " + joy_md5) - var map = js_maps[0] - map.md5 = joy_md5 - active_map[player] = map - return - - -func _device_connection(devnum, connected): - if connected: - debug_print("device " + str(devnum) + " connected") - get_assign_player_device(devnum) - else: - # only disconnect if the device is assigned to a slot - var player = get_device_player(devnum) - if player: - deregister_player(player) - return - - -func debug_print(message): - if verbose: - print("[SUTjoystick]: " + message) - return - - -# this function will load a json file into a mapping dictionary -# returns null if no file found -func load_mapping_file(joy_md5): - var os = OS.get_name().to_lower() - var f = File.new() - var mapfile = "user://joystick-" + joy_md5 + "-" + os + ".json" - if f.file_exists(mapfile): - debug_print("using mapping from user file.") - else: - mapfile = "res://js_maps/joystick-" + joy_md5 + "-" + os + ".json" - if f.file_exists(mapfile): - debug_print("using mapping from bundled file.") - if f.file_exists(mapfile): - var err = f.open(mapfile,File.READ) #TODO: handle error - var jsonmap = f.get_as_text() - f.close() - if jsonmap == "": - return - var map = js_map_template # not sure this does anything at all - map.parse_json(jsonmap) - return map - return - - -# this function will write a mapping dictionary out to a json file -func save_mapping_file(map): - debug_print("saving mapping to file...") - if map["os"] == null: - map["os"] = OS.get_name().to_lower() - var mapfile = "user://joystick-" + map["md5"] + "-" + map["os"].to_lower() + ".json" - var f = File.new() - var err = f.open(mapfile,File.WRITE) #TODO: handle error - f.store_string(map.to_json()) - f.close() - return -- 2.8.2