def _populate_ui(self): self.split_slider.setValue(self.action_data.center_point * 1e5) self.split_readout.setValue(self.action_data.center_point) try: if self.action_data.device_low_vjoy_id is None or \ self.action_data.device_low_axis is None: self.vjoy_selector_1.set_selection(InputType.JoystickAxis, -1, -1) else: self.vjoy_selector_1.set_selection( InputType.JoystickAxis, self.action_data.device_low_vjoy_id, self.action_data.device_low_axis) if self.action_data.device_high_vjoy_id is None or \ self.action_data.device_high_axis is None: self.vjoy_selector_2.set_selection(InputType.JoystickAxis, -1, -1) else: self.vjoy_selector_2.set_selection( InputType.JoystickAxis, self.action_data.device_high_vjoy_id, self.action_data.device_high_axis) self.save_vjoy_selection(1, self.vjoy_selector_1.get_selection()) self.save_vjoy_selection(2, self.vjoy_selector_2.get_selection()) except gremlin.error.GremlinError as e: # FIXME: This error here should only have been needed due to the # vJoy selector attempting to acquire a vJoy device, this # should no longer occur, check if this here is still needed util.display_error( "A needed vJoy device is not accessible: {}\n\n".format(e) + "Default values have been set for the input, but they are " "not what has been specified.") logging.getLogger("system").error(str(e))
def _populate_ui(self): """Populates the UI components.""" # Get the appropriate vjoy device identifier vjoy_dev_id = 0 if self.action_data.vjoy_device_id not in [0, None]: vjoy_dev_id = self.action_data.vjoy_device_id # Get the input type which can change depending on the container used input_type = self.action_data.input_type if self.action_data.parent.tag == "hat_buttons": input_type = InputType.JoystickButton # If no valid input item is selected get the next unused one if self.action_data.vjoy_input_id in [0, None]: free_inputs = self._get_profile_root().list_unused_vjoy_inputs() input_name = self.type_to_name_map[input_type].lower() input_type = self.name_to_type_map[input_name.capitalize()] if vjoy_dev_id == 0: vjoy_dev_id = sorted(free_inputs.keys())[0] input_list = free_inputs[vjoy_dev_id][input_name] # If we have an unused item use it, otherwise use the first one if len(input_list) > 0: vjoy_input_id = input_list[0] else: vjoy_input_id = 1 # If a valid input item is present use it else: vjoy_input_id = self.action_data.vjoy_input_id try: self.vjoy_selector.set_selection(input_type, vjoy_dev_id, vjoy_input_id) if self.action_data.input_type == InputType.JoystickAxis: if self.action_data.axis_mode == "absolute": self.absolute_checkbox.setChecked(True) else: self.relative_checkbox.setChecked(True) self.relative_scaling.setValue(self.action_data.axis_scaling) self.absolute_checkbox.clicked.connect(self.save_changes) self.relative_checkbox.clicked.connect(self.save_changes) self.relative_scaling.valueChanged.connect(self.save_changes) # Save changes so the UI updates properly self.save_changes() except gremlin.error.GremlinError as e: util.display_error( "A needed vJoy device is not accessible: {}\n\n".format(e) + "Default values have been set for the input, but they are " "not what has been specified.") logging.getLogger("system").error(str(e))
def _populate_ui(self): self.split_slider.setValue(self.action_data.center_point * 1e5) self.split_readout.setValue(self.action_data.center_point) try: if self.action_data.axis1 is None: self.vjoy_selector_1.set_selection(InputType.JoystickAxis, -1, -1) else: self.vjoy_selector_1.set_selection(InputType.JoystickAxis, self.action_data.axis1[0], self.action_data.axis1[1]) if self.action_data.axis2 is None: self.vjoy_selector_2.set_selection(InputType.JoystickAxis, -1, -1) else: self.vjoy_selector_2.set_selection(InputType.JoystickAxis, self.action_data.axis2[0], self.action_data.axis2[1]) except gremlin.error.GremlinError as e: util.display_error( "A needed vJoy device is not accessible: {}\n\n".format(e) + "Default values have been set for the input, but they are " "not what has been specified.") logging.getLogger("system").error(str(e))
def start(self, inheritance_tree, settings, start_mode, profile): """Starts listening to events and loads all existing callbacks. :param inheritance_tree tree encoding inheritance between the different modes :param settings profile settings to apply at launch :param start_mode the mode in which to start Gremlin :param profile the profile to use when generating all the callbacks """ # Reset states to their default values self._inheritance_tree = inheritance_tree self._reset_state() # Check if we want to override the star mode as determined by the # heuristic if settings.startup_mode is not None: if settings.startup_mode in gremlin.profile.mode_list(profile): start_mode = settings.startup_mode # Load the generated code try: # Load generated python code gremlin_code = util.load_module("gremlin_code") # Create callbacks fom the user code callback_count = 0 for dev_id, modes in input_devices.callback_registry.registry.items( ): for mode, callbacks in modes.items(): for event, callback_list in callbacks.items(): for callback in callback_list.values(): self.event_handler.add_callback( dev_id, mode, event, callback[0], callback[1]) callback_count += 1 # Create input callbacks based on the profile's content for device in profile.devices.values(): hid = device.hardware_id wid = device.windows_id dev_id = util.get_device_id(hid, wid) for mode in device.modes.values(): for input_items in mode.config.values(): for input_item in input_items.values(): # Only add callbacks for input items that actually # contain actions if len(input_item.containers) == 0: continue event = event_handler.Event( event_type=input_item.input_type, hardware_id=hid, windows_id=wid, identifier=input_item.input_id) self.event_handler.add_callback( dev_id, mode.name, event, InputItemCallback(input_item), input_item.always_execute) # Create merge axis callbacks for entry in profile.merge_axes: merge_axis = MergeAxis(entry["vjoy"]["device_id"], entry["vjoy"]["axis_id"]) self._merge_axes.append(merge_axis) # Lower axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, hardware_id=entry["lower"]["hardware_id"], windows_id=entry["lower"]["windows_id"], identifier=entry["lower"]["axis_id"]) self.event_handler.add_callback( util.get_device_id(entry["lower"]["hardware_id"], entry["lower"]["windows_id"]), entry["mode"], event, merge_axis.update_axis1, False) # Upper axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, hardware_id=entry["upper"]["hardware_id"], windows_id=entry["upper"]["windows_id"], identifier=entry["upper"]["axis_id"]) self.event_handler.add_callback( util.get_device_id(entry["upper"]["hardware_id"], entry["upper"]["windows_id"]), entry["mode"], event, merge_axis.update_axis2, False) # Create vJoy response curve setups self._vjoy_curves.profile_data = profile.vjoy_devices self.event_handler.mode_changed.connect( self._vjoy_curves.mode_changed) # Use inheritance to build input action lookup table self.event_handler.build_event_lookup(inheritance_tree) # Set vJoy axis default values for vid, data in settings.vjoy_initial_values.items(): vjoy_proxy = joystick_handling.VJoyProxy()[vid] for aid, value in data.items(): vjoy_proxy.axis(aid).set_absolute_value(value) # Connect signals evt_listener = event_handler.EventListener() kb = input_devices.Keyboard() evt_listener.keyboard_event.connect( self.event_handler.process_event) evt_listener.joystick_event.connect( self.event_handler.process_event) evt_listener.keyboard_event.connect(kb.keyboard_event) input_devices.periodic_registry.start() macro.MacroManager().start() self.event_handler.change_mode(start_mode) self.event_handler.resume() self._running = True except ImportError as e: util.display_error( "Unable to launch due to missing custom modules: {}".format( str(e)))
def start(self, inheritance_tree, settings, start_mode, profile): """Starts listening to events and loads all existing callbacks. :param inheritance_tree tree encoding inheritance between the different modes :param settings profile settings to apply at launch :param start_mode the mode in which to start Gremlin :param profile the profile to use when generating all the callbacks """ # Reset states to their default values self._inheritance_tree = inheritance_tree self._reset_state() # Check if we want to override the start mode as determined by the # heuristic if settings.startup_mode is not None: if settings.startup_mode in gremlin.profile.mode_list(profile): start_mode = settings.startup_mode # Set default macro action delay gremlin.macro.MacroManager().default_delay = settings.default_delay # Retrieve list of current paths searched by Python system_paths = [os.path.normcase(os.path.abspath(p)) for p in sys.path] # Load the generated code try: # Populate custom module variable registry var_reg = user_plugin.variable_registry for plugin in profile.plugins: # Perform system path mangling for import statements path, _ = os.path.split( os.path.normcase(os.path.abspath(plugin.file_name)) ) if path not in system_paths: system_paths.append(path) # Load module specification so we can later create multiple # instances if desired spec = importlib.util.spec_from_file_location( "".join(random.choices(string.ascii_lowercase, k=16)), plugin.file_name ) # Process each instance in turn for instance in plugin.instances: # Skip all instances that are not fully configured if not instance.is_configured(): continue # Store variable values in the registry for var in instance.variables.values(): var_reg.set( plugin.file_name, instance.name, var.name, var.value ) # Load the modules tmp = importlib.util.module_from_spec(spec) tmp.__gremlin_identifier = (plugin.file_name, instance.name) spec.loader.exec_module(tmp) # Update system path list searched by Python sys.path = system_paths # Create callbacks fom the user code callback_count = 0 for dev_id, modes in input_devices.callback_registry.registry.items(): for mode, events in modes.items(): for event, callback_list in events.items(): for callback in callback_list.values(): self.event_handler.add_callback( dev_id, mode, event, callback[0], callback[1] ) callback_count += 1 # Add a fake keyboard action which does nothing to the callbacks # in every mode in order to have empty modes be "present" for mode_name in gremlin.profile.mode_list(profile): self.event_handler.add_callback( 0, mode_name, None, lambda x: x, False ) # Create input callbacks based on the profile's content for device in profile.devices.values(): for mode in device.modes.values(): for input_items in mode.config.values(): for input_item in input_items.values(): # Only add callbacks for input items that actually # contain actions if len(input_item.containers) == 0: continue event = event_handler.Event( event_type=input_item.input_type, device_guid=device.device_guid, identifier=input_item.input_id ) # Create possibly several callbacks depending # on the input item's content callbacks = [] for container in input_item.containers: if not container.is_valid(): logging.getLogger("system").warning( "Incomplete container ignored" ) continue callbacks.extend(container.generate_callbacks()) for cb_data in callbacks: if cb_data.event is None: self.event_handler.add_callback( device.device_guid, mode.name, event, cb_data.callback, input_item.always_execute ) else: self.event_handler.add_callback( dill.GUID_Virtual, mode.name, cb_data.event, cb_data.callback, input_item.always_execute ) # Create merge axis callbacks for entry in profile.merge_axes: merge_axis = MergeAxis( entry["vjoy"]["vjoy_id"], entry["vjoy"]["axis_id"], entry["operation"] ) self._merge_axes.append(merge_axis) # Lower axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, device_guid=entry["lower"]["device_guid"], identifier=entry["lower"]["axis_id"] ) self.event_handler.add_callback( event.device_guid, entry["mode"], event, merge_axis.update_axis1, False ) # Upper axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, device_guid=entry["upper"]["device_guid"], identifier=entry["upper"]["axis_id"] ) self.event_handler.add_callback( event.device_guid, entry["mode"], event, merge_axis.update_axis2, False ) # Create vJoy response curve setups self._vjoy_curves.profile_data = profile.vjoy_devices self.event_handler.mode_changed.connect( self._vjoy_curves.mode_changed ) # Use inheritance to build input action lookup table self.event_handler.build_event_lookup(inheritance_tree) # Set vJoy axis default values for vid, data in settings.vjoy_initial_values.items(): vjoy_proxy = joystick_handling.VJoyProxy()[vid] for aid, value in data.items(): vjoy_proxy.axis(linear_index=aid).set_absolute_value(value) # Connect signals evt_listener = event_handler.EventListener() kb = input_devices.Keyboard() evt_listener.keyboard_event.connect( self.event_handler.process_event ) evt_listener.joystick_event.connect( self.event_handler.process_event ) evt_listener.virtual_event.connect( self.event_handler.process_event ) evt_listener.keyboard_event.connect(kb.keyboard_event) evt_listener.gremlin_active = True input_devices.periodic_registry.start() macro.MacroManager().start() self.event_handler.change_mode(start_mode) self.event_handler.resume() self._running = True sendinput.MouseController().start() except ImportError as e: util.display_error( "Unable to launch due to missing user plugin: {}" .format(str(e)) )