mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-08 07:27:29 -06:00
Merge branch '2.1'
Conflicts: plugins/CuraEngineBackend/StartSliceJob.py
This commit is contained in:
commit
4ef9c1a3e7
4 changed files with 84 additions and 72 deletions
|
@ -71,6 +71,7 @@ class CuraEngineBackend(Backend):
|
||||||
self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage
|
self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage
|
||||||
|
|
||||||
self._slicing = False
|
self._slicing = False
|
||||||
|
self._start_slice_job = None
|
||||||
self._restart = False
|
self._restart = False
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
self._always_restart = True
|
self._always_restart = True
|
||||||
|
@ -155,14 +156,19 @@ class CuraEngineBackend(Backend):
|
||||||
self._slicing = True
|
self._slicing = True
|
||||||
self.slicingStarted.emit()
|
self.slicingStarted.emit()
|
||||||
|
|
||||||
job = StartSliceJob.StartSliceJob(self._profile, self._socket)
|
slice_message = self._socket.createMessage("cura.proto.Slice")
|
||||||
job.start()
|
settings_message = self._socket.createMessage("cura.proto.SettingList");
|
||||||
job.finished.connect(self._onStartSliceCompleted)
|
self._start_slice_job = StartSliceJob.StartSliceJob(self._profile, slice_message, settings_message)
|
||||||
|
self._start_slice_job.start()
|
||||||
|
self._start_slice_job.finished.connect(self._onStartSliceCompleted)
|
||||||
|
|
||||||
def _terminate(self):
|
def _terminate(self):
|
||||||
self._slicing = False
|
self._slicing = False
|
||||||
self._restart = True
|
self._restart = True
|
||||||
self._stored_layer_data = []
|
self._stored_layer_data = []
|
||||||
|
if self._start_slice_job is not None:
|
||||||
|
self._start_slice_job.cancel()
|
||||||
|
|
||||||
self.slicingCancelled.emit()
|
self.slicingCancelled.emit()
|
||||||
self.processingProgress.emit(0)
|
self.processingProgress.emit(0)
|
||||||
Logger.log("d", "Attempting to kill the engine process")
|
Logger.log("d", "Attempting to kill the engine process")
|
||||||
|
@ -176,13 +182,19 @@ class CuraEngineBackend(Backend):
|
||||||
except Exception as e: # terminating a process that is already terminating causes an exception, silently ignore this.
|
except Exception as e: # terminating a process that is already terminating causes an exception, silently ignore this.
|
||||||
Logger.log("d", "Exception occured while trying to kill the engine %s", str(e))
|
Logger.log("d", "Exception occured while trying to kill the engine %s", str(e))
|
||||||
|
|
||||||
|
|
||||||
def _onStartSliceCompleted(self, job):
|
def _onStartSliceCompleted(self, job):
|
||||||
if job.getError() or job.getResult() != True:
|
# Note that cancelled slice jobs can still call this method.
|
||||||
|
if self._start_slice_job is job:
|
||||||
|
self._start_slice_job = None
|
||||||
|
if job.isCancelled() or job.getError() or job.getResult() != True:
|
||||||
if self._message:
|
if self._message:
|
||||||
self._message.hide()
|
self._message.hide()
|
||||||
self._message = None
|
self._message = None
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
# Preparation completed, send it to the backend.
|
||||||
|
self._socket.sendMessage(job.getSettingsMessage())
|
||||||
|
self._socket.sendMessage(job.getSliceMessage())
|
||||||
|
|
||||||
def _onSceneChanged(self, source):
|
def _onSceneChanged(self, source):
|
||||||
if type(source) is not SceneNode:
|
if type(source) is not SceneNode:
|
||||||
|
|
|
@ -28,89 +28,93 @@ class GcodeStartEndFormatter(Formatter):
|
||||||
Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key)
|
Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key)
|
||||||
return "{" + str(key) + "}"
|
return "{" + str(key) + "}"
|
||||||
|
|
||||||
|
## Job class that builds up the message of scene data to send to CuraEngine.
|
||||||
## Job that handles sending the current scene data to CuraEngine
|
|
||||||
class StartSliceJob(Job):
|
class StartSliceJob(Job):
|
||||||
def __init__(self, profile, socket):
|
def __init__(self, profile, slice_message, settings_message):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self._scene = Application.getInstance().getController().getScene()
|
self._scene = Application.getInstance().getController().getScene()
|
||||||
self._profile = profile
|
self._profile = profile
|
||||||
self._socket = socket
|
self._slice_message = slice_message
|
||||||
|
self._settings_message = settings_message
|
||||||
|
self._is_cancelled = False
|
||||||
|
|
||||||
|
def getSettingsMessage(self):
|
||||||
|
return self._settings_message
|
||||||
|
|
||||||
|
def getSliceMessage(self):
|
||||||
|
return self._slice_message
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self._scene.acquireLock()
|
with self._scene.getSceneLock():
|
||||||
|
for node in DepthFirstIterator(self._scene.getRoot()):
|
||||||
|
if node.callDecoration("getLayerData"):
|
||||||
|
node.getParent().removeChild(node)
|
||||||
|
break
|
||||||
|
|
||||||
for node in DepthFirstIterator(self._scene.getRoot()):
|
object_groups = []
|
||||||
if node.callDecoration("getLayerData"):
|
if self._profile.getSettingValue("print_sequence") == "one_at_a_time":
|
||||||
node.getParent().removeChild(node)
|
for node in OneAtATimeIterator(self._scene.getRoot()):
|
||||||
break
|
temp_list = []
|
||||||
|
|
||||||
object_groups = []
|
if getattr(node, "_outside_buildarea", False):
|
||||||
if self._profile.getSettingValue("print_sequence") == "one_at_a_time":
|
continue
|
||||||
for node in OneAtATimeIterator(self._scene.getRoot()):
|
|
||||||
|
children = node.getAllChildren()
|
||||||
|
children.append(node)
|
||||||
|
for child_node in children:
|
||||||
|
if type(child_node) is SceneNode and child_node.getMeshData() and child_node.getMeshData().getVertices() is not None:
|
||||||
|
temp_list.append(child_node)
|
||||||
|
|
||||||
|
if temp_list:
|
||||||
|
object_groups.append(temp_list)
|
||||||
|
Job.yieldThread()
|
||||||
|
if len(object_groups) == 0:
|
||||||
|
Logger.log("w", "No objects suitable for one at a time found, or no correct order found")
|
||||||
|
else:
|
||||||
temp_list = []
|
temp_list = []
|
||||||
|
for node in DepthFirstIterator(self._scene.getRoot()):
|
||||||
## Node can't be printed, so don't bother sending it.
|
if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
|
||||||
if getattr(node, "_outside_buildarea", False):
|
if not getattr(node, "_outside_buildarea", False):
|
||||||
continue
|
temp_list.append(node)
|
||||||
|
Job.yieldThread()
|
||||||
children = node.getAllChildren()
|
|
||||||
children.append(node)
|
|
||||||
for child_node in children:
|
|
||||||
if type(child_node) is SceneNode and child_node.getMeshData() and child_node.getMeshData().getVertices() is not None:
|
|
||||||
temp_list.append(child_node)
|
|
||||||
|
|
||||||
if temp_list:
|
if temp_list:
|
||||||
object_groups.append(temp_list)
|
object_groups.append(temp_list)
|
||||||
Job.yieldThread()
|
|
||||||
if len(object_groups) == 0:
|
|
||||||
Logger.log("w", "No objects suitable for one at a time found, or no correct order found")
|
|
||||||
else:
|
|
||||||
temp_list = []
|
|
||||||
for node in DepthFirstIterator(self._scene.getRoot()):
|
|
||||||
if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
|
|
||||||
if not getattr(node, "_outside_buildarea", False):
|
|
||||||
temp_list.append(node)
|
|
||||||
Job.yieldThread()
|
|
||||||
|
|
||||||
if temp_list:
|
if not object_groups:
|
||||||
object_groups.append(temp_list)
|
return
|
||||||
|
|
||||||
self._scene.releaseLock()
|
self._buildSettingsMessage(self._profile)
|
||||||
|
|
||||||
if not object_groups:
|
for group in object_groups:
|
||||||
return
|
group_message = self._slice_message.addRepeatedMessage("object_lists")
|
||||||
|
if group[0].getParent().callDecoration("isGroup"):
|
||||||
|
self._handlePerObjectSettings(group[0].getParent(), group_message)
|
||||||
|
for object in group:
|
||||||
|
mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
|
||||||
|
|
||||||
self._sendSettings(self._profile)
|
obj = group_message.addRepeatedMessage("objects")
|
||||||
|
obj.id = id(object)
|
||||||
|
verts = numpy.array(mesh_data.getVertices())
|
||||||
|
verts[:,[1,2]] = verts[:,[2,1]]
|
||||||
|
verts[:,1] *= -1
|
||||||
|
|
||||||
slice_message = self._socket.createMessage("cura.proto.Slice")
|
obj.vertices = verts
|
||||||
|
|
||||||
for group in object_groups:
|
self._handlePerObjectSettings(object, obj)
|
||||||
group_message = slice_message.addRepeatedMessage("object_lists")
|
|
||||||
if group[0].getParent().callDecoration("isGroup"):
|
|
||||||
self._handlePerObjectSettings(group[0].getParent(), group_message)
|
|
||||||
for current_object in group:
|
|
||||||
mesh_data = current_object.getMeshData().getTransformed(current_object.getWorldTransformation())
|
|
||||||
|
|
||||||
obj = group_message.addRepeatedMessage("objects")
|
Job.yieldThread()
|
||||||
obj.id = id(current_object)
|
|
||||||
|
|
||||||
verts = numpy.array(mesh_data.getVertices())
|
|
||||||
verts[:,[1,2]] = verts[:,[2,1]]
|
|
||||||
verts[:,1] *= -1
|
|
||||||
|
|
||||||
obj.vertices = verts
|
|
||||||
|
|
||||||
self._handlePerObjectSettings(current_object, obj)
|
|
||||||
|
|
||||||
Job.yieldThread()
|
|
||||||
|
|
||||||
Logger.log("d", "Sending data to engine for slicing.")
|
|
||||||
self._socket.sendMessage(slice_message)
|
|
||||||
Logger.log("d", "Sending data to engine is completed")
|
|
||||||
self.setResult(True)
|
self.setResult(True)
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
super().cancel()
|
||||||
|
self._is_cancelled = True
|
||||||
|
|
||||||
|
def isCancelled(self):
|
||||||
|
return self._is_cancelled
|
||||||
|
|
||||||
def _expandGcodeTokens(self, key, value, settings):
|
def _expandGcodeTokens(self, key, value, settings):
|
||||||
try:
|
try:
|
||||||
# any setting can be used as a token
|
# any setting can be used as a token
|
||||||
|
@ -120,22 +124,19 @@ class StartSliceJob(Job):
|
||||||
Logger.log("w", "Unabled to do token replacement on start/end gcode %s", traceback.format_exc())
|
Logger.log("w", "Unabled to do token replacement on start/end gcode %s", traceback.format_exc())
|
||||||
return str(value).encode("utf-8")
|
return str(value).encode("utf-8")
|
||||||
|
|
||||||
def _sendSettings(self, profile):
|
def _buildSettingsMessage(self, profile):
|
||||||
msg = self._socket.createMessage("cura.proto.SettingList")
|
|
||||||
settings = profile.getAllSettingValues(include_machine = True)
|
settings = profile.getAllSettingValues(include_machine = True)
|
||||||
start_gcode = settings["machine_start_gcode"]
|
start_gcode = settings["machine_start_gcode"]
|
||||||
settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode
|
settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode
|
||||||
settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode
|
settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode
|
||||||
for key, value in settings.items():
|
for key, value in settings.items():
|
||||||
s = msg.addRepeatedMessage("settings")
|
s = self._settings_message.addRepeatedMessage("settings")
|
||||||
s.name = key
|
s.name = key
|
||||||
if key == "machine_start_gcode" or key == "machine_end_gcode":
|
if key == "machine_start_gcode" or key == "machine_end_gcode":
|
||||||
s.value = self._expandGcodeTokens(key, value, settings)
|
s.value = self._expandGcodeTokens(key, value, settings)
|
||||||
else:
|
else:
|
||||||
s.value = str(value).encode("utf-8")
|
s.value = str(value).encode("utf-8")
|
||||||
|
|
||||||
self._socket.sendMessage(msg)
|
|
||||||
|
|
||||||
def _handlePerObjectSettings(self, node, message):
|
def _handlePerObjectSettings(self, node, message):
|
||||||
profile = node.callDecoration("getProfile")
|
profile = node.callDecoration("getProfile")
|
||||||
if profile:
|
if profile:
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"inherits": "ultimaker2plus.json",
|
"inherits": "ultimaker2plus.json",
|
||||||
|
|
||||||
"machine_settings": {
|
"machine_settings": {
|
||||||
"machine_height": { "default": 313 },
|
"machine_height": { "default": 305},
|
||||||
"machine_show_variants": { "default": true },
|
"machine_show_variants": { "default": true },
|
||||||
"machine_nozzle_head_distance": { "default": 5 },
|
"machine_nozzle_head_distance": { "default": 5 },
|
||||||
"machine_nozzle_expansion_angle": { "default": 45 }
|
"machine_nozzle_expansion_angle": { "default": 45 }
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
"line_width": { "inherit_function": "round(machine_nozzle_size * 0.875, 2)" },
|
"line_width": { "inherit_function": "round(machine_nozzle_size * 0.875, 2)" },
|
||||||
"speed_layer_0": { "default": "20" },
|
"speed_layer_0": { "default": "20" },
|
||||||
"speed_support": { "inherit_function": "speed_wall_0" },
|
"speed_support": { "inherit_function": "speed_wall_0" },
|
||||||
"machine_height": { "default": 203 },
|
|
||||||
"machine_show_variants": { "default": true },
|
"machine_show_variants": { "default": true },
|
||||||
"gantry_height": { "default": 52 },
|
"gantry_height": { "default": 52 },
|
||||||
"machine_nozzle_head_distance": { "default": 5 },
|
"machine_nozzle_head_distance": { "default": 5 },
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue