Apply offline wiresheet rules to live mode: meta positions and links
Three fixes so live wiresheets render identically to offline .sax files: 1. Inherit sys::Component base slots (meta) into every type's slot registry so component x/y positions are read from the device. 2. Place <link> elements under a <links> container element instead of directly under <app>, matching the .sax structure that draw_links and build_linked_slot_index expect. 3. Deduplicate links (each link appears on both endpoints in Sox) so wires are not drawn twice. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it.
|
|||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
|
|
||||||
VERSION = "0.0.0.083"
|
VERSION = "0.0.0.084"
|
||||||
PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties")
|
PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties")
|
||||||
DEFAULT_GRID_SIZE = 10
|
DEFAULT_GRID_SIZE = 10
|
||||||
DEFAULT_ADD_TIMESTAMP = True
|
DEFAULT_ADD_TIMESTAMP = True
|
||||||
|
|||||||
+47
-5
@@ -68,15 +68,49 @@ class DeviceSession:
|
|||||||
def _load_slot_registry(self, parts):
|
def _load_slot_registry(self, parts):
|
||||||
"""Builds slot_registry from kit manifests for the device's schema."""
|
"""Builds slot_registry from kit manifests for the device's schema."""
|
||||||
registry = {}
|
registry = {}
|
||||||
|
base_slots = []
|
||||||
for kit_id, part in enumerate(parts):
|
for kit_id, part in enumerate(parts):
|
||||||
kit_name = part.name
|
kit_name = part.name
|
||||||
checksum = part.checksum
|
checksum = part.checksum
|
||||||
manifest = schema.find_manifest(kit_name, checksum)
|
manifest = schema.find_manifest(kit_name, checksum)
|
||||||
if manifest is None:
|
if manifest is None:
|
||||||
continue
|
continue
|
||||||
|
if kit_name == "sys":
|
||||||
|
base_slots = self._extract_component_base_slots(manifest)
|
||||||
self._register_kit_types(registry, kit_id, kit_name, manifest)
|
self._register_kit_types(registry, kit_id, kit_name, manifest)
|
||||||
|
# Prepend inherited Component base slots (meta, etc.) to every type
|
||||||
|
if base_slots:
|
||||||
|
for key in registry:
|
||||||
|
existing_names = {s["name"] for s in registry[key]}
|
||||||
|
for bs in base_slots:
|
||||||
|
if bs["name"] not in existing_names:
|
||||||
|
registry[key].insert(0, bs)
|
||||||
self.sox_client.slot_registry = registry
|
self.sox_client.slot_registry = registry
|
||||||
|
|
||||||
|
def _extract_component_base_slots(self, manifest):
|
||||||
|
"""Extracts base slots from sys::Component that all types inherit."""
|
||||||
|
for type_elem in manifest.iter("type"):
|
||||||
|
if type_elem.get("name") == "Component":
|
||||||
|
slots = []
|
||||||
|
for slot_elem in type_elem.iter("slot"):
|
||||||
|
slot_name = slot_elem.get("name", "")
|
||||||
|
slot_id = int(slot_elem.get("id", "-1"))
|
||||||
|
slot_type = slot_elem.get("type", "int")
|
||||||
|
flags_str = slot_elem.get("flags", "")
|
||||||
|
slots.append({
|
||||||
|
"name": slot_name,
|
||||||
|
"id": slot_id,
|
||||||
|
"type_name": slot_type,
|
||||||
|
"is_config": "c" in flags_str or "p" in flags_str,
|
||||||
|
"is_runtime": "r" in flags_str,
|
||||||
|
"is_action": "a" in flags_str,
|
||||||
|
"is_operator": "o" in flags_str,
|
||||||
|
"is_as_str": slot_type == "Str",
|
||||||
|
"is_prop": "a" not in flags_str,
|
||||||
|
})
|
||||||
|
return slots
|
||||||
|
return []
|
||||||
|
|
||||||
def _register_kit_types(self, registry, kit_id, kit_name, manifest):
|
def _register_kit_types(self, registry, kit_id, kit_name, manifest):
|
||||||
root = manifest
|
root = manifest
|
||||||
for type_elem in root.iter("type"):
|
for type_elem in root.iter("type"):
|
||||||
@@ -239,14 +273,22 @@ class DeviceSession:
|
|||||||
return comp_elem
|
return comp_elem
|
||||||
|
|
||||||
def build_links_elements(self, sax_root):
|
def build_links_elements(self, sax_root):
|
||||||
"""Adds <link> elements under the app element from cached link data."""
|
"""Adds <link> elements under a <links> container, matching .sax structure."""
|
||||||
app_elem = sax_root.find("app")
|
links_elem = sax_root.find("links")
|
||||||
if app_elem is None:
|
if links_elem is None:
|
||||||
return
|
links_elem = ET.SubElement(sax_root, "links")
|
||||||
|
|
||||||
|
seen = set()
|
||||||
for c in self.sox_client.cache:
|
for c in self.sox_client.cache:
|
||||||
if c is None:
|
if c is None:
|
||||||
continue
|
continue
|
||||||
for lnk in c.links:
|
for lnk in c.links:
|
||||||
|
link_key = (lnk.from_comp_id, lnk.from_slot_id,
|
||||||
|
lnk.to_comp_id, lnk.to_slot_id)
|
||||||
|
if link_key in seen:
|
||||||
|
continue
|
||||||
|
seen.add(link_key)
|
||||||
|
|
||||||
from_comp = self.sox_client.cache_get(lnk.from_comp_id)
|
from_comp = self.sox_client.cache_get(lnk.from_comp_id)
|
||||||
to_comp = self.sox_client.cache_get(lnk.to_comp_id)
|
to_comp = self.sox_client.cache_get(lnk.to_comp_id)
|
||||||
if from_comp is None or to_comp is None:
|
if from_comp is None or to_comp is None:
|
||||||
@@ -261,7 +303,7 @@ class DeviceSession:
|
|||||||
to_path = self._comp_path(lnk.to_comp_id)
|
to_path = self._comp_path(lnk.to_comp_id)
|
||||||
|
|
||||||
if from_path and to_path and from_slot_name and to_slot_name:
|
if from_path and to_path and from_slot_name and to_slot_name:
|
||||||
ET.SubElement(app_elem, "link",
|
ET.SubElement(links_elem, "link",
|
||||||
**{"from": f"{from_path}.{from_slot_name}",
|
**{"from": f"{from_path}.{from_slot_name}",
|
||||||
"to": f"{to_path}.{to_slot_name}"})
|
"to": f"{to_path}.{to_slot_name}"})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user