Merge branch '2.1'

Conflicts:
	plugins/CuraEngineBackend/StartSliceJob.py
This commit is contained in:
Ghostkeeper 2016-05-04 13:43:35 +02:00
commit 4ef9c1a3e7
4 changed files with 84 additions and 72 deletions

View file

@ -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:

View file

@ -28,19 +28,25 @@ 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()): for node in DepthFirstIterator(self._scene.getRoot()):
if node.callDecoration("getLayerData"): if node.callDecoration("getLayerData"):
node.getParent().removeChild(node) node.getParent().removeChild(node)
@ -51,7 +57,6 @@ class StartSliceJob(Job):
for node in OneAtATimeIterator(self._scene.getRoot()): for node in OneAtATimeIterator(self._scene.getRoot()):
temp_list = [] temp_list = []
## Node can't be printed, so don't bother sending it.
if getattr(node, "_outside_buildarea", False): if getattr(node, "_outside_buildarea", False):
continue continue
@ -77,40 +82,39 @@ class StartSliceJob(Job):
if temp_list: if temp_list:
object_groups.append(temp_list) object_groups.append(temp_list)
self._scene.releaseLock()
if not object_groups: if not object_groups:
return return
self._sendSettings(self._profile) self._buildSettingsMessage(self._profile)
slice_message = self._socket.createMessage("cura.proto.Slice")
for group in object_groups: for group in object_groups:
group_message = slice_message.addRepeatedMessage("object_lists") group_message = self._slice_message.addRepeatedMessage("object_lists")
if group[0].getParent().callDecoration("isGroup"): if group[0].getParent().callDecoration("isGroup"):
self._handlePerObjectSettings(group[0].getParent(), group_message) self._handlePerObjectSettings(group[0].getParent(), group_message)
for current_object in group: for object in group:
mesh_data = current_object.getMeshData().getTransformed(current_object.getWorldTransformation()) mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
obj = group_message.addRepeatedMessage("objects") obj = group_message.addRepeatedMessage("objects")
obj.id = id(current_object) obj.id = id(object)
verts = numpy.array(mesh_data.getVertices()) verts = numpy.array(mesh_data.getVertices())
verts[:,[1,2]] = verts[:,[2,1]] verts[:,[1,2]] = verts[:,[2,1]]
verts[:,1] *= -1 verts[:,1] *= -1
obj.vertices = verts obj.vertices = verts
self._handlePerObjectSettings(current_object, obj) self._handlePerObjectSettings(object, obj)
Job.yieldThread() 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:

View file

@ -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 }

View file

@ -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 },