def __init__(self, string): params = [] shift = False for letter in string: if (letter >= 'a' and letter <= 'z') or (letter >= '0' and letter <= '9'): if hasattr(Keys, ("KEY_" + letter).upper()): if shift: params.append(ReleaseAction(Keys.KEY_LEFTSHIFT)) shift = False params.append( ButtonAction(getattr(Keys, ("KEY_" + letter).upper()))) continue if letter == ' ': params.append(ButtonAction(Keys.KEY_SPACE)) continue if letter >= 'A' and letter <= 'Z': if hasattr(Keys, "KEY_" + letter): if not shift: params.append(PressAction(Keys.KEY_LEFTSHIFT)) shift = True params.append(ButtonAction(getattr(Keys, "KEY_" + letter))) continue raise ValueError("Invalid character for type(): '%s'" % (letter, )) Macro.__init__(self, *params) self.letters = string
def on_key_grabbed(self, keys): """ Handles selecting key using "Grab the Key" dialog """ action = ButtonAction(keys[0]) if len(keys) > 1: actions = [ButtonAction(k) for k in keys] action = MultiAction(*actions) self.editor.set_action(action)
def apply_keys(self): """ Common part of on_*key_grabbed """ keys = list(self.keys) action = ButtonAction(keys[0]) if len(keys) > 1: actions = [ButtonAction(k) for k in keys] action = MultiAction(*actions) self.editor.set_action(action)
def test_cycle(self): """ Tests if Cycle can be converted to string and parsed back to same action. """ assert _parses_as_itself(Cycle( ButtonAction(Keys.BTN_LEFT), ButtonAction(Keys.BTN_RIGHT), ButtonAction(Keys.BTN_MIDDLE) ))
def apply_keys(self, *a): """ Common part of on_*key_grabbed """ cbToggle = self.builder.get_object("cbToggle") keys = list(sorted(self.keys, key=ButtonsComponent.modifiers_first)) action = ButtonAction(keys[0]) if len(keys) > 1: actions = [ButtonAction(k) for k in keys] action = MultiAction(*actions) if cbToggle.get_active(): action = Cycle(PressAction(action), ReleaseAction(action)) self.editor.set_action(action)
def test_repeat(self): """ Tests if Repeat can be converted to string and parsed back to same action. """ assert _parses_as_itself(Repeat(ButtonAction(Keys.BTN_LEFT))) assert _parses_as_itself(Repeat(Macro( ButtonAction(Keys.BTN_LEFT), ButtonAction(Keys.BTN_RIGHT), ButtonAction(Keys.BTN_MIDDLE) )))
def make_circular_action(self): """ Constructs Circular Modifier """ if self.circular_axis and any(self.circular_buttons): return CircularModifier( MultiAction(self.circular_axis, ButtonAction(*self.circular_buttons))) elif any(self.circular_buttons): return CircularModifier(ButtonAction(*self.circular_buttons)) else: return CircularModifier(self.circular_axis)
def update(self): cb = self.builder.get_object("cbActionType") key = cb.get_model().get_value(cb.get_active_iter(), 1) if key == "dpad8": # 8-way dpad self.editor.set_action(DPad8Action(*self.actions)) elif key == "dpad": # 4-way dpad self.editor.set_action(DPadAction(*self.actions[0:4])) elif key == "wsad": # special case of 4-way dpad a = DPadAction(ButtonAction(Keys.KEY_W), ButtonAction(Keys.KEY_S), ButtonAction(Keys.KEY_A), ButtonAction(Keys.KEY_D)) self.actions = [ NoAction() ] * 8 self.editor.set_action(a) self.update_button_desc(a) elif key == "arrows": # special case of 4-way dpad a = DPadAction(ButtonAction(Keys.KEY_UP), ButtonAction(Keys.KEY_DOWN), ButtonAction(Keys.KEY_LEFT), ButtonAction(Keys.KEY_RIGHT)) self.actions = [ NoAction() ] * 8 self.editor.set_action(a) self.update_button_desc(a) else: # Menu self.on_cbMenus_changed()
def on_cbAxisOutput_changed(self, *a): cbAxisOutput = self.builder.get_object("cbAxisOutput") stActionData = self.builder.get_object("stActionData") key = cbAxisOutput.get_model().get_value( cbAxisOutput.get_active_iter(), 2) if key == 'area': stActionData.set_visible_child(self.builder.get_object("grArea")) action = self.make_area_action() self.update_osd_area(action) elif key == "button": stActionData.set_visible_child(self.builder.get_object("vbButton")) self.button = self.button or ButtonAction(Keys.BTN_GAMEPAD) action = self.button elif key == "circular": stActionData.set_visible_child( self.builder.get_object("grCircular")) action = self.make_circular_action() elif key == 'mouse': stActionData.set_visible_child(self.builder.get_object("vbMose")) if not self._recursing and self.editor.friction == 0: # When switching to mouse, enable trackball by default self.editor.friction = 10 action = self.make_mouse_action() else: stActionData.set_visible_child(self.builder.get_object("nothing")) action = cbAxisOutput.get_model().get_value( cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.update_osd_area(None) self.editor.set_action(action)
def on_cbAxisOutput_changed(self, *a): cbAxisOutput = self.builder.get_object("cbAxisOutput") stActionData = self.builder.get_object("stActionData") key = cbAxisOutput.get_model().get_value( cbAxisOutput.get_active_iter(), 2) if key == 'area': stActionData.set_visible_child(self.builder.get_object("grArea")) action = self.make_area_action() self.update_osd_area(action) elif key == "button": stActionData.set_visible_child(self.builder.get_object("vbButton")) self.button = self.button or ButtonAction(Keys.BTN_GAMEPAD) action = self.button elif key == "circular": stActionData.set_visible_child( self.builder.get_object("grCircular")) action = self.make_circular_action() elif key == 'trackball': stActionData.set_visible_child( self.builder.get_object("vbTrackball")) action = self.make_trackball_action() else: stActionData.set_visible_child(self.builder.get_object("nothing")) action = cbAxisOutput.get_model().get_value( cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.update_osd_area(None) self.editor.set_action(action)
def test_name(self): """ Tests if NameModifier can be converted to string and parsed back to same. """ assert _parses_as_itself( NameModifier("Not A Button", ButtonAction(Keys.KEY_A)))
def on_buttonaction_type_change(self, cb, data): if cb.get_active() == 0: data[0] = ButtonAction(data[0].button) elif cb.get_active() == 1: data[0] = PressAction(data[0].button) else: data[0] = ReleaseAction(data[0].button) self.update_action_field()
def on_buttonaction_type_change(self, cb, i, action_data): if cb.get_active() == 0: self.actions[i] = action_data._replace( action=ButtonAction(action_data.action)) elif cb.get_active() == 1: self.actions[i] = action_data._replace( action=PressAction(action_data.action)) else: self.actions[i] = action_data._replace( action=ReleaseAction(action_data.action)) self.update_action_field()
def send(self): levels = [] half_level = int( self.builder.get_object("sclPartialLevel").get_value() + 0.1) full_level = int( self.builder.get_object("sclFullLevel").get_value() + 0.1) if half_level != TRIGGER_HALF or full_level != TRIGGER_CLICK: levels.append(half_level) if full_level != TRIGGER_CLICK: levels.append(full_level) self.editor.set_action(ButtonAction(self.half, self.full, *levels))
def on_ok(self, action): if isinstance(action.strip(), AreaAction): # Kinda hacky way to set action on LPAD press or RPAD press # when user selects Mouse Area as ouput and checks # 'Pressing the Pad Clicks' checkbox side = getattr(SCButtons, self.editor.get_id()) clicks = self.pressing_pad_clicks() if self.builder.get_object("cbAreaClickEnabled").get_active(): if not clicks: # Turn pad press into mouse clicks self.app.set_action(self.app.current, side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(self.app.current, side, NoAction())
def __init__(self, *parameters): Action.__init__(self, *parameters) self.actions = [] self.repeat = False self._active = False self._current = None self._release = None for p in parameters: if type(p) == float and len(self.actions): self.actions[-1].delay_after = p elif isinstance(p, Macro): self.actions += p.actions elif isinstance(p, Action): self.actions.append(p) else: self.actions.append(ButtonAction(p))
def update(self): cb = self.builder.get_object("cbActionType") scl = self.builder.get_object("sclDiagonalRange") key = cb.get_model().get_value(cb.get_active_iter(), 1) if key == "dpad8": # 8-way dpad self.editor.set_action(DPad8Action(scl.get_value(), *self.actions)) elif key == "dpad": # 4-way dpad self.editor.set_action( DPadAction(scl.get_value(), *self.actions[0:4])) elif key == "wsad": # special case of 4-way dpad a = DPadAction(scl.get_value(), ButtonAction(Keys.KEY_W), ButtonAction(Keys.KEY_S), ButtonAction(Keys.KEY_A), ButtonAction(Keys.KEY_D)) self.actions = [NoAction()] * 8 self.editor.set_action(a) self.update_button_desc(a) elif key == "arrows": # special case of 4-way dpad a = DPadAction(scl.get_value(), ButtonAction(Keys.KEY_UP), ButtonAction(Keys.KEY_DOWN), ButtonAction(Keys.KEY_LEFT), ButtonAction(Keys.KEY_RIGHT)) self.actions = [NoAction()] * 8 self.editor.set_action(a) self.update_button_desc(a) elif key == "actual_dpad": # maps to dpad as real gamepad usually has a = DPadAction(scl.get_value(), HatUpAction(Axes.ABS_HAT0Y), HatDownAction(Axes.ABS_HAT0Y), HatLeftAction(Axes.ABS_HAT0X), HatRightAction(Axes.ABS_HAT0X)) self.actions = [NoAction()] * 8 self.editor.set_action(a) self.update_button_desc(a) else: # Menu self.on_cbMenus_changed()
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 grab_action(self, button, cb): b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.hide_axes() b.display_action(Action.AC_BUTTON, ButtonAction(button)) b.show(self.editor.window)
def _convert(self, from_version): """ Performs conversion from older profile version """ if from_version < 1: from scc.modifiers import ModeModifier # Add 'display Default.menu if center button is held' for old profiles c = self.buttons[SCButtons.C] if not c: # Nothing set to C button self.buttons[SCButtons.C] = HoldModifier( MenuAction("Default.menu"), normalaction=MenuAction("Default.menu")) elif hasattr(c, "holdaction") and c.holdaction: # Already set to something, don't overwrite it pass elif c.to_string().startswith("OSK."): # Special case, don't touch this either pass else: self.buttons[SCButtons.C] = HoldModifier( MenuAction("Default.menu"), normalaction=self.buttons[SCButtons.C]) if from_version < 1.1: # Convert old scrolling wheel to new representation from scc.modifiers import FeedbackModifier, BallModifier from scc.actions import MouseAction, XYAction from scc.uinput import Rels iswheelaction = ( lambda x: isinstance(x, MouseAction) and x.parameters[0] in (Rels.REL_HWHEEL, Rels.REL_WHEEL)) for p in (Profile.LEFT, Profile.RIGHT): a, feedback = self.pads[p], None if isinstance(a, FeedbackModifier): feedback = a.haptic.get_position() a = a.action if isinstance(a, XYAction): if iswheelaction(a.x) or iswheelaction(a.y): n = BallModifier(XYAction(a.x, a.y)) if feedback is not None: n = FeedbackModifier(feedback, 4096, 16, n) self.pads[p] = n log.info("Converted %s to %s", a.to_string(), n.to_string()) if from_version < 1.2: # Convert old trigger settings that were done with ButtonAction # to new TriggerAction from scc.constants import TRIGGER_HALF, TRIGGER_MAX, TRIGGER_CLICK from scc.actions import ButtonAction, TriggerAction, MultiAction from scc.uinput import Keys for p in (Profile.LEFT, Profile.RIGHT): if isinstance(self.triggers[p], ButtonAction): buttons, numbers = [], [] n = None # There were one or two keys and zero to two numeric # parameters for old button action for param in self.triggers[p].parameters: if param in Keys: buttons.append(param) elif type(param) in (int, float): numbers.append(int(param)) if len(numbers) == 0: # Trigger range was not specified, assume defaults numbers = (TRIGGER_HALF, TRIGGER_CLICK) elif len(numbers) == 1: # Only lower range was specified, add default upper range numbers.append(TRIGGER_CLICK) if len(buttons) == 1: # If only one button was set, trigger should work like # one big button n = TriggerAction(numbers[0], ButtonAction(buttons[0])) elif len(buttons) == 2: # Both buttons were set n = MultiAction( TriggerAction(numbers[0], numbers[1], ButtonAction(buttons[0])), TriggerAction(numbers[1], TRIGGER_MAX, ButtonAction(buttons[1]))) if n: log.info("Converted %s to %s", self.triggers[p].to_string(), n.to_string()) self.triggers[p] = n
def area_action_selected(self, area, action): if area: self.set_active_area(area) if self.full: action = MultiAction(ButtonAction(None, self.full), action) self.editor.set_action(action)