diff --git a/joystick_diagrams/plugins/joystick_gremlin_plugin/joystick_gremlin.py b/joystick_diagrams/plugins/joystick_gremlin_plugin/joystick_gremlin.py
index 411cdee..59526a4 100644
--- a/joystick_diagrams/plugins/joystick_gremlin_plugin/joystick_gremlin.py
+++ b/joystick_diagrams/plugins/joystick_gremlin_plugin/joystick_gremlin.py
@@ -4,7 +4,6 @@
"""
import logging
from pathlib import Path
-from typing import Union
from xml.dom import minidom
from joystick_diagrams.exceptions import JoystickDiagramsError
@@ -25,15 +24,27 @@
8: "UL",
}
+VIRTUAL_HAT_POSITIONS = {
+ "north": HAT_POSITIONS[1],
+ "north-east": HAT_POSITIONS[2],
+ "east": HAT_POSITIONS[3],
+ "south-east": HAT_POSITIONS[4],
+ "south": HAT_POSITIONS[5],
+ "south-west": HAT_POSITIONS[6],
+ "west": HAT_POSITIONS[7],
+ "north-west": HAT_POSITIONS[8],
+}
+
class JoystickGremlinParser:
def __init__(self, filepath: Path):
- self.file = self.parse_xml_file(filepath)
+ import os
- def parse_xml_file(self, xml_file: Path) -> minidom.Document:
- file_path = str(xml_file)
- parsed_xml = minidom.parse(file_path)
+ _logger.debug(os.access(Path(filepath), os.R_OK))
+ self.file = self.parse_xml_file(Path(filepath))
+ def parse_xml_file(self, xml_file: Path) -> minidom.Document:
+ parsed_xml = minidom.parse(str(xml_file))
valid = self.validate_xml(parsed_xml)
if valid:
@@ -102,7 +113,7 @@ def create_dictionary(self) -> ProfileCollection:
return profile_collection
- def extract_hats(self, hat_node) -> list[Union[str, str] | None]:
+ def extract_hats(self, hat_node: minidom.Element) -> list[tuple[Hat, str]]:
"""Extract the hat positions for a given HAT node.
Each HAT node may contain a CONTAINER, which may contain N number of action-set nodes
@@ -114,47 +125,140 @@ def extract_hats(self, hat_node) -> list[Union[str, str] | None]:
hat_description: str = hat_node.getAttribute("description") or ""
hat_mappings: list = []
- _logger.debug("Hat ID: {hat_id}")
- _logger.debug("Hat has description: {hat_description}")
+ _logger.debug(f"Hat ID: {hat_id}")
+ _logger.debug(f"Hat has description: {hat_description}")
# Get the containers
- hat_container = hat_node.getElementsByTagName("container")
+ hat_containers = hat_node.getElementsByTagName("container")
- if not hat_container:
+ if not hat_containers:
return hat_mappings
- _logger.debug("Has containers: {hat_containers.length}")
+ # Gather container types
+ basic_containers = [
+ x for x in hat_containers if x.getAttribute("type") == "basic"
+ ]
+ filtered_hat_containers = [
+ x for x in hat_containers if x.getAttribute("type") == "hat_buttons"
+ ]
+
+ _logger.debug(f"Basic Containers: {len(basic_containers)}")
+ _logger.debug(f"Hat Containers: {len(filtered_hat_containers)}")
+
+ if filtered_hat_containers:
+ hat_mappings = self.handle_hat_button_container(
+ hat_id, filtered_hat_containers
+ )
+
+ if basic_containers:
+ hat_mappings = self.handle_virtual_button_container(hat_id, hat_containers)
- hat_positions = hat_container[0].getElementsByTagName("action-set")
+ return hat_mappings
+ def handle_virtual_button_container(
+ self, hat_id, containers: minidom.NodeList[minidom.Element]
+ ):
hat_mappings = []
+ for container in containers:
+ # Check if we have a top level description
+ container_description = (
+ container.getAttribute("description")
+ if container.getAttribute("description") != ""
+ else None
+ )
- for position in hat_positions:
- # Get REMAP of node (assumes 1)
- hat_position_id = int(
- position.getElementsByTagName("remap")[0].getAttribute("button")
+ # Try source description from inner block
+ if not container_description:
+ container_description = " - ".join(
+ {
+ x.getAttribute("description")
+ for x in container.getElementsByTagName("description")
+ }
+ )
+
+ # Skip processing if we have no descriptions
+ if not container_description:
+ print("No point continuing")
+ continue
+
+ virtual_buttons: minidom.Element = container.getElementsByTagName(
+ "virtual-button"
)
- # Get the description node if exists
- hat_description_check = position.getElementsByTagName("description")
+ if not virtual_buttons:
+ # If we don't have virtual buttons we have no hats to process
+ continue
- # If no node then continue
- if not hat_description_check:
+ if len(virtual_buttons) != 1:
+ print("Not expected number of virtual button elements")
continue
- hat_description = hat_description_check[0].getAttribute("description")
+ attributes = [x for x in virtual_buttons[0].attributes.keys()]
- if not hat_description:
- # If we don't have a description then no point using the item
- continue
+ for attribute in attributes:
+ hat_mappings.append(
+ (
+ Hat(hat_id, HatDirection[VIRTUAL_HAT_POSITIONS[attribute]]),
+ container_description,
+ )
+ )
- hat_position_to_string = HAT_POSITIONS[hat_position_id]
- hat_mappings.append(
- [Hat(hat_id, HatDirection[hat_position_to_string]), hat_description]
- )
+ return hat_mappings
+
+ def handle_hat_button_container(
+ self, hat_id, hat_containers: minidom.NodeList[minidom.Element]
+ ):
+ four_way_hat = 4
+
+ for container in hat_containers:
+ button_count = int(container.getAttribute("button-count"))
+
+ hat_positions = container.getElementsByTagName("action-set")
+
+ hat_mappings = []
+
+ # Iterate each ACTION_SET, for the HAT_BUTTONS
+ for hat_direction_no, position in enumerate(hat_positions, 1):
+ # Get the description node if exists
+ hat_description_node = position.getElementsByTagName("description")
+
+ hat_direction = hat_direction_no
+
+ if button_count == four_way_hat:
+ hat_direction = hat_direction_no + (hat_direction_no - 1)
+
+ # If no node then continue
+ if not hat_description_node:
+ continue
+
+ # What if multiple hat_description_nodes
+
+ hat_description = hat_description_node[0].getAttribute("description")
+
+ if not hat_description:
+ # If we don't have a description then no point using the item
+ continue
+
+ hat_position_to_string = HAT_POSITIONS[hat_direction]
+ hat_mappings.append(
+ (Hat(hat_id, HatDirection[hat_position_to_string]), hat_description)
+ )
return hat_mappings
if __name__ == "__main__":
- pass
+ pars = JoystickGremlinParser(
+ Path(
+ r"D:\Git Repos\joystick-diagrams\tests\data\joystick_gremlin\gremlin_pov_container_hat_buttons.xml"
+ )
+ )
+ # pars = JoystickGremlinParser(
+ # Path(
+ # r"D:\Git Repos\joystick-diagrams\tests\data\joystick_gremlin\gremlin_hat_virtual_buttons.xml"
+ # )
+ # )
+
+ _logger.setLevel(logging.DEBUG)
+ data = pars.create_dictionary()
+ print(data)
diff --git a/tests/data/joystick_gremlin/gremlin_hat_virtual_buttons.xml b/tests/data/joystick_gremlin/gremlin_hat_virtual_buttons.xml
new file mode 100644
index 0000000..f04bf5f
--- /dev/null
+++ b/tests/data/joystick_gremlin/gremlin_hat_virtual_buttons.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.05
+
+
+
diff --git a/tests/data/joystick_gremlin/gremlin_no_inherit.xml b/tests/data/joystick_gremlin/gremlin_no_inherit.xml
deleted file mode 100644
index 5ef3e62..0000000
--- a/tests/data/joystick_gremlin/gremlin_no_inherit.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0.05
-
-
-
diff --git a/tests/data/joystick_gremlin/gremlin_pov_4_8.xml b/tests/data/joystick_gremlin/gremlin_pov_4_8.xml
deleted file mode 100644
index 9dc961a..0000000
--- a/tests/data/joystick_gremlin/gremlin_pov_4_8.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0.05
-
-
-
diff --git a/tests/data/joystick_gremlin/gremlin_pov_multi.xml b/tests/data/joystick_gremlin/gremlin_pov_container_hat_buttons.xml
similarity index 79%
rename from tests/data/joystick_gremlin/gremlin_pov_multi.xml
rename to tests/data/joystick_gremlin/gremlin_pov_container_hat_buttons.xml
index 37ef691..02b95a6 100644
--- a/tests/data/joystick_gremlin/gremlin_pov_multi.xml
+++ b/tests/data/joystick_gremlin/gremlin_pov_container_hat_buttons.xml
@@ -8,56 +8,63 @@
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
diff --git a/tests/data/joystick_gremlin/gremlin_pov_single.xml b/tests/data/joystick_gremlin/gremlin_pov_single.xml
deleted file mode 100644
index 5cc69b0..0000000
--- a/tests/data/joystick_gremlin/gremlin_pov_single.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0.05
-
-
-