diff --git a/MultiExport.FCMacro b/MultiExport.FCMacro index a9dc5ae..8b31008 100755 --- a/MultiExport.FCMacro +++ b/MultiExport.FCMacro @@ -4,11 +4,31 @@ import FreeCADGui import Draft import os import Mesh +from PySide2.QtWidgets import QWidget, QLabel, QSpinBox, QHBoxLayout, QListWidgetItem +class ObjectListItem(QWidget): + def __init__(self, obj): + super().__init__() + self.obj = obj + self.label = QLabel(obj.Label) + self.spinbox = QSpinBox() + self.spinbox.setRange(0, 9999) + self.spinbox.setValue(1) + + layout = QHBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.spinbox) + layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(layout) + + def get_value(self): + return self.spinbox.value() + class WindowDialog(): def __init__(self): + self.selectedItems = [] self.outputRacine = self._createFolder() self.ui_file = os.path.join(FreeCAD.getUserMacroDir(True), 'MultiExport/MultiExport.ui') self.form = FreeCADGui.PySideUic.loadUi(self.ui_file) @@ -25,21 +45,26 @@ class WindowDialog(): def _populate_selector_list(self): - self.form.listWidgetSelector.clear() # Clear the list first + self.form.listWidgetSelector.clear() for obj in FreeCAD.ActiveDocument.Objects: - if obj.Label.startswith("EXP-"): - self.form.listWidgetSelector.addItem(obj.Label) + if obj.Label.startswith("SVG-") or obj.Label.startswith("STL-"): + item = QListWidgetItem() + widget = ObjectListItem(obj) + + item.setSizeHint(widget.sizeHint()) + self.form.listWidgetSelector.addItem(item) + self.form.listWidgetSelector.setItemWidget(item, widget) def _on_selector_item_changed(self): - selected_items = self.form.listWidgetSelector.selectedItems() - selected_labels = [item.text() for item in selected_items] - - FreeCADGui.Selection.clearSelection() # Clear previous selection + self.selectedItems = [] + FreeCADGui.Selection.clearSelection() - # Select objects in FreeCAD based on labels selected in the list - for obj in FreeCAD.ActiveDocument.Objects: - if obj.Label in selected_labels: - FreeCADGui.Selection.addSelection(obj) + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + if item.isSelected(): + FreeCADGui.Selection.addSelection(widget.obj) + self.selectedItems.append((widget.obj, widget.get_value())) def _createFolder(self): folderPath = f"{FreeCAD.activeDocument().getFileName().rpartition('.')[0]}-Exports/" @@ -48,6 +73,7 @@ class WindowDialog(): os.makedirs(folderPath) return folderPath + # -------- MODIFICATION DE LA MACRO "exportSketchEnMasse-SVG" de Gauthier Brière -------- # @@ -156,26 +182,35 @@ class WindowDialog(): plateLength = self.form.doubleSpinBoxLength.value() plateWidth = self.form.doubleSpinBoxWidth.value() spacing = self.form.doubleSpinBoxSpacing.value() - # laserSize = self.form.doubleSpinBoxLaserSize.value() sketchList = [] - for selectedObject in FreeCADGui.Selection.getSelectionEx(): - if hasattr(selectedObject.Object, 'Dir'): - sv0 = Draft.make_shape2dview(selectedObject.Object, FreeCAD.Vector(selectedObject.Object.Dir)) - elif hasattr(selectedObject.Object, 'Objects'): - for child in selectedObject.Object.Objects: - if hasattr(child, 'Dir'): - sv0 = Draft.make_shape2dview(selectedObject.Object, FreeCAD.Vector(child.Dir)) - break - - FreeCAD.ActiveDocument.recompute() - sk = Draft.make_sketch(sv0, autoconstraints=True) - sk.ViewObject.LineColor = (1.0, 0.0, 0.0) - FreeCAD.ActiveDocument.recompute() - sketchList.append(sk) - if hasattr(sv0, 'Name'): - FreeCAD.ActiveDocument.removeObject(sv0.Name) - + # Loop over all selected items in list widget, not GUI selection + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + if item.isSelected(): + count = widget.get_value() + obj = widget.obj + + for _ in range(count): + # Create 2D view and sketch for each instance + if hasattr(obj, 'Dir'): + sv0 = Draft.make_shape2dview(obj, FreeCAD.Vector(obj.Dir)) + elif hasattr(obj, 'Objects'): + for child in obj.Objects: + if hasattr(child, 'Dir'): + sv0 = Draft.make_shape2dview(child, FreeCAD.Vector(child.Dir)) + break + + FreeCAD.ActiveDocument.recompute() + sk = Draft.make_sketch(sv0, autoconstraints=True) + sk.ViewObject.LineColor = (1.0, 0.0, 0.0) + FreeCAD.ActiveDocument.recompute() + sketchList.append(sk) + + if hasattr(sv0, 'Name'): + FreeCAD.ActiveDocument.removeObject(sv0.Name) + if isCalepinage: self._exportSketchCalepinage(sketchList, plateLength, plateWidth, spacing) else: @@ -184,32 +219,40 @@ class WindowDialog(): FreeCADGui.Selection.clearSelection() self._populate_selector_list() - def exportSTL(self, singleMode): - __obj__ = [] - for selectedObject in FreeCADGui.Selection.getSelectionEx(): - __obj__.append(selectedObject.Object) - if not singleMode: - filename = u"" + self.outputRacine + __obj__[0].Label + '.stl' - if hasattr(Mesh, "exportOptions"): - options = Mesh.exportOptions(self.outputRacine) - Mesh.export(__obj__, filename, options) - else: - Mesh.export(__obj__, filename) - print(f'Export STL de : {__obj__[0].Label}.stl') - __obj__.clear() - if singleMode: - filename = u"" + self.outputRacine + __obj__[0].Label + '.stl' if len(__obj__) == 1 else u"" + self.outputRacine + f"{FreeCAD.activeDocument().Name}.stl" - if hasattr(Mesh, "exportOptions"): - options = Mesh.exportOptions(self.outputRacine) - Mesh.export(__obj__, filename, options) - else: - Mesh.export(__obj__, filename) - if len(__obj__) == 1: - print(f'Export STL de : {__obj__[0].Label}.stl') - else: - print(f'Export STL de : {FreeCAD.activeDocument().Name}.stl') - del __obj__ + def exportSTL(self, singleMode): + objects_to_export = [] + + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + if item.isSelected(): + count = widget.get_value() + obj = widget.obj + for i in range(count): + clone = Draft.clone(obj) + objects_to_export.append((clone, obj.Label, i + 1)) + + FreeCAD.ActiveDocument.recompute() + + if not singleMode: + for obj, label, i in objects_to_export: + filename = os.path.join(self.outputRacine, f"{label}_{i}.stl") + Mesh.export([obj], filename) + print(f"Exported STL: {filename}") + FreeCAD.ActiveDocument.removeObject(obj.Name) + else: + # Combine all into one STL + export_objs = [obj for obj, _, _ in objects_to_export] + if export_objs: + label = FreeCAD.activeDocument().Name + filename = os.path.join(self.outputRacine, f"{label}.stl") + Mesh.export(export_objs, filename) + print(f"Exported merged STL: {filename}") + for obj in export_objs: + FreeCAD.ActiveDocument.removeObject(obj.Name) + + FreeCAD.ActiveDocument.recompute() FreeCADGui.Selection.clearSelection() self._populate_selector_list()