def process_event(self, event, value): if self.input_type == InputType.JoystickAxis: if self.axis_mode == "absolute": joystick_handling.VJoyProxy()[self.vjoy_device_id] \ .axis(self.vjoy_input_id).value = value.current else: self.should_stop_thread = abs(event.value) < 0.05 self.axis_delta_value = \ value.current * (self.axis_scaling / 1000.0) self.thread_last_update = time.time() if self.thread_running is False: if isinstance(self.thread, threading.Thread): self.thread.join() self.thread = threading.Thread( target=self.relative_axis_thread) self.thread.start() elif self.input_type == InputType.JoystickButton: if event.event_type in [InputType.JoystickButton, InputType.Keyboard] \ and event.is_pressed \ and self.needs_auto_release: input_devices.ButtonReleaseActions().register_button_release( (self.vjoy_device_id, self.vjoy_input_id), event) joystick_handling.VJoyProxy()[self.vjoy_device_id] \ .button(self.vjoy_input_id).is_pressed = value.current elif self.input_type == InputType.JoystickHat: joystick_handling.VJoyProxy()[self.vjoy_device_id] \ .hat(self.vjoy_input_id).direction = value.current return True
def relative_axis_thread(self): self.thread_running = True vjoy_dev = joystick_handling.VJoyProxy()[self.vjoy_device_id] self.axis_value = vjoy_dev.axis(self.vjoy_input_id).value while self.thread_running: try: # If the vjoy value has was changed from what we set it to # in the last iteration, terminate the thread change = vjoy_dev.axis( self.vjoy_input_id).value - self.axis_value if abs(change) > 0.0001: self.thread_running = False self.should_stop_thread = True return self.axis_value = max( -1.0, min(1.0, self.axis_value + self.axis_delta_value)) vjoy_dev.axis(self.vjoy_input_id).value = self.axis_value if self.should_stop_thread and \ self.thread_last_update + 1.0 < time.time(): self.thread_running = False time.sleep(0.01) except gremlin.error.VJoyError: self.thread_running = False
def process_event(self, event, value): if self.input_type == InputType.JoystickAxis: joystick_handling.VJoyProxy()[self.vjoy_device_id] \ .axis(self.vjoy_input_id).value = value.current elif self.input_type == InputType.JoystickButton: if event.event_type in [InputType.JoystickButton, InputType.Keyboard] \ and event.is_pressed \ and self.needs_auto_release: input_devices.ButtonReleaseActions().register_button_release( (self.vjoy_device_id, self.vjoy_input_id), event) joystick_handling.VJoyProxy()[self.vjoy_device_id] \ .button(self.vjoy_input_id).is_pressed = value.current elif self.input_type == InputType.JoystickHat: joystick_handling.VJoyProxy()[self.vjoy_device_id] \ .hat(self.vjoy_input_id).direction = value.current return True
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)) )