def on_link(self, link): parser = GuiActionParser() if link.startswith("quick://"): action = parser.restart(link[8:]).parse() self.reset_active_component() self.set_action(action, from_custom=True) elif link == "grab://trigger_button": def cb(action): action = TriggerAction(254, 255, action) self.set_action(action, from_custom=True) self.force_page("trigger") b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.hide_axes() b.show(self.window) elif link.startswith("page://"): def cb(): self.force_page(link[7:]) GLib.timeout_add(0.1, cb) elif link.startswith("advanced://"): exMore = self.builder.get_object("exMore") rvMore = self.builder.get_object("rvMore") ntbMore = self.builder.get_object("ntbMore") assert exMore.get_visible() exMore.set_expanded(True) rvMore.set_reveal_child(True) if "#" in link: link, name = link.split("#") self.blink_widget(name) ntbMore.set_current_page(int(link.split("/")[-1])) else: log.warning("Activated unknown link: %s", link)
class CustomActionComponent(AEComponent): GLADE = "ae/custom.glade" NAME = "custom" PRIORITY = -1 CTXS = Action.AC_ALL def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser() def handles(self, mode, action): # Custom Action Editor handles all actions" return isinstance(action, Action) def get_button_title(self): return _("Custom Action") def load(self): if self.loaded : return AEComponent.load(self) try: txCustomAction = self.builder.get_object("txCustomAction") txCustomAction.set_monospace(True) except: pass def set_action(self, mode, action): action = self.editor.generate_modifiers(action) tbCustomAction = self.builder.get_object("tbCustomAction") tbCustomAction.set_text(action.to_string(True)) def on_tbCustomAction_changed(self, tbCustomAction, *a): """ Converts text from Custom Action text area into action instance and sends that instance back to editor. """ txCustomAction = self.builder.get_object("txCustomAction") txt = tbCustomAction.get_text(tbCustomAction.get_start_iter(), tbCustomAction.get_end_iter(), True) if len(txt.strip(" \t\r\n")) > 0: action = self.parser.restart(txt).parse() self.editor.set_action(action) def shown(self): self.editor.set_modifiers_enabled(False) def hidden(self): self.editor.set_modifiers_enabled(True)
class CustomActionComponent(AEComponent): GLADE = "ae/custom.glade" NAME = "custom" PRIORITY = -1 CTXS = Action.AC_ALL def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser() def handles(self, mode, action): # Custom Action Editor handles all actions return isinstance(action, Action) def get_button_title(self): return _("Custom Action") def load(self): if self.loaded: return AEComponent.load(self) try: txCustomAction = self.builder.get_object("txCustomAction") txCustomAction.set_monospace(True) except: pass def set_action(self, mode, action): action = self.editor.generate_modifiers(action, from_custom=True) tbCustomAction = self.builder.get_object("tbCustomAction") tbCustomAction.set_text(action.to_string(True)) def on_tbCustomAction_changed(self, tbCustomAction, *a): """ Converts text from Custom Action text area into action instance and sends that instance back to editor. """ txCustomAction = self.builder.get_object("txCustomAction") txt = tbCustomAction.get_text(tbCustomAction.get_start_iter(), tbCustomAction.get_end_iter(), True) if len(txt.strip(" \t\r\n")) > 0: action = self.parser.restart(txt).parse() self.editor.set_action(action, from_custom=True) def shown(self): self.editor.set_modifiers_enabled(False) def hidden(self): self.editor.set_modifiers_enabled(True)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK | Action.AC_PAD PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.on_wayland = False self.circular = MouseAction(Rels.REL_WHEEL) self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" ) self.on_wayland = "WAYLAND_DISPLAY" in os.environ or not isinstance(Gdk.Display.get_default(), GdkX11.X11Display) if self.on_wayland: self.builder.get_object("lblArea").set_text(_("Note: Mouse Region option is not available with Wayland-based display server")) self.builder.get_object("grArea").set_sensitive(False) # Remove options that are not applicable to currently editted input if self.editor.get_id() in STICKS: # Remove "Mouse Region", "Trackball", "Trackpad" # and "Mouse (Emulate Stick)" options when editing stick bindings cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_pad", "area", "mouse_pad", "trackpad", "trackball"): cb.get_model().remove(row.iter) else: # Remove "Mouse" option when editing pads # (it's effectivelly same as Trackpad) cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_stick", "mouse_stick", ): cb.get_model().remove(row.iter) def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, MouseAction): self.set_cb(cb, "trackpad", 2) elif isinstance(action, BallModifier): self.load_trackball_action(action) elif isinstance(action, CircularModifier): self.load_circular_action(action) elif isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.set_cb(cb, "rstick", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: if self.on_wayland: # Cannot display preview with non-X11 backends return self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_circular_action(self, action): self.circular = action.action cbAxisOutput = self.builder.get_object("cbAxisOutput") btCircularAxis = self.builder.get_object("btCircularAxis") btCircularAxis.set_label(self.circular.describe(Action.AC_PAD)) self.set_cb(cbAxisOutput, "circular", 2) def load_trackball_action(self, action): cbTracballOutput = self.builder.get_object("cbTracballOutput") cbAxisOutput = self.builder.get_object("cbAxisOutput") sclFriction = self.builder.get_object("sclFriction") self._recursing = True if isinstance(action.action, MouseAction): self.set_cb(cbTracballOutput, "mouse", 1) self.set_cb(cbAxisOutput, "trackball", 2) elif isinstance(action.action, XYAction): if isinstance(action.action.x, AxisAction): if action.action.x.parameters[0] == Axes.ABS_X: self.set_cb(cbTracballOutput, "left", 1) else: self.set_cb(cbTracballOutput, "right", 1) self.set_cb(cbAxisOutput, "trackball", 2) elif isinstance(action.action.x, MouseAction): self.set_cb(cbAxisOutput, "wheel", 2) if action.friction <= 0: sclFriction.set_value(0) else: sclFriction.set_value(math.log(action.friction * 1000.0, 10)) self._recursing = False def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1 : x1, x2 = x2, x1 if y2 < y1 : y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_btCircularAxis_clicked(self, *a): def cb(action): self.circular = action btCircularAxis = self.builder.get_object("btCircularAxis") btCircularAxis.set_label(action.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) b = SimpleChooser(self.app, "axis", cb) b.set_title(_("Select Axis")) b.display_action(Action.AC_STICK, self.circular) b.show(self.editor.window) def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False 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 make_trackball_action(self): """ Loads values from UI into trackball-related action """ sclFriction = self.builder.get_object("sclFriction") cbTracballOutput = self.builder.get_object("cbTracballOutput") a_str = cbTracballOutput.get_model().get_value(cbTracballOutput.get_active_iter(), 2) a = self.parser.restart(a_str).parse() if sclFriction.get_value() <= 0: friction = 0 else: friction = ((10.0**sclFriction.get_value())/1000.0) return BallModifier(round(friction, 3), a) def make_circular_action(self): """ Constructs Circular Modifier """ return CircularModifier(self.circular) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick / Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, MouseAction, CircularModifier, InvalidAction, AreaAction)): return True if isinstance(action, BallModifier): if isinstance(action.action, XYAction): return ( isinstance(action.action.x, (AxisAction, MouseAction)) and isinstance(action.action.x, (AxisAction, MouseAction)) ) return isinstance(action.action, MouseAction) if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing : return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_trackball_options_changed(self, *a): if self._recursing : return action = self.make_trackball_action() self.editor.set_action(action) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) def on_btClearFriction_clicked(self, *a): sclFriction = self.builder.get_object("sclFriction") sclFriction.set_value(math.log(10 * 1000.0, 10)) def on_sclFriction_format_value(self, scale, value): if value <= 0: return "0.000" elif value >= 6: return "1000.00" else: return "%0.3f" % ((10.0**value)/1000.0) 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 == "circular": stActionData.set_visible_child(self.builder.get_object("vbCircular")) 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)
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO, PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger') ), (SCButtons.RT, _('Right Trigger') ), (SCButtons.LB, _('Left Bumper') ), (SCButtons.RB, _('Right Bumper') ), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched') ), (SCButtons.RPADTOUCH, _('Right Pad Touched') ), (SCButtons.LPAD, _('Left Pad Pressed') ), (SCButtons.RPAD, _('Right Pad Pressed') ), (None, None), (SCButtons.LGRIP, _('Left Grip') ), (SCButtons.RGRIP, _('Right Grip') ), (None, None), (SCButtons.A, _('A') ), (SCButtons.B, _('B') ), (SCButtons.X, _('X') ), (SCButtons.Y, _('Y') ), (None, None), (SCButtons.BACK, _('Back (select)') ), (SCButtons.C, _('Center') ), (SCButtons.START, _('Start') ), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(None) return if isinstance(action, ModeModifier): b = action.order[0] action = action.mods[b] self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, MouseAction): self.select_gyro_output("mouse") if len(action.parameters) >= 2 and action.parameters[1] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") self.select_yaw_roll(ROLL) elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") self.select_yaw_roll(ROLL) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods[action.order[0]] if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True if ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True return False if isinstance(action, MultiAction): return False return True def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, button): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") model = cb.get_model() self._recursing = True if button is not None: button = button.name for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def update(self, *a): pass def send(self, *a): if self._recursing : return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") cbGyroButton = self.builder.get_object("cbGyroButton") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) button = cbGyroButton.get_model().get_value(cbGyroButton.get_active_iter(), 0) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if button: action = ModeModifier(getattr(SCButtons, button), action) self.editor.set_action(action)
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger') ), (SCButtons.RT, _('Right Trigger') ), (SCButtons.LB, _('Left Bumper') ), (SCButtons.RB, _('Right Bumper') ), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched') ), (SCButtons.RPADTOUCH, _('Right Pad Touched') ), (SCButtons.LPAD, _('Left Pad Pressed') ), (SCButtons.RPAD, _('Right Pad Pressed') ), (None, None), (SCButtons.LGRIP, _('Left Grip') ), (SCButtons.RGRIP, _('Right Grip') ), (STICK, _('Stick Tilted') ), (None, None), (SCButtons.A, _('A') ), (SCButtons.B, _('B') ), (SCButtons.X, _('X') ), (SCButtons.Y, _('Y') ), (None, None), (SCButtons.BACK, _('Back (select)') ), (SCButtons.C, _('Center') ), (SCButtons.START, _('Start') ), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(SCButtons.RPADTOUCH) return if isinstance(action, ModeModifier): self._recursing = True self.builder.get_object("cbInvertGyro").set_active(bool(action.default)) self._recursing = False b = action.mods.keys()[0] action = action.mods[b] or action.default self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, SensitivityModifier) and isinstance(action.action, MouseAction): # Mouse (Desktop) self.select_gyro_output("mouse") if len(action.action.parameters) > 0 and action.action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) self.editor.set_default_sensitivity(3.5, 3.5, 3.5) self.editor.set_sensitivity(*action.speeds) elif isinstance(action, MouseAction): # Mouse (Camera) self.select_gyro_output("mouse_cam") if len(action.parameters) > 0 and action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: self.select_gyro_output("mouse_stick") self.modifier_updated() def modifier_updated(self): cbInvertY = self.builder.get_object("cbInvertY") sens = self.editor.get_sensitivity() inverted = len(sens) >= 2 and sens[1] < 0 if cbInvertY.get_active() != inverted: self._recursing = True cbInvertY.set_active(inverted) self._recursing = False def cbInvertY_toggled_cb(self, cb, *a): if self._recursing: return sens = list(self.editor.get_sensitivity()) # Ensure that editor accepts Y sensitivity if len(sens) >= 2: sens[1] = abs(sens[1]) if cb.get_active(): # Ensure that Y sensitivity is negative sens[1] *= -1 self.editor.set_sensitivity(*sens) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods.values()[0] or action.default if isinstance(action, SensitivityModifier): action = action.action if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: return True return False if isinstance(action, (MouseAction, MouseAbsAction)): return True return False def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, item): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") rvSoftLevel = self.builder.get_object("rvSoftLevel") sclSoftLevel = self.builder.get_object("sclSoftLevel") model = cb.get_model() self._recursing = True button = None if isinstance(item, RangeOP): button = nameof(item.what) sclSoftLevel.set_value(item.value) rvSoftLevel.set_reveal_child(True) elif item is not None: button = nameof(item.name) for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def on_cbInvertGyro_toggled(self, cb, *a): lblGyroEnable = self.builder.get_object("lblGyroEnable") if cb.get_active(): lblGyroEnable.set_label(_("Gyro Disable Button")) else: lblGyroEnable.set_label(_("Gyro Enable Button")) if not self._recursing: self.send() def on_sclSoftLevel_format_value(self, scale, value): return "%s%%" % (int(value * 100.0),) def update(self, *a): pass def hidden(self): self.editor.set_default_sensitivity(1, 1, 1) def send(self, *a): if self._recursing : return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") rvSoftLevel = self.builder.get_object("rvSoftLevel") sclSoftLevel = self.builder.get_object("sclSoftLevel") cbGyroButton = self.builder.get_object("cbGyroButton") cbInvertGyro = self.builder.get_object("cbInvertGyro") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) key = cbMode.get_model().get_value(cbMode.get_active_iter(), 2) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) item = cbGyroButton.get_model().get_value(cbGyroButton.get_active_iter(), 0) rvSoftLevel.set_reveal_child(item in TRIGGERS) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if item and action: if item in TRIGGERS: what = RangeOP(getattr(SCButtons, item), ">=", sclSoftLevel.get_value()) elif item == STICK: what = RangeOP(item, ">=", sclSoftLevel.get_value()) else: what = getattr(SCButtons, item) if cbInvertGyro.get_active(): action = ModeModifier(what, NoAction(), action) else: action = ModeModifier(what, action) if key == "mouse": self.editor.set_default_sensitivity(3.5, 3.5, 3.5) else: self.editor.set_default_sensitivity(1, 1, 1) self.editor.set_action(action)
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger')), (SCButtons.RT, _('Right Trigger')), (SCButtons.LB, _('Left Bumper')), (SCButtons.RB, _('Right Bumper')), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched')), (SCButtons.RPADTOUCH, _('Right Pad Touched')), (SCButtons.LPAD, _('Left Pad Pressed')), (SCButtons.RPAD, _('Right Pad Pressed')), (None, None), (SCButtons.LGRIP, _('Left Grip')), (SCButtons.RGRIP, _('Right Grip')), (None, None), (SCButtons.A, _('A')), (SCButtons.B, _('B')), (SCButtons.X, _('X')), (SCButtons.Y, _('Y')), (None, None), (SCButtons.BACK, _('Back (select)')), (SCButtons.C, _('Center')), (SCButtons.START, _('Start')), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded: return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(SCButtons.RPADTOUCH) return if isinstance(action, ModeModifier): self._recursing = True self.builder.get_object("cbInvertGyro").set_active( bool(action.default)) self._recursing = False b = action.order[0] action = action.mods[b] or action.default self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, SensitivityModifier) and isinstance( action.action, MouseAction): # Mouse (Desktop) self.select_gyro_output("mouse") if len(action.action.parameters ) > 0 and action.action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) self.editor.set_default_sensitivity(3.5, 3.5, 3.5) self.editor.set_sensitivity(*action.speeds) elif isinstance(action, MouseAction): # Mouse (Camera) self.select_gyro_output("mouse_cam") if len(action.parameters) > 0 and action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: self.select_gyro_output("mouse_stick") self.modifier_updated() def modifier_updated(self): cbInvertY = self.builder.get_object("cbInvertY") sens = self.editor.get_sensitivity() inverted = len(sens) >= 2 and sens[1] < 0 if cbInvertY.get_active() != inverted: self._recursing = True cbInvertY.set_active(inverted) self._recursing = False def cbInvertY_toggled_cb(self, cb, *a): if self._recursing: return sens = list(self.editor.get_sensitivity()) # Ensure that editor accepts Y sensitivity if len(sens) >= 2: sens[1] = abs(sens[1]) if cb.get_active(): # Ensure that Y sensitivity is negative sens[1] *= -1 self.editor.set_sensitivity(*sens) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods[action.order[0]] or action.default if isinstance(action, SensitivityModifier): action = action.action if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: return True return False if isinstance(action, (MouseAction, MouseAbsAction)): return True return False def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, button): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") model = cb.get_model() self._recursing = True if button is not None: button = button.name for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def on_cbInvertGyro_toggled(self, cb, *a): lblGyroEnable = self.builder.get_object("lblGyroEnable") if cb.get_active(): lblGyroEnable.set_label(_("Gyro Disable Button")) else: lblGyroEnable.set_label(_("Gyro Enable Button")) if not self._recursing: self.send() def update(self, *a): pass def hidden(self): self.editor.set_default_sensitivity(1, 1, 1) def send(self, *a): if self._recursing: return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") cbGyroButton = self.builder.get_object("cbGyroButton") cbInvertGyro = self.builder.get_object("cbInvertGyro") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) key = cbMode.get_model().get_value(cbMode.get_active_iter(), 2) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) button = cbGyroButton.get_model().get_value( cbGyroButton.get_active_iter(), 0) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if button and action: if cbInvertGyro.get_active(): action = ModeModifier(getattr(SCButtons, button), NoAction(), action) else: action = ModeModifier(getattr(SCButtons, button), action) if key == "mouse": self.editor.set_default_sensitivity(3.5, 3.5, 3.5) else: self.editor.set_default_sensitivity(1, 1, 1) self.editor.set_action(action)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK, Action.AC_PAD, PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" ) def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, TrackpadAction): self.set_cb(cb, "trackpad", 2) elif isinstance(action, TrackballAction): self.set_cb(cb, "trackball", 2) elif isinstance(action, CircularAction): self.set_cb(cb, "circular", 2) elif isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.set_cb(cb, "rstick", 2) elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: self.set_cb(cb, "dpad", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1 : x1, x2 = x2, x1 if y2 < y1 : y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False 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(side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(side, NoAction()) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction, AreaAction)): return True if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing : return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) 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) 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)
class AxisActionComponent(AEComponent): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK, Action.AC_PAD, PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, TrackpadAction): self.select_axis_output("trackpad") elif isinstance(action, TrackballAction): self.select_axis_output("trackball") elif isinstance(action, CircularAction): self.select_axis_output("circular") elif isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.select_axis_output("lstick") elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.select_axis_output("rstick") elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: self.select_axis_output("dpad") elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.select_axis_output("wheel") else: self.select_axis_output("none") def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction)): return True if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def select_axis_output(self, key): """ Just sets combobox value """ model = self.builder.get_object("lstOutputMode") cb = self.builder.get_object("cbAxisOutput") self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def on_cbAxisOutput_changed(self, *a): if self._recursing : return cbAxisOutput = self.builder.get_object("cbAxisOutput") action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.editor.set_action(action)
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO, PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger')), (SCButtons.RT, _('Right Trigger')), (SCButtons.LB, _('Left Bumper')), (SCButtons.RB, _('Right Bumper')), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched')), (SCButtons.RPADTOUCH, _('Right Pad Touched')), (SCButtons.LPAD, _('Left Pad Pressed')), (SCButtons.RPAD, _('Right Pad Pressed')), (None, None), (SCButtons.LGRIP, _('Left Grip')), (SCButtons.RGRIP, _('Right Grip')), (None, None), (SCButtons.A, _('A')), (SCButtons.B, _('B')), (SCButtons.X, _('X')), (SCButtons.Y, _('Y')), (None, None), (SCButtons.BACK, _('Back (select)')), (SCButtons.C, _('Center')), (SCButtons.START, _('Start')), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded: return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(None) return if isinstance(action, ModeModifier): b = action.order[0] action = action.mods[b] self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, MouseAction): self.select_gyro_output("mouse") if len(action.parameters) >= 2 and action.parameters[1] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") self.select_yaw_roll(ROLL) elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") self.select_yaw_roll(ROLL) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods[action.order[0]] if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True if ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True return False if isinstance(action, MultiAction): return False return True def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, button): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") model = cb.get_model() self._recursing = True if button is not None: button = button.name for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def update(self, *a): pass def send(self, *a): if self._recursing: return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") cbGyroButton = self.builder.get_object("cbGyroButton") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) button = cbGyroButton.get_model().get_value( cbGyroButton.get_active_iter(), 0) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if button: action = ModeModifier(getattr(SCButtons, button), action) self.editor.set_action(action)
class FirstPage(AEComponent): GLADE = "ae/first_page.glade" NAME = "first_page" CTXS = 0 PRIORITY = 999 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser() def load(self): if AEComponent.load(self): # Unlike mose region, gesutres kinda work with XWayland markup = "" if self.editor.get_mode() == Action.AC_PAD: markup = MARKUP_PAD elif self.editor.get_mode() == Action.AC_STICK: markup = MARKUP_STICK elif self.editor.get_mode() == Action.AC_GYRO: markup = MARKUP_GYRO elif self.editor.get_mode() == Action.AC_TRIGGER: markup = MARKUP_TRIGGER else: markup = MARKUP_BUTTON long_names = { 'LPAD': _("Left Pad"), 'RPAD': _("Right Pad"), 'LGRIP': _("Left Grip"), 'RGRIP': _("Right Grip"), 'LB': _("Left Bumper"), 'RB': _("Right Bumper"), 'LEFT': _("Left Trigger"), 'RIGHT': _("Right Trigger"), 'STICK': _("Stick"), } markup = markup % { 'what': long_names.get(nameof(self.editor.get_id()), nameof(self.editor.get_id()).title()) } self.builder.get_object("lblMarkup").set_markup( markup.strip(" \r\n\t")) return True def on_lblMarkup_activate_link(self, trash, link): if link.startswith("quick://"): action = self.parser.restart(link[8:]).parse() self.editor.reset_active_component() self.editor.set_action(action, from_custom=True) elif link == "grab://trigger_button": def cb(action): action = TriggerAction(254, 255, action) self.editor.set_action(action, from_custom=True) self.editor.force_page("trigger") b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.hide_axes() b.show(self.editor.window) elif link.startswith("page://"): def cb(): self.editor.force_page(link[7:]) GLib.timeout_add(0.1, cb)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK, Action.AC_PAD, PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.parser = GuiActionParser() def load(self): if self.loaded: return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter: model.get_value(iter, 0) == "-") def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, TrackpadAction): self.set_cb(cb, "trackpad", 2) elif isinstance(action, TrackballAction): self.set_cb(cb, "trackball", 2) elif isinstance(action, CircularAction): self.set_cb(cb, "circular", 2) elif isinstance(action, XYAction): p = [None, None] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.set_cb(cb, "rstick", 2) elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: self.set_cb(cb, "dpad", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1: x1, x2 = x2, x1 if y2 < y1: y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active( self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False 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(side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(side, NoAction()) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction, AreaAction)): return True if isinstance(action, XYAction): p = [None, None] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing: return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) 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) 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)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK | Action.AC_PAD PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.on_wayland = False self.circular_axis = MouseAction(Rels.REL_WHEEL) self.circular_buttons = [ None, None ] self.button = None self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" ) self.on_wayland = "WAYLAND_DISPLAY" in os.environ or not isinstance(Gdk.Display.get_default(), GdkX11.X11Display) if self.on_wayland: self.builder.get_object("lblArea").set_text(_("Note: Mouse Region option is not available with Wayland-based display server")) self.builder.get_object("grArea").set_sensitive(False) # Remove options that are not applicable to currently editted input if self.editor.get_id() in STICKS: # Remove "Mouse Region", "Mouse" and "Mouse (Emulate Stick)" options # when editing stick bindings cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_pad", "area", "mouse", "mouse_pad"): cb.get_model().remove(row.iter) else: # Remove "Mouse" option when editing pads # (it's effectivelly same as Trackpad) cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_stick", "mouse_stick"): cb.get_model().remove(row.iter) def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, MouseAction): self.load_mouse_action(action) elif isinstance(action, CircularModifier): self.load_circular_action(action) elif isinstance(action, ButtonAction): self.load_button_action(action) elif isinstance(action, XYAction): if self.editor.friction > 0: self.load_mouse_action(action) else: p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: if isinstance(action, RelXYAction): self.set_cb(cb, "rstick_rel", 2) else: self.set_cb(cb, "rstick", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel_pad", 2) self.set_cb(cb, "wheel_stick", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: if self.on_wayland: # Cannot display preview with non-X11 backends return self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_circular_action(self, action): cbAxisOutput = self.builder.get_object("cbAxisOutput") btCircularAxis = self.builder.get_object("btCircularAxis") btCircularButton0 = self.builder.get_object("btCircularButton0") btCircularButton1 = self.builder.get_object("btCircularButton1") # Turn action into list of subactions (even if it's just single action) if isinstance(action.action, MultiAction): actions = action.action.actions else: actions = [ action.action ] # Parse that list self.circular_axis, self.circular_buttons = NoAction(), [ None, None ] for action in actions: if isinstance(action, ButtonAction): self.circular_buttons = [ action.button, action.button2 ] else: self.circular_axis = action # Set labels b0, b1 = self.circular_buttons btCircularButton0.set_label(ButtonAction.describe_button(b0)) btCircularButton1.set_label(ButtonAction.describe_button(b1)) btCircularAxis.set_label(self.circular_axis.describe(Action.AC_PAD)) self.set_cb(cbAxisOutput, "circular", 2) def load_button_action(self, action): self.button = action cbAxisOutput = self.builder.get_object("cbAxisOutput") btSingleButton = self.builder.get_object("btSingleButton") btSingleButton.set_label(self.button.describe(Action.AC_PAD)) self.set_cb(cbAxisOutput, "button", 2) def load_mouse_action(self, action): cbMouseOutput = self.builder.get_object("cbMouseOutput") cbAxisOutput = self.builder.get_object("cbAxisOutput") self._recursing = True if isinstance(action, MouseAction): self.set_cb(cbMouseOutput, "mouse", 1) self.set_cb(cbAxisOutput, "mouse", 2) elif isinstance(action, XYAction): if isinstance(action.x, AxisAction): if action.x.parameters[0] == Axes.ABS_X: self.set_cb(cbMouseOutput, "left", 1) else: self.set_cb(cbMouseOutput, "right", 1) self.set_cb(cbAxisOutput, "mouse", 2) elif isinstance(action.x, MouseAction): if self.editor.get_id() in STICKS: self.set_cb(cbAxisOutput, "wheel_stick", 2) else: self.set_cb(cbAxisOutput, "wheel_pad", 2) self._recursing = False def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1 : x1, x2 = x2, x1 if y2 < y1 : y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_btCircularAxis_clicked(self, *a): def cb(action): self.circular_axis = action btCircularAxis = self.builder.get_object("btCircularAxis") btCircularAxis.set_label(action.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) b = SimpleChooser(self.app, "axis", cb) b.set_title(_("Select Axis")) b.display_action(Action.AC_STICK, self.circular_axis) b.show(self.editor.window) def on_btCircularButton_clicked(self, button, *a): index = 0 if button == self.builder.get_object("btCircularButton0") else 1 def cb(action): self.circular_buttons[index] = action.button btCircularButton = self.builder.get_object("btCircularButton%s" % (index, )) btCircularButton.set_label(action.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.display_action(Action.AC_STICK, self.circular_axis) b.show(self.editor.window) def on_btClearCircularAxis_clicked(self, *a): btCircularAxis = self.builder.get_object("btCircularAxis") self.circular_axis = NoAction() btCircularAxis.set_label(self.circular_axis.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) def on_btClearCircularButtons_clicked(self, *a): btCircularButton0 = self.builder.get_object("btCircularButton0") btCircularButton1 = self.builder.get_object("btCircularButton1") self.circular_buttons = [ None, None ] btCircularButton0.set_label(NoAction().describe(Action.AC_PAD)) btCircularButton1.set_label(NoAction().describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) def on_btSingleButton_clicked(self, *a): def cb(action): self.button = action btSingleButton = self.builder.get_object("btSingleButton") btSingleButton.set_label(self.button.describe(Action.AC_PAD)) self.editor.set_action(self.button) b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.display_action(Action.AC_STICK, self.circular_axis) b.show(self.editor.window) def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False 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 on_mouse_options_changed(self, *a): if self._recursing : return action = self.make_mouse_action() self.editor.set_action(action) def make_mouse_action(self): """ Loads values from UI into trackball-related action """ cbMouseOutput = self.builder.get_object("cbMouseOutput") a_str = cbMouseOutput.get_model().get_value(cbMouseOutput.get_active_iter(), 2) return self.parser.restart(a_str).parse() 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 make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick / Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, MouseAction, CircularModifier, InvalidAction, AreaAction, ButtonAction)): return True if isinstance(action, BallModifier): if isinstance(action.action, XYAction): return ( isinstance(action.action.x, (AxisAction, MouseAction)) and isinstance(action.action.x, (AxisAction, MouseAction)) ) return isinstance(action.action, MouseAction) if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing : return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) def on_lblSetupTrackball_activate_link(self, trash, link): self.editor.on_link(link) 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 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)