123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817 |
- from UM.Backend.Backend import Backend, BackendState
- from UM.Application import Application
- from UM.Scene.SceneNode import SceneNode
- from UM.Preferences import Preferences
- from UM.Signal import Signal
- from UM.Logger import Logger
- from UM.Message import Message
- from UM.PluginRegistry import PluginRegistry
- from UM.Resources import Resources
- from UM.Platform import Platform
- from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
- from UM.Qt.Duration import DurationFormat
- from PyQt5.QtCore import QObject, pyqtSlot
- from collections import defaultdict
- from cura.Settings.ExtruderManager import ExtruderManager
- from . import ProcessSlicedLayersJob
- from . import StartSliceJob
- import os
- import sys
- from time import time
- from PyQt5.QtCore import QTimer
- import Arcus
- from UM.i18n import i18nCatalog
- catalog = i18nCatalog("cura")
- class CuraEngineBackend(QObject, Backend):
- backendError = Signal()
-
-
-
-
-
- def __init__(self, parent = None):
- super().__init__(parent = parent)
-
-
- executable_name = "CuraEngine"
- if Platform.isWindows():
- executable_name += ".exe"
- default_engine_location = executable_name
- if os.path.exists(os.path.join(Application.getInstallPrefix(), "bin", executable_name)):
- default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", executable_name)
- if hasattr(sys, "frozen"):
- default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name)
- if Platform.isLinux() and not default_engine_location:
- if not os.getenv("PATH"):
- raise OSError("There is something wrong with your Linux installation.")
- for pathdir in os.getenv("PATH").split(os.pathsep):
- execpath = os.path.join(pathdir, executable_name)
- if os.path.exists(execpath):
- default_engine_location = execpath
- break
- self._application = Application.getInstance()
- self._multi_build_plate_model = None
- self._machine_error_checker = None
- if not default_engine_location:
- raise EnvironmentError("Could not find CuraEngine")
- Logger.log("i", "Found CuraEngine at: %s", default_engine_location)
- default_engine_location = os.path.abspath(default_engine_location)
- Preferences.getInstance().addPreference("backend/location", default_engine_location)
-
- self._layer_view_active = False
- self._onActiveViewChanged()
- self._stored_layer_data = []
- self._stored_optimized_layer_data = {}
- self._scene = self._application.getController().getScene()
- self._scene.sceneChanged.connect(self._onSceneChanged)
-
-
-
-
-
-
-
-
- self._global_container_stack = None
-
- self._message_handlers["cura.proto.Layer"] = self._onLayerMessage
- self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage
- self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
- self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
- self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
- self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates
- self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage
- self._start_slice_job = None
- self._start_slice_job_build_plate = None
- self._slicing = False
- self._restart = False
- self._tool_active = False
- self._always_restart = True
- self._process_layers_job = None
- self._build_plates_to_be_sliced = []
- self._engine_is_fresh = True
- self._backend_log_max_lines = 20000
- self._error_message = None
- self._last_num_objects = defaultdict(int)
- self._postponed_scene_change_sources = []
- self._slice_start_time = None
- Preferences.getInstance().addPreference("general/auto_slice", True)
- self._use_timer = False
-
-
-
- self._change_timer = QTimer()
- self._change_timer.setSingleShot(True)
- self._change_timer.setInterval(500)
- self.determineAutoSlicing()
- Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
- self._application.initializationFinished.connect(self.initialize)
- def initialize(self):
- self._multi_build_plate_model = self._application.getMultiBuildPlateModel()
- self._application.getController().activeViewChanged.connect(self._onActiveViewChanged)
- self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged)
- self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged)
- self._onGlobalStackChanged()
-
- ExtruderManager.getInstance().extrudersChanged.connect(self._extruderChanged)
- self.backendQuit.connect(self._onBackendQuit)
- self.backendConnected.connect(self._onBackendConnected)
-
- self._application.getController().toolOperationStarted.connect(self._onToolOperationStarted)
- self._application.getController().toolOperationStopped.connect(self._onToolOperationStopped)
- self._machine_error_checker = self._application.getMachineErrorChecker()
- self._machine_error_checker.errorCheckFinished.connect(self._onStackErrorCheckFinished)
-
-
-
-
- def close(self):
-
- self._terminate()
-
-
-
- def getEngineCommand(self):
- json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json")
- return [Preferences.getInstance().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]
-
-
-
-
- printDurationMessage = Signal()
-
- slicingStarted = Signal()
-
- slicingCancelled = Signal()
- @pyqtSlot()
- def stopSlicing(self):
- self.backendStateChange.emit(BackendState.NotStarted)
- if self._slicing:
- self._terminate()
- self._createSocket()
- if self._process_layers_job:
- Logger.log("d", "Aborting process layers job...")
- self._process_layers_job.abort()
- self._process_layers_job = None
- if self._error_message:
- self._error_message.hide()
-
- @pyqtSlot()
- def forceSlice(self):
- self.markSliceAll()
- self.slice()
-
- def slice(self):
- Logger.log("d", "Starting to slice...")
- self._slice_start_time = time()
- if not self._build_plates_to_be_sliced:
- self.processingProgress.emit(1.0)
- Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
- return
- if self._process_layers_job:
- Logger.log("d", "Process layers job still busy, trying later.")
- return
- if not hasattr(self._scene, "gcode_dict"):
- self._scene.gcode_dict = {}
-
- active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
- build_plate_to_be_sliced = self._build_plates_to_be_sliced.pop(0)
- Logger.log("d", "Going to slice build plate [%s]!" % build_plate_to_be_sliced)
- num_objects = self._numObjectsPerBuildPlate()
- self._stored_layer_data = []
- self._stored_optimized_layer_data[build_plate_to_be_sliced] = []
- if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0:
- self._scene.gcode_dict[build_plate_to_be_sliced] = []
- Logger.log("d", "Build plate %s has no objects to be sliced, skipping", build_plate_to_be_sliced)
- if self._build_plates_to_be_sliced:
- self.slice()
- return
- if Application.getInstance().getPrintInformation() and build_plate_to_be_sliced == active_build_plate:
- Application.getInstance().getPrintInformation().setToZeroPrintInformation(build_plate_to_be_sliced)
- if self._process is None:
- self._createSocket()
- self.stopSlicing()
- self._engine_is_fresh = False
- self.processingProgress.emit(0.0)
- self.backendStateChange.emit(BackendState.NotStarted)
- self._scene.gcode_dict[build_plate_to_be_sliced] = []
- self._slicing = True
- self.slicingStarted.emit()
- self.determineAutoSlicing()
- slice_message = self._socket.createMessage("cura.proto.Slice")
- self._start_slice_job = StartSliceJob.StartSliceJob(slice_message)
- self._start_slice_job_build_plate = build_plate_to_be_sliced
- self._start_slice_job.setBuildPlate(self._start_slice_job_build_plate)
- self._start_slice_job.start()
- self._start_slice_job.finished.connect(self._onStartSliceCompleted)
-
-
- def _terminate(self):
- self._slicing = False
- self._stored_layer_data = []
- if self._start_slice_job_build_plate in self._stored_optimized_layer_data:
- del self._stored_optimized_layer_data[self._start_slice_job_build_plate]
- if self._start_slice_job is not None:
- self._start_slice_job.cancel()
- self.slicingCancelled.emit()
- self.processingProgress.emit(0)
- Logger.log("d", "Attempting to kill the engine process")
- if Application.getInstance().getCommandLineOption("external-backend", False):
- return
- if self._process is not None:
- Logger.log("d", "Killing engine process")
- try:
- self._process.terminate()
- Logger.log("d", "Engine process is killed. Received return code %s", self._process.wait())
- self._process = None
- except Exception as e:
- Logger.log("d", "Exception occurred while trying to kill the engine %s", str(e))
-
-
-
-
-
-
-
-
- def _onStartSliceCompleted(self, job):
- if self._error_message:
- self._error_message.hide()
-
- if self._start_slice_job is job:
- self._start_slice_job = None
- if job.isCancelled() or job.getError() or job.getResult() == StartSliceJob.StartJobResult.Error:
- self.backendStateChange.emit(BackendState.Error)
- self.backendError.emit(job)
- return
- if job.getResult() == StartSliceJob.StartJobResult.MaterialIncompatible:
- if Application.getInstance().platformActivity:
- self._error_message = Message(catalog.i18nc("@info:status",
- "Unable to slice with the current material as it is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Unable to slice"))
- self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
- self.backendError.emit(job)
- else:
- self.backendStateChange.emit(BackendState.NotStarted)
- return
- if job.getResult() == StartSliceJob.StartJobResult.SettingError:
- if Application.getInstance().platformActivity:
- extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
- error_keys = []
- for extruder in extruders:
- error_keys.extend(extruder.getErrorKeys())
- if not extruders:
- error_keys = self._global_container_stack.getErrorKeys()
- error_labels = set()
- for key in error_keys:
- for stack in [self._global_container_stack] + extruders:
- definitions = stack.getBottom().findDefinitions(key = key)
- if definitions:
- break
- else:
- Logger.log("w", "When checking settings for errors, unable to find definition for key: {key}".format(key = key))
- continue
- error_labels.add(definitions[0].label)
- error_labels = ", ".join(error_labels)
- self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}").format(error_labels),
- title = catalog.i18nc("@info:title", "Unable to slice"))
- self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
- self.backendError.emit(job)
- else:
- self.backendStateChange.emit(BackendState.NotStarted)
- return
- elif job.getResult() == StartSliceJob.StartJobResult.ObjectSettingError:
- errors = {}
- for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
- stack = node.callDecoration("getStack")
- if not stack:
- continue
- for key in stack.getErrorKeys():
- definition = self._global_container_stack.getBottom().findDefinitions(key = key)
- if not definition:
- Logger.log("e", "When checking settings for errors, unable to find definition for key {key} in per-object stack.".format(key = key))
- continue
- definition = definition[0]
- errors[key] = definition.label
- error_labels = ", ".join(errors.values())
- self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}").format(error_labels = error_labels),
- title = catalog.i18nc("@info:title", "Unable to slice"))
- self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
- self.backendError.emit(job)
- return
- if job.getResult() == StartSliceJob.StartJobResult.BuildPlateError:
- if Application.getInstance().platformActivity:
- self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because the prime tower or prime position(s) are invalid."),
- title = catalog.i18nc("@info:title", "Unable to slice"))
- self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
- self.backendError.emit(job)
- else:
- self.backendStateChange.emit(BackendState.NotStarted)
- if job.getResult() == StartSliceJob.StartJobResult.NothingToSlice:
- if Application.getInstance().platformActivity:
- self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."),
- title = catalog.i18nc("@info:title", "Unable to slice"))
- self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
- self.backendError.emit(job)
- else:
- self.backendStateChange.emit(BackendState.NotStarted)
- self._invokeSlice()
- return
-
- self._socket.sendMessage(job.getSliceMessage())
-
- self.backendStateChange.emit(BackendState.Processing)
- Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time )
-
-
-
-
- def determineAutoSlicing(self):
- enable_timer = True
- if not Preferences.getInstance().getValue("general/auto_slice"):
- enable_timer = False
- for node in DepthFirstIterator(self._scene.getRoot()):
- if node.callDecoration("isBlockSlicing"):
- enable_timer = False
- self.backendStateChange.emit(BackendState.Disabled)
- gcode_list = node.callDecoration("getGCodeList")
- if gcode_list is not None:
- self._scene.gcode_dict[node.callDecoration("getBuildPlateNumber")] = gcode_list
- if self._use_timer == enable_timer:
- return self._use_timer
- if enable_timer:
- self.backendStateChange.emit(BackendState.NotStarted)
- self.enableTimer()
- return True
- else:
- self.disableTimer()
- return False
-
- def _numObjectsPerBuildPlate(self):
- num_objects = defaultdict(int)
- for node in DepthFirstIterator(self._scene.getRoot()):
-
- if node.callDecoration("isSliceable"):
- build_plate_number = node.callDecoration("getBuildPlateNumber")
- num_objects[build_plate_number] += 1
- return num_objects
-
-
-
-
-
- def _onSceneChanged(self, source):
- if not isinstance(source, SceneNode):
- return
-
-
- if source.callDecoration("isBlockSlicing") and source.callDecoration("getLayerData"):
- self._stored_optimized_layer_data = {}
- build_plate_changed = set()
- source_build_plate_number = source.callDecoration("getBuildPlateNumber")
- if source == self._scene.getRoot():
-
- num_objects = self._numObjectsPerBuildPlate()
- for build_plate_number in list(self._last_num_objects.keys()) + list(num_objects.keys()):
- if build_plate_number not in self._last_num_objects or num_objects[build_plate_number] != self._last_num_objects[build_plate_number]:
- self._last_num_objects[build_plate_number] = num_objects[build_plate_number]
- build_plate_changed.add(build_plate_number)
- else:
-
- if not source.callDecoration("isGroup"):
- if source.getMeshData() is None:
- return
- if source.getMeshData().getVertices() is None:
- return
- build_plate_changed.add(source_build_plate_number)
- build_plate_changed.discard(None)
- build_plate_changed.discard(-1)
- if not build_plate_changed:
- return
- if self._tool_active:
-
- if source not in self._postponed_scene_change_sources:
- self._postponed_scene_change_sources.append(source)
- return
- self.stopSlicing()
- for build_plate_number in build_plate_changed:
- if build_plate_number not in self._build_plates_to_be_sliced:
- self._build_plates_to_be_sliced.append(build_plate_number)
- self.printDurationMessage.emit(source_build_plate_number, {}, [])
- self.processingProgress.emit(0.0)
- self.backendStateChange.emit(BackendState.NotStarted)
-
-
- self._clearLayerData(build_plate_changed)
- self._invokeSlice()
-
-
-
- def _onSocketError(self, error):
- if Application.getInstance().isShuttingDown():
- return
- super()._onSocketError(error)
- if error.getErrorCode() == Arcus.ErrorCode.Debug:
- return
- self._terminate()
- self._createSocket()
- if error.getErrorCode() not in [Arcus.ErrorCode.BindFailedError, Arcus.ErrorCode.ConnectionResetError, Arcus.ErrorCode.Debug]:
- Logger.log("w", "A socket error caused the connection to be reset")
-
- def _clearLayerData(self, build_plate_numbers = set()):
- for node in DepthFirstIterator(self._scene.getRoot()):
- if node.callDecoration("getLayerData"):
- if not build_plate_numbers or node.callDecoration("getBuildPlateNumber") in build_plate_numbers:
- node.getParent().removeChild(node)
- def markSliceAll(self):
- for build_plate_number in range(Application.getInstance().getMultiBuildPlateModel().maxBuildPlate + 1):
- if build_plate_number not in self._build_plates_to_be_sliced:
- self._build_plates_to_be_sliced.append(build_plate_number)
-
- def needsSlicing(self):
- self.stopSlicing()
- self.markSliceAll()
- self.processingProgress.emit(0.0)
- self.backendStateChange.emit(BackendState.NotStarted)
- if not self._use_timer:
-
- self._clearLayerData()
-
-
-
- def _onSettingChanged(self, instance, property):
- if property == "value":
- self.needsSlicing()
- self._onChanged()
- elif property == "validationState":
- if self._use_timer:
- self._change_timer.stop()
- def _onStackErrorCheckFinished(self):
- if not self._slicing and self._build_plates_to_be_sliced:
- self.needsSlicing()
- self._onChanged()
-
-
-
- def _onLayerMessage(self, message):
- self._stored_layer_data.append(message)
-
-
-
- def _onOptimizedLayerMessage(self, message):
- if self._start_slice_job_build_plate not in self._stored_optimized_layer_data:
- self._stored_optimized_layer_data[self._start_slice_job_build_plate] = []
- self._stored_optimized_layer_data[self._start_slice_job_build_plate].append(message)
-
-
-
- def _onProgressMessage(self, message):
- self.processingProgress.emit(message.amount)
- self.backendStateChange.emit(BackendState.Processing)
- def _invokeSlice(self):
- if self._use_timer:
-
-
- if self._machine_error_checker is None:
- self._change_timer.stop()
- return
- if self._machine_error_checker.needToWaitForResult:
- self._change_timer.stop()
- else:
- self._change_timer.start()
-
-
-
- def _onSlicingFinishedMessage(self, message):
- self.backendStateChange.emit(BackendState.Done)
- self.processingProgress.emit(1.0)
- gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate]
- for index, line in enumerate(gcode_list):
- replaced = line.replace("{print_time}", str(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601)))
- replaced = replaced.replace("{filament_amount}", str(Application.getInstance().getPrintInformation().materialLengths))
- replaced = replaced.replace("{filament_weight}", str(Application.getInstance().getPrintInformation().materialWeights))
- replaced = replaced.replace("{filament_cost}", str(Application.getInstance().getPrintInformation().materialCosts))
- replaced = replaced.replace("{jobname}", str(Application.getInstance().getPrintInformation().jobName))
- gcode_list[index] = replaced
- self._slicing = False
- Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )
-
- active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
- if (
- self._layer_view_active and
- (self._process_layers_job is None or not self._process_layers_job.isRunning()) and
- active_build_plate == self._start_slice_job_build_plate and
- active_build_plate not in self._build_plates_to_be_sliced):
- self._startProcessSlicedLayersJob(active_build_plate)
-
- self._start_slice_job_build_plate = None
- Logger.log("d", "See if there is more to slice...")
-
-
-
- if self._build_plates_to_be_sliced:
- self.enableTimer()
- self._invokeSlice()
-
-
-
- def _onGCodeLayerMessage(self, message):
- self._scene.gcode_dict[self._start_slice_job_build_plate].append(message.data.decode("utf-8", "replace"))
-
-
-
-
- def _onGCodePrefixMessage(self, message):
- self._scene.gcode_dict[self._start_slice_job_build_plate].insert(0, message.data.decode("utf-8", "replace"))
-
- def _createSocket(self):
- super()._createSocket(os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")))
- self._engine_is_fresh = True
-
-
-
- def _onChanged(self, *args, **kwargs):
- self.needsSlicing()
- if self._use_timer:
-
-
- if self._machine_error_checker is None:
- self._change_timer.stop()
- return
- if self._machine_error_checker.needToWaitForResult:
- self._change_timer.stop()
- else:
- self._change_timer.start()
-
-
-
-
- def _onPrintTimeMaterialEstimates(self, message):
- material_amounts = []
- for index in range(message.repeatedMessageCount("materialEstimates")):
- material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount)
- times = self._parseMessagePrintTimes(message)
- self.printDurationMessage.emit(self._start_slice_job_build_plate, times, material_amounts)
-
-
-
- def _parseMessagePrintTimes(self, message):
- result = {
- "inset_0": message.time_inset_0,
- "inset_x": message.time_inset_x,
- "skin": message.time_skin,
- "infill": message.time_infill,
- "support_infill": message.time_support_infill,
- "support_interface": message.time_support_interface,
- "support": message.time_support,
- "skirt": message.time_skirt,
- "travel": message.time_travel,
- "retract": message.time_retract,
- "none": message.time_none
- }
- return result
-
- def _onBackendConnected(self):
- if self._restart:
- self._restart = False
- self._onChanged()
-
-
-
-
-
-
- def _onToolOperationStarted(self, tool):
- self._tool_active = True
- self.disableTimer()
-
- if not self._engine_is_fresh:
- self._terminate()
- self._createSocket()
-
-
-
-
-
- def _onToolOperationStopped(self, tool):
- self._tool_active = False
- self.determineAutoSlicing()
-
- while self._postponed_scene_change_sources:
- source = self._postponed_scene_change_sources.pop(0)
- self._onSceneChanged(source)
- def _startProcessSlicedLayersJob(self, build_plate_number):
- self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_optimized_layer_data[build_plate_number])
- self._process_layers_job.setBuildPlate(build_plate_number)
- self._process_layers_job.finished.connect(self._onProcessLayersFinished)
- self._process_layers_job.start()
-
- def _onActiveViewChanged(self):
- application = Application.getInstance()
- view = application.getController().getActiveView()
- if view:
- active_build_plate = application.getMultiBuildPlateModel().activeBuildPlate
- if view.getPluginId() == "SimulationView":
- self._layer_view_active = True
-
-
-
- if (active_build_plate in self._stored_optimized_layer_data and
- not self._slicing and
- not self._process_layers_job and
- active_build_plate not in self._build_plates_to_be_sliced):
- self._startProcessSlicedLayersJob(active_build_plate)
- else:
- self._layer_view_active = False
-
-
-
- def _onBackendQuit(self):
- if not self._restart:
- if self._process:
- Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait())
- self._process = None
-
- def _onGlobalStackChanged(self):
- if self._global_container_stack:
- self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
- self._global_container_stack.containersChanged.disconnect(self._onChanged)
- extruders = list(self._global_container_stack.extruders.values())
- for extruder in extruders:
- extruder.propertyChanged.disconnect(self._onSettingChanged)
- extruder.containersChanged.disconnect(self._onChanged)
- self._global_container_stack = Application.getInstance().getGlobalContainerStack()
- if self._global_container_stack:
- self._global_container_stack.propertyChanged.connect(self._onSettingChanged)
- self._global_container_stack.containersChanged.connect(self._onChanged)
- extruders = list(self._global_container_stack.extruders.values())
- for extruder in extruders:
- extruder.propertyChanged.connect(self._onSettingChanged)
- extruder.containersChanged.connect(self._onChanged)
- self._onChanged()
- def _onProcessLayersFinished(self, job):
- del self._stored_optimized_layer_data[job.getBuildPlate()]
- self._process_layers_job = None
- Logger.log("d", "See if there is more to slice(2)...")
- self._invokeSlice()
-
- def enableTimer(self):
- if not self._use_timer:
- self._change_timer.timeout.connect(self.slice)
- self._use_timer = True
-
-
- def disableTimer(self):
- if self._use_timer:
- self._use_timer = False
- self._change_timer.timeout.disconnect(self.slice)
- def _onPreferencesChanged(self, preference):
- if preference != "general/auto_slice":
- return
- auto_slice = self.determineAutoSlicing()
- if auto_slice:
- self._change_timer.start()
-
- def tickle(self):
- if self._use_timer:
- self._change_timer.start()
- def _extruderChanged(self):
- for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
- if build_plate_number not in self._build_plates_to_be_sliced:
- self._build_plates_to_be_sliced.append(build_plate_number)
- self._invokeSlice()
|