def test_deadzone(self): """ Tests if DeadzoneModifier can be converted to string and parsed back to same. """ # Lower only assert _parses_as_itself(DeadzoneModifier(100, AxisAction(Axes.ABS_X))) # Lower and upper assert _parses_as_itself( DeadzoneModifier(100, 20000, AxisAction(Axes.ABS_X)))
def test_sens(self): """ Tests if SensitivityModifier can be converted to string and parsed back to same. """ assert _parses_as_itself( SensitivityModifier(2.0, AxisAction(Axes.ABS_X))) assert _parses_as_itself( SensitivityModifier(2.0, 3.0, AxisAction(Axes.ABS_X))) assert _parses_as_itself( SensitivityModifier(2.0, 3.0, 4.0, AxisAction(Axes.ABS_X)))
def parse_switches(self, group): """ Used for special cases of input groups that contains buttons """ inputs = VDFProfile.get_inputs(group) for button in inputs: if button in ("trigger_left", "left_trigger"): self.add_by_binding("left_trigger", AxisAction(Axes.ABS_Z)) elif button in ("trigger_right", "right_trigger"): self.add_by_binding("right_trigger", AxisAction(Axes.ABS_RZ)) elif button in VDFProfile.BUTTON_TO_BUTTON: self.add_by_binding(VDFProfile.BUTTON_TO_BUTTON[button], self.parse_button(inputs[button], button)) else: raise ParseError("Unknown button: '%s'" % (button, ))
def test_hold_doubleclick(self): """ Tests if DoubleclickModifier and HoldModifier can be converted to string and parsed back to same. """ for cls in (DoubleclickModifier, HoldModifier): # With doubleclick action only assert _parses_as_itself(cls(AxisAction(Axes.ABS_X))) # With doubleclick and normal action assert _parses_as_itself( cls(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y))) # With all parameters assert _parses_as_itself( cls(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y), 1.5))
def test_ball(self): """ Tests if BallModifier can be converted to string and parsed back to same. """ assert _parses_as_itself(BallModifier(AxisAction(Axes.ABS_X))) assert _parses_as_itself(BallModifier(MouseAction()))
def test_mode(self): """ Tests if ModeModifier can be converted to string and parsed back to same. """ # Without default assert _parses_as_itself( ModeModifier( SCButtons.A, AxisAction(Axes.ABS_X), SCButtons.B, AxisAction(Axes.ABS_Y), )) # With default assert _parses_as_itself( ModeModifier(SCButtons.A, AxisAction(Axes.ABS_X), SCButtons.B, AxisAction(Axes.ABS_Y), AxisAction(Axes.ABS_Z)))
def on_btAnalog_clicked(self, *a): """ 'Analog Output' handler """ b = SimpleChooser( self.app, "axis", lambda action: self.on_action_chosen("analog", action)) b.set_title(_("Select Analog Axis")) b.display_action(Action.AC_STICK, AxisAction(self.analog)) b.show(self.editor.window)
def test_ball(self): """ Tests if BallModifier can be converted from string """ # All options assert _parses_as( "ball(15, 40, 15, 0.1, 3265, 4, axis(ABS_X))", BallModifier(15, 40, 15, 0.1, 3265, 4, AxisAction(Axes.ABS_X)))
def on_select_axis(self, source, *a): i = self.buttons.index(source) def cb(action): self.axes[i] = action.parameters[0] self.update() self.send() b = SimpleChooser(self.app, "axis", cb) b.set_title(_("Select Axis")) b.hide_mouse() b.display_action(Action.AC_STICK, AxisAction(self.axes[i])) b.show(self.editor.window)
def test_hold_doubleclick_combinations(self): """ Tests if combinations of DoubleclickModifier and HoldModifier are convertable to string and parsable back to same objects. """ # Test combinations assert _parses_as_itself( DoubleclickModifier(AxisAction(Axes.ABS_X), HoldModifier(AxisAction(Axes.ABS_Y)), AxisAction(Axes.ABS_Z))) assert _parses_as_itself( HoldModifier(AxisAction(Axes.ABS_X), DoubleclickModifier(AxisAction(Axes.ABS_Y)), AxisAction(Axes.ABS_Z))) assert _parses_as_itself( DoubleclickModifier( AxisAction(Axes.ABS_X), HoldModifier(AxisAction(Axes.ABS_Y), AxisAction(Axes.ABS_Z)))) assert _parses_as_itself( HoldModifier( AxisAction(Axes.ABS_X), DoubleclickModifier(AxisAction(Axes.ABS_Y), AxisAction(Axes.ABS_Z))))
def test_click(self): """ Tests if ClickModifier can be converted to string and parsed back to same. """ assert _parses_as_itself(ClickModifier(AxisAction(Axes.ABS_X)))
def parse_action(self, lst_or_str, button=None): """ Parses action from vdf file. a_string can be either string or list of strings, in which case MultiAction is returned. Returns Action instance or ParseError if action is not recognized. """ if type(lst_or_str) == list: return MultiAction.make( *[self.parse_action(x) for x in lst_or_str]) # Split string into binding type, name and parameters binding, params = lst_or_str.split(" ", 1) if "," in params: params, name = params.split(",", 1) else: params, name = params, None params = params.split(" ") if name: name = name.strip() # Return apropriate Action for binding type if binding in ("key_press", "mouse_button"): if binding == "mouse_button": b = VDFProfile.convert_button_name(params[0]) else: b = VDFProfile.convert_key_name(params[0]) return ButtonAction(b).set_name(name) elif binding == "xinput_button": # Special cases, as dpad is apparently button on Windows b = params[0].strip().lower() if b == "dpad_up": return HatUpAction(Axes.ABS_HAT0Y) elif b == "dpad_down": return HatDownAction(Axes.ABS_HAT0Y) elif b == "dpad_left": return HatLeftAction(Axes.ABS_HAT0X) elif b == "dpad_right": return HatRightAction(Axes.ABS_HAT0X) elif b == "trigger_left": return AxisAction(Axes.ABS_Z) elif b == "trigger_right": return AxisAction(Axes.ABS_RZ) else: b = VDFProfile.convert_button_name(b) return ButtonAction(b).set_name(name) elif binding in ("mode_shift"): if button is None: log.warning("Ignoring modeshift assigned to no button: '%s'" % (lst_or_str, )) return NoAction() if button not in VDFProfile.BUTTON_TO_BUTTON: log.warning( "Ignoring modeshift assigned to unknown button: '%s'" % (button, )) return NoAction() self.modeshift_buttons[VDFProfile.BUTTON_TO_BUTTON[button]] = ( params[1], params[0]) return NoAction() elif binding in ("controller_action"): if params[0] == "CHANGE_PRESET": id = int(params[1]) - 1 cpa = ChangeProfileAction("action_set:%s" % (id, )) self.action_set_switches.add(cpa) return cpa log.warning("Ignoring controller_action '%s' binding" % (params[0], )) return NoAction() elif binding == "mouse_wheel": if params[0].lower() == "scroll_down": return MouseAction(Rels.REL_WHEEL, -1) else: return MouseAction(Rels.REL_WHEEL, 1) else: raise ParseError("Unknown binding: '%s'" % (binding, ))
def parse_group(self, group, side): """ Parses output (group) from vdf profile. Returns Action. """ if not "mode" in group: raise ParseError("Group without mode") mode = group["mode"] inputs = VDFProfile.get_inputs(group) settings = group["settings"] if "settings" in group else {} for o in ("output_trigger", "output_joystick"): if o in settings: if int(settings[o]) <= 1: side = Profile.LEFT else: side = Profile.RIGHT if mode == "dpad": keys = [] for k in ("dpad_north", "dpad_south", "dpad_east", "dpad_west"): if k in inputs: keys.append(self.parse_button(inputs[k])) else: keys.append(NoAction()) action = DPadAction(*keys) elif mode == "four_buttons": keys = [] for k in ("button_y", "button_a", "button_x", "button_b"): if k in inputs: keys.append(self.parse_button(inputs[k])) else: keys.append(NoAction()) action = DPadAction(*keys) elif mode == "joystick_move": if side == Profile.LEFT: # Left action = XYAction(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y)) else: # Right action = XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY)) elif mode == "joystick_camera": output_joystick = 0 if 'output_joystick' in settings: output_joystick = int(settings['output_joystick']) if output_joystick == 0: action = BallModifier( XYAction(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y))) elif output_joystick == 1: action = BallModifier( XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY))) else: # TODO: Absolute mouse? Doesn't seems to do anything in Steam action = BallModifier( SensitivityModifier(0.1, 0.1, MouseAction())) elif mode == "mouse_joystick": action = BallModifier( XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY))) elif mode == "scrollwheel": action = BallModifier( XYAction(MouseAction(Rels.REL_HWHEEL), MouseAction(Rels.REL_WHEEL))) elif mode == "touch_menu": # Touch menu is converted to GridMenu items = [] next_item_id = 1 for k in inputs: action = self.parse_button(inputs[k]) items.append( MenuItem("item_%s" % (next_item_id, ), action.describe(Action.AC_BUTTON), action)) next_item_id += 1 # Menu is stored in profile, with generated ID menu_id = "menu_%s" % (self.next_menu_id, ) self.next_menu_id += 1 self.menus[menu_id] = MenuData(*items) action = GridMenuAction( menu_id, 'LEFT' if side == Profile.LEFT else 'RIGHT', SCButtons.LPAD if side == Profile.LEFT else SCButtons.RPAD) elif mode == "absolute_mouse": if "click" in inputs: if side == Profile.LEFT: self.add_by_binding(SCButtons.LPAD, self.parse_button(inputs["click"])) else: self.add_by_binding(SCButtons.RPAD, self.parse_button(inputs["click"])) if "gyro_axis" in settings: if int(settings["gyro_axis"]) == 1: action = MouseAction(ROLL) else: action = MouseAction(YAW) else: action = MouseAction() elif mode == "mouse_wheel": action = BallModifier( XYAction(MouseAction(Rels.REL_HWHEEL), ouseAction(Rels.REL_WHEEL))) elif mode == "trigger": actions = [] if "click" in inputs: actions.append( TriggerAction(TRIGGER_CLICK, self.parse_button(inputs["click"]))) if side == Profile.LEFT: actions.append(AxisAction(Axes.ABS_Z)) else: actions.append(AxisAction(Axes.ABS_RZ)) action = MultiAction.make(*actions) elif mode == "mouse_region": # Read value and assume dafaults scale = float(settings["scale"]) if "scale" in settings else 100.0 x = float( settings["position_x"]) if "position_x" in settings else 50.0 y = float( settings["position_y"]) if "position_y" in settings else 50.0 w = float(settings["sensitivity_horiz_scale"] ) if "sensitivity_horiz_scale" in settings else 100.0 h = float(settings["sensitivity_vert_scale"] ) if "sensitivity_vert_scale" in settings else 100.0 # Apply scale w = w * scale / 100.0 h = h * scale / 100.0 # Convert to (0, 1) range x, y = x / 100.0, 1.0 - (y / 100.0) w, h = w / 100.0, h / 100.0 # Convert to rectangle x1 = max(0.0, x - (w * VDFProfile.REGION_IMPORT_FACTOR)) x2 = min(1.0, x + (w * VDFProfile.REGION_IMPORT_FACTOR)) y1 = max(0.0, y - (h * VDFProfile.REGION_IMPORT_FACTOR)) y2 = min(1.0, y + (h * VDFProfile.REGION_IMPORT_FACTOR)) action = RelAreaAction(x1, y1, x2, y2) else: raise ParseError("Unknown mode: '%s'" % (group["mode"], )) action = VDFProfile.parse_modifiers(group, action, side) return action