コード例 #1
0
	def on_link(self, link):
		parser = GuiActionParser()
		if link.startswith("quick://"):
			action = parser.restart(link[8:]).parse()
			self.reset_active_component()
			self.set_action(action, from_custom=True)
		elif link == "grab://trigger_button":
			def cb(action):
				action = TriggerAction(254, 255, action)
				self.set_action(action, from_custom=True)
				self.force_page("trigger")
			b = SimpleChooser(self.app, "buttons", cb)
			b.set_title(_("Select Button"))
			b.hide_axes()
			b.show(self.window)
		elif link.startswith("page://"):
			def cb():
				self.force_page(link[7:])
			GLib.timeout_add(0.1, cb)
		elif link.startswith("advanced://"):
			exMore = self.builder.get_object("exMore")
			rvMore = self.builder.get_object("rvMore")
			ntbMore = self.builder.get_object("ntbMore")
			assert exMore.get_visible()
			exMore.set_expanded(True)
			rvMore.set_reveal_child(True)
			if "#" in link:
				link, name = link.split("#")
				self.blink_widget(name)
			ntbMore.set_current_page(int(link.split("/")[-1]))
		else:
			log.warning("Activated unknown link: %s", link)
コード例 #2
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.parser = GuiActionParser()
コード例 #3
0
 def on_cbTriggersAction_changed(self, cb):
     if self._recursing: return
     key = cb.get_model().get_value(cb.get_active_iter(), 1)
     l, r = key.split("|")
     profile = self._load_osk_profile()
     profile.triggers[LEFT] = GuiActionParser().restart(l).parse()
     profile.triggers[RIGHT] = GuiActionParser().restart(r).parse()
     self._save_osk_profile(profile)
コード例 #4
0
ファイル: axis_action.py プロジェクト: soekul/sc-controller
	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()
コード例 #5
0
	def load_osk(self):
		cbStickAction = self.builder.get_object("cbStickAction")
		cbTriggersAction = self.builder.get_object("cbTriggersAction")
		profile = Profile(GuiActionParser())
		profile.load(find_profile(OSDKeyboard.OSK_PROF_NAME))
		self._recursing = True
		
		# Load triggers
		triggers = "%s|%s" % (
				profile.triggers[LEFT].to_string(),
				profile.triggers[RIGHT].to_string()
		)
		if not self.set_cb(cbTriggersAction, triggers, keyindex=1):
			self.add_custom(cbTriggersAction, triggers)
		
		# Load stick
		if not self.set_cb(cbStickAction, profile.stick.to_string(), keyindex=1):
			self.add_custom(cbStickAction, profile.stick.to_string())
		
		# Load sensitivity
		s = profile.pads[LEFT].compress().speed
		self.builder.get_object("sclSensX").set_value(s[0])
		self.builder.get_object("sclSensY").set_value(s[1])
		
		self._recursing = False
コード例 #6
0
ファイル: app.py プロジェクト: frankjardel/sc-controller
	def enable_osd_mode(self):
		# TODO: Support for multiple controllers here
		self.osd_mode_controller = 0
		osd_mode_profile = Profile(GuiActionParser())
		osd_mode_profile.load(find_profile(App.OSD_MODE_PROF_NAME))
		try:
			c = self.dm.get_controllers()[self.osd_mode_controller]
		except IndexError:
			log.error("osd_mode: Controller not connected")
			self.quit()
			return
		
		def on_lock_failed(*a):
			log.error("osd_mode: Locking failed")
			self.quit()
		
		def on_lock_success(*a):
			log.debug("osd_mode: Locked everything")
			from scc.gui.osd_mode_mapper import OSDModeMapper
			self.osd_mode_mapper = OSDModeMapper(osd_mode_profile)
			self.osd_mode_mapper.set_target_window(self.window.get_window())
			GLib.timeout_add(10, self.osd_mode_mapper.run_scheduled)
		
		# Locks everything but pads. Pads are emulating mouse and this is
		# better left in daemon - involving socket in mouse controls
		# adds too much lags.
		c.lock(on_lock_success, on_lock_failed,
			'A', 'B', 'X', 'Y', 'START', 'BACK', 'LB', 'RB', 'C', 'LPAD', 'RPAD',
			'STICK', 'LGRIP', 'RGRIP', 'LT', 'RT', 'STICKPRESS')
		
		# Ask daemon to temporaly reconfigure pads for mouse emulation
		c.replace(DaemonManager.nocallback, on_lock_failed,
			LEFT, osd_mode_profile.pads[LEFT])
		c.replace(DaemonManager.nocallback, on_lock_failed,
			RIGHT, osd_mode_profile.pads[RIGHT])
コード例 #7
0
ファイル: axis_action.py プロジェクト: wendeldr/sc-controller
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		TimerManager.__init__(self)
		self._recursing = False
		self.relative_area = False
		self.osd_area_instance = None
		self.parser = GuiActionParser()
コード例 #8
0
 def __init__(self, app):
     BindingEditor.__init__(self, app)
     self.app = app
     self.gladepath = app.gladepath
     self.imagepath = app.imagepath
     self.current = Profile(GuiActionParser())
     self.current.load(find_profile(OSDKeyboard.OSK_PROF_NAME))
     self.setup_widgets()
コード例 #9
0
    def _load_osk_profile(self):
        """
		Loads and returns on-screen keyboard profile.
		Used by methods that are changing it.
		"""
        profile = Profile(GuiActionParser())
        profile.load(find_profile(OSDKeyboard.OSK_PROF_NAME))
        return profile
コード例 #10
0
    def load_profile(self, giofile):
        """
		Loads profile from 'giofile' into 'profile' object
		Calls on_profiles_loaded when done
		"""
        # This may get asynchronous later, but that load runs under 1ms...
        profile = Profile(GuiActionParser())
        profile.load(giofile.get_path())
        self.on_profile_loaded(profile, giofile)
コード例 #11
0
ファイル: axis_action.py プロジェクト: kozec/sc-controller
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		TimerManager.__init__(self)
		self._recursing = False
		self.relative_area = False
		self.osd_area_instance = None
		self.on_wayland = False
		self.circular_axis = MouseAction(Rels.REL_WHEEL)
		self.circular_buttons = [ None, None ]
		self.button = None
		self.parser = GuiActionParser()
コード例 #12
0
ファイル: custom.py プロジェクト: wendeldr/sc-controller
class CustomActionComponent(AEComponent):
	GLADE = "ae/custom.glade"
	NAME = "custom"
	PRIORITY = -1
	CTXS = Action.AC_ALL
	
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		self.parser = GuiActionParser()
	
	
	def handles(self, mode, action):
		# Custom Action Editor handles all actions"
		return isinstance(action, Action)
	
	
	def get_button_title(self):
		return _("Custom Action")
	
	
	def load(self):
		if self.loaded : return
		AEComponent.load(self)
		try:
			txCustomAction = self.builder.get_object("txCustomAction")
			txCustomAction.set_monospace(True)
		except: pass
	
	
	def set_action(self, mode, action):
		action = self.editor.generate_modifiers(action)
		tbCustomAction = self.builder.get_object("tbCustomAction")
		tbCustomAction.set_text(action.to_string(True))
	
	
	def on_tbCustomAction_changed(self, tbCustomAction, *a):
		"""
		Converts text from Custom Action text area into action instance and
		sends that instance back to editor.
		"""
		txCustomAction = self.builder.get_object("txCustomAction")
		txt = tbCustomAction.get_text(tbCustomAction.get_start_iter(), tbCustomAction.get_end_iter(), True)
		if len(txt.strip(" \t\r\n")) > 0:
			action = self.parser.restart(txt).parse()
			self.editor.set_action(action)
	
	
	def shown(self):
		self.editor.set_modifiers_enabled(False)
	
	
	def hidden(self):
		self.editor.set_modifiers_enabled(True)
コード例 #13
0
ファイル: app.py プロジェクト: frankjardel/sc-controller
	def on_mnuPaste_activate(self, *a):
		"""
		Handler for 'Paste' context menu item.
		Reads string from clipboard, parses it as action and sets that action
		on selected input.
		"""
		clp = Gtk.Clipboard.get_default(Gdk.Display.get_default())
		text = clp.wait_for_text()
		if text:
			a = GuiActionParser().restart(text.decode('utf-8')).parse()
			if not isinstance(a, InvalidAction):
				self.on_action_chosen(self.context_menu_for, a)
コード例 #14
0
class CustomActionComponent(AEComponent):
    GLADE = "ae/custom.glade"
    NAME = "custom"
    PRIORITY = -1
    CTXS = Action.AC_ALL

    def __init__(self, app, editor):
        AEComponent.__init__(self, app, editor)
        self.parser = GuiActionParser()

    def handles(self, mode, action):
        # Custom Action Editor handles all actions
        return isinstance(action, Action)

    def get_button_title(self):
        return _("Custom Action")

    def load(self):
        if self.loaded: return
        AEComponent.load(self)
        try:
            txCustomAction = self.builder.get_object("txCustomAction")
            txCustomAction.set_monospace(True)
        except:
            pass

    def set_action(self, mode, action):
        action = self.editor.generate_modifiers(action, from_custom=True)
        tbCustomAction = self.builder.get_object("tbCustomAction")
        tbCustomAction.set_text(action.to_string(True))

    def on_tbCustomAction_changed(self, tbCustomAction, *a):
        """
		Converts text from Custom Action text area into action instance and
		sends that instance back to editor.
		"""
        txCustomAction = self.builder.get_object("txCustomAction")
        txt = tbCustomAction.get_text(tbCustomAction.get_start_iter(),
                                      tbCustomAction.get_end_iter(), True)
        if len(txt.strip(" \t\r\n")) > 0:
            action = self.parser.restart(txt).parse()
            self.editor.set_action(action, from_custom=True)

    def shown(self):
        self.editor.set_modifiers_enabled(False)

    def hidden(self):
        self.editor.set_modifiers_enabled(True)
