This commit is contained in:
Jaime van Kessel 2015-08-19 10:27:41 +02:00
commit d683a6b77b
5 changed files with 67 additions and 50 deletions

View file

@ -79,6 +79,7 @@ class CuraApplication(QtApplication):
self._platform_activity = False
self.activeMachineChanged.connect(self._onActiveMachineChanged)
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
Preferences.getInstance().addPreference("cura/active_machine", "")
Preferences.getInstance().addPreference("cura/active_mode", "simple")
@ -214,24 +215,15 @@ class CuraApplication(QtApplication):
def getPlatformActivity(self):
return self._platform_activity
@pyqtSlot(bool)
def setPlatformActivity(self, activity):
##Sets the _platform_activity variable on true or false depending on whether there is a mesh on the platform
if activity == True:
self._platform_activity = activity
elif activity == False:
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode or not node.getMeshData():
continue
nodes.append(node)
i = 0
for node in nodes:
if not node.getMeshData():
continue
i += 1
if i <= 1: ## i == 0 when the meshes are removed using the deleteAll function; i == 1 when the last remaining mesh is removed using the deleteObject function
self._platform_activity = activity
def updatePlatformActivity(self, node = None):
count = 0
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode or not node.getMeshData():
continue
count += 1
self._platform_activity = True if count > 0 else False
self.activityChanged.emit()
## Remove an object from the scene
@ -252,8 +244,7 @@ class CuraApplication(QtApplication):
group_node = group_node.getParent()
op = RemoveSceneNodeOperation(group_node)
op.push()
self.setPlatformActivity(False)
## Create a number of copies of existing object.
@pyqtSlot("quint64", int)
def multiplyObject(self, object_id, count):
@ -300,8 +291,7 @@ class CuraApplication(QtApplication):
op.addOperation(RemoveSceneNodeOperation(node))
op.push()
self.setPlatformActivity(False)
## Reset all translation on nodes with mesh data.
@pyqtSlot()
def resetAllTranslation(self):

View file

@ -15,16 +15,21 @@ import os
import struct
import math
from os import listdir
import untangle
import zipfile
import xml.etree.ElementTree as ET
## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
class ThreeMFReader(MeshReader):
def __init__(self):
super(ThreeMFReader, self).__init__()
self._supported_extension = ".3mf"
self._namespaces = {
"3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
"cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
}
def read(self, file_name):
result = None
extension = os.path.splitext(file_name)[1]
@ -33,32 +38,39 @@ class ThreeMFReader(MeshReader):
# The base object of 3mf is a zipped archive.
archive = zipfile.ZipFile(file_name, 'r')
try:
# The model is always stored in this place.
root = untangle.parse(archive.read("3D/3dmodel.model").decode("utf-8"))
for object in root.model.resources.object: # There can be multiple objects, try to load all of them.
root = ET.parse(archive.open("3D/3dmodel.model"))
# There can be multiple objects, try to load all of them.
objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
for object in objects:
mesh = MeshData()
node = SceneNode()
vertex_list = []
for vertex in object.mesh.vertices.vertex:
vertex_list.append([vertex['x'],vertex['y'],vertex['z']])
#for vertex in object.mesh.vertices.vertex:
for vertex in object.findall(".//3mf:vertex", self._namespaces):
vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
triangles = object.findall(".//3mf:triangle", self._namespaces)
mesh.reserveFaceCount(len(triangles))
mesh.reserveFaceCount(len(object.mesh.triangles.triangle))
for triangle in object.mesh.triangles.triangle:
v1 = int(triangle["v1"])
v2 = int(triangle["v2"])
v3 = int(triangle["v3"])
#for triangle in object.mesh.triangles.triangle:
for triangle in triangles:
v1 = int(triangle.get("v1"))
v2 = int(triangle.get("v2"))
v3 = int(triangle.get("v3"))
mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2])
#TODO: We currently do not check for normals and simply recalculate them.
mesh.calculateNormals()
node.setMeshData(mesh)
node.setSelectable(True)
# Magical python comprehension; looks for the matching transformation
transformation = next((x for x in root.model.build.item if x["objectid"] == object["id"]), None)
if transformation["transform"]:
splitted_transformation = transformation["transform"].split()
transformation = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(object.get("id")), self._namespaces)
if transformation:
transformation = transformation[0]
if transformation.get("transform"):
splitted_transformation = transformation.get("transform").split()
## Transformation is saved as:
## M00 M01 M02 0.0
## M10 M11 M12 0.0
@ -99,10 +111,10 @@ class ThreeMFReader(MeshReader):
rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
node.rotate(rotation)
result.addChild(node)
# If there is more then one object, group them.
#If there is more then one object, group them.
try:
if len(root.model.resources.object) > 1:
if len(objects) > 1:
group_decorator = GroupDecorator()
result.addDecorator(group_decorator)
except:

