logical_layers/backend/resolvers.py

112 lines
3.6 KiB
Python

# backend/resolvers.py
import pcbnew
def get_item_uuid(item):
"""
Robustly retrieve the UUID string from a KiCad item.
Prioritizes m_Uuid property (KiCad 9 SWIG) over GetKIID().
"""
if not item: return None
try:
# KiCad 9 / SWIG property access
if hasattr(item, 'm_Uuid'):
return item.m_Uuid.AsString()
# Legacy / Alternative accessor
if hasattr(item, 'GetKIID'):
return item.GetKIID().AsString()
except:
pass
return None
def resolve_to_trackable_item(item):
"""
Resolves an item to the actual object we want to track.
- If item is a Pad/Text/Shape inside a Footprint -> Returns the Footprint.
- If item is a Group -> Returns None (we track contents, not groups).
- Otherwise -> Returns the item itself.
"""
if not item: return None
cls = item.GetClass()
if cls == "PCB_GROUP":
return None
# Check for Parent (e.g. Pad -> Footprint)
parent = item.GetParent()
if parent and parent.GetClass() == "FOOTPRINT":
return parent
return item
def cast_item(item):
"""
Casts a generic BOARD_ITEM to its specific class type.
Required for methods like Serialize or Format to work correctly.
"""
if not item: return None
# Try generic Cast() first (Available on some BOARD_ITEM wrappers)
if hasattr(item, 'Cast'):
try:
return item.Cast()
except:
pass
# Fallback to manual casting based on class name
cls = item.GetClass()
try:
if cls == "FOOTPRINT": return pcbnew.Cast_to_FOOTPRINT(item)
if cls == "PCB_TRACK": return pcbnew.Cast_to_PCB_TRACK(item)
if cls == "PCB_VIA": return pcbnew.Cast_to_PCB_VIA(item)
if cls == "PCB_ARC": return pcbnew.Cast_to_PCB_ARC(item)
if cls == "PCB_SHAPE": return pcbnew.Cast_to_PCB_SHAPE(item)
if cls == "PCB_TEXT": return pcbnew.Cast_to_PCB_TEXT(item)
if cls == "PCB_TEXTBOX": return pcbnew.Cast_to_PCB_TEXTBOX(item)
if cls == "ZONE": return pcbnew.Cast_to_ZONE(item)
if cls == "PCB_GROUP": return pcbnew.Cast_to_PCB_GROUP(item)
if cls == "PCB_TARGET": return pcbnew.Cast_to_PCB_TARGET(item)
if cls == "PCB_DIM_ALIGNED": return pcbnew.Cast_to_PCB_DIM_ALIGNED(item)
if cls == "PCB_DIM_ORTHOGONAL": return pcbnew.Cast_to_PCB_DIM_ORTHOGONAL(item)
if cls == "PCB_DIM_CENTER": return pcbnew.Cast_to_PCB_DIM_CENTER(item)
if cls == "PCB_DIM_LEADER": return pcbnew.Cast_to_PCB_DIM_LEADER(item)
if cls == "PCB_DIM_RADIAL": return pcbnew.Cast_to_PCB_DIM_RADIAL(item)
except:
pass
return item
def find_item_by_uuid(board, uuid):
"""
Locates an item on the board by its UUID string.
Checks standard lists (Tracks, Footprints, Drawings, Zones).
Returns a CAST item (specific type) if found.
"""
item = None
if hasattr(board, 'GetItem'):
try:
item = board.GetItem(pcbnew.KIID(uuid))
except: pass
if not item:
# Fallback lists for older API or if GetItem fails
lists = []
try: lists.append(board.GetTracks())
except: pass
try: lists.append(board.GetFootprints())
except: pass
try: lists.append(board.GetDrawings())
except: pass
try: lists.append(board.Zones())
except: pass
for lst in lists:
for candidate in lst:
if get_item_uuid(candidate) == uuid:
item = candidate
break
if item: break
if item:
return cast_item(item)
return None