コード例 #15
0
	def load_autoswitch(self):
		""" Transfers autoswitch settings from config to UI """
		tvItems = self.builder.get_object("tvItems")
		cbShowOSD = self.builder.get_object("cbShowOSD")
		model = tvItems.get_model()
		model.clear()
		for x in self.app.config['autoswitch']:
			o = GObject.GObject()
			o.condition = Condition.parse(x['condition'])
			o.action = GuiActionParser().restart(x["action"]).parse()
			a_str = o.action.describe(Action.AC_SWITCHER)
			model.append((o, o.condition.describe(), a_str))
		self._recursing = True
		self.on_tvItems_cursor_changed()
		cbShowOSD.set_active(bool(self.app.config['autoswitch_osd']))
		self._recursing = False
コード例 #16
0
    def import_scc(self, filename):
        """
		Imports simple, single-file scc-profile.
		Just loads it, checks for shell() actions and asks user to enter name.
		"""
        files = self.builder.get_object("lstImportPackage")
        # Load profile
        profile = Profile(GuiActionParser())
        try:
            profile.load(filename)
        except Exception, e:
            # Profile cannot be parsed. Display error message and let user to quit
            # Error message reuses page from VDF import, because they are
            # basically the same
            log.error(e)
            self.error(str(e))
            return
コード例 #17
0
ファイル: app.py プロジェクト: frankjardel/sc-controller
	def __init__(self, gladepath="/usr/share/scc",
						imagepath="/usr/share/scc/images"):
		Gtk.Application.__init__(self,
				application_id="me.kozec.scc",
				flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE | Gio.ApplicationFlags.NON_UNIQUE )
		UserDataManager.__init__(self)
		BindingEditor.__init__(self, self)
		# Setup Gtk.Application
		self.setup_commandline()
		# Setup DaemonManager
		self.dm = DaemonManager()
		self.dm.connect("alive", self.on_daemon_alive)
		self.dm.connect("controller-count-changed", self.on_daemon_ccunt_changed)
		self.dm.connect("dead", self.on_daemon_dead)
		self.dm.connect("error", self.on_daemon_error)
		self.dm.connect('reconfigured', self.on_daemon_reconfigured),
		self.dm.connect("version", self.on_daemon_version)
		# Set variables
		self.config = Config()
		self.gladepath = gladepath
		self.imagepath = imagepath
		self.builder = None
		self.recursing = False
		self.statusicon = None
		self.status = "unknown"
		self.context_menu_for = None
		self.daemon_changed_profile = False
		self.osd_mode = False	# In OSD mode, only active profile can be editted
		self.osd_mode_mapper = None
		self.background = None
		self.outdated_version = None
		self.profile_switchers = []
		self.current_file = None	# Currently edited file
		self.controller_count = 0
		self.current = Profile(GuiActionParser())
		self.just_started = True
		self.button_widgets = {}
		self.hilights = { App.HILIGHT_COLOR : set(), App.OBSERVE_COLOR : set() }
		self.undo = []
		self.redo = []
コード例 #18
0
    def import_scc_tar(self, filename):
        """
		Imports packaged profiles.
		Checks for shell() actions everywhere and ask user to
		enter main name, check generated ones and optionaly change
		them as he wish.
		"""
        files = self.builder.get_object("lstImportPackage")
        try:
            # Open tar
            tar = tarfile.open(filename, "r:gz")
            files.clear()
            # Grab 1st profile
            name = tar.extractfile(Export.PN_NAME).read()
            main_profile = "%s.sccprofile" % name
            parser = GuiActionParser()
            o = GObject.GObject()
            o.obj = Profile(parser).load_fileobj(tar.extractfile(main_profile))
            files.append((2, name, name, _("(profile)"), o))
            for x in tar:
                name = ".".join(x.name.split(".")[0:-1])
                if x.name.endswith(".sccprofile") and x.name != main_profile:
                    o = GObject.GObject()
                    o.obj = Profile(parser).load_fileobj(tar.extractfile(x))
                    files.append((True, name, name, _("(profile)"), o))
                elif x.name.endswith(".menu"):
                    o = GObject.GObject()
                    o.obj = MenuData.from_fileobj(tar.extractfile(x), parser)
                    files.append((True, name, name, _("(menu)"), o))
        except Exception, e:
            # Either entire tar or some profile cannot be parsed.
            # Display error message and let user to quit
            # Error message reuses same page as above.
            log.error(e)
            self.error(str(e))
            return
コード例 #19
0
    def on_cbMI_toggled(self, widget):
        """
		Called when one of 'Default Menu Items' checkboxes is toggled.
		This actually does kind of magic:
		- 1st, default menu file is loaded
		- 2nd, based on widget name, option from DEFAULT_MENU_OPTIONS is
		  selected
		- 3rd, if this option is not present in loaded menu and checkbox is
		  toggled on, option is added
		- (same for option that is present while checkbox was toggled off)
		- 4rd, default menu is saved
		"""
        if self._recursing: return
        try:
            data = MenuData.from_fileobj(open(find_menu("Default.menu"), "r"),
                                         GuiActionParser())
            index = int(widget.get_name().split("_")[-1])
            instance = GlobalSettings._make_mi_instance(index)
        except Exception, e:
            log.error(traceback.format_exc())
            self._recursing = True
            widget.set_active(not widget.get_active())
            self._recursing = False
            return
コード例 #20
0
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		self._recursing = False
		self.parser = GuiActionParser()
コード例 #21
0
class GyroActionComponent(AEComponent):
	GLADE = "ae/gyro_action.glade"
	NAME = "gyro_action"
	CTXS = Action.AC_GYRO,
	PRIORITY = 3
	
	BUTTONS = (	# in order as displayed in combobox
		(None,					_('Always Active')),
		(None, None),
		(SCButtons.LT,			_('Left Trigger') ),
		(SCButtons.RT,			_('Right Trigger') ),
		(SCButtons.LB,			_('Left Bumper') ),
		(SCButtons.RB,			_('Right Bumper') ),
		(None, None),
		(SCButtons.LPADTOUCH,	_('Left Pad Touched') ),
		(SCButtons.RPADTOUCH,	_('Right Pad Touched') ),
		(SCButtons.LPAD,		_('Left Pad Pressed') ),
		(SCButtons.RPAD,		_('Right Pad Pressed') ),
		(None, None),
		(SCButtons.LGRIP,		_('Left Grip') ),
		(SCButtons.RGRIP,		_('Right Grip') ),
		(None, None),
		(SCButtons.A,			_('A') ),
		(SCButtons.B,			_('B') ),
		(SCButtons.X,			_('X') ),
		(SCButtons.Y,			_('Y') ),
		(None, None),
		(SCButtons.BACK,		_('Back (select)') ),
		(SCButtons.C,			_('Center') ),
		(SCButtons.START,		_('Start') ),
	)
	
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		self._recursing = False
		self.parser = GuiActionParser()
	
	
	def load(self):
		if self.loaded : return
		AEComponent.load(self)
		self._recursing = True
		cbGyroButton = self.builder.get_object("cbGyroButton")
		fill_buttons(cbGyroButton)
		self._recursing = False
	
	
	def set_action(self, mode, action):
		if self.handles(mode, action):
			if isinstance(action, NoAction):
				self.select_gyro_output("none")
				self.select_gyro_button(None)
				return
			if isinstance(action, ModeModifier):
				b = action.order[0]
				action = action.mods[b]
				self.select_gyro_button(b)
			else:
				self.select_gyro_button(None)
			if isinstance(action, MouseAction):
				self.select_gyro_output("mouse")
				if len(action.parameters) >= 2 and action.parameters[1] == YAW:
					self.select_yaw_roll(YAW)
				else:
					self.select_yaw_roll(ROLL)
			elif isinstance(action, GyroAction):
				ap = action.parameters
				if len(ap) == 2:
					self.select_yaw_roll(YAW)
				else:
					self.select_yaw_roll(ROLL)
				if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
					if isinstance(action, GyroAbsAction):
						self.select_gyro_output("left_abs")
					else:
						self.select_gyro_output("left")
					self.select_yaw_roll(ROLL)
				elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
					if isinstance(action, GyroAbsAction):
						self.select_gyro_output("right_abs")
					else:
						self.select_gyro_output("right")
					self.select_yaw_roll(ROLL)
	
	
	def get_button_title(self):
		return _("Joystick or Mouse")
	
	
	def handles(self, mode, action):
		if isinstance(action, NoAction):
			return True
		if is_gyro_enable(action):
			action = action.mods[action.order[0]]
		if isinstance(action, GyroAction):	# Takes GyroAbsAction as well
			ap = action.parameters
			if (len(ap) == 3 and not ap[1]) or len(ap) == 2:
				if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
					return True
				if ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
					return True
			return False
		if isinstance(action, MultiAction):
			return False
		return True
	
	
	def select_gyro_output(self, key):
		""" Just sets combobox value """
		cb = self.builder.get_object("cbMode")
		model = cb.get_model()
		self._recursing = True
		for row in model:
			if key == row[2]:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	
	def select_yaw_roll(self, yawroll):
		""" Just sets combobox value """
		cb = self.builder.get_object("cbYawRoll")
		model = cb.get_model()
		self._recursing = True
		for row in model:
			if yawroll == row[0]:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	
	def select_gyro_button(self, button):
		""" Just sets combobox value """
		cb = self.builder.get_object("cbGyroButton")
		model = cb.get_model()
		self._recursing = True
		if button is not None:
			button = button.name
		for row in model:
			if button == row[0] and row[1] != None:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	def update(self, *a):
		pass
	
	
	def send(self, *a):
		if self._recursing : return
		
		cbMode = self.builder.get_object("cbMode")
		cbYawRoll = self.builder.get_object("cbYawRoll")
		cbGyroButton = self.builder.get_object("cbGyroButton")
		action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0)
		yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0)
		button = cbGyroButton.get_model().get_value(cbGyroButton.get_active_iter(), 0)
		
		match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action)
		if match:
			grps = match.groups()
			if yawroll == YAW:
				action = "%s%s%s" % (grps[0], grps[1], grps[3])
			else:
				action = "%s%s%s" % (grps[0], grps[2], grps[3])
		action = self.parser.restart(action).parse()
		
		if button:
			action = ModeModifier(getattr(SCButtons, button), action)
		
		self.editor.set_action(action)
