86 lines
3.5 KiB
Python
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
|