diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 39fa3a56ae..0d4975aca4 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -2,14 +2,12 @@ syntax = "proto3"; package cura.proto; - message ObjectList { repeated Object objects = 1; repeated Setting settings = 2; } -// typeid 1 message Slice { repeated ObjectList object_lists = 1; @@ -24,28 +22,13 @@ message Object repeated Setting settings = 5; // Setting override per object, overruling the global settings. } -// typeid 3 message Progress { float amount = 1; } -// typeid 2 -message SlicedObjectList -{ - repeated SlicedObject objects = 1; -} - -message SlicedObject -{ - int64 id = 1; - - repeated Layer layers = 2; -} - message Layer { int32 id = 1; - float height = 2; float thickness = 3; @@ -70,20 +53,16 @@ message Polygon { float line_width = 3; } -// typeid 4 message GCodeLayer { - int64 id = 1; bytes data = 2; } -// typeid 5 message ObjectPrintTime { int64 id = 1; float time = 2; float material_amount = 3; } -// typeid 6 message SettingList { repeated Setting settings = 1; } @@ -94,11 +73,9 @@ message Setting { bytes value = 2; } -// typeid 7 message GCodePrefix { bytes data = 2; } -// typeid 8 message SlicingFinished { -} +} \ No newline at end of file diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 4985852247..b163386867 100644 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -16,7 +16,7 @@ from UM.Message import Message from UM.PluginRegistry import PluginRegistry from cura.OneAtATimeIterator import OneAtATimeIterator -from . import ProcessSlicedObjectListJob +from . import ProcessSlicedLayersJob from . import ProcessGCodeJob from . import StartSliceJob @@ -51,7 +51,7 @@ class CuraEngineBackend(Backend): self._layer_view_active = False Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() - self._stored_layer_data = None + self._stored_layer_data = [] # When there are current settings and machine instance is changed, there is no profile changed event. We should # pretend there is though. @@ -66,7 +66,7 @@ class CuraEngineBackend(Backend): self._change_timer.setSingleShot(True) self._change_timer.timeout.connect(self.slice) - self._message_handlers["cura.proto.SlicedObjectList"] = self._onSlicedObjectListMessage + self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage @@ -157,6 +157,7 @@ class CuraEngineBackend(Backend): def _terminate(self): self._slicing = False self._restart = True + self._stored_layer_data = [] self.slicingCancelled.emit() self.processingProgress.emit(0) Logger.log("d", "Attempting to kill the engine process") @@ -213,12 +214,9 @@ class CuraEngineBackend(Backend): def _onSettingChanged(self, setting): self._onChanged() - def _onSlicedObjectListMessage(self, message): - if self._layer_view_active: - self._process_layers_job = ProcessSlicedObjectListJob.ProcessSlicedObjectListJob(message) - self._process_layers_job.start() - else : - self._stored_layer_data = message + def _onLayerMessage(self, message): + self._stored_layer_data.append(message) + def _onProgressMessage(self, message): if self._message: @@ -238,6 +236,11 @@ class CuraEngineBackend(Backend): self._message.hide() self._message = None + if self._layer_view_active and (self._process_layers_job is None or not self._process_layers_job.isRunning()): + self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_layer_data) + self._process_layers_job.start() + self._stored_layer_data = [] + def _onGCodeLayerMessage(self, message): self._scene.gcode_list.append(message.data.decode("utf-8", "replace")) @@ -280,9 +283,9 @@ class CuraEngineBackend(Backend): # There is data and we're not slicing at the moment # if we are slicing, there is no need to re-calculate the data as it will be invalid in a moment. if self._stored_layer_data and not self._slicing: - self._process_layers_job = ProcessSlicedObjectListJob.ProcessSlicedObjectListJob(self._stored_layer_data) + self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_layer_data) self._process_layers_job.start() - self._stored_layer_data = None + self._stored_layer_data = [] else: self._layer_view_active = False diff --git a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py similarity index 60% rename from plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py rename to plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index df2e5966e9..d3053f9175 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from UM.Job import Job @@ -20,10 +20,10 @@ import struct catalog = i18nCatalog("cura") -class ProcessSlicedObjectListJob(Job): - def __init__(self, message): +class ProcessSlicedLayersJob(Job): + def __init__(self, layers): super().__init__() - self._message = message + self._layers = layers self._scene = Application.getInstance().getController().getScene() self._progress = None self._abort_requested = False @@ -51,13 +51,12 @@ class ProcessSlicedObjectListJob(Job): object_id_map = {} new_node = SceneNode() - ## Put all nodes in a dict identified by ID + + ## Remove old layer data (if any) for node in DepthFirstIterator(self._scene.getRoot()): if type(node) is SceneNode and node.getMeshData(): if node.callDecoration("getLayerData"): self._scene.getRoot().removeChild(node) - else: - object_id_map[id(node)] = node Job.yieldThread() if self._abort_requested: if self._progress: @@ -68,56 +67,45 @@ class ProcessSlicedObjectListJob(Job): mesh = MeshData() layer_data = LayerData.LayerData() - - layer_count = 0 - for i in range(self._message.repeatedMessageCount("objects")): - layer_count += self._message.getRepeatedMessage("objects", i).repeatedMessageCount("layers") + layer_count = len(self._layers) current_layer = 0 - for i in range(self._message.repeatedMessageCount("objects")): - object = self._message.getRepeatedMessage("objects", i) - try: - node = object_id_map[object.id] - except KeyError: - continue - for l in range(object.repeatedMessageCount("layers")): - layer = object.getRepeatedMessage("layers", l) + for layer in self._layers: + layer_data.addLayer(layer.id) + layer_data.setLayerHeight(layer.id, layer.height) + layer_data.setLayerThickness(layer.id, layer.thickness) - layer_data.addLayer(layer.id) - layer_data.setLayerHeight(layer.id, layer.height) - layer_data.setLayerThickness(layer.id, layer.thickness) + for p in range(layer.repeatedMessageCount("polygons")): + polygon = layer.getRepeatedMessage("polygons", p) - for p in range(layer.repeatedMessageCount("polygons")): - polygon = layer.getRepeatedMessage("polygons", p) + points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array + points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. - points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array - points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. + # Create a new 3D-array, copy the 2D points over and insert the right height. + # This uses manual array creation + copy rather than numpy.insert since this is + # faster. + new_points = numpy.empty((len(points), 3), numpy.float32) + new_points[:,0] = points[:,0] + new_points[:,1] = layer.height + new_points[:,2] = -points[:,1] - # Create a new 3D-array, copy the 2D points over and insert the right height. - # This uses manual array creation + copy rather than numpy.insert since this is - # faster. - new_points = numpy.empty((len(points), 3), numpy.float32) - new_points[:,0] = points[:,0] - new_points[:,1] = layer.height - new_points[:,2] = -points[:,1] + new_points /= 1000 - new_points /= 1000 - - layer_data.addPolygon(layer.id, polygon.type, new_points, polygon.line_width) - Job.yieldThread() + layer_data.addPolygon(layer.id, polygon.type, new_points, polygon.line_width) Job.yieldThread() - current_layer += 1 - progress = (current_layer / layer_count) * 100 - # TODO: Rebuild the layer data mesh once the layer has been processed. - # This needs some work in LayerData so we can add the new layers instead of recreating the entire mesh. + Job.yieldThread() + current_layer += 1 + progress = (current_layer / layer_count) * 100 + # TODO: Rebuild the layer data mesh once the layer has been processed. + # This needs some work in LayerData so we can add the new layers instead of recreating the entire mesh. - if self._abort_requested: - if self._progress: - self._progress.hide() - return + if self._abort_requested: if self._progress: - self._progress.setProgress(progress) + self._progress.hide() + return + if self._progress: + self._progress.setProgress(progress) # We are done processing all the layers we got from the engine, now create a mesh out of the data layer_data.build()