コード例 #22
0
 def on_cbStickAction_changed(self, cb):
     if self._recursing: return
     key = cb.get_model().get_value(cb.get_active_iter(), 1)
     profile = self._load_osk_profile()
     profile.stick = GuiActionParser().restart(key).parse()
     self._save_osk_profile(profile)
コード例 #23
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.parser = GuiActionParser()

    def load(self):
        if self.loaded: return
        AEComponent.load(self)
        cbAreaType = self.builder.get_object("cbAreaType")
        cbAreaType.set_row_separator_func(
            lambda model, iter: model.get_value(iter, 0) == "-")

    def hidden(self):
        self.update_osd_area(None)

    def set_action(self, mode, action):
        if self.handles(mode, action):
            cb = self.builder.get_object("cbAxisOutput")
            if isinstance(action, AreaAction):
                self.load_area_action(action)
                self.set_cb(cb, "area", 2)
                self.update_osd_area(action)
                return
            self.update_osd_area(None)
            if isinstance(action, TrackpadAction):
                self.set_cb(cb, "trackpad", 2)
            elif isinstance(action, TrackballAction):
                self.set_cb(cb, "trackball", 2)
            elif isinstance(action, CircularAction):
                self.set_cb(cb, "circular", 2)
            elif isinstance(action, XYAction):
                p = [None, None]
                for x in (0, 1):
                    if len(action.actions[0].strip().parameters) >= x:
                        if len(action.actions[x].strip().parameters) > 0:
                            p[x] = action.actions[x].strip().parameters[0]
                if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
                    self.set_cb(cb, "lstick", 2)
                elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
                    self.set_cb(cb, "rstick", 2)
                elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
                    self.set_cb(cb, "dpad", 2)
                elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
                    self.set_cb(cb, "wheel", 2)
            else:
                self.set_cb(cb, "none", 2)

    def update_osd_area(self, action):
        """ Updates preview area displayed on screen """
        if action:
            if self.osd_area_instance is None:
                self.osd_area_instance = Area()
                self.osd_area_instance.show()
            action.update_osd_area(self.osd_area_instance,
                                   FakeMapper(self.editor))
            self.timer("area", 0.5, self.update_osd_area, action)
        elif self.osd_area_instance:
            self.osd_area_instance.quit()
            self.osd_area_instance = None
            self.cancel_timer("area")

    def load_area_action(self, action):
        """
		Load AreaAction values into UI.
		"""
        cbAreaType = self.builder.get_object("cbAreaType")

        x1, y1, x2, y2 = action.coords
        self.relative_area = False
        if isinstance(action, RelAreaAction):
            key = "screensize"
            self.relative_area = True
            x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0
        elif isinstance(action, RelWinAreaAction):
            key = "windowsize"
            self.relative_area = True
            x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0
        else:
            t1 = "1" if x1 < 0 and x2 < 0 else "0"
            t2 = "1" if y1 < 0 and y2 < 0 else "0"
            x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2)
            if x2 < x1: x1, x2 = x2, x1
            if y2 < y1: y1, y2 = y2, y1
            if isinstance(action, WinAreaAction):
                key = "window-%s%s" % (t1, t2)
            else:
                key = "screen-%s%s" % (t1, t2)

        self._recursing = True
        self.builder.get_object("sbAreaX1").set_value(x1)
        self.builder.get_object("sbAreaY1").set_value(y1)
        self.builder.get_object("sbAreaX2").set_value(x2)
        self.builder.get_object("sbAreaY2").set_value(y2)
        self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd)
        self.builder.get_object("cbAreaClickEnabled").set_active(
            self.pressing_pad_clicks())
        for row in cbAreaType.get_model():
            if key == row[1]:
                cbAreaType.set_active_iter(row.iter)
                break
        self._recursing = False

    def on_cbAreaOSDEnabled_toggled(self, *a):
        self.editor.builder.get_object("cbOSD").set_active(
            self.builder.get_object("cbAreaOSDEnabled").get_active())

    def pressing_pad_clicks(self):
        """
		Returns True if currently edited pad is set to press left mouse
		button when pressed.
		(yes, this is used somewhere)
		"""
        side = getattr(SCButtons, self.editor.get_id())
        c_action = self.app.current.buttons[side]
        if isinstance(c_action, ButtonAction):
            return c_action.button == Keys.BTN_LEFT
        return False

    def on_ok(self, action):
        if isinstance(action.strip(), AreaAction):
            # Kinda hacky way to set action on LPAD press or RPAD press
            # when user selects Mouse Area as ouput and checks
            # 'Pressing the Pad Clicks' checkbox
            side = getattr(SCButtons, self.editor.get_id())
            clicks = self.pressing_pad_clicks()

            if self.builder.get_object("cbAreaClickEnabled").get_active():
                if not clicks:
                    # Turn pad press into mouse clicks
                    self.app.set_action(side, ButtonAction(Keys.BTN_LEFT))
            else:
                if clicks:
                    # Clear action created above if checkbox is uncheck
                    self.app.set_action(side, NoAction())

    def make_area_action(self):
        """
		Loads values from UI into new AreaAction or subclass.
		"""
        # Prepare
        cbAreaType = self.builder.get_object("cbAreaType")
        # Read numbers
        x1 = self.builder.get_object("sbAreaX1").get_value()
        y1 = self.builder.get_object("sbAreaY1").get_value()
        x2 = self.builder.get_object("sbAreaX2").get_value()
        y2 = self.builder.get_object("sbAreaY2").get_value()
        # Determine exact action type by looking into Area Type checkbox
        # (this part may seem little crazy)
        # ... numbers
        key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1)
        if "-" in key:
            if key[-2] == "1":
                # Before-last character ius "1", that means that X coords are
                # counted from other side and has to be negated
                x1, x2 = -x1, -x2
            if key[-1] == "1":
                # Key ends with "1". Same thing as above but for Y coordinate
                y1, y2 = -y1, -y2
        if "size" in key:
            x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0
        # ... class
        if "window-" in key:
            cls = WinAreaAction
            self.relative_area = False
        elif "screensize" == key:
            cls = RelAreaAction
            self.relative_area = True
        elif "windowsize" == key:
            cls = RelWinAreaAction
            self.relative_area = True
        else:  # "screen" in key
            cls = AreaAction
            self.relative_area = False
        if not self.relative_area:
            x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)

        return cls(x1, y1, x2, y2)

    def get_button_title(self):
        return _("Joystick or Mouse")

    def handles(self, mode, action):
        if isinstance(action, (NoAction, TrackballAction, CircularAction,
                               InvalidAction, AreaAction)):
            return True
        if isinstance(action, XYAction):
            p = [None, None]
            for x in (0, 1):
                if len(action.actions[0].strip().parameters) >= x:
                    if len(action.actions[x].strip().parameters) > 0:
                        p[x] = action.actions[x].strip().parameters[0]
            if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
                return True
            elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
                return True
            elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
                return True
            elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
                return True
        return False

    def on_area_options_changed(self, *a):
        if self._recursing: return
        action = self.make_area_action()
        self.editor.set_action(action)
        self.update_osd_area(action)
        for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'):
            spin = self.builder.get_object(x)
            if self.relative_area:
                spin.get_adjustment().set_upper(100)
            else:
                spin.get_adjustment().set_upper(1000)
            self.on_sbArea_output(spin)

    def on_sbArea_output(self, button, *a):
        if self.relative_area:
            button.set_text("%s %%" % (button.get_value()))
        else:
            button.set_text("%s px" % (int(button.get_value())))

    def on_sbArea_focus_out_event(self, button, *a):
        GLib.idle_add(self.on_sbArea_output, button)

    def on_sbArea_changed(self, button, *a):
        self.on_sbArea_output(button)
        self.on_area_options_changed(button)

    def on_cbAxisOutput_changed(self, *a):
        cbAxisOutput = self.builder.get_object("cbAxisOutput")
        stActionData = self.builder.get_object("stActionData")
        key = cbAxisOutput.get_model().get_value(
            cbAxisOutput.get_active_iter(), 2)
        if key == 'area':
            stActionData.set_visible_child(self.builder.get_object("grArea"))
            action = self.make_area_action()
            self.update_osd_area(action)
        else:
            stActionData.set_visible_child(self.builder.get_object("nothing"))
            action = cbAxisOutput.get_model().get_value(
                cbAxisOutput.get_active_iter(), 0)
            action = self.parser.restart(action).parse()
            self.update_osd_area(None)

        self.editor.set_action(action)
コード例 #24
0
 def __init__(self):
     UserDataManager.__init__(self)
     self._current_menu = None
     self.parser = GuiActionParser()
     self.allow_globals = True
     self.allow_in_profile = True
コード例 #25
0
class FirstPage(AEComponent):
    GLADE = "ae/first_page.glade"
    NAME = "first_page"
    CTXS = 0
    PRIORITY = 999

    def __init__(self, app, editor):
        AEComponent.__init__(self, app, editor)
        self.parser = GuiActionParser()

    def load(self):
        if AEComponent.load(self):
            # Unlike mose region, gesutres kinda work with XWayland
            markup = ""
            if self.editor.get_mode() == Action.AC_PAD:
                markup = MARKUP_PAD
            elif self.editor.get_mode() == Action.AC_STICK:
                markup = MARKUP_STICK
            elif self.editor.get_mode() == Action.AC_GYRO:
                markup = MARKUP_GYRO
            elif self.editor.get_mode() == Action.AC_TRIGGER:
                markup = MARKUP_TRIGGER
            else:
                markup = MARKUP_BUTTON

            long_names = {
                'LPAD': _("Left Pad"),
                'RPAD': _("Right Pad"),
                'LGRIP': _("Left Grip"),
                'RGRIP': _("Right Grip"),
                'LB': _("Left Bumper"),
                'RB': _("Right Bumper"),
                'LEFT': _("Left Trigger"),
                'RIGHT': _("Right Trigger"),
                'STICK': _("Stick"),
            }

            markup = markup % {
                'what':
                long_names.get(nameof(self.editor.get_id()),
                               nameof(self.editor.get_id()).title())
            }
            self.builder.get_object("lblMarkup").set_markup(
                markup.strip(" \r\n\t"))
            return True

    def on_lblMarkup_activate_link(self, trash, link):
        if link.startswith("quick://"):
            action = self.parser.restart(link[8:]).parse()
            self.editor.reset_active_component()
            self.editor.set_action(action, from_custom=True)
        elif link == "grab://trigger_button":

            def cb(action):
                action = TriggerAction(254, 255, action)
                self.editor.set_action(action, from_custom=True)
                self.editor.force_page("trigger")

            b = SimpleChooser(self.app, "buttons", cb)
            b.set_title(_("Select Button"))
            b.hide_axes()
            b.show(self.editor.window)
        elif link.startswith("page://"):

            def cb():
                self.editor.force_page(link[7:])

            GLib.timeout_add(0.1, cb)
