Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
	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,))
Ejemplo n.º 3
0
	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))
Ejemplo n.º 4
0
    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))
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
	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)
Ejemplo n.º 10
0
 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)
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
	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))
Ejemplo n.º 14
0
	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)
Ejemplo n.º 15
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
Ejemplo n.º 16
0
    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
Ejemplo n.º 17
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)
		elif binding == "game_action":
			log.warning("Ignoring game_action binding: '%s'" % (lst_or_str,))
			return NoAction()

		else:
			raise ParseError("Unknown binding: '%s'" % (binding,))
Ejemplo n.º 18
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, ))
Ejemplo n.º 19
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
Ejemplo n.º 20
0
    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)