mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-10 23:35:07 -06:00
231 lines
10 KiB
Python
231 lines
10 KiB
Python
# Copyright (c) 2017 Thomas Karl Pietrowski
|
|
|
|
# TODOs:
|
|
# * Adding selection to separately import parts from an assembly
|
|
|
|
# Buildings
|
|
import math
|
|
|
|
# Uranium/Cura
|
|
from UM.i18n import i18nCatalog
|
|
from UM.Message import Message
|
|
from UM.Logger import Logger
|
|
from UM.Math.Vector import Vector
|
|
from UM.Math.Quaternion import Quaternion
|
|
from UM.Mesh.MeshReader import MeshReader
|
|
|
|
# Our plugin
|
|
from .CommonComReader import CommonCOMReader
|
|
from .SolidWorksConstants import SolidWorksEnums
|
|
from .SolidWorksReaderUI import SolidWorksReaderUI
|
|
|
|
i18n_catalog = i18nCatalog("CuraSolidWorksIntegrationPlugin")
|
|
|
|
|
|
class SolidWorksReader(CommonCOMReader):
|
|
def __init__(self):
|
|
super().__init__("SldWorks.Application", "SolidWorks")
|
|
|
|
self._extension_part = ".SLDPRT"
|
|
self._extension_assembly = ".SLDASM"
|
|
self._supported_extensions = [self._extension_part.lower(),
|
|
self._extension_assembly.lower(),
|
|
]
|
|
|
|
self._convert_assembly_into_once = True # False is not implemented now!
|
|
self._file_formats_first_choice = []
|
|
self._revision = None
|
|
self._revision_major = None
|
|
self._revision_minor = None
|
|
self._revision_patch = None
|
|
|
|
self._ui = SolidWorksReaderUI()
|
|
self._selected_quality = None
|
|
self._quality_value_map = {"coarse": SolidWorksEnums.swSTLQuality_e.swSTLQuality_Coarse,
|
|
"find": SolidWorksEnums.swSTLQuality_e.swSTLQuality_Fine}
|
|
|
|
self.root_component = None
|
|
|
|
def preRead(self, file_name, *args, **kwargs):
|
|
self._ui.showConfigUI()
|
|
self._ui.waitForUIToClose()
|
|
|
|
if self._ui.getCancelled():
|
|
return MeshReader.PreReadResult.cancelled
|
|
|
|
# get quality
|
|
self._selected_quality = self._ui.quality
|
|
if self._selected_quality is None:
|
|
self._selected_quality = "fine"
|
|
self._selected_quality = self._selected_quality.lower()
|
|
|
|
# give actual value for quality
|
|
self._selected_quality = self._quality_value_map.get(self._selected_quality,
|
|
SolidWorksEnums.swSTLQuality_e.swSTLQuality_Fine)
|
|
|
|
return MeshReader.PreReadResult.accepted
|
|
|
|
def setAppVisible(self, state, **options):
|
|
options["app_instance"].Visible = state
|
|
|
|
def getAppVisible(self, state, **options):
|
|
return options["app_instance"].Visible
|
|
|
|
def startApp(self, visible=False):
|
|
app_instance = super().startApp(visible = visible)
|
|
|
|
# Getting revision after starting
|
|
revision_number = app_instance.RevisionNumber()
|
|
Logger.log("d", "SolidWorks RevisionNumber: %s", revision_number)
|
|
self._revision = [int(x) for x in revision_number.split(".")]
|
|
self._revision_major = self._revision[0]
|
|
self._revision_minor = self._revision[1]
|
|
self._revision_patch = self._revision[2]
|
|
|
|
# Re-generate a list of preferred file formats
|
|
self.updateFormatsFirstChoise()
|
|
|
|
return app_instance
|
|
|
|
def updateFormatsFirstChoise(self):
|
|
self._file_formats_first_choice = ["stl"]
|
|
if self._revision_major >= 25 and "3mf" in self._reader_for_file_format.keys():
|
|
self._file_formats_first_choice.insert(0, "3mf")
|
|
|
|
return self._file_formats_first_choice
|
|
|
|
def checkApp(self, **options):
|
|
functions_to_be_checked = ("OpenDoc", "CloseDoc")
|
|
for func in functions_to_be_checked:
|
|
try:
|
|
getattr(options["app_instance"], func)
|
|
except:
|
|
Logger.logException("e", "Error which occurred when checking for a valid app instance")
|
|
return False
|
|
return True
|
|
|
|
def closeApp(self, **options):
|
|
if "app_instance" in options.keys():
|
|
del options["app_instance"]
|
|
|
|
def walkComponentsInAssembly(self, root = None):
|
|
if root is None:
|
|
root = self.root_component
|
|
|
|
children = root.GetChildren
|
|
|
|
if children:
|
|
children = [self.walkComponentsInAssembly(child) for child in children]
|
|
return root, children
|
|
else:
|
|
return root
|
|
|
|
"""
|
|
models = options["sw_model"].GetComponents(True)
|
|
|
|
for model in models:
|
|
#Logger.log("d", model.GetModelDoc2())
|
|
#Logger.log("d", repr(model.GetTitle))
|
|
Logger.log("d", repr(model.GetPathName))
|
|
#Logger.log("d", repr(model.GetType))
|
|
if model.GetPathName in ComponentsCount.keys():
|
|
ComponentsCount[model.GetPathName] = ComponentsCount[model.GetPathName] + 1
|
|
else:
|
|
ComponentsCount[model.GetPathName] = 1
|
|
|
|
for key in ComponentsCount.keys():
|
|
Logger.log("d", "Found %s %s-times in the assembly!" %(key, ComponentsCount[key]))
|
|
"""
|
|
|
|
def openForeignFile(self, **options):
|
|
if options["foreignFormat"].upper() == self._extension_part:
|
|
filetype = SolidWorksEnums.FileTypes.SWpart
|
|
elif options["foreignFormat"].upper() == self._extension_assembly:
|
|
filetype = SolidWorksEnums.FileTypes.SWassembly
|
|
else:
|
|
raise NotImplementedError("Unknown extension. Something went terribly wrong!")
|
|
|
|
#options["sw_model"] = options["app_instance"].OpenDoc(options["foreignFile"], filetype)
|
|
documentSpecification = options["app_instance"].GetOpenDocSpec(options["foreignFile"])
|
|
|
|
## NOTE: SPEC: FileName
|
|
#documentSpecification.FileName
|
|
|
|
## NOTE: SPEC: DocumentType
|
|
## TODO: Really needed here?!
|
|
documentSpecification.DocumentType = filetype
|
|
|
|
## TODO: Test the impact of LightWeight = True
|
|
#documentSpecification.LightWeight = True
|
|
documentSpecification.Silent = True
|
|
|
|
## TODO: Double check, whether file was really opened read-only..
|
|
documentSpecification.ReadOnly = True
|
|
|
|
options["sw_model"] = options["app_instance"].OpenDoc7(documentSpecification._comobj)
|
|
|
|
if documentSpecification.Warning:
|
|
Logger.log("w", "Warnings happened while opening your SolidWorks file!")
|
|
if documentSpecification.Error:
|
|
Logger.log("e", "Errors happened while opening your SolidWorks file!")
|
|
error_message = Message(i18n_catalog.i18nc("@info:status", "Errors appeared while opening your SolidWorks file! \
|
|
Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!" % (self._app_friendly_name)))
|
|
error_message.show()
|
|
|
|
# Might be useful in the future, but no need for this ATM
|
|
#self.configuration = self.model.getActiveConfiguration
|
|
#self.root_component = self.configuration.GetRootComponent
|
|
|
|
## EXPERIMENTAL: Browse single parts in assembly
|
|
#if filetype == SolidWorksEnums.FileTypes.SWassembly:
|
|
# Logger.log("d", 'walkComponentsInAssembly: ' + repr(self.walkComponentsInAssembly()))
|
|
|
|
return options
|
|
|
|
def exportFileAs(self, **options):
|
|
if options["tempType"] == "stl":
|
|
if options["foreignFormat"].upper() == self._extension_assembly:
|
|
# Backing up current setting of swSTLComponentsIntoOneFile
|
|
swSTLComponentsIntoOneFileBackup = options["app_instance"].GetUserPreferenceToggle(SolidWorksEnums.UserPreferences.swSTLComponentsIntoOneFile)
|
|
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.UserPreferences.swSTLComponentsIntoOneFile, self._convert_assembly_into_once)
|
|
|
|
swExportSTLQualityBackup = options["app_instance"].GetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportSTLQuality)
|
|
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportSTLQuality, SolidWorksEnums.swSTLQuality_e.swSTLQuality_Fine)
|
|
|
|
# Changing the default unit for STLs to mm, which is expected by Cura
|
|
swExportStlUnitsBackup = options["app_instance"].GetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportStlUnits)
|
|
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportStlUnits, SolidWorksEnums.swLengthUnit_e.swMM)
|
|
|
|
# Changing the output type temporary to binary
|
|
swSTLBinaryFormatBackup = options["app_instance"].GetUserPreferenceToggle(SolidWorksEnums.swUserPreferenceToggle_e.swSTLBinaryFormat)
|
|
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.swUserPreferenceToggle_e.swSTLBinaryFormat, True)
|
|
|
|
options["sw_model"].SaveAs(options["tempFile"])
|
|
|
|
if options["tempType"] == "stl":
|
|
# Restoring swSTLBinaryFormat
|
|
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.swUserPreferenceToggle_e.swSTLBinaryFormat, swSTLBinaryFormatBackup)
|
|
|
|
# Restoring swExportStlUnits
|
|
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportStlUnits, swExportStlUnitsBackup)
|
|
|
|
# Restoring swSTLQuality_Fine
|
|
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportSTLQuality, swExportSTLQualityBackup)
|
|
|
|
if options["foreignFormat"].upper() == self._extension_assembly:
|
|
# Restoring swSTLComponentsIntoOneFile
|
|
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.UserPreferences.swSTLComponentsIntoOneFile, swSTLComponentsIntoOneFileBackup)
|
|
|
|
def closeForeignFile(self, **options):
|
|
options["app_instance"].CloseDoc(options["foreignFile"])
|
|
|
|
def areReadersAvailable(self):
|
|
return bool(self._reader_for_file_format)
|
|
|
|
def nodePostProcessing(self, node):
|
|
if self._revision_major == 24: # Known problem under SolidWorks 2016: Exported models are rotated by -90 degrees. This rotates it back!
|
|
rotation = Quaternion.fromAngleAxis(math.radians(90), Vector.Unit_X)
|
|
node.rotate(rotation)
|
|
return node
|
|
|
|
## Decide if we need to use ascii or binary in order to read file
|