コード例 #26
0
class AxisActionComponent(AEComponent):
	GLADE = "ae/axis_action.glade"
	NAME = "axis_action"
	CTXS = Action.AC_STICK, Action.AC_PAD,
	PRIORITY = 3
	
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		self._recursing = False
		self.parser = GuiActionParser()
	
	
	def set_action(self, mode, action):
		if self.handles(mode, action):
			if isinstance(action, TrackpadAction):
				self.select_axis_output("trackpad")
			elif isinstance(action, TrackballAction):
				self.select_axis_output("trackball")
			elif isinstance(action, CircularAction):
				self.select_axis_output("circular")
			elif isinstance(action, XYAction):
				p = [ None, None ]
				for x in (0, 1):
					if len(action.actions[0].strip().parameters) >= x:
						if len(action.actions[x].strip().parameters) > 0:
							p[x] = action.actions[x].strip().parameters[0]
				if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
					self.select_axis_output("lstick")
				elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
					self.select_axis_output("rstick")
				elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
					self.select_axis_output("dpad")
				elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
					self.select_axis_output("wheel")
			else:
				self.select_axis_output("none")
				
	
	def get_button_title(self):
		return _("Joystick or Mouse")
	
	
	def handles(self, mode, action):
		if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction)):
			return True
		if isinstance(action, XYAction):
			p = [ None, None ]
			for x in (0, 1):
				if len(action.actions[0].strip().parameters) >= x:
					if len(action.actions[x].strip().parameters) > 0:
						p[x] = action.actions[x].strip().parameters[0]
			if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
				return True
			elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
				return True
			elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
				return True
			elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
				return True
		return False
	
	
	def select_axis_output(self, key):
		""" Just sets combobox value """
		model = self.builder.get_object("lstOutputMode")
		cb = self.builder.get_object("cbAxisOutput")
		self._recursing = True
		for row in model:
			if key == row[2]:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	
	def on_cbAxisOutput_changed(self, *a):
		if self._recursing : return
		cbAxisOutput = self.builder.get_object("cbAxisOutput")
		action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0)
		action = self.parser.restart(action).parse()
		
		self.editor.set_action(action)
コード例 #27
0
 def __init__(self, app, editor):
     AEComponent.__init__(self, app, editor)
     self.parser = GuiActionParser()
コード例 #28
0
 def __init__(self, app, editor):
     AEComponent.__init__(self, app, editor)
     self._recursing = False
     self.parser = GuiActionParser()
コード例 #29
0
ファイル: gyro_action.py プロジェクト: kozec/sc-controller
class GyroActionComponent(AEComponent):
	GLADE = "ae/gyro_action.glade"
	NAME = "gyro_action"
	CTXS = Action.AC_GYRO
	PRIORITY = 3
	
	BUTTONS = (	# in order as displayed in combobox
		(None,					_('Always Active')),
		(None, None),
		(SCButtons.LT,			_('Left Trigger') ),
		(SCButtons.RT,			_('Right Trigger') ),
		(SCButtons.LB,			_('Left Bumper') ),
		(SCButtons.RB,			_('Right Bumper') ),
		(None, None),
		(SCButtons.LPADTOUCH,	_('Left Pad Touched') ),
		(SCButtons.RPADTOUCH,	_('Right Pad Touched') ),
		(SCButtons.LPAD,		_('Left Pad Pressed') ),
		(SCButtons.RPAD,		_('Right Pad Pressed') ),
		(None, None),
		(SCButtons.LGRIP,		_('Left Grip') ),
		(SCButtons.RGRIP,		_('Right Grip') ),
		(STICK,					_('Stick Tilted') ),
		(None, None),
		(SCButtons.A,			_('A') ),
		(SCButtons.B,			_('B') ),
		(SCButtons.X,			_('X') ),
		(SCButtons.Y,			_('Y') ),
		(None, None),
		(SCButtons.BACK,		_('Back (select)') ),
		(SCButtons.C,			_('Center') ),
		(SCButtons.START,		_('Start') ),
	)
	
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		self._recursing = False
		self.parser = GuiActionParser()
	
	
	def load(self):
		if self.loaded : return
		AEComponent.load(self)
		self._recursing = True
		cbGyroButton = self.builder.get_object("cbGyroButton")
		fill_buttons(cbGyroButton)
		self._recursing = False
	
	
	def set_action(self, mode, action):
		if self.handles(mode, action):
			if isinstance(action, NoAction):
				self.select_gyro_output("none")
				self.select_gyro_button(SCButtons.RPADTOUCH)
				return
			if isinstance(action, ModeModifier):
				self._recursing = True
				self.builder.get_object("cbInvertGyro").set_active(bool(action.default))
				self._recursing = False
				b = action.mods.keys()[0]
				action = action.mods[b] or action.default
				self.select_gyro_button(b)
			else:
				self.select_gyro_button(None)
			if isinstance(action, SensitivityModifier) and isinstance(action.action, MouseAction):
				# Mouse (Desktop)
				self.select_gyro_output("mouse")
				if len(action.action.parameters) > 0 and action.action.parameters[0] == YAW:
					self.select_yaw_roll(YAW)
				else:
					self.select_yaw_roll(ROLL)
				self.editor.set_default_sensitivity(3.5, 3.5, 3.5)
				self.editor.set_sensitivity(*action.speeds)
			elif isinstance(action, MouseAction):
				# Mouse (Camera)
				self.select_gyro_output("mouse_cam")
				if len(action.parameters) > 0 and action.parameters[0] == YAW:
					self.select_yaw_roll(YAW)
				else:
					self.select_yaw_roll(ROLL)
			elif isinstance(action, GyroAction):
				ap = action.parameters
				if len(ap) == 2:
					self.select_yaw_roll(YAW)
				else:
					self.select_yaw_roll(ROLL)
				if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
					if isinstance(action, GyroAbsAction):
						self.select_gyro_output("left_abs")
					else:
						self.select_gyro_output("left")
				elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
					if isinstance(action, GyroAbsAction):
						self.select_gyro_output("right_abs")
					else:
						self.select_gyro_output("right")
				elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X:
					self.select_gyro_output("mouse_stick")
			self.modifier_updated()
	
	
	def modifier_updated(self):
		cbInvertY = self.builder.get_object("cbInvertY")
		sens = self.editor.get_sensitivity()
		inverted = len(sens) >= 2 and sens[1] < 0
		if cbInvertY.get_active() != inverted:
			self._recursing = True
			cbInvertY.set_active(inverted)
			self._recursing = False
	
	
	def cbInvertY_toggled_cb(self, cb, *a):
		if self._recursing: return
		sens = list(self.editor.get_sensitivity())
		# Ensure that editor accepts Y sensitivity
		if len(sens) >= 2:
			sens[1] = abs(sens[1])
			if cb.get_active():
				# Ensure that Y sensitivity is negative
				sens[1] *= -1
		self.editor.set_sensitivity(*sens)
	
	
	def get_button_title(self):
		return _("Joystick or Mouse")
	
	
	def handles(self, mode, action):
		if isinstance(action, NoAction):
			return True
		if is_gyro_enable(action):
			action = action.mods.values()[0] or action.default
			if isinstance(action, SensitivityModifier):
				action = action.action
		if isinstance(action, GyroAction):	# Takes GyroAbsAction as well
			ap = action.parameters
			if (len(ap) == 3 and not ap[1]) or len(ap) == 2:
				if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
					return True
				elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
					return True
				elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X:
					return True
			return False
		if isinstance(action, (MouseAction, MouseAbsAction)):
			return True
		return False
	
	
	def select_gyro_output(self, key):
		""" Just sets combobox value """
		cb = self.builder.get_object("cbMode")
		model = cb.get_model()
		self._recursing = True
		for row in model:
			if key == row[2]:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	
	def select_yaw_roll(self, yawroll):
		""" Just sets combobox value """
		cb = self.builder.get_object("cbYawRoll")
		model = cb.get_model()
		self._recursing = True
		for row in model:
			if yawroll == row[0]:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	
	def select_gyro_button(self, item):
		""" Just sets combobox value """
		cb = self.builder.get_object("cbGyroButton")
		rvSoftLevel = self.builder.get_object("rvSoftLevel")
		sclSoftLevel = self.builder.get_object("sclSoftLevel")
		model = cb.get_model()
		self._recursing = True
		button = None
		if isinstance(item, RangeOP):
			button = nameof(item.what)
			sclSoftLevel.set_value(item.value)
			rvSoftLevel.set_reveal_child(True)
		elif item is not None:
			button = nameof(item.name)
		for row in model:
			if button == row[0] and row[1] != None:
				cb.set_active_iter(row.iter)
				self._recursing = False
				return
		self._recursing = False
	
	
	def on_cbInvertGyro_toggled(self, cb, *a):
		lblGyroEnable = self.builder.get_object("lblGyroEnable")
		if cb.get_active():
			lblGyroEnable.set_label(_("Gyro Disable Button"))
		else:
			lblGyroEnable.set_label(_("Gyro Enable Button"))
		if not self._recursing:
			self.send()
	
	
	def on_sclSoftLevel_format_value(self, scale, value):
		return  "%s%%" % (int(value * 100.0),)
	
	
	def update(self, *a):
		pass
	
	
	def hidden(self):
		self.editor.set_default_sensitivity(1, 1, 1)
	
	
	def send(self, *a):
		if self._recursing : return
		
		cbMode = self.builder.get_object("cbMode")
		cbYawRoll = self.builder.get_object("cbYawRoll")
		rvSoftLevel = self.builder.get_object("rvSoftLevel")
		sclSoftLevel = self.builder.get_object("sclSoftLevel")
		cbGyroButton = self.builder.get_object("cbGyroButton")
		cbInvertGyro = self.builder.get_object("cbInvertGyro")
		action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0)
		key = cbMode.get_model().get_value(cbMode.get_active_iter(), 2)
		yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0)
		item = cbGyroButton.get_model().get_value(cbGyroButton.get_active_iter(), 0)
		rvSoftLevel.set_reveal_child(item in TRIGGERS)
		
		match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action)
		if match:
			grps = match.groups()
			if yawroll == YAW:
				action = "%s%s%s" % (grps[0], grps[1], grps[3])
			else:
				action = "%s%s%s" % (grps[0], grps[2], grps[3])
		action = self.parser.restart(action).parse()
		
		if item and action:
			if item in TRIGGERS:
				what = RangeOP(getattr(SCButtons, item), ">=", sclSoftLevel.get_value())
			elif item == STICK:
				what = RangeOP(item, ">=", sclSoftLevel.get_value())
			else:
				what = getattr(SCButtons, item)
			if cbInvertGyro.get_active():
				action = ModeModifier(what, NoAction(), action)
			else:
				action = ModeModifier(what, action)
		if key == "mouse":
			self.editor.set_default_sensitivity(3.5, 3.5, 3.5)
		else:
			self.editor.set_default_sensitivity(1, 1, 1)
		
		self.editor.set_action(action)
