kiconnect/freecad/kiconnect/parts.py
2025-05-19 21:23:11 -07:00

86 lines
3.5 KiB
Python

import os
import ImportGui
import FreeCADGui as Gui
import FreeCAD as App
import Materials
import Part
from kipy import KiCad
from kipy.board_types import Footprint3DModel, BoardPolygon, BoardSegment, PadStackShape
from kipy.util.board_layer import BoardLayer
from . import settings
from .bases import BaseObject, BaseViewProvider
class PartsObject(BaseObject):
TYPE = 'KiConnect::Parts'
def __init__(self, feature):
super(PartsObject, self).__init__(feature)
def execute(self, feature):
super(PartsObject, self).execute(feature)
def sync_from(self):
kiconn_board = self.feature.getParentGroup()
kicad_board = self.get_api().kicad.get_board()
existing_footprints_by_ref = { part.KiCadRef: part for part in self.feature.Group }
for footprint in kicad_board.get_footprints():
# NOTE this doesn't handle footprints that have been removed
reference = footprint.reference_field.text.value
if reference in existing_footprints_by_ref:
model = existing_footprints_by_ref[reference]
placement = App.Placement()
placement.Base.x = (footprint.position.x / 1000000.0) - kiconn_board.BoardOffset.Base.x
placement.Base.y = (-footprint.position.y / 1000000.0) - kiconn_board.BoardOffset.Base.y
# TODO get from kicad board settings
placement.Base.z = 0.8
placement.Rotation.Angle = footprint.orientation.to_radians()
if model.Placement != placement:
model.Placement = placement
continue
for item in [item for item in footprint.definition.items if isinstance(item, Footprint3DModel)]:
filename = item.filename.replace('${KICAD9_3DMODEL_DIR}', settings.KICAD9_3DMODEL_DIR).replace('wrl', 'step')
try:
ImportGui.insert(filename, App.ActiveDocument.Name)
# simply grabs the last object in the document, probably need to figure out a safer way to handle
model = App.ActiveDocument.findObjects()[-1]
model.Label = reference
model.Label2 = reference
model.addProperty('App::PropertyPlacement', 'BoardOffset', 'Base', 'Internal offset for zeroing out Footprint offset', hidden=True, read_only=True)
model.addProperty('App::PropertyString', 'KiCadRef', 'KiConnect', 'Original KiCAD REF', hidden=True, read_only=True)
model.KiCadRef = reference
self.feature.addObject(model)
model.Placement.Base.x = (footprint.position.x / 1000000.0) - kiconn_board.BoardOffset.Base.x
model.Placement.Base.y = (-footprint.position.y / 1000000.0) - kiconn_board.BoardOffset.Base.y
# TODO get from kicad board settings
model.Placement.Base.z = 0.8
model.Placement.Rotation.Angle = footprint.orientation.to_radians()
model.BoardOffset = model.Placement
except Exception as e:
print('failed to load', filename)
print(e)
class PartsViewProvider(BaseViewProvider):
ICON = 'icon_footprint_browser.svg'
TYPE = 'KiConnect::Parts'
def makeParts(parent):
feature = App.ActiveDocument.addObject('App::DocumentObjectGroupPython', 'Parts')
parent.addObject(feature)
PartsObject(feature)
PartsViewProvider(feature.ViewObject)
return feature