View file

@ -17,8 +17,8 @@ class RemovableDriveOutputDevice(OutputDevice):
super().__init__(device_id)
self.setName(device_name)
self.setShortDescription(catalog.i18nc("", "Save to Removable Drive"))
self.setDescription(catalog.i18nc("", "Save to Removable Drive {0}").format(device_name))
self.setShortDescription(catalog.i18nc("@action:button", "Save to Removable Drive"))
self.setDescription(catalog.i18nc("@info:tooltip", "Save to Removable Drive {0}").format(device_name))
self.setIconName("save_sd")
self.setPriority(1)
@ -49,7 +49,7 @@ class RemovableDriveOutputDevice(OutputDevice):
job.progress.connect(self._onProgress)
job.finished.connect(self._onFinished)
message = Message(catalog.i18nc("", "Saving to Removable Drive {0}").format(self.getName()), 0, False, -1)
message = Message(catalog.i18nc("@info:status", "Saving to Removable Drive <filename>{0}</filename>").format(self.getName()), 0, False, -1)
message.show()
job._message = message

View file

@ -63,8 +63,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
self._listen_thread.daemon = True
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
self._update_firmware_thread.demon = True
self._update_firmware_thread.deamon = True
self._heatup_wait_start_time = time.time()
## Queue for commands that need to be send. Used when command is sent when a print is active.
@ -222,6 +222,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
self.setProgress(100, 100)
self.firmwareUpdateComplete.emit()
## Upload new firmware to machine
# \param filename full path of firmware file to be uploaded
def updateFirmware(self, file_name):
@ -277,9 +279,9 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
if line is None:
self.setIsConnected(False) # Something went wrong with reading, could be that close was called.
return
if b"T:" in line:
self._serial.timeout = 0.5
self._sendCommand("M105")
sucesfull_responses += 1
if sucesfull_responses >= self._required_responses_auto_baud:
self._serial.timeout = 2 #Reset serial timeout
@ -287,6 +289,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
return
self._sendCommand("M105") # Send M105 as long as we are listening, otherwise we end up in an undefined state
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
self.close() # Unable to connect, wrap up.
self.setIsConnected(False)
@ -319,6 +323,9 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
except Exception as e:
pass # This should work, but it does fail sometimes for some reason
self._connect_thread = threading.Thread(target=self._connect)
self._connect_thread.daemon = True
if self._serial is not None:
self.setIsConnected(False)
try:
@ -327,6 +334,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
pass
self._serial.close()
self._listen_thread = threading.Thread(target=self._listen)
self._listen_thread.daemon = True
self._serial = None
def isConnected(self):
@ -579,3 +588,10 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
def _getBaudrateList(self):
ret = [250000, 230400, 115200, 57600, 38400, 19200, 9600]
return ret
def _onFirmwareUpdateComplete(self):
self._update_firmware_thread.join()
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
self._update_firmware_thread.deamon = True
self.connect()

View file

@ -481,7 +481,6 @@ UM.MainWindow {
onAccepted:
{
UM.MeshFileHandler.readLocalFile(fileUrl)
Printer.setPlatformActivity(true)
}
}