コード例 #30
0
class GyroActionComponent(AEComponent):
    GLADE = "ae/gyro_action.glade"
    NAME = "gyro_action"
    CTXS = Action.AC_GYRO
    PRIORITY = 3

    BUTTONS = (  # in order as displayed in combobox
        (None, _('Always Active')),
        (None, None),
        (SCButtons.LT, _('Left Trigger')),
        (SCButtons.RT, _('Right Trigger')),
        (SCButtons.LB, _('Left Bumper')),
        (SCButtons.RB, _('Right Bumper')),
        (None, None),
        (SCButtons.LPADTOUCH, _('Left Pad Touched')),
        (SCButtons.RPADTOUCH, _('Right Pad Touched')),
        (SCButtons.LPAD, _('Left Pad Pressed')),
        (SCButtons.RPAD, _('Right Pad Pressed')),
        (None, None),
        (SCButtons.LGRIP, _('Left Grip')),
        (SCButtons.RGRIP, _('Right Grip')),
        (None, None),
        (SCButtons.A, _('A')),
        (SCButtons.B, _('B')),
        (SCButtons.X, _('X')),
        (SCButtons.Y, _('Y')),
        (None, None),
        (SCButtons.BACK, _('Back (select)')),
        (SCButtons.C, _('Center')),
        (SCButtons.START, _('Start')),
    )

    def __init__(self, app, editor):
        AEComponent.__init__(self, app, editor)
        self._recursing = False
        self.parser = GuiActionParser()

    def load(self):
        if self.loaded: return
        AEComponent.load(self)
        self._recursing = True
        cbGyroButton = self.builder.get_object("cbGyroButton")
        fill_buttons(cbGyroButton)
        self._recursing = False

    def set_action(self, mode, action):
        if self.handles(mode, action):
            if isinstance(action, NoAction):
                self.select_gyro_output("none")
                self.select_gyro_button(SCButtons.RPADTOUCH)
                return
            if isinstance(action, ModeModifier):
                self._recursing = True
                self.builder.get_object("cbInvertGyro").set_active(
                    bool(action.default))
                self._recursing = False
                b = action.order[0]
                action = action.mods[b] or action.default
                self.select_gyro_button(b)
            else:
                self.select_gyro_button(None)
            if isinstance(action, SensitivityModifier) and isinstance(
                    action.action, MouseAction):
                # Mouse (Desktop)
                self.select_gyro_output("mouse")
                if len(action.action.parameters
                       ) > 0 and action.action.parameters[0] == YAW:
                    self.select_yaw_roll(YAW)
                else:
                    self.select_yaw_roll(ROLL)
                self.editor.set_default_sensitivity(3.5, 3.5, 3.5)
                self.editor.set_sensitivity(*action.speeds)
            elif isinstance(action, MouseAction):
                # Mouse (Camera)
                self.select_gyro_output("mouse_cam")
                if len(action.parameters) > 0 and action.parameters[0] == YAW:
                    self.select_yaw_roll(YAW)
                else:
                    self.select_yaw_roll(ROLL)
            elif isinstance(action, GyroAction):
                ap = action.parameters
                if len(ap) == 2:
                    self.select_yaw_roll(YAW)
                else:
                    self.select_yaw_roll(ROLL)
                if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
                    if isinstance(action, GyroAbsAction):
                        self.select_gyro_output("left_abs")
                    else:
                        self.select_gyro_output("left")
                elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
                    if isinstance(action, GyroAbsAction):
                        self.select_gyro_output("right_abs")
                    else:
                        self.select_gyro_output("right")
                elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X:
                    self.select_gyro_output("mouse_stick")
            self.modifier_updated()

    def modifier_updated(self):
        cbInvertY = self.builder.get_object("cbInvertY")
        sens = self.editor.get_sensitivity()
        inverted = len(sens) >= 2 and sens[1] < 0
        if cbInvertY.get_active() != inverted:
            self._recursing = True
            cbInvertY.set_active(inverted)
            self._recursing = False

    def cbInvertY_toggled_cb(self, cb, *a):
        if self._recursing: return
        sens = list(self.editor.get_sensitivity())
        # Ensure that editor accepts Y sensitivity
        if len(sens) >= 2:
            sens[1] = abs(sens[1])
            if cb.get_active():
                # Ensure that Y sensitivity is negative
                sens[1] *= -1
        self.editor.set_sensitivity(*sens)

    def get_button_title(self):
        return _("Joystick or Mouse")

    def handles(self, mode, action):
        if isinstance(action, NoAction):
            return True
        if is_gyro_enable(action):
            action = action.mods[action.order[0]] or action.default
            if isinstance(action, SensitivityModifier):
                action = action.action
        if isinstance(action, GyroAction):  # Takes GyroAbsAction as well
            ap = action.parameters
            if (len(ap) == 3 and not ap[1]) or len(ap) == 2:
                if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
                    return True
                elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
                    return True
                elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X:
                    return True
            return False
        if isinstance(action, (MouseAction, MouseAbsAction)):
            return True
        return False

    def select_gyro_output(self, key):
        """ Just sets combobox value """
        cb = self.builder.get_object("cbMode")
        model = cb.get_model()
        self._recursing = True
        for row in model:
            if key == row[2]:
                cb.set_active_iter(row.iter)
                self._recursing = False
                return
        self._recursing = False

    def select_yaw_roll(self, yawroll):
        """ Just sets combobox value """
        cb = self.builder.get_object("cbYawRoll")
        model = cb.get_model()
        self._recursing = True
        for row in model:
            if yawroll == row[0]:
                cb.set_active_iter(row.iter)
                self._recursing = False
                return
        self._recursing = False

    def select_gyro_button(self, button):
        """ Just sets combobox value """
        cb = self.builder.get_object("cbGyroButton")
        model = cb.get_model()
        self._recursing = True
        if button is not None:
            button = button.name
        for row in model:
            if button == row[0] and row[1] != None:
                cb.set_active_iter(row.iter)
                self._recursing = False
                return
        self._recursing = False

    def on_cbInvertGyro_toggled(self, cb, *a):
        lblGyroEnable = self.builder.get_object("lblGyroEnable")
        if cb.get_active():
            lblGyroEnable.set_label(_("Gyro Disable Button"))
        else:
            lblGyroEnable.set_label(_("Gyro Enable Button"))
        if not self._recursing:
            self.send()

    def update(self, *a):
        pass

    def hidden(self):
        self.editor.set_default_sensitivity(1, 1, 1)

    def send(self, *a):
        if self._recursing: return

        cbMode = self.builder.get_object("cbMode")
        cbYawRoll = self.builder.get_object("cbYawRoll")
        cbGyroButton = self.builder.get_object("cbGyroButton")
        cbInvertGyro = self.builder.get_object("cbInvertGyro")
        action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0)
        key = cbMode.get_model().get_value(cbMode.get_active_iter(), 2)
        yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(),
                                                  0)
        button = cbGyroButton.get_model().get_value(
            cbGyroButton.get_active_iter(), 0)

        match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action)
        if match:
            grps = match.groups()
            if yawroll == YAW:
                action = "%s%s%s" % (grps[0], grps[1], grps[3])
            else:
                action = "%s%s%s" % (grps[0], grps[2], grps[3])
        action = self.parser.restart(action).parse()

        if button and action:
            if cbInvertGyro.get_active():
                action = ModeModifier(getattr(SCButtons, button), NoAction(),
                                      action)
            else:
                action = ModeModifier(getattr(SCButtons, button), action)
        if key == "mouse":
            self.editor.set_default_sensitivity(3.5, 3.5, 3.5)
        else:
            self.editor.set_default_sensitivity(1, 1, 1)

        self.editor.set_action(action)
