def _make_action(self): """ Generates and returns Action instance """ cbMode = self.builder.get_object("cbMode") key = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) if key == "inner": return MultiAction( self.actions[1], RingAction(self.radius, self.actions[0], NoAction())) elif key == "outer": return MultiAction( self.actions[0], RingAction(self.radius, NoAction(), self.actions[1])) else: return RingAction(self.radius, *self.actions)
def parse_button(self, bdef, button=None): """ Parses button definition from vdf file. Parameter can be either string, as used in v2, or dict used in v3. """ if type(bdef) == str: # V2 return self.parse_action(bdef, button) elif type(bdef) == list: # V2 return MultiAction.make(*[ self.parse_action(x, button) for x in bdef ]) elif "activators" in bdef: # V3 act_actions = [] for k in ("full_press", "double_press", "long_press"): a = NoAction() if k in bdef["activators"]: # TODO: Handle multiple bindings bindings = ensure_list(bdef["activators"][k])[0] a = self.parse_action(bindings["bindings"]["binding"], button) a = VDFProfile.parse_modifiers(bindings, a, Profile.RIGHT) # holly... act_actions.append(a) normal, double, hold = act_actions if not double and not hold: return normal elif hold and not double: return HoldModifier(hold, normal) else: action = DoubleclickModifier(double, normal) action.holdaction = hold return action else: log.warning("Failed to parse button definition: %s" % (bdef,))
def send(self): actions = [] half_level = int(self.builder.get_object("sclPartialLevel").get_value()) full_level = int(self.builder.get_object("sclFullLevel").get_value()) cb = self.builder.get_object("cbActionType") trigger_style = cb.get_model().get_value(cb.get_active_iter(), 1) timeout = self.builder.get_object("sclTimeOut").get_value() if (trigger_style == "HIPFIRE_NORMAL") and self.half and self.full: actions.append(HipfireAction(half_level, full_level, self.half, self.full, HIPFIRE_NORMAL,timeout)) elif (trigger_style == "HIPFIRE_EXCLUSIVE") and self.half and self.full: actions.append(HipfireAction(half_level, full_level, self.half, self.full, HIPFIRE_EXCLUSIVE,timeout)) elif (trigger_style == "HIPFIRE_SENSIBLE") and self.half and self.full: actions.append(HipfireAction(half_level, full_level, self.half, self.full, HIPFIRE_SENSIBLE,timeout)) else: if self.half: if self.full and trigger_style == "NORMAL_EXCLUSIVE": actions.append(TriggerAction(half_level, full_level, self.half)) else: actions.append(TriggerAction(half_level, TRIGGER_MAX, self.half)) if self.full: actions.append(TriggerAction(full_level, TRIGGER_MAX, self.full)) if self.analog: analog_start = int(self.builder.get_object("sclARangeStart").get_value()) analog_end = int(self.builder.get_object("sclARangeEnd").get_value()) if analog_start == TRIGGER_MIN and analog_end == TRIGGER_MAX: actions.append(self.analog) else: actions.append(TriggerAction(analog_start, analog_end, self.analog)) self.editor.set_action(MultiAction.make(*actions))
def send(self): actions = [] half_level = int( self.builder.get_object("sclPartialLevel").get_value()) full_level = int(self.builder.get_object("sclFullLevel").get_value()) release = self.builder.get_object("cbReleasePartially").get_active() if self.half: if self.full and release: actions.append(TriggerAction(half_level, full_level, self.half)) else: actions.append( TriggerAction(half_level, TRIGGER_MAX, self.half)) if self.full: actions.append(TriggerAction(full_level, TRIGGER_MAX, self.full)) if self.analog: analog_start = int( self.builder.get_object("sclARangeStart").get_value()) analog_end = int( self.builder.get_object("sclARangeEnd").get_value()) if analog_start == TRIGGER_MIN and analog_end == TRIGGER_MAX: actions.append(self.analog) else: actions.append( TriggerAction(analog_start, analog_end, self.analog)) self.editor.set_action(MultiAction.make(*actions))
def send(self, *a): if self._recursing: return cbGyroButton = self.builder.get_object("cbGyroButton") button = cbGyroButton.get_model().get_value( cbGyroButton.get_active_iter(), 0) normal, n_set = [None, None, None], False absolute, a_set = [None, None, None], False for i in xrange(0, 3): if self.axes[i] is not None: if self.cbs[i].get_active(): absolute[i] = self.axes[i] a_set = True else: normal[i] = self.axes[i] n_set = True if n_set and a_set: action = MultiAction(GyroAction(*normal), GyroAbsAction(*absolute)) elif n_set: action = GyroAction(*normal) elif a_set: action = GyroAbsAction(*absolute) else: action = NoAction() if button and action: action = ModeModifier(getattr(SCButtons, button), action) self.editor.set_action(action)
def on_key_grabbed(self, keys): """ Handles selecting key using "Grab the Key" dialog """ action = ButtonAction(keys[0]) if len(keys) > 1: actions = [ButtonAction(k) for k in keys] action = MultiAction(*actions) self.editor.set_action(action)
def apply_keys(self): """ Common part of on_*key_grabbed """ keys = list(self.keys) action = ButtonAction(keys[0]) if len(keys) > 1: actions = [ButtonAction(k) for k in keys] action = MultiAction(*actions) self.editor.set_action(action)
def add_by_binding(self, binding, action): """ As set_by_binding, but if there is alrady action for specified binding set, creates MultiAction. """ old = self.get_by_binding(binding) new = MultiAction.make(old, action) if isinstance(new, MultiAction): new = new.deduplicate() self.set_by_binding(binding, new)
def apply_keys(self, *a): """ Common part of on_*key_grabbed """ cbToggle = self.builder.get_object("cbToggle") keys = list(sorted(self.keys, key=ButtonsComponent.modifiers_first)) action = ButtonAction(keys[0]) if len(keys) > 1: actions = [ButtonAction(k) for k in keys] action = MultiAction(*actions) if cbToggle.get_active(): action = Cycle(PressAction(action), ReleaseAction(action)) self.editor.set_action(action)
def 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 send(self, *a): if self._recursing: return rvSoftLevel = self.builder.get_object("rvSoftLevel") sclSoftLevel = self.builder.get_object("sclSoftLevel") cbGyroButton = self.builder.get_object("cbGyroButton") cbInvertGyro = self.builder.get_object("cbInvertGyro") item = cbGyroButton.get_model().get_value( cbGyroButton.get_active_iter(), 0) rvSoftLevel.set_reveal_child(item in TRIGGERS) normal, n_set = [None, None, None], False absolute, a_set = [None, None, None], False for i in xrange(0, 3): if self.axes[i] is not None: if self.cbs[i].get_active(): absolute[i] = self.axes[i] a_set = True else: normal[i] = self.axes[i] n_set = True if n_set and a_set: action = MultiAction(GyroAction(*normal), GyroAbsAction(*absolute)) elif n_set: action = GyroAction(*normal) elif a_set: action = GyroAbsAction(*absolute) else: action = NoAction() if item and action: what = getattr(SCButtons, item) if item in TRIGGERS: what = RangeOP(what, ">=", sclSoftLevel.get_value()) if cbInvertGyro.get_active(): action = ModeModifier(what, NoAction(), action) else: action = ModeModifier(what, action) self.editor.set_action(action)
def send(self): actions = [] half_level = int(self.builder.get_object("sclPartialLevel").get_value()) full_level = int(self.builder.get_object("sclFullLevel").get_value()) release = self.builder.get_object("cbReleasePartially").get_active() if self.half: if self.full and release: actions.append(TriggerAction(half_level, full_level, self.half)) else: actions.append(TriggerAction(half_level, TRIGGER_MAX, self.half)) if self.full: actions.append(TriggerAction(full_level, TRIGGER_MAX, self.full)) if self.analog: analog_start = int(self.builder.get_object("sclARangeStart").get_value()) analog_end = int(self.builder.get_object("sclARangeEnd").get_value()) if analog_start == TRIGGER_MIN and analog_end == TRIGGER_MAX: actions.append(self.analog) else: actions.append(TriggerAction(analog_start, analog_end, self.analog)) self.editor.set_action(MultiAction.make(*actions))
def area_action_selected(self, area, action): if area: self.set_active_area(area) if self.full: action = MultiAction(ButtonAction(None, self.full), action) self.editor.set_action(action)
def parse_group(self, group, side): """ Parses output (group) from vdf profile. Returns Action. """ if not "mode" in group: raise ParseError("Group without mode") mode = group["mode"] inputs = VDFProfile.get_inputs(group) settings = group["settings"] if "settings" in group else {} for o in ("output_trigger", "output_joystick"): if o in settings: if int(settings[o]) <= 1: side = Profile.LEFT else: side = Profile.RIGHT if mode == "dpad": keys = [] for k in ("dpad_north", "dpad_south", "dpad_east", "dpad_west"): if k in inputs: keys.append(self.parse_button(inputs[k])) else: keys.append(NoAction()) action = DPadAction(*keys) elif mode == "four_buttons": keys = [] for k in ("button_y", "button_a", "button_x", "button_b"): if k in inputs: keys.append(self.parse_button(inputs[k])) else: keys.append(NoAction()) action = DPadAction(*keys) elif mode == "joystick_move": if side == Profile.LEFT: # Left action = XYAction(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y)) else: # Right action = XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY)) elif mode == "joystick_camera": output_joystick = 0 if 'output_joystick' in settings: output_joystick = int(settings['output_joystick']) if output_joystick == 0: action = BallModifier(XYAction(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y))) elif output_joystick == 1: action = BallModifier(XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY))) else: # TODO: Absolute mouse? Doesn't seems to do anything in Steam action = BallModifier(SensitivityModifier(0.1, 0.1, MouseAction())) elif mode == "mouse_joystick": action = BallModifier(XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY))) elif mode == "scrollwheel": action = BallModifier(XYAction(MouseAction(Rels.REL_HWHEEL), MouseAction(Rels.REL_WHEEL))) elif mode == "touch_menu": # Touch menu is converted to GridMenu items = [] next_item_id = 1 for k in inputs: action = self.parse_button(inputs[k]) items.append(MenuItem( "item_%s" % (next_item_id,), action.describe(Action.AC_BUTTON), action )) next_item_id += 1 # Menu is stored in profile, with generated ID menu_id = "menu_%s" % (self.next_menu_id,) self.next_menu_id += 1 self.menus[menu_id] = MenuData(*items) action = GridMenuAction(menu_id, 'LEFT' if side == Profile.LEFT else 'RIGHT', SCButtons.LPAD if side == Profile.LEFT else SCButtons.RPAD ) elif mode == "absolute_mouse": if "click" in inputs: if side == Profile.LEFT: self.add_by_binding(SCButtons.LPAD, self.parse_button(inputs["click"])) else: self.add_by_binding(SCButtons.RPAD, self.parse_button(inputs["click"])) if "gyro_axis" in settings: if int(settings["gyro_axis"]) == 1: action = MouseAction(ROLL) else: action = MouseAction(YAW) else: action = MouseAction() elif mode == "mouse_wheel": action = BallModifier(XYAction(MouseAction(Rels.REL_HWHEEL), ouseAction(Rels.REL_WHEEL))) elif mode == "trigger": actions = [] if "click" in inputs: actions.append(TriggerAction(TRIGGER_CLICK, self.parse_button(inputs["click"]))) if side == Profile.LEFT: actions.append(AxisAction(Axes.ABS_Z)) else: actions.append(AxisAction(Axes.ABS_RZ)) action = MultiAction.make(*actions) elif mode == "mouse_region": # Read value and assume dafaults scale = float(settings["scale"]) if "scale" in settings else 100.0 x = float(settings["position_x"]) if "position_x" in settings else 50.0 y = float(settings["position_y"]) if "position_y" in settings else 50.0 w = float(settings["sensitivity_horiz_scale"]) if "sensitivity_horiz_scale" in settings else 100.0 h = float(settings["sensitivity_vert_scale"]) if "sensitivity_vert_scale" in settings else 100.0 # Apply scale w = w * scale / 100.0 h = h * scale / 100.0 # Convert to (0, 1) range x, y = x / 100.0, 1.0 - (y / 100.0) w, h = w / 100.0, h / 100.0 # Convert to rectangle x1 = max(0.0, x - (w * VDFProfile.REGION_IMPORT_FACTOR)) x2 = min(1.0, x + (w * VDFProfile.REGION_IMPORT_FACTOR)) y1 = max(0.0, y - (h * VDFProfile.REGION_IMPORT_FACTOR)) y2 = min(1.0, y + (h * VDFProfile.REGION_IMPORT_FACTOR)) action = RelAreaAction(x1, y1, x2, y2) else: raise ParseError("Unknown mode: '%s'" % (group["mode"],)) action = VDFProfile.parse_modifiers(group, action, side) return action
def _convert(self, from_version): """ Performs conversion from older profile version """ if from_version < 1: from scc.modifiers import ModeModifier # Add 'display Default.menu if center button is held' for old profiles c = self.buttons[SCButtons.C] if not c: # Nothing set to C button self.buttons[SCButtons.C] = HoldModifier( MenuAction("Default.menu"), normalaction=MenuAction("Default.menu")) elif hasattr(c, "holdaction") and c.holdaction: # Already set to something, don't overwrite it pass elif c.to_string().startswith("OSK."): # Special case, don't touch this either pass else: self.buttons[SCButtons.C] = HoldModifier( MenuAction("Default.menu"), normalaction=self.buttons[SCButtons.C]) if from_version < 1.1: # Convert old scrolling wheel to new representation from scc.modifiers import FeedbackModifier, BallModifier from scc.actions import MouseAction, XYAction from scc.uinput import Rels iswheelaction = ( lambda x: isinstance(x, MouseAction) and x.parameters[0] in (Rels.REL_HWHEEL, Rels.REL_WHEEL)) for p in (Profile.LEFT, Profile.RIGHT): a, feedback = self.pads[p], None if isinstance(a, FeedbackModifier): feedback = a.haptic.get_position() a = a.action if isinstance(a, XYAction): if iswheelaction(a.x) or iswheelaction(a.y): n = BallModifier(XYAction(a.x, a.y)) if feedback is not None: n = FeedbackModifier(feedback, 4096, 16, n) self.pads[p] = n log.info("Converted %s to %s", a.to_string(), n.to_string()) if from_version < 1.2: # Convert old trigger settings that were done with ButtonAction # to new TriggerAction from scc.constants import TRIGGER_HALF, TRIGGER_MAX, TRIGGER_CLICK from scc.actions import ButtonAction, TriggerAction, MultiAction from scc.uinput import Keys for p in (Profile.LEFT, Profile.RIGHT): if isinstance(self.triggers[p], ButtonAction): buttons, numbers = [], [] n = None # There were one or two keys and zero to two numeric # parameters for old button action for param in self.triggers[p].parameters: if param in Keys: buttons.append(param) elif type(param) in (int, float): numbers.append(int(param)) if len(numbers) == 0: # Trigger range was not specified, assume defaults numbers = (TRIGGER_HALF, TRIGGER_CLICK) elif len(numbers) == 1: # Only lower range was specified, add default upper range numbers.append(TRIGGER_CLICK) if len(buttons) == 1: # If only one button was set, trigger should work like # one big button n = TriggerAction(numbers[0], ButtonAction(buttons[0])) elif len(buttons) == 2: # Both buttons were set n = MultiAction( TriggerAction(numbers[0], numbers[1], ButtonAction(buttons[0])), TriggerAction(numbers[1], TRIGGER_MAX, ButtonAction(buttons[1]))) if n: log.info("Converted %s to %s", self.triggers[p].to_string(), n.to_string()) self.triggers[p] = n
def parse_action(self, lst_or_str, button=None): """ Parses action from vdf file. a_string can be either string or list of strings, in which case MultiAction is returned. Returns Action instance or ParseError if action is not recognized. """ if type(lst_or_str) == list: return MultiAction.make(*[ self.parse_action(x) for x in lst_or_str ]) # Split string into binding type, name and parameters binding, params = lst_or_str.split(" ", 1) if "," in params: params, name = params.split(",", 1) else: params, name = params, None params = params.split(" ") if name: name = name.strip() # Return apropriate Action for binding type if binding in ("key_press", "mouse_button"): if binding == "mouse_button": b = VDFProfile.convert_button_name(params[0]) else: b = VDFProfile.convert_key_name(params[0]) return ButtonAction(b).set_name(name) elif binding == "xinput_button": # Special cases, as dpad is apparently button on Windows b = params[0].strip().lower() if b == "dpad_up": return HatUpAction(Axes.ABS_HAT0Y) elif b == "dpad_down": return HatDownAction(Axes.ABS_HAT0Y) elif b == "dpad_left": return HatLeftAction(Axes.ABS_HAT0X) elif b == "dpad_right": return HatRightAction(Axes.ABS_HAT0X) elif b == "trigger_left": return AxisAction(Axes.ABS_Z) elif b == "trigger_right": return AxisAction(Axes.ABS_RZ) else: b = VDFProfile.convert_button_name(b) return ButtonAction(b).set_name(name) elif binding in ("mode_shift"): if button is None: log.warning("Ignoring modeshift assigned to no button: '%s'" % (lst_or_str,)) return NoAction() if button not in VDFProfile.BUTTON_TO_BUTTON: log.warning("Ignoring modeshift assigned to unknown button: '%s'" % (button,)) return NoAction() self.modeshift_buttons[VDFProfile.BUTTON_TO_BUTTON[button]] = ( params[1], params[0] ) return NoAction() elif binding in ("controller_action"): if params[0] == "CHANGE_PRESET": id = int(params[1]) - 1 cpa = ChangeProfileAction("action_set:%s" % (id,)) self.action_set_switches.add(cpa) return cpa log.warning("Ignoring controller_action '%s' binding" % (params[0],)) return NoAction() elif binding == "mouse_wheel": if params[0].lower() == "scroll_down": return MouseAction(Rels.REL_WHEEL, -1) else: return MouseAction(Rels.REL_WHEEL, 1) elif binding == "game_action": log.warning("Ignoring game_action binding: '%s'" % (lst_or_str,)) return NoAction() else: raise ParseError("Unknown binding: '%s'" % (binding,))
def parse_action(self, lst_or_str, button=None): """ Parses action from vdf file. a_string can be either string or list of strings, in which case MultiAction is returned. Returns Action instance or ParseError if action is not recognized. """ if type(lst_or_str) == list: return MultiAction.make( *[self.parse_action(x) for x in lst_or_str]) # Split string into binding type, name and parameters binding, params = lst_or_str.split(" ", 1) if "," in params: params, name = params.split(",", 1) else: params, name = params, None params = params.split(" ") if name: name = name.strip() # Return apropriate Action for binding type if binding in ("key_press", "mouse_button"): if binding == "mouse_button": b = VDFProfile.convert_button_name(params[0]) else: b = VDFProfile.convert_key_name(params[0]) return ButtonAction(b).set_name(name) elif binding == "xinput_button": # Special cases, as dpad is apparently button on Windows b = params[0].strip().lower() if b == "dpad_up": return HatUpAction(Axes.ABS_HAT0Y) elif b == "dpad_down": return HatDownAction(Axes.ABS_HAT0Y) elif b == "dpad_left": return HatLeftAction(Axes.ABS_HAT0X) elif b == "dpad_right": return HatRightAction(Axes.ABS_HAT0X) elif b == "trigger_left": return AxisAction(Axes.ABS_Z) elif b == "trigger_right": return AxisAction(Axes.ABS_RZ) else: b = VDFProfile.convert_button_name(b) return ButtonAction(b).set_name(name) elif binding in ("mode_shift"): if button is None: log.warning("Ignoring modeshift assigned to no button: '%s'" % (lst_or_str, )) return NoAction() if button not in VDFProfile.BUTTON_TO_BUTTON: log.warning( "Ignoring modeshift assigned to unknown button: '%s'" % (button, )) return NoAction() self.modeshift_buttons[VDFProfile.BUTTON_TO_BUTTON[button]] = ( params[1], params[0]) return NoAction() elif binding in ("controller_action"): if params[0] == "CHANGE_PRESET": id = int(params[1]) - 1 cpa = ChangeProfileAction("action_set:%s" % (id, )) self.action_set_switches.add(cpa) return cpa log.warning("Ignoring controller_action '%s' binding" % (params[0], )) return NoAction() elif binding == "mouse_wheel": if params[0].lower() == "scroll_down": return MouseAction(Rels.REL_WHEEL, -1) else: return MouseAction(Rels.REL_WHEEL, 1) else: raise ParseError("Unknown binding: '%s'" % (binding, ))
def parse_group(self, group, side): """ Parses output (group) from vdf profile. Returns Action. """ if not "mode" in group: raise ParseError("Group without mode") mode = group["mode"] inputs = VDFProfile.get_inputs(group) settings = group["settings"] if "settings" in group else {} for o in ("output_trigger", "output_joystick"): if o in settings: if int(settings[o]) <= 1: side = Profile.LEFT else: side = Profile.RIGHT if mode == "dpad": keys = [] for k in ("dpad_north", "dpad_south", "dpad_east", "dpad_west"): if k in inputs: keys.append(self.parse_button(inputs[k])) else: keys.append(NoAction()) action = DPadAction(*keys) elif mode == "four_buttons": keys = [] for k in ("button_y", "button_a", "button_x", "button_b"): if k in inputs: keys.append(self.parse_button(inputs[k])) else: keys.append(NoAction()) action = DPadAction(*keys) elif mode == "joystick_move": if side == Profile.LEFT: # Left action = XYAction(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y)) else: # Right action = XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY)) elif mode == "joystick_camera": output_joystick = 0 if 'output_joystick' in settings: output_joystick = int(settings['output_joystick']) if output_joystick == 0: action = BallModifier( XYAction(AxisAction(Axes.ABS_X), AxisAction(Axes.ABS_Y))) elif output_joystick == 1: action = BallModifier( XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY))) else: # TODO: Absolute mouse? Doesn't seems to do anything in Steam action = BallModifier( SensitivityModifier(0.1, 0.1, MouseAction())) elif mode == "mouse_joystick": action = BallModifier( XYAction(AxisAction(Axes.ABS_RX), AxisAction(Axes.ABS_RY))) elif mode == "scrollwheel": action = BallModifier( XYAction(MouseAction(Rels.REL_HWHEEL), MouseAction(Rels.REL_WHEEL))) elif mode == "touch_menu": # Touch menu is converted to GridMenu items = [] next_item_id = 1 for k in inputs: action = self.parse_button(inputs[k]) items.append( MenuItem("item_%s" % (next_item_id, ), action.describe(Action.AC_BUTTON), action)) next_item_id += 1 # Menu is stored in profile, with generated ID menu_id = "menu_%s" % (self.next_menu_id, ) self.next_menu_id += 1 self.menus[menu_id] = MenuData(*items) action = GridMenuAction( menu_id, 'LEFT' if side == Profile.LEFT else 'RIGHT', SCButtons.LPAD if side == Profile.LEFT else SCButtons.RPAD) elif mode == "absolute_mouse": if "click" in inputs: if side == Profile.LEFT: self.add_by_binding(SCButtons.LPAD, self.parse_button(inputs["click"])) else: self.add_by_binding(SCButtons.RPAD, self.parse_button(inputs["click"])) if "gyro_axis" in settings: if int(settings["gyro_axis"]) == 1: action = MouseAction(ROLL) else: action = MouseAction(YAW) else: action = MouseAction() elif mode == "mouse_wheel": action = BallModifier( XYAction(MouseAction(Rels.REL_HWHEEL), ouseAction(Rels.REL_WHEEL))) elif mode == "trigger": actions = [] if "click" in inputs: actions.append( TriggerAction(TRIGGER_CLICK, self.parse_button(inputs["click"]))) if side == Profile.LEFT: actions.append(AxisAction(Axes.ABS_Z)) else: actions.append(AxisAction(Axes.ABS_RZ)) action = MultiAction.make(*actions) elif mode == "mouse_region": # Read value and assume dafaults scale = float(settings["scale"]) if "scale" in settings else 100.0 x = float( settings["position_x"]) if "position_x" in settings else 50.0 y = float( settings["position_y"]) if "position_y" in settings else 50.0 w = float(settings["sensitivity_horiz_scale"] ) if "sensitivity_horiz_scale" in settings else 100.0 h = float(settings["sensitivity_vert_scale"] ) if "sensitivity_vert_scale" in settings else 100.0 # Apply scale w = w * scale / 100.0 h = h * scale / 100.0 # Convert to (0, 1) range x, y = x / 100.0, 1.0 - (y / 100.0) w, h = w / 100.0, h / 100.0 # Convert to rectangle x1 = max(0.0, x - (w * VDFProfile.REGION_IMPORT_FACTOR)) x2 = min(1.0, x + (w * VDFProfile.REGION_IMPORT_FACTOR)) y1 = max(0.0, y - (h * VDFProfile.REGION_IMPORT_FACTOR)) y2 = min(1.0, y + (h * VDFProfile.REGION_IMPORT_FACTOR)) action = RelAreaAction(x1, y1, x2, y2) else: raise ParseError("Unknown mode: '%s'" % (group["mode"], )) action = VDFProfile.parse_modifiers(group, action, side) return action
def _parse_action(self, frm=Action.ALL): """ Parses one action, that is one of: - something(params) - something() - something """ # Check if next token is TokenType.NAME and grab action name from it t = self._next_token() if t.type != TokenType.NAME: raise ParseError("Expected action name, got '%s'" % (t.value, )) if t.value not in frm: raise ParseError("Unknown action '%s'" % (t.value, )) action_name = t.value action_class = frm[action_name] # Check if there are any tokens left - return action without parameters # if not if not self._tokens_left(): return self._create_action(action_class) # Check if token after action name is parenthesis and if yes, parse # parameters from it t = self._peek_token() parameters = [] if t.type == TokenType.OP and t.value == '.': # ACTION dict can have nested dicts; SOMETHING.action if type(action_class) == dict: self._next_token() return self._parse_action(action_class) else: raise ParseError("Unexpected '.' after '%s'" % (action_name, )) if t.type == TokenType.OP and t.value == '(': parameters = self._parse_parameters() if not self._tokens_left(): return self._create_action(action_class, *parameters) t = self._peek_token() # ... or, if it is one of ';', 'and' or 'or' and if yes, parse next action if t.type == TokenType.NAME and t.value == 'and': # Two (or more) actions joined by 'and' self._next_token() if not self._tokens_left(): raise ParseError("Expected action after 'and'") action1 = self._create_action(action_class, *parameters) action2 = self._parse_action() return MultiAction(action1, action2) if t.type == TokenType.NEWLINE or t.value == "\n": # Newline can be used to join actions instead of 'and' self._next_token() if not self._tokens_left(): # Newline at end of string is not error return self._create_action(action_class, *parameters) t = self._peek_token() if t.type == TokenType.OP and t.value in (')', ','): # ')' starts next line return self._create_action(action_class, *parameters) action1 = self._create_action(action_class, *parameters) action2 = self._parse_action() return MultiAction(action1, action2) if t.type == TokenType.OP and t.value == ';': # Two (or more) actions joined by ';' self._next_token() while self._tokens_left() and self._peek_token( ).type == TokenType.NEWLINE: self._next_token() if not self._tokens_left(): # Having ';' at end of string is not actually error return self._create_action(action_class, *parameters) action1 = self._create_action(action_class, *parameters) action2 = self._parse_action() return Macro(action1, action2) return self._create_action(action_class, *parameters)