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") lblSoftLevel = self.builder.get_object("lblSoftLevel") 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) if item.what == STICK: lblSoftLevel.set_label(_("Stick deadzone")) else: lblSoftLevel.set_label(_("Trigger Pull Level")) 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 _mod_to_string(self, params, multiline, pad): """ Adds action at end of params list and generates string """ if multiline: childstr = self.action.to_string(True, pad + 2) if len(params) > 0: return "%s%s(%s,%s%s)" % ( " " * pad, self.COMMAND, ", ".join([ nameof(s) for s in params ]), '\n' if '\n' in childstr else ' ', childstr ) return "%s%s(%s)" % ( " " * pad, self.COMMAND, childstr.strip() ) childstr = self.action.to_string(False, pad) if len(params) > 0: return "%s%s(%s, %s)" % ( " " * pad, self.COMMAND, ", ".join([ nameof(s) for s in params ]), childstr ) return "%s%s(%s)" % ( " " * pad, self.COMMAND, childstr )
def to_string(self, multiline=False, pad=0): if multiline: rv = [ (" " * pad) + "mode(" ] for check in self.mods: a_str = NameModifier.unstrip(self.mods[check]).to_string(True).split("\n") a_str[0] = (" " * pad) + " " + (nameof(check) + ",").ljust(11) + a_str[0] # Key has to be one of SCButtons for i in xrange(1, len(a_str)): a_str[i] = (" " * pad) + " " + a_str[i] a_str[-1] = a_str[-1] + "," rv += a_str if self.default is not None: a_str = [ (" " * pad) + " " + x for x in NameModifier.unstrip(self.default).to_string(True).split("\n") ] rv += a_str if rv[-1][-1] == ",": rv[-1] = rv[-1][0:-1] rv += [ (" " * pad) + ")" ] return "\n".join(rv) else: rv = [ ] for check in self.mods: rv += [ nameof(check), NameModifier.unstrip(self.mods[check]).to_string(False) ] if self.default is not None: rv += [ NameModifier.unstrip(self.default).to_string(False) ] return "mode(" + ", ".join(rv) + ")"
def load(self): if AEComponent.load(self): 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 load_menu_data(self, action): if isinstance(action, PositionModifier): # Load menu position modifier, if used x, y = action.position self.builder.get_object("cbMenuPosX").set_active(0 if x >= 0 else 1) self.builder.get_object("cbMenuPosY").set_active(0 if y >= 0 else 1) self.builder.get_object("spMenuPosX").set_value(abs(x)) self.builder.get_object("spMenuPosY").set_value(abs(y)) action = action.action self._current_menu = action.menu_id cbm = self.builder.get_object("cbMenuType") self.set_cb(cbm, self.menu_class_to_key(action), 1) if self.builder.get_object("rvMenuSize"): spMenuSize = self.builder.get_object("spMenuSize") if self.update_size_display(action): size = spMenuSize.get_adjustment().set_value(action.size) cbControlWith = self.builder.get_object("cbControlWith") cbConfirmWith = self.builder.get_object("cbConfirmWith") cbCancelWith = self.builder.get_object("cbCancelWith") cbMenuAutoConfirm = self.builder.get_object("cbMenuAutoConfirm") cbMenuConfirmWithClick = self.builder.get_object("cbMenuConfirmWithClick") cbMenuAutoCancel = self.builder.get_object("cbMenuAutoCancel") if cbControlWith: self.set_cb(cbControlWith, nameof(action.control_with), 1) cow = action.confirm_with caw = action.cancel_with if cbConfirmWith: if cow == SAME and cbMenuAutoConfirm: cbMenuAutoConfirm.set_active(True) cbConfirmWith.set_sensitive(False) elif cbMenuConfirmWithClick and cow == self.get_default_confirm(): cbMenuConfirmWithClick.set_active(True) cbConfirmWith.set_sensitive(False) else: if cbMenuAutoConfirm: cbMenuAutoConfirm.set_active(False) if cbMenuConfirmWithClick: cbMenuAutoConfirm.set_active(False) cbConfirmWith.set_sensitive(True) self.set_cb(cbConfirmWith, nameof(cow), 1) if cbCancelWith: if caw == SAME and cbMenuAutoCancel: cbMenuAutoCancel.set_active(True) cbCancelWith.set_sensitive(False) else: if cbMenuAutoCancel: cbMenuAutoCancel.set_active(False) self.set_cb(cbCancelWith, nameof(caw), 1) self.on_cbMenus_changed()
def on_cursor_motion(self, trash, event): # self.icon.get_allocation().x + self.icon.get_allocation().width # yields nonsense ix2 = 74 # Check if cursor is placed on icon if event.x < ix2: what = { Profile.LPAD : LEFT, Profile.RPAD : RIGHT, Profile.CPAD : nameof(SCButtons.CPADPRESS), Profile.STICK : nameof(SCButtons.STICKPRESS), }[self.name] self.app.hilight(what) self.over_icon = True else: self.app.hilight(self.name) self.over_icon = False
def __str__(self): rv = [ ] for check in self.mods: rv += [ nameof(check), self.mods[check] ] if self.default is not None: rv += [ self.default ] return "<Modifier '%s', %s>" % (self.COMMAND, rv)
def _fill_button_images(self, buttons): e = self.edit() SVGEditor.update_parents(e) target = SVGEditor.get_element(e, "controller") target_x, target_y = SVGEditor.get_translation(target) for i in xrange(len(ControllerImage.BUTTONS_WITH_IMAGES)): b = nameof(ControllerImage.BUTTONS_WITH_IMAGES[i]) try: elm = SVGEditor.get_element(e, "AREA_%s" % (b,)) if elm is None: log.warning("Area for button %s not found", b) continue x, y = SVGEditor.get_translation(elm) scale = 1.0 if "scc-button-scale" in elm.attrib: w, h = SVGEditor.get_size(elm) scale = float(elm.attrib['scc-button-scale']) tw, th = w * scale, h * scale if scale < 1.0: x += (w - tw) * 0.5 y += (h - th) * 0.5 else: x -= (tw - w) * 0.25 y -= (th - h) * 0.25 path = os.path.join(self.app.imagepath, "button-images", "%s.svg" % (buttons[i], )) img = SVGEditor.get_element(SVGEditor.load_from_file(path), "button") img.attrib["transform"] = "translate(%s, %s) scale(%s)" % ( x - target_x, y - target_y, scale) img.attrib["id"] = b SVGEditor.add_element(target, img) except Exception, err: log.warning("Failed to add image for button %s", b) log.exception(err)
def add(self, icon, context, action): if not action: return LineCollection() if isinstance(action, MultiAction): if not action.is_key_combination(): return LineCollection([ self.add(icon, context, child) for child in action.actions ]) elif isinstance(action, ModeModifier): lines = [ self.add(icon, context, action.default) ] for x in action.mods: lines.append( self.add(nameof(x), context, action.mods[x]) .add_icon(icon) ) return LineCollection(*lines) elif isinstance(action, DoubleclickModifier): lines = [] if action.normalaction: lines.append( self.add(icon, context, action.normalaction) ) if action.action: lines.append( self.add("DOUBLECLICK", context, action.action) .add_icon(icon) ) if action.holdaction: lines.append( self.add("HOLD", context, action.holdaction) .add_icon(icon) ) return LineCollection(*lines) action = action.strip() if isinstance(action, MenuAction): if self.name == "bcs" and action.menu_id == "Default.menu": # Special case, this action is expected in every profile, # so there is no need to draw it here return LineCollection() elif isinstance(action, DPadAction): return LineCollection( self.add("DPAD_UP", Action.AC_BUTTON, action.actions[0]), self.add("DPAD_DOWN", Action.AC_BUTTON, action.actions[1]), self.add("DPAD_LEFT", Action.AC_BUTTON, action.actions[2]), self.add("DPAD_RIGHT", Action.AC_BUTTON, action.actions[3]) ) elif isinstance(action, XYAction): if isinstance(action.x, MouseAction) and isinstance(action.y, MouseAction): if action.x.get_axis() in (Rels.REL_HWHEEL, Rels.REL_WHEEL): # Special case, pad bound to wheel line = Line(icon, _("Mouse Wheel")) self.lines.append(line) return line if isinstance(action.x, AxisAction) and isinstance(action.y, AxisAction): if action.x.axis and action.y.axis: line = Line(icon, action.x.describe(Action.AC_BUTTON)) self.lines.append(line) return line return LineCollection( self.add("AXISX", Action.AC_BUTTON, action.x), self.add("AXISY", Action.AC_BUTTON, action.y) ) line = Line(icon, action.describe(context)) self.lines.append(line) return line
def set_mapping(self, keycode, what): parent = self.parent if isinstance(what, AxisData) and what in parent._mappings.values(): for c in parent._mappings.keys(): if parent._mappings[c] == what: del parent._mappings[c] parent._mappings[keycode] = what log.debug("Reassigned %s to %s", keycode, what) if nameof(what) in parent._unassigned: parent._unassigned.remove(nameof(what)) parent.unhilight(nameof(what)) self.parent.generate_unassigned() self.parent.generate_raw_data() self.cancel()
def to_string(self, multiline=False, pad=0): rv = "%s%s(" % (" " * pad, self.COMMAND) if self.confirm_with != DEFAULT: rv += "%s, " % (nameof(self.confirm_with),) if self.cancel_with != DEFAULT: rv += "%s, " % (nameof(self.cancel_with),) rv += "'%s', " % (self.text.encode('string_escape'),) if multiline: rv += "\n%s" % (" " * (pad + 2)) for option in self.options: rv += "%s, " % (option.to_string(False),) if multiline: rv += "\n%s" % (" " * (pad + 2)) rv = rv.strip("\n ,") if multiline: rv += "\n)" else: rv += ")" return rv
def get_button_name(config, button): """ As get_button_icon, but returns icon name instead of filename. """ name = nameof(button) try: index = BUTTON_ORDER.index(button) name = ControllerManager.DEFAULT_ICONS[index] name = config['gui']['buttons'][index] except: pass return name
def button_press(self, mapper): if not self.show_with_release: confirm_with = self.confirm_with cancel_with = self.cancel_with args = [ mapper ] if confirm_with == SAME: confirm_with = mapper.get_pressed_button() or DEFAULT elif confirm_with == DEFAULT: confirm_with = DEFAULT if cancel_with == DEFAULT: cancel_with = DEFAULT if nameof(self.control_with) in (LEFT, RIGHT): args += [ '--use-cursor' ] args += [ '--control-with', nameof(self.control_with), '-x', str(self.x), '-y', str(self.y), '--size', str(self.size), '--confirm-with', nameof(confirm_with), '--cancel-with', nameof(cancel_with) ] self.execute(*args)
def on_clearb_clicked(self, trash, index, button): grActions = self.action_widgets[index][0] cbButtonChooser = self.builder.get_object("cbButtonChooser") model = cbButtonChooser.get_model() # Remove requested action from the list for i in xrange(0, len(self.actions[index])): if self.actions[index][i][0] == button: button, action, l, b, clearb = self.actions[index][i] for w in (l, b, clearb): grActions.remove(w) del self.actions[index][i] break # Move everything after that action one position up # - remove it for j in xrange(i, len(self.actions[index])): button, action, l, b, clearb = self.actions[index][j] for w in (l, b, clearb): grActions.remove(w) # - add it again for j in xrange(i, len(self.actions[index])): button, action, l, b, clearb = self.actions[index][j] grActions.attach(l, 0, j + 1, 1, 1) grActions.attach(b, 1, j + 1, 1, 1) grActions.attach(clearb, 2, j + 1, 1, 1) # Regenereate combobox with removed button added back to it # - Store acive item from in combobox active, i, index = None, 0, -1 try: active = model.get_value(cbButtonChooser.get_active_iter(), 0) except: pass # Clear entire combobox model.clear() # Fill it again for button, text in self.BUTTONS: model.append(( None if button is None else nameof(button), text )) if button is not None: if nameof(button) == active: index = i i += 1 # Reselect formely active item if index >= 0: cbButtonChooser.set_active(index)
def button_press(self, mapper): if not self.show_with_release: if self.confirm_with == SAME: confirm_with = mapper.get_pressed_button( ) or self.DEFAULT_CONFIRM x, y = self.position self.execute(mapper, '--control-with', nameof(self.control_with), '-x', str(self.x), '-y', str(self.y), '--use-cursor', '--confirm-with', confirm_with.name, '--cancel-with', self.cancel_with.name) else: self.execute(mapper, '-x', str(self.x), '-y', str(self.y))
def _fill_button_chooser(self, *a): cbButtonChooser = self.builder.get_object("cbButtonChooser") model = cbButtonChooser.get_model() model.clear() for item, text in self.BUTTONS: if any([x[0] == item for x in self.actions[self.current_page]]): # Skip already added buttons continue if type(item) in (str, unicode): # Special case for soft pull items button = getattr(SCButtons, item.split(" ")[-1]) if any([(isinstance(x, RangeOP) and x.what == button) for x in self.actions[self.current_page]]): # Skip already added soft pulls continue if item == SCButtons.STICKPRESS: if self.id == nameof(SCButtons.LPAD): # Controller cannot handle pressing stick and lpad at once continue model.append((None if item is None else nameof(item), text)) cbButtonChooser.set_active(0)
def whole(self, mapper, x, y, what, *params): if x == 0 and y == 0: # Sent when pad is released - don't display menu then return if self.haptic: params = list(params) + [ "--feedback-amplitude", str(self.haptic.get_amplitude()) ] if what in (LEFT, RIGHT): confirm_with = self.confirm_with cancel_with = self.cancel_with if what == LEFT: if confirm_with == DEFAULT: confirm_with = SCButtons.LPAD if cancel_with == DEFAULT: cancel_with = SCButtons.LPADTOUCH elif what == RIGHT: if confirm_with == DEFAULT: confirm_with = SCButtons.RPAD if cancel_with == DEFAULT: cancel_with = SCButtons.RPADTOUCH else: # Stick if confirm_with == DEFAULT: confirm_with = SCButtons.STICKPRESS if cancel_with == DEFAULT: cancel_with = SCButtons.B if not mapper.was_pressed(cancel_with): self.execute(mapper, '--control-with', what, '-x', str(self.x), '-y', str(self.y), '--use-cursor', '--size', str(self.size), '--confirm-with', nameof(confirm_with), '--cancel-with', nameof(cancel_with), *params) if what == STICK: # Special case, menu is displayed only if is moved enought distance = sqrt(x * x + y * y) if self._stick_distance < MenuAction.MIN_STICK_DISTANCE and distance > MenuAction.MIN_STICK_DISTANCE: self.execute(mapper, '--control-with', STICK, '-x', str(self.x), '-y', str(self.y), '--use-cursor', '--size', str(self.size), '--confirm-with', "STICKPRESS", '--cancel-with', STICK, *params) self._stick_distance = distance
def button_release(self, mapper): confirm_with = self.confirm_with cancel_with = self.cancel_with args = [mapper] if confirm_with == DEFAULT: confirm_with = MenuAction.DEFAULT_CONFIRM if cancel_with == DEFAULT: cancel_with = MenuAction.DEFAULT_CANCEL args += [ '-x', str(self.x), '-y', str(self.y), '--confirm-with', nameof(confirm_with), '--cancel-with', nameof(cancel_with), '--text', self.text, ] for x in self.options: args.append(x) self.execute(*args)
def _fill_button_chooser(self, *a): cbButtonChooser = self.builder.get_object("cbButtonChooser") model = cbButtonChooser.get_model() model.clear() for button, text in self.BUTTONS: if any([ True for x in self.actions[self.current_page] if x[0] == button ]): # Skip already added buttons continue if button == SCButtons.STICKPRESS: if self.id == nameof(SCButtons.LPAD): # Controller cannot handle pressing stick and lpad at once continue model.append(( None if button is None else button.name, text )) cbButtonChooser.set_active(0)
def load_menu_data(self, action): if isinstance(action, PositionModifier): # Load menu position modifier, if used x, y = action.position self.builder.get_object("cbMenuPosX").set_active(0 if x >= 0 else 1) self.builder.get_object("cbMenuPosY").set_active(0 if y >= 0 else 1) self.builder.get_object("spMenuPosX").set_value(abs(x)) self.builder.get_object("spMenuPosY").set_value(abs(y)) action = action.action self._current_menu = action.menu_id cbm = self.builder.get_object("cbMenuType") self.set_cb(cbm, self.menu_class_to_key(action), 1) cbControlWith = self.builder.get_object("cbControlWith") cbConfirmWith = self.builder.get_object("cbConfirmWith") cbCancelWith = self.builder.get_object("cbCancelWith") cbMenuAutoConfirm = self.builder.get_object("cbMenuAutoConfirm") if cbControlWith: self.set_cb(cbControlWith, nameof(action.control_with), 1) self.set_cb(cbConfirmWith, nameof(action.confirm_with), 1) self.set_cb(cbCancelWith, nameof(action.cancel_with), 1) if cbMenuAutoConfirm: cbMenuAutoConfirm.set_active(action.confirm_with == SAME)
def set_input(self, id, action, mode=None): btDefault = self.builder.get_object("btDefault") lblPressAlone = self.builder.get_object("lblPressAlone") cbHoldFeedback = self.builder.get_object("cbHoldFeedback") sclHoldFeedback = self.builder.get_object("sclHoldFeedback") self.id = id self._fill_button_chooser() if id in STICKS: lblPressAlone.set_label(_("(no button pressed)")) self.mode = mode = mode or Action.AC_STICK elif id in PADS: lblPressAlone.set_label(_("(no button pressed)")) self.mode = mode = mode or Action.AC_PAD else: lblPressAlone.set_label(_("(pressed alone)")) self.mode = mode = mode or Action.AC_BUTTON self.set_title("Modeshift for %s" % (nameof(id) if id in SCButtons else str(id), )) if isinstance(action, FeedbackModifier): cbHoldFeedback.set_active(True) sclHoldFeedback.set_value(action.haptic.get_amplitude()) action = action.action else: cbHoldFeedback.set_active(False) sclHoldFeedback.set_value(512) if isinstance(action, ModeModifier): self._load_modemod(0, action) self._set_nomod_button(0, action.default) self._set_nomod_button(1, NoAction()) self._set_nomod_button(2, NoAction()) elif isinstance(action, DoubleclickModifier): # includes HoldModifier self._set_nomod_button(0, action.normalaction) self._set_nomod_button(1, action.holdaction) self._set_nomod_button(2, action.action) self.builder.get_object("adjTime").set_value(action.timeout) if mode == Action.AC_OSK: # This is kinda bad, but allowing Custom Editor # from OSK editor is in TODO self.builder.get_object("btCustomActionEditor").set_visible(False) if mode != Action.AC_BUTTON: for w in ("vbHold", "vbDoubleClick", "lblHold", "lblDoubleClick"): self.builder.get_object(w).set_sensitive(False)
def add(self, icon, context, action): if not action: return LineCollection() if isinstance(action, ModeModifier): lines = [ self.add(icon, context, action.default) ] for x in action.mods: lines.append( self.add(nameof(x), context, action.mods[x]) .add_icon(icon) ) return LineCollection(*lines) elif isinstance(action, DoubleclickModifier): lines = [] if action.normalaction: lines.append( self.add(icon, context, action.normalaction) ) if action.action: lines.append( self.add("DOUBLECLICK", context, action.action) .add_icon(icon) ) if action.holdaction: lines.append( self.add("HOLD", context, action.holdaction) .add_icon(icon) ) return LineCollection(*lines) action = action.strip() if isinstance(action, MenuAction): if self.name == "bcs" and action.menu_id == "Default.menu": # Special case, this action is expected in every profile, # so there is no need to draw it here return LineCollection() elif isinstance(action, DPadAction): return LineCollection( self.add("DPAD_UP", Action.AC_BUTTON, action.actions[0]), self.add("DPAD_DOWN", Action.AC_BUTTON, action.actions[1]), self.add("DPAD_LEFT", Action.AC_BUTTON, action.actions[2]), self.add("DPAD_RIGHT", Action.AC_BUTTON, action.actions[3]) ) elif isinstance(action, XYAction): if isinstance(action.x, MouseAction) and isinstance(action.y, MouseAction): if action.x.get_axis() in (Rels.REL_HWHEEL, Rels.REL_WHEEL): # Special case, pad bound to wheel line = Line(icon, _("Mouse Wheel")) self.lines.append(line) return line return LineCollection( self.add("AXISX", Action.AC_BUTTON, action.x), self.add("AXISY", Action.AC_BUTTON, action.y) ) line = Line(icon, action.describe(context)) self.lines.append(line) return line
def fill_buttons(cb): cb.set_row_separator_func( lambda model, iter : model.get_value(iter, 1) is None ) model = cb.get_model() for button, text in GyroActionComponent.BUTTONS: model.append(( None if button is None else nameof(button), text )) cb.set_active(0)
def _parse_parameter(self): """ Parses single parameter """ t = self._next_token() while t.type == TokenType.NEWLINE or t.value == "\n": if not self._tokens_left(): raise ParseError("Expected parameter at end of string") t = self._next_token() if t.type == TokenType.NAME: # Constant or action used as parameter if self._tokens_left() and self._peek_token( ).type == TokenType.OP and self._peek_token().value == '(': # Action used as parameter self.index -= 1 # go step back and reparse as action parameter = self._parse_action() elif self._tokens_left() and t.value in Action.ALL and type( Action.ALL[ t.value]) == dict and self._peek_token().value == '.': # SOMETHING.Action used as parameter self.index -= 1 # go step back and reparse as action parameter = self._parse_action() else: # Constant if not t.value in ActionParser.CONSTS: raise ParseError( "Expected parameter, got '%s' which is not defined" % (t.value, )) parameter = ActionParser.CONSTS[t.value] # Check for dots while self._tokens_left() and self._peek_token( ).type == TokenType.OP and self._peek_token().value == '.': self._next_token() if not self._tokens_left(): raise ParseError("Expected NAME after '.'") t = self._next_token() if not hasattr(parameter, t.value): raise ParseError("%s has no attribute '%s'" % ( parameter, t.value, )) parameter = getattr(parameter, t.value) # Check for ranges (<, >, <=, >=) if self._tokens_left() and self._peek_token().type == TokenType.OP: if self._peek_token().value in RangeOP.OPS: op = self._next_token().value # TODO: Maybe other axes if parameter not in (STICK, SCButtons.LT, SCButtons.RT, SCButtons.X, SCButtons.Y): raise ParseError("'%s' is not trigger nor axis" % (nameof(parameter), )) if not self._tokens_left(): raise ParseError("Excepted number after '%s'" % (op, )) try: number = float(self._next_token().value) except ValueError: raise ParseError("Excepted number after '%s'" % (op, )) parameter = RangeOP(parameter, op, number) return parameter if t.type == TokenType.OP and t.value == "-": if not self._tokens_left( ) or self._peek_token().type != TokenType.NUMBER: raise ParseError("Expected number after '-'") return -self._parse_number() if t.type == TokenType.NUMBER: self.index -= 1 return self._parse_number() if t.type == TokenType.STRING: return t.value[1:-1].decode('string_escape') raise ParseError("Expected parameter, got '%s'" % (t.value, ))
def set_input(self, id, action, mode=None): """ Setups action editor for editing specified input. Mode (buttton/axis/trigger...) is either provided or chosen based on id. Also sets title, but that can be overriden by calling set_title after. """ self.id = id if id in SCButtons or mode in (Action.AC_MENU, Action.AC_BUTTON): if id in PRESSABLE: self.set_title(_("%s Press") % (nameof(id),)) elif id in SCButtons: self.set_title(nameof(id),) self._set_mode(action, mode or Action.AC_BUTTON) self.hide_sensitivity(0, 1, 2) self.hide_rotation() self.hide_hide_enable_deadzones() self.hide_require_click() self.set_action(action) elif id in TRIGGERS: self.set_title(_("%s Trigger") % (id,)) self._set_mode(action, mode or Action.AC_TRIGGER) self.hide_modifiers() self.set_action(action) self.hide_macro() elif id in STICKS: self.set_title(_("Stick")) self._set_mode(action, mode or Action.AC_STICK) self.hide_sensitivity(2) # Z only self.hide_require_click() self.hide_osd() self.set_action(action) self.hide_macro() self.id = Profile.STICK elif id in GYROS: self.set_title(_("Gyro")) self._set_mode(action, mode or Action.AC_GYRO) self.set_action(action) self.hide_rotation() self.hide_require_click() self.hide_hide_enable_deadzones() self.hide_osd() self.hide_macro() self.hide_modeshift() self.id = Profile.GYRO elif id in PADS: self._set_mode(action, mode or Action.AC_PAD) self.hide_sensitivity(2) # Z only self.set_action(action) self.hide_osd() self.hide_macro() if id == "LPAD": self.set_title(_("Left Pad")) else: self.set_title(_("Right Pad")) if mode == Action.AC_OSK: self.hide_osd() self.hide_name() self.hide_macro() self.hide_modeshift() self.hide_rotation() elif mode == Action.AC_MENU: self.hide_modeshift() self.hide_macro()
from scc.actions import Action, NoAction, MouseAction, MultiAction, RangeOP from scc.actions import GyroAction, GyroAbsAction, MouseAbsAction from scc.special_actions import CemuHookAction from scc.modifiers import ModeModifier, SensitivityModifier from scc.uinput import Axes, Rels from scc.constants import SCButtons, STICK, YAW, ROLL from scc.gui.parser import GuiActionParser from scc.gui.ae import AEComponent from scc.tools import nameof import logging, re log = logging.getLogger("AE.GyroAction") __all__ = ['GyroActionComponent'] TRIGGERS = (nameof(SCButtons.LT), nameof(SCButtons.RT)) 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')),
from scc.tools import _ from scc.actions import Action, NoAction, MouseAction, MultiAction, RangeOP from scc.actions import GyroAction, GyroAbsAction, MouseAbsAction from scc.modifiers import ModeModifier, SensitivityModifier from scc.uinput import Axes, Rels from scc.constants import SCButtons, STICK, YAW, ROLL from scc.gui.parser import GuiActionParser from scc.gui.ae import AEComponent from scc.tools import nameof import logging, re log = logging.getLogger("AE.GyroAction") __all__ = [ 'GyroActionComponent' ] TRIGGERS = ( nameof(SCButtons.LT), nameof(SCButtons.RT) ) 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') ),
def encode(self): rv = Modifier.encode(self) pars = self.strip_defaults() pars[0] = nameof(pars[0]) rv[FeedbackModifier.COMMAND] = pars return rv
def set_input(self, id, action, mode=None): """ Setups action editor for editing specified input. Mode (buttton/axis/trigger...) is either provided or chosen based on id. Also sets title, but that can be overriden by calling set_title after. """ self.id = id if id in SCButtons or mode in (Action.AC_MENU, Action.AC_BUTTON): if id in PRESSABLE: self.set_title(_("%s Press") % (nameof(id),)) elif id in SCButtons: self.set_title(nameof(id),) self._set_mode(action, mode or Action.AC_BUTTON) self.hide_sensitivity(0, 1, 2) self.hide_enable_feedback() self.hide_hide_enable_deadzones() self.hide_require_click() self.set_action(action) elif id in TRIGGERS: self.set_title(_("%s Trigger") % (id,)) self._set_mode(action, mode or Action.AC_TRIGGER) self.hide_sensitivity(1, 2) # YZ self.hide_require_click() self.hide_hide_enable_deadzones() self.hide_osd() self.set_action(action) self.hide_macro() elif id in STICKS: self.set_title(_("Stick")) self._set_mode(action, mode or Action.AC_STICK) self.hide_sensitivity(2) # Z only self.hide_require_click() self.hide_osd() self.set_action(action) self.hide_macro() self.id = Profile.STICK elif id in GYROS: self.set_title(_("Gyro")) self._set_mode(action, mode or Action.AC_GYRO) self.set_action(action) self.hide_require_click() self.hide_hide_enable_deadzones() self.hide_osd() self.hide_macro() self.hide_modeshift() self.id = Profile.GYRO elif id in PADS: self._set_mode(action, mode or Action.AC_PAD) self.hide_sensitivity(2) # Z only self.set_action(action) self.hide_osd() self.hide_macro() if id == "LPAD": self.set_title(_("Left Pad")) else: self.set_title(_("Right Pad")) if mode == Action.AC_OSK: self.hide_osd() self.hide_name() self.hide_macro() self.hide_modeshift() elif mode == Action.AC_MENU: self.hide_modeshift() self.hide_macro()
def load_menu_data(self, action): if isinstance(action, PositionModifier): # Load menu position modifier, if used x, y = action.position self.builder.get_object("cbMenuPosX").set_active( 0 if x >= 0 else 1) self.builder.get_object("cbMenuPosY").set_active( 0 if y >= 0 else 1) self.builder.get_object("spMenuPosX").set_value(abs(x)) self.builder.get_object("spMenuPosY").set_value(abs(y)) action = action.action self._current_menu = action.menu_id cbm = self.builder.get_object("cbMenuType") self.set_cb(cbm, self.menu_class_to_key(action), 1) if self.builder.get_object("rvMenuSize"): spMenuSize = self.builder.get_object("spMenuSize") if self.update_size_display(action): size = spMenuSize.get_adjustment().set_value(action.size) cbControlWith = self.builder.get_object("cbControlWith") cbConfirmWith = self.builder.get_object("cbConfirmWith") cbCancelWith = self.builder.get_object("cbCancelWith") cbMenuAutoConfirm = self.builder.get_object("cbMenuAutoConfirm") cbMenuConfirmWithClick = self.builder.get_object( "cbMenuConfirmWithClick") cbMenuAutoCancel = self.builder.get_object("cbMenuAutoCancel") if cbControlWith: self.set_cb(cbControlWith, nameof(action.control_with), 1) cow = action.confirm_with caw = action.cancel_with if cow == DEFAULT: cow = self.get_default_confirm() if caw == DEFAULT: caw = self.get_default_cancel() if cbConfirmWith: if cow == SAME and cbMenuAutoConfirm: cbMenuAutoConfirm.set_active(True) cbConfirmWith.set_sensitive(False) elif cbMenuConfirmWithClick and cow == self.get_default_confirm(): cbMenuConfirmWithClick.set_active(True) cbConfirmWith.set_sensitive(False) else: if cbMenuAutoConfirm: cbMenuAutoConfirm.set_active(False) if cbMenuConfirmWithClick: cbMenuAutoConfirm.set_active(False) cbConfirmWith.set_sensitive(True) self.set_cb(cbConfirmWith, nameof(cow), 1) if cbCancelWith: if caw == SAME and cbMenuAutoCancel: cbMenuAutoCancel.set_active(True) cbCancelWith.set_sensitive(False) else: if cbMenuAutoCancel: cbMenuAutoCancel.set_active(False) self.set_cb(cbCancelWith, nameof(caw), 1) self.on_cbMenus_changed()
class ControllerImage(SVGWidget): DEFAULT = "sc" BUTTONS_WITH_IMAGES = (SCButtons.A, SCButtons.B, SCButtons.X, SCButtons.Y, SCButtons.BACK, SCButtons.C, SCButtons.START) DEFAULT_AXES = ( # Shared between DS4 and Steam Controller "stick_x", "stick_y", "lpad_x", "lpad_x", "rpad_y", "rpad_y", "ltrig", "rtrig", ) DEFAULT_BUTTONS = [nameof(x) for x in BUTTONS_WITH_IMAGES] + [ # Used only by Steam Controller nameof(SCButtons.LB), nameof(SCButtons.RB), nameof(SCButtons.LT), nameof(SCButtons.RT), nameof(SCButtons.STICKPRESS), nameof(SCButtons.RPAD), nameof(SCButtons.LPAD), nameof(SCButtons.LGRIP), nameof(SCButtons.RGRIP), ] def __init__(self, app, config=None): self.app = app self.current = self._ensure_config({}) filename = self._make_controller_image_path(ControllerImage.DEFAULT) SVGWidget.__init__(self, filename) if config: self._controller_image.use_config(config) def _make_controller_image_path(self, img): return os.path.join(self.app.imagepath, "controller-images/%s.svg" % (img, )) def get_config(self): """ Returns last used config """ return self.current def _ensure_config(self, data): """ Ensure that required keys are present in config data """ data['gui'] = data.get('gui', {}) data['gui']['background'] = data['gui'].get("background", "sc") data['gui']['buttons'] = data['gui'].get( "buttons") or self._get_default_images() data['buttons'] = data.get( "buttons") or ControllerImage.DEFAULT_BUTTONS data['axes'] = data.get("axes") or ControllerImage.DEFAULT_AXES data['gyros'] = data.get("gyros", data['gui']["background"] == "sc") return data @staticmethod def get_names(dict_or_tuple): """ There are three different ways how button and axis names are stored in config. This wrapper provides unified way to get list of them. """ if type(dict_or_tuple) in (list, tuple): return dict_or_tuple return [(x["axis"] if type(x) == dict else x) for x in dict_or_tuple.values()] def use_config(self, config): """ Loads controller settings from provided config, adding default values when needed. Returns same config. """ self.current = self._ensure_config(config or {}) self.set_image( os.path.join( self.app.imagepath, "controller-images/%s.svg" % (self.current["gui"]["background"], ))) self._fill_button_images(self.current["gui"]["buttons"]) self.hilight({}) return self.current def get_button_groups(self): groups = json.loads( open( os.path.join(self.app.imagepath, "button-images", "groups.json"), "r").read()) return { x['key']: x['buttons'] for x in groups if x['type'] == "buttons" } def _get_default_images(self): return self.get_button_groups()[ControllerImage.DEFAULT] def _fill_button_images(self, buttons): e = self.edit() SVGEditor.update_parents(e) target = SVGEditor.get_element(e, "controller") target_x, target_y = SVGEditor.get_translation(target) for i in xrange(len(ControllerImage.BUTTONS_WITH_IMAGES)): b = nameof(ControllerImage.BUTTONS_WITH_IMAGES[i]) try: elm = SVGEditor.get_element(e, "AREA_%s" % (b, )) if elm is None: log.warning("Area for button %s not found", b) continue x, y = SVGEditor.get_translation(elm) scale = 1.0 if "scc-button-scale" in elm.attrib: w, h = SVGEditor.get_size(elm) scale = float(elm.attrib['scc-button-scale']) tw, th = w * scale, h * scale if scale < 1.0: x += (w - tw) * 0.5 y += (h - th) * 0.5 else: x -= (tw - w) * 0.25 y -= (th - h) * 0.25 path = os.path.join(self.app.imagepath, "button-images", "%s.svg" % (buttons[i], )) img = SVGEditor.get_element(SVGEditor.load_from_file(path), "button") img.attrib["transform"] = "translate(%s, %s) scale(%s)" % ( x - target_x, y - target_y, scale) img.attrib["id"] = b SVGEditor.add_element(target, img) except Exception, err: log.warning("Failed to add image for button %s", b) log.exception(err) e.commit()