コード例 #31
0
ファイル: custom.py プロジェクト: wendeldr/sc-controller
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		self.parser = GuiActionParser()
コード例 #32
0
ファイル: axis_action.py プロジェクト: wendeldr/sc-controller
class AxisActionComponent(AEComponent, TimerManager):
	GLADE = "ae/axis_action.glade"
	NAME = "axis_action"
	CTXS = Action.AC_STICK, Action.AC_PAD,
	PRIORITY = 3
	
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		TimerManager.__init__(self)
		self._recursing = False
		self.relative_area = False
		self.osd_area_instance = None
		self.parser = GuiActionParser()
	
	
	def load(self):
		if self.loaded : return
		AEComponent.load(self)
		cbAreaType = self.builder.get_object("cbAreaType")
		cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" )
	
	
	def hidden(self):
		self.update_osd_area(None)
	
	
	def set_action(self, mode, action):
		if self.handles(mode, action):
			cb = self.builder.get_object("cbAxisOutput")
			if isinstance(action, AreaAction):
				self.load_area_action(action)
				self.set_cb(cb, "area", 2)
				self.update_osd_area(action)
				return
			self.update_osd_area(None)
			if isinstance(action, TrackpadAction):
				self.set_cb(cb, "trackpad", 2)
			elif isinstance(action, TrackballAction):
				self.set_cb(cb, "trackball", 2)
			elif isinstance(action, CircularAction):
				self.set_cb(cb, "circular", 2)
			elif isinstance(action, XYAction):
				p = [ None, None ]
				for x in (0, 1):
					if len(action.actions[0].strip().parameters) >= x:
						if len(action.actions[x].strip().parameters) > 0:
							p[x] = action.actions[x].strip().parameters[0]
				if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
					self.set_cb(cb, "lstick", 2)
				elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
					self.set_cb(cb, "rstick", 2)
				elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
					self.set_cb(cb, "dpad", 2)
				elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
					self.set_cb(cb, "wheel", 2)
			else:
				self.set_cb(cb, "none", 2)
	
	
	def update_osd_area(self, action):
		""" Updates preview area displayed on screen """
		if action:
			if self.osd_area_instance is None:
				self.osd_area_instance = Area()
				self.osd_area_instance.show()
			action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor))
			self.timer("area", 0.5, self.update_osd_area, action)
		elif self.osd_area_instance:
			self.osd_area_instance.quit()
			self.osd_area_instance = None
			self.cancel_timer("area")
	
	
	def load_area_action(self, action):
		"""
		Load AreaAction values into UI.
		"""
		cbAreaType = self.builder.get_object("cbAreaType")
		
		x1, y1, x2, y2 = action.coords
		self.relative_area = False
		if isinstance(action, RelAreaAction):
			key = "screensize"
			self.relative_area = True
			x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0
		elif isinstance(action, RelWinAreaAction):
			key = "windowsize"
			self.relative_area = True
			x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0
		else:
			t1 = "1" if x1 < 0 and x2 < 0 else "0"
			t2 = "1" if y1 < 0 and y2 < 0 else "0"
			x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2)
			if x2 < x1 : x1, x2 = x2, x1
			if y2 < y1 : y1, y2 = y2, y1
			if isinstance(action, WinAreaAction):
				key = "window-%s%s" % (t1, t2)
			else:
				key = "screen-%s%s" % (t1, t2)
		
		self._recursing = True
		self.builder.get_object("sbAreaX1").set_value(x1)
		self.builder.get_object("sbAreaY1").set_value(y1)
		self.builder.get_object("sbAreaX2").set_value(x2)
		self.builder.get_object("sbAreaY2").set_value(y2)
		self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd)
		self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks())
		for row in cbAreaType.get_model():
			if key == row[1]:
				cbAreaType.set_active_iter(row.iter)
				break
		self._recursing = False
	
	
	def on_cbAreaOSDEnabled_toggled(self, *a):
		self.editor.builder.get_object("cbOSD").set_active(
			self.builder.get_object("cbAreaOSDEnabled").get_active())
	
	
	def pressing_pad_clicks(self):
		"""
		Returns True if currently edited pad is set to press left mouse
		button when pressed.
		(yes, this is used somewhere)
		"""
		side = getattr(SCButtons, self.editor.get_id())
		c_action = self.app.current.buttons[side]
		if isinstance(c_action, ButtonAction):
			return c_action.button == Keys.BTN_LEFT
		return False
	
	
	def on_ok(self, action):
		if isinstance(action.strip(), AreaAction):
			# Kinda hacky way to set action on LPAD press or RPAD press
			# when user selects Mouse Area as ouput and checks
			# 'Pressing the Pad Clicks' checkbox
			side = getattr(SCButtons, self.editor.get_id())
			clicks = self.pressing_pad_clicks()
			
			if self.builder.get_object("cbAreaClickEnabled").get_active():
				if not clicks:
					# Turn pad press into mouse clicks
					self.app.set_action(side, ButtonAction(Keys.BTN_LEFT))
			else:
				if clicks:
					# Clear action created above if checkbox is uncheck
					self.app.set_action(side, NoAction())
	
	
	def make_area_action(self):
		"""
		Loads values from UI into new AreaAction or subclass.
		"""
		# Prepare
		cbAreaType = self.builder.get_object("cbAreaType")
		# Read numbers
		x1 = self.builder.get_object("sbAreaX1").get_value()
		y1 = self.builder.get_object("sbAreaY1").get_value()
		x2 = self.builder.get_object("sbAreaX2").get_value()
		y2 = self.builder.get_object("sbAreaY2").get_value()
		# Determine exact action type by looking into Area Type checkbox
		# (this part may seem little crazy)
		# ... numbers
		key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1)
		if "-" in key:
			if key[-2] == "1":
				# Before-last character ius "1", that means that X coords are
				# counted from other side and has to be negated
				x1, x2 = -x1, -x2
			if key[-1] == "1":
				# Key ends with "1". Same thing as above but for Y coordinate
				y1, y2 = -y1, -y2
		if "size" in key:
			x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0
		# ... class 
		if "window-" in key:
			cls = WinAreaAction
			self.relative_area = False
		elif "screensize" == key:
			cls = RelAreaAction
			self.relative_area = True
		elif "windowsize" == key:
			cls = RelWinAreaAction
			self.relative_area = True
		else: # "screen" in key
			cls = AreaAction
			self.relative_area = False
		if not self.relative_area:
			x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
			
		return cls(x1, y1, x2, y2)
	
	
	def get_button_title(self):
		return _("Joystick or Mouse")
	
	
	def handles(self, mode, action):
		if isinstance(action, (NoAction, TrackballAction, CircularAction,
					InvalidAction, AreaAction)):
			return True
		if isinstance(action, XYAction):
			p = [ None, None ]
			for x in (0, 1):
				if len(action.actions[0].strip().parameters) >= x:
					if len(action.actions[x].strip().parameters) > 0:
						p[x] = action.actions[x].strip().parameters[0]
			if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
				return True
			elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
				return True
			elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
				return True
			elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
				return True
		return False
	
	
	def on_area_options_changed(self, *a):
		if self._recursing : return
		action = self.make_area_action()
		self.editor.set_action(action)
		self.update_osd_area(action)
		for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'):
			spin = self.builder.get_object(x)
			if self.relative_area:
				spin.get_adjustment().set_upper(100)
			else:
				spin.get_adjustment().set_upper(1000)
			self.on_sbArea_output(spin)
	
	
	def on_sbArea_output(self, button, *a):
		if self.relative_area:
			button.set_text("%s %%" % (button.get_value()))
		else:
			button.set_text("%s px" % (int(button.get_value())))
	
	
	def on_sbArea_focus_out_event(self, button, *a):
		GLib.idle_add(self.on_sbArea_output, button)
	
	
	def on_sbArea_changed(self, button, *a):
		self.on_sbArea_output(button)
		self.on_area_options_changed(button)
	
	
	def on_cbAxisOutput_changed(self, *a):
		cbAxisOutput = self.builder.get_object("cbAxisOutput")
		stActionData = self.builder.get_object("stActionData")
		key = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 2)
		if key == 'area':
			stActionData.set_visible_child(self.builder.get_object("grArea"))
			action = self.make_area_action()
			self.update_osd_area(action)
		else:
			stActionData.set_visible_child(self.builder.get_object("nothing"))
			action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0)
			action = self.parser.restart(action).parse()
			self.update_osd_area(None)
		
		self.editor.set_action(action)
