def _createView(self) -> None: Logger.log("d", "Creating post processing plugin view.") self.loadAllScripts() # Create the plugin dialog component path = os.path.join( cast( str, PluginRegistry.getInstance().getPluginPath( "PostProcessingPlugin")), "PostProcessingPlugin.qml") self._view = SteSlicerApplication.getInstance().createQmlComponent( path, {"manager": self}) if self._view is None: Logger.log( "e", "Not creating PostProcessing button near save button because the QML component failed to be created." ) return Logger.log("d", "Post processing view created.") # Create the save button component SteSlicerApplication.getInstance().addAdditionalComponent( "saveButton", self._view.findChild(QObject, "postProcessingSaveAreaButton"))
def __init__(self): super().__init__() self._shortcut_key = Qt.Key_P self._controller = self.getController() self._visible = False self._plane_size = 100 self._selection_pass = None self._global_container_stack = None SteSlicerApplication.getInstance().globalContainerStackChanged.connect( self._onStackChanged) self._onStackChanged() self._printing_mode = None # Note: if the selection is cleared with this tool active, there is no way to switch to # another tool than to reselect an object (by clicking it) because the tool buttons in the # toolbar will have been disabled. That is why we need to ignore the first press event # after the selection has been cleared. Selection.selectionChanged.connect(self._onSelectionChanged) self._had_selection = False self._skip_press = False self._had_selection_timer = QTimer() self._had_selection_timer.setInterval(0) self._had_selection_timer.setSingleShot(True) self._had_selection_timer.timeout.connect(self._selectionChangeDelay)
def exceptHook(hook_type, value, traceback): from steslicer.CrashHandler import CrashHandler from steslicer.SteSlicerApplication import SteSlicerApplication has_started = False if SteSlicerApplication.Created: has_started = SteSlicerApplication.getInstance().started from PyQt5.Qt import QApplication if SteSlicerApplication.Created: _crash_handler = CrashHandler(hook_type, value, traceback, has_started) if SteSlicerApplication.splash is not None: SteSlicerApplication.splash.close() if not has_started: SteSlicerApplication.getInstance().removePostedEvents(None) _crash_handler.early_crash_dialog.show() sys.exit(SteSlicerApplication.getInstance().exec_()) else: _crash_handler.show() else: application = QApplication(sys.argv) application.removePostedEvents(None) _crash_handler = CrashHandler(hook_type, value, traceback, has_started) if SteSlicerApplication.splash is not None: SteSlicerApplication.splash.close() _crash_handler.early_crash_dialog.show() sys.exit(application.exec_())
def _saveAuthentication(self) -> None: global_container_stack = SteSlicerApplication.getInstance( ).getGlobalContainerStack() if self._authentication_key is None: Logger.log("e", "Authentication key is None, nothing to save.") return if self._authentication_id is None: Logger.log("e", "Authentication id is None, nothing to save.") return if global_container_stack: global_container_stack.setMetaDataEntry( "network_authentication_key", self._authentication_key) global_container_stack.setMetaDataEntry( "network_authentication_id", self._authentication_id) # Force save so we are sure the data is not lost. SteSlicerApplication.getInstance().saveStack( global_container_stack) Logger.log("i", "Authentication succeeded for id %s and key %s", self._authentication_id, self._getSafeAuthKey()) else: Logger.log("e", "Unable to save authentication for id %s and key %s", self._authentication_id, self._getSafeAuthKey())
def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], parent: QObject = None) -> None: super().__init__(device_id=device_id, parent=parent) self._manager = None # type: Optional[QNetworkAccessManager] self._last_manager_create_time = None # type: Optional[float] self._recreate_network_manager_time = 30 self._timeout_time = 10 # After how many seconds of no response should a timeout occur? self._last_response_time = None # type: Optional[float] self._last_request_time = None # type: Optional[float] self._api_prefix = "" self._address = address self._properties = properties self._user_agent = "%s/%s " % ( SteSlicerApplication.getInstance().getApplicationName(), SteSlicerApplication.getInstance().getVersion()) self._onFinishedCallbacks = { } # type: Dict[str, Callable[[QNetworkReply], None]] self._authentication_state = AuthState.NotAuthenticated # QHttpMultiPart objects need to be kept alive and not garbage collected during the # HTTP which uses them. We hold references to these QHttpMultiPart objects here. self._kept_alive_multiparts = { } # type: Dict[QNetworkReply, QHttpMultiPart] self._sending_gcode = False self._compressing_gcode = False self._gcode = [] # type: List[str] self._connection_state_before_timeout = None # type: Optional[ConnectionState]
def __init__(self, parent=None) -> None: QObject.__init__(self, parent) Extension.__init__(self) self.addMenuItem(i18n_catalog.i18n("Modify G-Code"), self.showPopup) self._view = None # Loaded scripts are all scripts that can be used self._loaded_scripts = {} # type: Dict[str, Type[Script]] self._script_labels = {} # type: Dict[str, str] # Script list contains instances of scripts in loaded_scripts. # There can be duplicates, which will be executed in sequence. self._script_list = [] # type: List[Script] self._hidden_list = [ ] #type: List[Script] #hidden list of scripts that always execute self._selected_script_index = -1 Application.getInstance().getOutputDeviceManager( ).writeStarted.connect(self.execute) Application.getInstance().globalContainerStackChanged.connect( self._onGlobalContainerStackChanged ) # When the current printer changes, update the list of scripts. SteSlicerApplication.getInstance().mainWindowChanged.connect( self._createView ) # When the main window is created, create the view so that we can display the post-processing icon if necessary.
def __init__(self) -> None: super().__init__() self._convex_hull_node = None # type: Optional["SceneNode"] self._init2DConvexHullCache() self._global_stack = None # type: Optional[GlobalStack] # Make sure the timer is created on the main thread self._recompute_convex_hull_timer = None # type: Optional[QTimer] from steslicer.SteSlicerApplication import SteSlicerApplication if SteSlicerApplication.getInstance() is not None: SteSlicerApplication.getInstance().callLater( self.createRecomputeConvexHullTimer) self._raft_thickness = 0.0 self._build_volume = SteSlicerApplication.getInstance().getBuildVolume( ) self._build_volume.raftThicknessChanged.connect(self._onChanged) SteSlicerApplication.getInstance().globalContainerStackChanged.connect( self._onGlobalStackChanged) SteSlicerApplication.getInstance().getController( ).toolOperationStarted.connect(self._onChanged) SteSlicerApplication.getInstance().getController( ).toolOperationStopped.connect(self._onChanged) self._onGlobalStackChanged()
def _progressMessageActionTriggered(self, message_id=None, action_id=None): if action_id == "Abort": Logger.log("d", "User aborted sending print to remote.") self._progress_message.hide() self._compressing_gcode = False self._sending_gcode = False SteSlicerApplication.getInstance().getController().setActiveStage( "PrepareStage")
def _updateEnabled(self): plugin_enabled = False global_container_stack = SteSlicerApplication.getInstance( ).getGlobalContainerStack() if global_container_stack: plugin_enabled = global_container_stack.getProperty( "anti_overhang_mesh", "enabled") SteSlicerApplication.getInstance().getController( ).toolEnabledChanged.emit(self._plugin_id, plugin_enabled)
def _call_on_qt_thread_wrapper(*args, **kwargs): def _handle_call(ico, *args, **kwargs): ico.result = func(*args, **kwargs) ico.finish_event.set() inter_call_object = InterCallObject() new_args = tuple([inter_call_object] + list(args)[:]) SteSlicerApplication.getInstance().callLater(_handle_call, *new_args, **kwargs) inter_call_object.finish_event.wait() return inter_call_object.result
def _removeEraserMesh(self, node: SteSlicerSceneNode): parent = node.getParent() if parent == self._controller.getScene().getRoot(): parent = None op = RemoveSceneNodeOperation(node) op.push() if parent and not Selection.isSelected(parent): Selection.add(parent) SteSlicerApplication.getInstance().getController().getScene( ).sceneChanged.emit(node)
def __init__(self) -> None: super().__init__("DiscoverUM3Action", catalog.i18nc("@action", "Connect via Network")) self._qml_url = "resources/qml/DiscoverUM3Action.qml" self._network_plugin = None # type: Optional[UM3OutputDevicePlugin] self.__additional_components_view = None # type: Optional[QObject] SteSlicerApplication.getInstance().engineCreatedSignal.connect(self._createAdditionalComponentsView) self._last_zero_conf_event_time = time.time() # type: float # Time to wait after a zero-conf service change before allowing a zeroconf reset self._zero_conf_change_grace_period = 0.25 # type: float
def __init__(self, process, output_path: List[str], slice_message: Arcus.PythonMessage): super().__init__() self._output_path = output_path #type: List[str] self._process = process #type: subprocess.Popen self._scene = SteSlicerApplication.getInstance().getController( ).getScene() #type: Scene self._global_stack = SteSlicerApplication.getInstance( ).getGlobalContainerStack() self._slice_message = slice_message #type: Arcus.PythonMessage self._is_cancelled = False #type: bool self._build_plate_number = None #type: Optional[int] self._all_extruders_settings = None # type: Optional[Dict[str, Any]] # cache for all setting values from all stacks (global & extruder) for the current machine
def materialHotendChangedMessage(self, callback): SteSlicerApplication.getInstance().messageBox( i18n_catalog.i18nc("@window:title", "Sync with your printer"), i18n_catalog.i18nc( "@label", "Would you like to use your current printer configuration in Cura?" ), i18n_catalog.i18nc( "@label", "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer." ), buttons=QMessageBox.Yes + QMessageBox.No, icon=QMessageBox.Question, callback=callback)
def _updateEnabled(self): plugin_enabled = False global_container_stack = SteSlicerApplication.getInstance( ).getGlobalContainerStack() if global_container_stack: plugin_enabled = global_container_stack.getProperty( "printing_mode", "value") in ["discrete"] machine_width = global_container_stack.getProperty( "machine_width", "value") machine_depth = global_container_stack.getProperty( "machine_depth", "value") self._plane_size = max(machine_width, machine_depth, 100) SteSlicerApplication.getInstance().getController( ).toolEnabledChanged.emit(self._plugin_id, plugin_enabled)
def _checkForErrors(self): errors = [] print_information = SteSlicerApplication.getInstance( ).getPrintInformation() if not print_information.materialLengths: Logger.log( "w", "There is no material length information. Unable to check for errors." ) return errors for index, extruder in enumerate(self.activePrinter.extruders): # Due to airflow issues, both slots must be loaded, regardless if they are actually used or not. if extruder.hotendID == "": # No Printcore loaded. errors.append( i18n_catalog.i18nc( "@info:status", "No Printcore loaded in slot {slot_number}".format( slot_number=index + 1))) if index < len(print_information.materialLengths ) and print_information.materialLengths[index] != 0: # The extruder is by this print. if extruder.activeMaterial is None: # No active material errors.append( i18n_catalog.i18nc( "@info:status", "No material loaded in slot {slot_number}".format( slot_number=index + 1))) return errors
def _buildObjectFiles(self, indicies_collection, vertices_collection): mesh_collection = [] for index, vertices in enumerate(vertices_collection): mesh = trimesh.Trimesh(vertices=vertices, faces=indicies_collection[index]) mesh_collection.append(mesh) Job.yieldThread() output_mesh = trimesh.util.concatenate( mesh_collection) # type: trimesh.Trimesh trimesh.repair.fix_winding(output_mesh) Job.yieldThread() trimesh.repair.fix_inversion(output_mesh, multibody=True) output_mesh.fill_holes() output_mesh.fix_normals() # create_cutting_cylinder global_stack = SteSlicerApplication.getInstance( ).getGlobalContainerStack() radius = global_stack.getProperty("cylindrical_mode_base_diameter", "value") / 2 height = global_stack.getProperty("machine_height", "value") * 2 cutting_cylinder = trimesh.primitives.Cylinder(radius=radius, height=height, sections=64) # cut mesh by cylinder try: result = output_mesh.difference(cutting_cylinder, engine="scad") except Exception as e: Logger.log("e", "Exception while differece model! %s", e) result = output_mesh temp_mesh = tempfile.NamedTemporaryFile('w', delete=False) result.export(temp_mesh.name, 'stl') self._slice_message.append('-m') self._slice_message.append(temp_mesh.name)
def generate(self): application = SteSlicerApplication.getInstance() extruder_stack = application.getExtruderManager( ).getActiveExtruderStack() root = eltree.Element("root") for region, params in params_dict.items(): for name, value in params.items(): sub = eltree.SubElement(root, "param", attrib={ 'NAME': name, 'REGION': region, 'PARAM': '' }) setting_value = extruder_stack.getProperty( value.get("stack_key", ""), "value") if setting_value is not None: if isinstance(setting_value, bool): if setting_value: setting_value = "1" else: setting_value = "0" if name in ["rsize", "first_offset", "last_offset"]: setting_value /= 2 if name == "skin_width": setting_value = setting_value if setting_value <= 4 else 4 else: setting_value = value.get("default_value", "") sub.text = setting_value.__str__() return eltree.tostring(root, encoding='Windows-1251').decode("Windows-1251")
def _buildReplacementTokens(self, stack: ContainerStack) -> Dict[str, Any]: result = {} for key in stack.getAllKeys(): value = stack.getProperty(key, "value") result[key] = value Job.yieldThread() result["print_bed_temperature"] = result[ "material_bed_temperature"] # Renamed settings. result["print_temperature"] = result["material_print_temperature"] result["time"] = time.strftime("%H:%M:%S") # Some extra settings. result["date"] = time.strftime("%d-%m-%Y") result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))] printing_mode = result["printing_mode"] if printing_mode in ["cylindrical_full", "cylindrical"]: result["cylindrical_rotate"] = "G0 A%.2f" % ( 90 * result["machine_a_axis_multiplier"] / result["machine_a_axis_divider"]) result["coordinate_system"] = "G56" elif printing_mode in ["spherical_full", "spherical"]: result["cylindrical_rotate"] = "G0 A0" result["coordinate_system"] = "G55" initial_extruder_stack = SteSlicerApplication.getInstance( ).getExtruderManager().getUsedExtruderStacks()[0] initial_extruder_nr = initial_extruder_stack.getProperty( "extruder_nr", "value") result["initial_extruder_nr"] = initial_extruder_nr return result
def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1) -> str: if not self._all_extruders_settings: global_stack = cast( ContainerStack, SteSlicerApplication.getInstance().getGlobalContainerStack()) # NB: keys must be strings for the string formatter self._all_extruders_settings = { "-1": self._buildReplacementTokens(global_stack) } for extruder_stack in ExtruderManager.getInstance( ).getActiveExtruderStacks(): extruder_nr = extruder_stack.getProperty( "extruder_nr", "value") self._all_extruders_settings[str( extruder_nr)] = self._buildReplacementTokens( extruder_stack) try: # any setting can be used as a token fmt = GcodeStartEndFormatter( default_extruder_nr=default_extruder_nr) settings = self._all_extruders_settings.copy() settings["default_extruder_nr"] = default_extruder_nr return str(fmt.format(value, **settings)) except: Logger.logException( "w", "Unable to do token replacement on start/end g-code") return str(value)
def _createNetworkManager(self) -> None: Logger.log("d", "Creating network manager") if self._manager: self._manager.finished.disconnect(self.__handleOnFinished) self._manager.authenticationRequired.disconnect( self._onAuthenticationRequired) self._manager = QNetworkAccessManager() self._manager.finished.connect(self.__handleOnFinished) self._last_manager_create_time = time() self._manager.authenticationRequired.connect( self._onAuthenticationRequired) if self._properties.get(b"temporary", b"false") != b"true": SteSlicerApplication.getInstance().getMachineManager( ).checkCorrectGroupName(self.getId(), self.name)
def createGlobalStack( cls, new_stack_id: str, definition: DefinitionContainerInterface, variant_container: "InstanceContainer", material_container: "InstanceContainer", quality_container: "InstanceContainer") -> GlobalStack: from steslicer.SteSlicerApplication import SteSlicerApplication application = SteSlicerApplication.getInstance() registry = application.getContainerRegistry() stack = GlobalStack(new_stack_id) stack.setDefinition(definition) # Create user container user_container = cls.createUserChangesContainer(new_stack_id + "_user", definition.getId(), new_stack_id, is_global_stack=True) stack.definitionChanges = cls.createDefinitionChangesContainer( stack, new_stack_id + "_settings") stack.variant = variant_container stack.material = material_container stack.quality = quality_container stack.qualityChanges = application.empty_quality_changes_container stack.userChanges = user_container registry.addContainer(user_container) return stack
def startDiscovery(self): if not self._network_plugin: Logger.log("d", "Starting device discovery.") self._network_plugin = SteSlicerApplication.getInstance().getOutputDeviceManager().getOutputDevicePlugin( "UM3NetworkPrinting") self._network_plugin.discoveredDevicesChanged.connect(self._onDeviceDiscoveryChanged) self.discoveredDevicesChanged.emit()
def resetMaterialsQualitiesAndUninstall(self) -> None: application = SteSlicerApplication.getInstance() material_manager = application.getMaterialManager() quality_manager = application.getQualityManager() machine_manager = application.getMachineManager() for global_stack, extruder_nr, container_id in self._package_used_materials: default_material_node = material_manager.getDefaultMaterial( global_stack, extruder_nr, global_stack.extruders[extruder_nr].variant.getName()) machine_manager.setMaterial(extruder_nr, default_material_node, global_stack=global_stack) for global_stack, extruder_nr, container_id in self._package_used_qualities: default_quality_group = quality_manager.getDefaultQualityType( global_stack) machine_manager.setQualityGroup(default_quality_group, global_stack=global_stack) if self._package_id_to_uninstall is not None: self._markPackageMaterialsAsToBeUninstalled( self._package_id_to_uninstall) self.uninstall(self._package_id_to_uninstall) self._resetUninstallVariables() self.closeConfirmResetDialog()
def __init__(self) -> None: SteSlicerApplication.getInstance().hideMessageSignal.connect(self._onHideMessage) self._is_layers_in_file = False self._cancelled = False self._message = None self._layer_number = -1 self._extruder_number = 0 self._pi_faction = 0 self._position = Position self._gcode_position = Position # stack to get print settingd via getProperty method self._application = SteSlicerApplication.getInstance() self._global_stack = self._application.getGlobalContainerStack() #type: GlobalStack self._licensed = self._application.getLicenseManager().licenseValid self._rot_nwp = Matrix() self._rot_nws = Matrix() self._scene_node = None self._extruder_number = 0 # type: Dict[int, List[float]] # Offsets for multi extruders. key is index, value is [x-offset, y-offset] self._extruder_offsets = {} self._gcode_list = [] self._current_layer_thickness = 0 self._current_layer_height = 0 #speeds self._travel_speed = 0 self._wall_0_speed = 0 self._skin_speed = 0 self._infill_speed = 0 self._support_speed = 0 self._retraction_speed = 0 self._prime_speed = 0 #retraction self._enable_retraction = False self._retraction_amount = 0 self._retraction_min_travel = 1.5 self._retraction_hop_enabled = False self._retraction_hop = 1 self._filament_diameter = 1.75 self._line_width = 0.4 self._layer_thickness = 0.2 self._clearValues()
def write(self, stream, nodes, mode=MeshWriter.OutputMode.BinaryMode): radius = SteSlicerApplication.getInstance().getGlobalContainerStack( ).getProperty("cylindrical_mode_base_diameter", "value") / 2 height = SteSlicerApplication.getInstance().getGlobalContainerStack( ).getProperty("machine_height", "value") # try: MeshWriter._meshNodes(nodes).__next__() for node in nodes: mesh_data = node.getMeshData().getTransformed( node.getWorldTransformation()) verts = mesh_data.getVertices() if verts is None: continue faces = None if mesh_data.hasIndices(): faces = mesh_data.getIndices() else: num_verts = mesh_data.getVertexCount() faces = numpy.empty((int(num_verts / 3 + 1), 3), numpy.int32) for i in range(0, num_verts - 2, 3): faces[int(i / 3):] = [i, i + 1, i + 2] if faces is None: continue vertices = [] for vert in verts: vertices.append([vert[0], -vert[2], vert[1]]) mesh = trimesh.Trimesh(vertices=vertices, faces=faces) cutting_cylinder = trimesh.primitives.Cylinder(radius=radius, height=height) result = mesh.difference(cutting_cylinder, engine="scad") stream.write("Uranium STLWriter {0}".format( time.strftime("%a %d %b %Y %H:%M:%S")).encode().ljust( 80, b"\000")) face_count = len(result.faces) # Write number of faces to STL stream.write(struct.pack("<I", int(face_count))) verts = result.vertices for face in result.faces: v1 = verts[face[0]] v2 = verts[face[1]] v3 = verts[face[2]] stream.write(struct.pack("<fff", 0.0, 0.0, 0.0)) stream.write(struct.pack("<fff", v1[0], v1[1], v1[2])) stream.write(struct.pack("<fff", v2[0], v2[1], v2[2])) stream.write(struct.pack("<fff", v3[0], v3[1], v3[2])) stream.write(struct.pack("<H", 0)) return True
def loadConfigurationFromPrinter(self) -> None: machine_manager = SteSlicerApplication.getInstance().getMachineManager() hotend_ids = machine_manager.printerOutputDevices[0].hotendIds for index in range(len(hotend_ids)): machine_manager.printerOutputDevices[0].hotendIdChanged.emit(index, hotend_ids[index]) material_ids = machine_manager.printerOutputDevices[0].materialIds for index in range(len(material_ids)): machine_manager.printerOutputDevices[0].materialIdChanged.emit(index, material_ids[index])
def getStoredKey(self) -> str: global_container_stack = SteSlicerApplication.getInstance().getGlobalContainerStack() if global_container_stack: meta_data = global_container_stack.getMetaData() if "um_network_key" in meta_data: return global_container_stack.getMetaDataEntry("um_network_key") return ""
def __init__(self) -> None: SteSlicerApplication.getInstance().hideMessageSignal.connect(self._onHideMessage) self._cancelled = False self._message = None self._layer_number = 0 self._extruder_number = 0 self._clearValues() self._scene_node = None # X, Y, Z position, F feedrate and E extruder values are stored self._position = Position self._is_layers_in_file = False # Does the Gcode have the layers comment? self._extruder_offsets = {} # type: Dict[int, List[float]] # Offsets for multi extruders. key is index, value is [x-offset, y-offset] self._current_layer_thickness = 0.2 # default self._filament_diameter = 1.75 # default self._previous_extrusion_value = 0.0 # keep track of the filament retractions SteSlicerApplication.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
def _checkForWarnings(self): warnings = [] print_information = SteSlicerApplication.getInstance( ).getPrintInformation() if not print_information.materialLengths: Logger.log( "w", "There is no material length information. Unable to check for warnings." ) return warnings extruder_manager = ExtruderManager.getInstance() for index, extruder in enumerate(self.activePrinter.extruders): if index < len(print_information.materialLengths ) and print_information.materialLengths[index] != 0: # The extruder is by this print. # TODO: material length check # Check if the right Printcore is active. variant = extruder_manager.getExtruderStack( index).findContainer({"type": "variant"}) if variant: if variant.getName() != extruder.hotendID: warnings.append( i18n_catalog.i18nc( "@label", "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}" .format( cura_printcore_name=variant.getName(), remote_printcore_name=extruder.hotendID, extruder_id=index + 1))) else: Logger.log("w", "Unable to find variant.") # Check if the right material is loaded. local_material = extruder_manager.getExtruderStack( index).findContainer({"type": "material"}) if local_material: if extruder.activeMaterial.guid != local_material.getMetaDataEntry( "GUID"): Logger.log( "w", "Extruder %s has a different material (%s) as Cura (%s)", index + 1, extruder.activeMaterial.guid, local_material.getMetaDataEntry("GUID")) warnings.append( i18n_catalog.i18nc( "@label", "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}" ).format(local_material.getName(), extruder.activeMaterial.name, index + 1)) else: Logger.log("w", "Unable to find material.") return warnings