Esempio n. 1
0
	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()
Esempio n. 2
0
    def test_ball(self):
        """
		Tests if BallModifier can be converted to string and parsed
		back to same.
		"""
        assert _parses_as_itself(BallModifier(AxisAction(Axes.ABS_X)))
        assert _parses_as_itself(BallModifier(MouseAction()))
Esempio n. 3
0
 def __init__(self, *params):
     # Piece of backwards compatibility
     if len(params) >= 1 and params[0] in Rels:
         params = [MouseAction(params[0])]
     self._haptic_counter = 0
     Modifier.__init__(self, *params)
     HapticEnabledAction.__init__(self)
Esempio n. 4
0
    def test_feedback(self):
        """
		Tests if FeedbackModifier can be converted to string and parsed
		back to same.
		"""
        assert _parses_as_itself(
            FeedbackModifier(HapticPos.BOTH, MouseAction()))
        assert _parses_as_itself(
            FeedbackModifier(HapticPos.BOTH, 10, MouseAction()))
        assert _parses_as_itself(
            FeedbackModifier(HapticPos.BOTH, 10, 8, MouseAction()))
        assert _parses_as_itself(
            FeedbackModifier(HapticPos.BOTH, 10, 8, 512, MouseAction()))
        # Bellow was failing in past
        assert _parses_as_itself(
            FeedbackModifier(HapticPos.LEFT, MouseAction()))
        assert _parses_as_itself(
            FeedbackModifier(HapticPos.RIGHT, MouseAction()))
Esempio n. 5
0
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)
Esempio n. 6
0
    def test_rotate(self):
        """
		Tests if RotateInputModifier can be converted to string and parsed
		back to same.
		"""
        assert _parses_as_itself(RotateInputModifier(61, MouseAction()))
Esempio n. 7
0
    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, ))
Esempio n. 8
0
    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
Esempio n. 9
0
 def __init__(self, *params):
     # Piece of backwards compatibility
     if len(params) >= 1 and params[0] in Rels:
         params = [MouseAction(params[0])]
     Modifier.__init__(self, *params)
     WholeHapticAction.__init__(self)