コード例 #33
0
ファイル: axis_action.py プロジェクト: soekul/sc-controller
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)
コード例 #34
0
class GyroActionComponent(AEComponent):
    GLADE = "ae/gyro_action.glade"
    NAME = "gyro_action"
    CTXS = Action.AC_GYRO,
    PRIORITY = 3

    BUTTONS = (  # in order as displayed in combobox
        (None, _('Always Active')),
        (None, None),
        (SCButtons.LT, _('Left Trigger')),
        (SCButtons.RT, _('Right Trigger')),
        (SCButtons.LB, _('Left Bumper')),
        (SCButtons.RB, _('Right Bumper')),
        (None, None),
        (SCButtons.LPADTOUCH, _('Left Pad Touched')),
        (SCButtons.RPADTOUCH, _('Right Pad Touched')),
        (SCButtons.LPAD, _('Left Pad Pressed')),
        (SCButtons.RPAD, _('Right Pad Pressed')),
        (None, None),
        (SCButtons.LGRIP, _('Left Grip')),
        (SCButtons.RGRIP, _('Right Grip')),
        (None, None),
        (SCButtons.A, _('A')),
        (SCButtons.B, _('B')),
        (SCButtons.X, _('X')),
        (SCButtons.Y, _('Y')),
        (None, None),
        (SCButtons.BACK, _('Back (select)')),
        (SCButtons.C, _('Center')),
        (SCButtons.START, _('Start')),
    )

    def __init__(self, app, editor):
        AEComponent.__init__(self, app, editor)
        self._recursing = False
        self.parser = GuiActionParser()

    def load(self):
        if self.loaded: return
        AEComponent.load(self)
        self._recursing = True
        cbGyroButton = self.builder.get_object("cbGyroButton")
        fill_buttons(cbGyroButton)
        self._recursing = False

    def set_action(self, mode, action):
        if self.handles(mode, action):
            if isinstance(action, NoAction):
                self.select_gyro_output("none")
                self.select_gyro_button(None)
                return
            if isinstance(action, ModeModifier):
                b = action.order[0]
                action = action.mods[b]
                self.select_gyro_button(b)
            else:
                self.select_gyro_button(None)
            if isinstance(action, MouseAction):
                self.select_gyro_output("mouse")
                if len(action.parameters) >= 2 and action.parameters[1] == YAW:
                    self.select_yaw_roll(YAW)
                else:
                    self.select_yaw_roll(ROLL)
            elif isinstance(action, GyroAction):
                ap = action.parameters
                if len(ap) == 2:
                    self.select_yaw_roll(YAW)
                else:
                    self.select_yaw_roll(ROLL)
                if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
                    if isinstance(action, GyroAbsAction):
                        self.select_gyro_output("left_abs")
                    else:
                        self.select_gyro_output("left")
                    self.select_yaw_roll(ROLL)
                elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
                    if isinstance(action, GyroAbsAction):
                        self.select_gyro_output("right_abs")
                    else:
                        self.select_gyro_output("right")
                    self.select_yaw_roll(ROLL)

    def get_button_title(self):
        return _("Joystick or Mouse")

    def handles(self, mode, action):
        if isinstance(action, NoAction):
            return True
        if is_gyro_enable(action):
            action = action.mods[action.order[0]]
        if isinstance(action, GyroAction):  # Takes GyroAbsAction as well
            ap = action.parameters
            if (len(ap) == 3 and not ap[1]) or len(ap) == 2:
                if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y:
                    return True
                if ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY:
                    return True
            return False
        if isinstance(action, MultiAction):
            return False
        return True

    def select_gyro_output(self, key):
        """ Just sets combobox value """
        cb = self.builder.get_object("cbMode")
        model = cb.get_model()
        self._recursing = True
        for row in model:
            if key == row[2]:
                cb.set_active_iter(row.iter)
                self._recursing = False
                return
        self._recursing = False

    def select_yaw_roll(self, yawroll):
        """ Just sets combobox value """
        cb = self.builder.get_object("cbYawRoll")
        model = cb.get_model()
        self._recursing = True
        for row in model:
            if yawroll == row[0]:
                cb.set_active_iter(row.iter)
                self._recursing = False
                return
        self._recursing = False

    def select_gyro_button(self, button):
        """ Just sets combobox value """
        cb = self.builder.get_object("cbGyroButton")
        model = cb.get_model()
        self._recursing = True
        if button is not None:
            button = button.name
        for row in model:
            if button == row[0] and row[1] != None:
                cb.set_active_iter(row.iter)
                self._recursing = False
                return
        self._recursing = False

    def update(self, *a):
        pass

    def send(self, *a):
        if self._recursing: return

        cbMode = self.builder.get_object("cbMode")
        cbYawRoll = self.builder.get_object("cbYawRoll")
        cbGyroButton = self.builder.get_object("cbGyroButton")
        action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0)
        yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(),
                                                  0)
        button = cbGyroButton.get_model().get_value(
            cbGyroButton.get_active_iter(), 0)

        match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action)
        if match:
            grps = match.groups()
            if yawroll == YAW:
                action = "%s%s%s" % (grps[0], grps[1], grps[3])
            else:
                action = "%s%s%s" % (grps[0], grps[2], grps[3])
        action = self.parser.restart(action).parse()

        if button:
            action = ModeModifier(getattr(SCButtons, button), action)

        self.editor.set_action(action)
