def inherit_joystick_dictionary(self): for item in self.joystick_dictionary: for profile in self.joystick_dictionary[item]: if self.joystick_dictionary[item][profile]['Inherit']: helper.log( "{} Profile has inheritance in mode {}".format( item, profile), 'debug') helper.log( "Profile inherits from {}".format( self.joystick_dictionary[item][profile] ['Inherit']), 'debug') inherit = self.joystick_dictionary[item][profile][ 'Inherit'] inherited_profile = self.joystick_dictionary[item][inherit] helper.log( "Inherited Profile Contains {}".format( inherited_profile), 'debug') helper.log( "Starting Profile Contains {}".format( self.joystick_dictionary[item][profile] ['Buttons']), 'debug') for button, desc in inherited_profile['Buttons'].items(): check_button = button in self.joystick_dictionary[ item][profile]['Buttons'] if not check_button: self.joystick_dictionary[item][profile][ 'Buttons'].update({button: desc}) elif self.joystick_dictionary[item][profile][ 'Buttons'][button] == self.no_bind_text: self.joystick_dictionary[item][profile]['Buttons'][ button] = desc helper.log( "Ending Profile Contains {}".format( self.joystick_dictionary[item][profile] ['Buttons']), 'debug')
def inheritProfiles(self): for item in self.formattedButtons: for profile in self.formattedButtons[item]: if self.formattedButtons[item][profile]['Inherit']: helper.log( "{} Profile has inheritance in mode {}".format( item, profile), 'debug') helper.log( "Profile inherits from {}".format( self.formattedButtons[item][profile]['Inherit']), 'debug') inherit = self.formattedButtons[item][profile]['Inherit'] inheritConfig = self.formattedButtons[item][inherit] helper.log( "Inherited Profile Contains {}".format(inheritConfig), 'debug') helper.log( "Starting Profile Contains {}".format( self.formattedButtons[item][profile]['Buttons']), 'debug') for button, desc in inheritConfig['Buttons'].items(): checkButton = button in self.formattedButtons[item][ profile]['Buttons'] if checkButton == False: self.formattedButtons[item][profile][ 'Buttons'].update({button: desc}) elif self.formattedButtons[item][profile]['Buttons'][ button] == self.no_bind_text: self.formattedButtons[item][profile]['Buttons'][ button] = desc helper.log( "Ending Profile Contains {}".format( self.formattedButtons[item][profile]['Buttons']), 'debug')
def create_directory(directory: str) -> bool: if not os.path.exists(directory): try: os.makedirs(directory) return True except PermissionError as e: helper.log(str(e), "error") raise else: return False
def export_to_svg(self, data, parser_type: str): self.export_progress_bar.setValue(0) self.clear_info() self.print_to_info("Export Started") exporter = export.Export(data, parser_type) success = exporter.export_config(self.export_progress_bar) for item in success: self.print_to_info(item) self.print_to_info("Export Finished") helper.log(str(success), 'info')
def create_directory(self,directory): if not os.path.exists(directory): try: return os.makedirs(directory) except PermissionError as e: helper.log(e, "error") raise else: return False else: return False
def save_template(self, joystick, mode, template): output_path = self.export_directory + self.executor + "_" + joystick + "_" + mode + ".svg" if not os.path.exists(self.export_directory): self.create_directory(self.export_directory) try: output_file = open(output_path, "w", encoding="UTF-8") output_file.write(template) output_file.close() except PermissionError as e: helper.log(str(e) + 'error') raise
def __validate_profiles(self) -> list[str]: """ Validate Profiles Routine """ if len(self.base_directory) <= 0: raise FileExistsError("DCS: No profiles exist in Input directory!") valid_items: list[str] = [] for item in self.base_directory: valid = self.__validate_profile(item) if not valid: helper.log( "DCS: Profile {} has no joystick directory files".format( item)) continue valid_items.append(item) return valid_items
def __validateProfiles(self): ''' Validate Profiles Routine ''' if len(self.base_directory) > 0: valid_items = [] for item in self.base_directory: valid = self.__validateProfile(item) if valid: valid_items.append(item) else: helper.log( "DCS: Profile {} has no joystick directory files". format(item)) else: raise FileExistsError("DCS: No profiles exist in Input directory!") return valid_items
def refresh(self): if self.selected_device_id not in self.deviceState: log(f"{self.selected_device_id} not found in {self.deviceState}") return selected_device = self.deviceState[self.selected_device_id] selected_device_name = selected_device.deviceName if selected_device_name in self._template_cache: base_template = self._template_cache[selected_device_name] else: # TODO: we need mapping here as not all devices are the same reported e.g virpil device_template_path = Path( os.path.join("templates", f"{selected_device_name}.svg")) if not device_template_path.exists(): log(f"{selected_device_name} not found in templates", "error") return templater = Templater(device_template_path, brand_template=selected_device_name) # TODO: pull real bindings here: currently this is a dummy temp_bindings_buttons = selected_device.buttons.keys() templater.replace_with_bindings( dict(zip(temp_bindings_buttons, temp_bindings_buttons))) base_template = templater.get_template_as_bytes() if not base_template: log(f"{selected_device_name} not found in templates", "error") return self._template_cache[selected_device_name] = base_template # start = time() # TODO 1: cache parsed tree and use references for switching # TODO 2: use stax parser tree = etree.parse(BytesIO(base_template)) # print(f"etree parse {(time() - start) * 1000:.2f}ms") for button_name, pressed in selected_device.buttons.items(): if not pressed: continue # start = time() # TODO: we could use XPath class to only compile once # TODO: usually you would do something lie /svg:svg/svg:g/svg:rect[@id='Button_1'] but somehow this seems to not work # TODO: don't map unbound buttons by checking list length button_in_xml = tree.xpath( f"/svg:svg/svg:g/svg:rect[@id='{button_name}_rect']", namespaces={'svg': 'http://www.w3.org/2000/svg'})[0] # print(f"xpath {(time() - start) * 1000:.2f}ms") button_in_xml.attrib['fill'] = 'red' new_bytes = etree.tostring(tree) if new_bytes != self._old_template: log(f"update render for {self.selected_device_id}") self.load(new_bytes) self._old_template = new_bytes self.update()
def exportGremlin(): parsedConfig = gremlin.Gremlin(selectedFile) devices = parsedConfig.createDictionary() global runState runState = [] for joystick in devices: for mode in devices[joystick]: success = helper.exportDevice(devices, joystick, mode) helper.log(success, 'debug') # Log failures if success[0] == False and success[1] not in runState: helper.log( "Device: {} does not have a valid template".format( success[1]), 'debug') runState.append(success[1]) if (len(runState) > 0): errorText = "The following devices did not have matching templates in /templates. \n\n Device names must match the template name exactly.\n" for item in runState: errorText = errorText + '\n' + item errorText = errorText + '\n\n' + "No diagrams have been created for the above" message(errorText) helper.log(errorText, 'warning')
def create_dictionary(self, profiles: list[str] = None ) -> dict[str, dict[str, dict]]: if profiles is None: profiles = [] self.devices = self.get_devices() helper.log(f"Number of Devices: {len(self.devices)}", 'debug') using_inheritance = False for device in self.devices: current_device = device.attrib['name'] modes = device.findall('mode') helper.log( f"All Modes: {list(map(lambda e: e.attrib['name'], modes))}") for mode in modes: current_inherit, using_inheritance = self.extract_inheritance( mode) current_mode = mode.attrib['name'] helper.log(f"Selected Mode: {current_mode}", 'debug') buttons = mode.findall('button') button_array = self.extract_buttons(buttons) self.update_joystick_dictionary(current_device, current_mode, current_inherit, button_array) if using_inheritance: self.inherit_joystick_dictionary() self.filter_dictionary(profiles) return self.joystick_dictionary else: self.filter_dictionary(profiles) return self.joystick_dictionary
def export_to_svg(self, data, parser_type): self.export_progress_bar.setValue(0) data = data type = parser_type joycount = len(data) run_state = [] for joystick in data: for mode in data[joystick]: success = helper.exportDevice(type, data, joystick, mode) helper.log(success, 'debug') # Log failures if success[0] == False and success[1] not in run_state: helper.log( "Device: {} does not have a valid template".format( success[1]), 'debug') run_state.append(success[1]) self.export_progress_bar.setValue( self.export_progress_bar.value() + int(100 / joycount)) if (len(run_state) > 0): errorText = "The following devices did not have matching templates in /templates. \n\n Device names must match the template name exactly.\n" for item in run_state: errorText = errorText + '\n' + item errorText = errorText + '\n\n' + "No diagrams have been created for the above" helper.log(errorText, 'warning') self.print_to_info(errorText)
def createDictionary(self, profiles=[]): self.profiles = profiles self.devices = self.getDevices() helper.log("Number of Devices: {}".format(str(self.devices.length)), 'debug') for self.device in self.devices: self.currentdevice = self.getSingleDevice() self.modes = self.getDeviceModes() helper.log("All Modes: {}".format(self.modes)) for self.mode in self.modes: self.currentInherit = self.hasInheritance() self.buttonArray = {} self.currentMode = self.getSingleMode() helper.log("Selected Mode: {}".format(self.currentMode), 'debug') self.buttons = self.getModeButtons() self.extractButtons() self.update_joystick_dictionary(self.currentdevice, self.currentMode, self.currentInherit, self.buttonArray) if self.usingInheritance: self.inherit_joystick_dictionary() self.filter_dictionary() return self.joystick_dictionary else: self.filter_dictionary() return self.joystick_dictionary
def refresh(self): if self.device_render_display: known_devices: list[str] = [] currently_connected_devices = len(self.deviceState) if currently_connected_devices != self._connected_devices: self._connected_devices = currently_connected_devices log(f"Updating {currently_connected_devices} devices") # Add new devices for device_id, device_state in self.deviceState.items(): known_devices.append(device_state.deviceName) stick_present = False for i in range(self.stick_selector.count()): if self.stick_selector.itemText( i) != device_state.deviceName: continue log(f"device {device_state.deviceName} found") stick_present = True if not stick_present: log(f"adding new device {device_state.deviceName}") switch_action = QtWidgets.QAction(self.stick_selector) switch_action.setText(device_id) self.stick_selector.addItem( device_state.deviceName, QtCore.QVariant(switch_action)) log(f"known devices: {known_devices}") # Cleanup devices that not anymore connected for i in range(self.stick_selector.count()): item_text = self.stick_selector.itemText(i) if item_text not in known_devices: log(f"removing item {item_text}") self.stick_selector.removeItem(i) self.device_render_display.refresh()
def run(self): clock = pygame.time.Clock() while not self.isInterruptionRequested(): for event in pygame.event.get(): if event.type == pygame.QUIT: # TODO: do something with these events # log("Quit pressed") pass elif event.type == pygame.JOYBUTTONDOWN: # TODO: do something with these events # log("Joystick button pressed.") pass elif event.type == pygame.JOYBUTTONUP: # TODO: do something with these events # log("Joystick button released.") pass joystick_count = pygame.joystick.get_count() for i in range(joystick_count): joystick = pygame.joystick.Joystick(i) joystick.init() try: jid = joystick.get_instance_id() except AttributeError: # get_instance_id() is an SDL2 method jid = joystick.get_id() device_id = f"Joystick {jid}" # Get the name from the OS for the controller/joystick. name = joystick.get_name() if jid not in self._deviceState: self._deviceState[device_id] = DeviceState(device_id, name) device_state = self._deviceState[device_id] try: guid = joystick.get_guid() except AttributeError: # get_guid() is an SDL2 method pass else: device_state.guid = guid # Usually axis run in pairs, up/down for one, and left/right for the other. axes = joystick.get_numaxes() for j in range(axes): axis = joystick.get_axis(j) device_state.axes[f"Axis_{j + 1}"] = axis buttons = joystick.get_numbuttons() for j in range(buttons): button = joystick.get_button(j) device_state.buttons[f"Button_{j + 1}"] = button hats = joystick.get_numhats() # Hat position. All or nothing for direction, not a float like get_axis(). Position is a tuple of int # values (x, y). for j in range(hats): hat = joystick.get_hat(j) device_state.hats[f"Hat_{j + 1}"] = hat # # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT # # Limit to 20 frames per second. clock.tick(20) log(f"render {clock}") self._refresher()
def _switch_stick(self): switch_action: QtWidgets.QAction = self.stick_selector.itemData( self.stick_selector.currentIndex()) self.device_render_display.selected_device_id = switch_action.text() log(f"switch selected device to {self.device_render_display.selected_device_id}" )
"Exporting the following profile(s): {}".format(profiles)) data = self.dcs_parser_instance.processProfiles(profiles) else: data = self.dcs_parser_instance.processProfiles() self.export_to_svg(data, 'DCS') else: pass # no other tabs have functionality right now def export_to_svg(self, data, parser_type): self.export_progress_bar.setValue(0) self.clear_info() self.print_to_info("Export Started") exporter = export.Export(data, parser_type) success = exporter.export_config(self.export_progress_bar) for item in success: self.print_to_info(item) self.print_to_info("Export Finished") helper.log(success, 'info') if __name__ == '__main__': try: app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() app.exec() except Exception as error: helper.log(error, "error") raise
text="Open diagrams folder", bg="white", anchor="e", padx=(15), font=buttonFont, command=openDiagramsDirectory, compound="left") nlist.pack() selected_item_button.pack() selected_item_label.pack() gremlinLogo.grid(row=0, column=3) bugLogo.grid(row=0, column=2) step_1_info.grid(row=1, column=0, sticky="W") chooseFile.grid(row=1, column=1) step_2_info.grid(row=2, column=0, sticky="W") step_2_button.grid(row=2, column=1) step_2_secondary.grid(row=3, column=0) step_3_info.grid(row=4, column=0, sticky="W") step_3_button.grid(row=4, column=1, sticky="W") step_3_secondary.grid(row=5, column=0, sticky="W") version.grid(row=5, column=3, sticky="E") info.grid(row=5, column=1) helper.log(helper.getVersion(), 'warning') root.mainloop()
def export_to_svg(self, data, parser_type: str): self.export_progress_bar.setValue(0) self.clear_info() self.print_to_info("Export Started") exporter = export.Export(data, parser_type) success = exporter.export_config(self.export_progress_bar) for item in success: self.print_to_info(item) self.print_to_info("Export Finished") helper.log(str(success), 'info') if __name__ == '__main__': try: pygame.init() app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() visualizerWindow = VisualizerWindow() visualizerWindow.show() app.exec() except Exception as error: helper.log(str(error), "error") raise pygame.quit()
def openDiagramsDirectory(): helper.log(os.getcwd(), 'error') path = os.path.join(os.getcwd(), 'diagrams') helper.log(path, 'error') FILEBROWSER_PATH = os.path.join(os.getenv('WINDIR'), 'explorer.exe') subprocess.run([FILEBROWSER_PATH, path])