コード例 #35
0
ファイル: axis_action.py プロジェクト: kozec/sc-controller
class AxisActionComponent(AEComponent, TimerManager):
	GLADE = "ae/axis_action.glade"
	NAME = "axis_action"
	CTXS = Action.AC_STICK | Action.AC_PAD
	PRIORITY = 3
	
	def __init__(self, app, editor):
		AEComponent.__init__(self, app, editor)
		TimerManager.__init__(self)
		self._recursing = False
		self.relative_area = False
		self.osd_area_instance = None
		self.on_wayland = False
		self.circular_axis = MouseAction(Rels.REL_WHEEL)
		self.circular_buttons = [ None, None ]
		self.button = None
		self.parser = GuiActionParser()
	
	
	def load(self):
		if self.loaded : return
		AEComponent.load(self)
		cbAreaType = self.builder.get_object("cbAreaType")
		cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" )
		self.on_wayland = "WAYLAND_DISPLAY" in os.environ or not isinstance(Gdk.Display.get_default(), GdkX11.X11Display)
		if self.on_wayland:
			self.builder.get_object("lblArea").set_text(_("Note: Mouse Region option is not available with Wayland-based display server"))
			self.builder.get_object("grArea").set_sensitive(False)
		
		# Remove options that are not applicable to currently editted input
		if self.editor.get_id() in STICKS:
			# Remove "Mouse Region", "Mouse" and "Mouse (Emulate Stick)" options
			# when editing stick bindings
			cb = self.builder.get_object("cbAxisOutput")
			for row in cb.get_model():
				if row[2] in ("wheel_pad", "area", "mouse", "mouse_pad"):
					cb.get_model().remove(row.iter)
		else:
			# Remove "Mouse" option when editing pads
			# (it's effectivelly same as Trackpad)
			cb = self.builder.get_object("cbAxisOutput")
			for row in cb.get_model():
				if row[2] in ("wheel_stick", "mouse_stick"):
					cb.get_model().remove(row.iter)
	
	
	def hidden(self):
		self.update_osd_area(None)
	
	
	def set_action(self, mode, action):
		if self.handles(mode, action):
			cb = self.builder.get_object("cbAxisOutput")
			if isinstance(action, AreaAction):
				self.load_area_action(action)
				self.set_cb(cb, "area", 2)
				self.update_osd_area(action)
				return
			self.update_osd_area(None)
			if isinstance(action, MouseAction):
				self.load_mouse_action(action)
			elif isinstance(action, CircularModifier):
				self.load_circular_action(action)
			elif isinstance(action, ButtonAction):
				self.load_button_action(action)
			elif isinstance(action, XYAction):
				if self.editor.friction > 0:
					self.load_mouse_action(action)
				else:
					p = [ None, None ]
					for x in (0, 1):
						if len(action.actions[0].strip().parameters) >= x:
							if len(action.actions[x].strip().parameters) > 0:
								p[x] = action.actions[x].strip().parameters[0]
					if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
						self.set_cb(cb, "lstick", 2)
					elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
						if isinstance(action, RelXYAction):
							self.set_cb(cb, "rstick_rel", 2)
						else:
							self.set_cb(cb, "rstick", 2)
					elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
						self.set_cb(cb, "wheel_pad", 2)
						self.set_cb(cb, "wheel_stick", 2)
			else:
				self.set_cb(cb, "none", 2)
	
	
	def update_osd_area(self, action):
		""" Updates preview area displayed on screen """
		if action:
			if self.osd_area_instance is None:
				if self.on_wayland:
					# Cannot display preview with non-X11 backends
					return
				self.osd_area_instance = Area()
				self.osd_area_instance.show()
			action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor))
			self.timer("area", 0.5, self.update_osd_area, action)
		elif self.osd_area_instance:
			self.osd_area_instance.quit()
			self.osd_area_instance = None
			self.cancel_timer("area")
	
	
	def load_circular_action(self, action):
		cbAxisOutput = self.builder.get_object("cbAxisOutput")
		btCircularAxis = self.builder.get_object("btCircularAxis")
		btCircularButton0 = self.builder.get_object("btCircularButton0")
		btCircularButton1 = self.builder.get_object("btCircularButton1")
		
		# Turn action into list of subactions (even if it's just single action)
		if isinstance(action.action, MultiAction):
			actions = action.action.actions
		else:
			actions = [ action.action ]
		
		# Parse that list
		self.circular_axis, self.circular_buttons = NoAction(), [ None, None ]
		for action in actions:
			if isinstance(action, ButtonAction):
				self.circular_buttons = [ action.button, action.button2 ]
			else:
				self.circular_axis = action
		
		# Set labels
		b0, b1 = self.circular_buttons
		btCircularButton0.set_label(ButtonAction.describe_button(b0))
		btCircularButton1.set_label(ButtonAction.describe_button(b1))
		btCircularAxis.set_label(self.circular_axis.describe(Action.AC_PAD))
		
		self.set_cb(cbAxisOutput, "circular", 2)
	
	
	def load_button_action(self, action):
		self.button = action
		cbAxisOutput = self.builder.get_object("cbAxisOutput")
		btSingleButton = self.builder.get_object("btSingleButton")
		btSingleButton.set_label(self.button.describe(Action.AC_PAD))
		self.set_cb(cbAxisOutput, "button", 2)
	
	
	def load_mouse_action(self, action):
		cbMouseOutput = self.builder.get_object("cbMouseOutput")
		cbAxisOutput = self.builder.get_object("cbAxisOutput")
		self._recursing = True
		if isinstance(action, MouseAction):
			self.set_cb(cbMouseOutput, "mouse", 1)
			self.set_cb(cbAxisOutput, "mouse", 2)
		elif isinstance(action, XYAction):
			if isinstance(action.x, AxisAction):
				if action.x.parameters[0] == Axes.ABS_X:
					self.set_cb(cbMouseOutput, "left", 1)
				else:
					self.set_cb(cbMouseOutput, "right", 1)
				self.set_cb(cbAxisOutput, "mouse", 2)
			elif isinstance(action.x, MouseAction):
				if self.editor.get_id() in STICKS:
					self.set_cb(cbAxisOutput, "wheel_stick", 2)
				else:
					self.set_cb(cbAxisOutput, "wheel_pad", 2)
		self._recursing = False
	
	
	def load_area_action(self, action):
		"""
		Load AreaAction values into UI.
		"""
		cbAreaType = self.builder.get_object("cbAreaType")
		
		x1, y1, x2, y2 = action.coords
		self.relative_area = False
		if isinstance(action, RelAreaAction):
			key = "screensize"
			self.relative_area = True
			x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0
		elif isinstance(action, RelWinAreaAction):
			key = "windowsize"
			self.relative_area = True
			x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0
		else:
			t1 = "1" if x1 < 0 and x2 < 0 else "0"
			t2 = "1" if y1 < 0 and y2 < 0 else "0"
			x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2)
			if x2 < x1 : x1, x2 = x2, x1
			if y2 < y1 : y1, y2 = y2, y1
			if isinstance(action, WinAreaAction):
				key = "window-%s%s" % (t1, t2)
			else:
				key = "screen-%s%s" % (t1, t2)
		
		self._recursing = True
		self.builder.get_object("sbAreaX1").set_value(x1)
		self.builder.get_object("sbAreaY1").set_value(y1)
		self.builder.get_object("sbAreaX2").set_value(x2)
		self.builder.get_object("sbAreaY2").set_value(y2)
		self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd)
		self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks())
		for row in cbAreaType.get_model():
			if key == row[1]:
				cbAreaType.set_active_iter(row.iter)
				break
		self._recursing = False
	
	
	def on_btCircularAxis_clicked(self, *a):
		def cb(action):
			self.circular_axis = action
			btCircularAxis = self.builder.get_object("btCircularAxis")
			btCircularAxis.set_label(action.describe(Action.AC_PAD))
			self.editor.set_action(self.make_circular_action())
		
		b = SimpleChooser(self.app, "axis", cb)
		b.set_title(_("Select Axis"))
		b.display_action(Action.AC_STICK, self.circular_axis)
		b.show(self.editor.window)
	
	
	def on_btCircularButton_clicked(self, button, *a):
		index = 0 if button == self.builder.get_object("btCircularButton0") else 1
		def cb(action):
			self.circular_buttons[index] = action.button
			btCircularButton = self.builder.get_object("btCircularButton%s" % (index, ))
			btCircularButton.set_label(action.describe(Action.AC_PAD))
			self.editor.set_action(self.make_circular_action())
		
		b = SimpleChooser(self.app, "buttons", cb)
		b.set_title(_("Select Button"))
		b.display_action(Action.AC_STICK, self.circular_axis)
		b.show(self.editor.window)
	
	
	def on_btClearCircularAxis_clicked(self, *a):
		btCircularAxis = self.builder.get_object("btCircularAxis")
		self.circular_axis = NoAction()
		btCircularAxis.set_label(self.circular_axis.describe(Action.AC_PAD))
		self.editor.set_action(self.make_circular_action())
	
	
	def on_btClearCircularButtons_clicked(self, *a):
		btCircularButton0 = self.builder.get_object("btCircularButton0")
		btCircularButton1 = self.builder.get_object("btCircularButton1")
		self.circular_buttons = [ None, None ]
		btCircularButton0.set_label(NoAction().describe(Action.AC_PAD))
		btCircularButton1.set_label(NoAction().describe(Action.AC_PAD))
		self.editor.set_action(self.make_circular_action())
	
	
	def on_btSingleButton_clicked(self, *a):
		def cb(action):
			self.button = action
			btSingleButton = self.builder.get_object("btSingleButton")
			btSingleButton.set_label(self.button.describe(Action.AC_PAD))
			self.editor.set_action(self.button)
		
		b = SimpleChooser(self.app, "buttons", cb)
		b.set_title(_("Select Button"))
		b.display_action(Action.AC_STICK, self.circular_axis)
		b.show(self.editor.window)
	
	
	def on_cbAreaOSDEnabled_toggled(self, *a):
		self.editor.builder.get_object("cbOSD").set_active(
			self.builder.get_object("cbAreaOSDEnabled").get_active())
	
	
	def pressing_pad_clicks(self):
		"""
		Returns True if currently edited pad is set to press left mouse
		button when pressed.
		(yes, this is used somewhere)
		"""
		side = getattr(SCButtons, self.editor.get_id())
		c_action = self.app.current.buttons[side]
		if isinstance(c_action, ButtonAction):
			return c_action.button == Keys.BTN_LEFT
		return False
	
	
	def on_ok(self, action):
		if isinstance(action.strip(), AreaAction):
			# Kinda hacky way to set action on LPAD press or RPAD press
			# when user selects Mouse Area as ouput and checks
			# 'Pressing the Pad Clicks' checkbox
			side = getattr(SCButtons, self.editor.get_id())
			clicks = self.pressing_pad_clicks()
			
			if self.builder.get_object("cbAreaClickEnabled").get_active():
				if not clicks:
					# Turn pad press into mouse clicks
					self.app.set_action(self.app.current, side, ButtonAction(Keys.BTN_LEFT))
			else:
				if clicks:
					# Clear action created above if checkbox is uncheck
					self.app.set_action(self.app.current, side, NoAction())
	
	
	def on_mouse_options_changed(self, *a):
		if self._recursing : return
		action = self.make_mouse_action()
		self.editor.set_action(action)
	
	
	def make_mouse_action(self):
		"""
		Loads values from UI into trackball-related action
		"""
		cbMouseOutput = self.builder.get_object("cbMouseOutput")
		a_str = cbMouseOutput.get_model().get_value(cbMouseOutput.get_active_iter(), 2)
		return self.parser.restart(a_str).parse()
	
	
	def make_circular_action(self):
		"""
		Constructs Circular Modifier
		"""
		if self.circular_axis and any(self.circular_buttons):
			return CircularModifier(MultiAction(
				self.circular_axis, ButtonAction(*self.circular_buttons)))
		elif any(self.circular_buttons):
			return CircularModifier(ButtonAction(*self.circular_buttons))
		else:
			return CircularModifier(self.circular_axis)
	
	
	def make_area_action(self):
		"""
		Loads values from UI into new AreaAction or subclass.
		"""
		# Prepare
		cbAreaType = self.builder.get_object("cbAreaType")
		# Read numbers
		x1 = self.builder.get_object("sbAreaX1").get_value()
		y1 = self.builder.get_object("sbAreaY1").get_value()
		x2 = self.builder.get_object("sbAreaX2").get_value()
		y2 = self.builder.get_object("sbAreaY2").get_value()
		# Determine exact action type by looking into Area Type checkbox
		# (this part may seem little crazy)
		# ... numbers
		key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1)
		if "-" in key:
			if key[-2] == "1":
				# Before-last character ius "1", that means that X coords are
				# counted from other side and has to be negated
				x1, x2 = -x1, -x2
			if key[-1] == "1":
				# Key ends with "1". Same thing as above but for Y coordinate
				y1, y2 = -y1, -y2
		if "size" in key:
			x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0
		# ... class 
		if "window-" in key:
			cls = WinAreaAction
			self.relative_area = False
		elif "screensize" == key:
			cls = RelAreaAction
			self.relative_area = True
		elif "windowsize" == key:
			cls = RelWinAreaAction
			self.relative_area = True
		else: # "screen" in key
			cls = AreaAction
			self.relative_area = False
		if not self.relative_area:
			x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
			
		return cls(x1, y1, x2, y2)
	
	
	def get_button_title(self):
		return _("Joystick / Mouse")
	
	
	def handles(self, mode, action):
		if isinstance(action, (NoAction, MouseAction, CircularModifier,
					InvalidAction, AreaAction, ButtonAction)):
			return True
		if isinstance(action, BallModifier):
			if isinstance(action.action, XYAction):
				return (
					isinstance(action.action.x, (AxisAction, MouseAction))
					and isinstance(action.action.x, (AxisAction, MouseAction))
				)
			return isinstance(action.action, MouseAction)
		if isinstance(action, XYAction):
			p = [ None, None ]
			for x in (0, 1):
				if len(action.actions[0].strip().parameters) >= x:
					if len(action.actions[x].strip().parameters) > 0:
						p[x] = action.actions[x].strip().parameters[0]
			if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y:
				return True
			elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY:
				return True
			elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y:
				return True
			elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL:
				return True
		return False
	
	
	def on_area_options_changed(self, *a):
		if self._recursing : return
		action = self.make_area_action()
		self.editor.set_action(action)
		self.update_osd_area(action)
		for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'):
			spin = self.builder.get_object(x)
			if self.relative_area:
				spin.get_adjustment().set_upper(100)
			else:
				spin.get_adjustment().set_upper(1000)
			self.on_sbArea_output(spin)
	
	
	def on_sbArea_output(self, button, *a):
		if self.relative_area:
			button.set_text("%s %%" % (button.get_value()))
		else:
			button.set_text("%s px" % (int(button.get_value())))
	
	
	def on_sbArea_focus_out_event(self, button, *a):
		GLib.idle_add(self.on_sbArea_output, button)
	
	
	def on_sbArea_changed(self, button, *a):
		self.on_sbArea_output(button)
		self.on_area_options_changed(button)
	
	
	def on_lblSetupTrackball_activate_link(self, trash, link):
		self.editor.on_link(link)
	
	
	def on_cbAxisOutput_changed(self, *a):
		cbAxisOutput = self.builder.get_object("cbAxisOutput")
		stActionData = self.builder.get_object("stActionData")
		key = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 2)
		if key == 'area':
			stActionData.set_visible_child(self.builder.get_object("grArea"))
			action = self.make_area_action()
			self.update_osd_area(action)
		elif key == "button":
			stActionData.set_visible_child(self.builder.get_object("vbButton"))
			self.button = self.button or ButtonAction(Keys.BTN_GAMEPAD)
			action = self.button
		elif key == "circular":
			stActionData.set_visible_child(self.builder.get_object("grCircular"))
			action = self.make_circular_action()
		elif key == 'mouse':
			stActionData.set_visible_child(self.builder.get_object("vbMose"))
			if self.editor.friction == 0:
				# When switching to mouse, enable trackball by default
				self.editor.friction = 10
			action = self.make_mouse_action()
		else:
			stActionData.set_visible_child(self.builder.get_object("nothing"))
			action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0)
			action = self.parser.restart(action).parse()
			self.update_osd_area(None)
		
		self.editor.set_action(action)
コード例 #36
0
 def on_cbActionType_changed(self, *a):
     cbActionType = self.builder.get_object("cbActionType")
     key = cbActionType.get_model().get_value(
         cbActionType.get_active_iter(), 0)
     self.editor.set_action(GuiActionParser().restart(key).parse())