mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 06:39:04 +08:00
Merge branch 'master' of github.com:Ultimaker/Cura
This commit is contained in:
commit
b714f0ff3e
@ -91,6 +91,8 @@ class MachineManager(QObject):
|
||||
|
||||
self._printer_output_devices = []
|
||||
Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
|
||||
# There might already be some output devices by the time the signal is connected
|
||||
self._onOutputDevicesChanged()
|
||||
|
||||
if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacks(id = active_machine_id):
|
||||
# An active machine was saved, so restore it.
|
||||
|
@ -76,9 +76,28 @@ class CuraEngineBackend(QObject, Backend):
|
||||
self._scene = Application.getInstance().getController().getScene()
|
||||
self._scene.sceneChanged.connect(self._onSceneChanged)
|
||||
|
||||
# trigger auto-slicing on error check finished
|
||||
# Triggers for auto-slicing. Auto-slicing is triggered as follows:
|
||||
# - auto-slicing is started with a timer
|
||||
# - whenever there is a value change, we start the timer
|
||||
# - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the
|
||||
# auto-slicing timer when that error check is finished
|
||||
# If there is an error check, it will set the "_is_error_check_scheduled" flag, stop the auto-slicing timer,
|
||||
# and only wait for the error check to be finished to start the auto-slicing timer again.
|
||||
#
|
||||
self._global_container_stack = None
|
||||
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
|
||||
self._onGlobalStackChanged()
|
||||
|
||||
self._active_extruder_stack = None
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
|
||||
self._onActiveExtruderChanged()
|
||||
|
||||
Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)
|
||||
|
||||
# A flag indicating if an error check was scheduled
|
||||
# If so, we will stop the auto-slice timer and start upon the error check
|
||||
self._is_error_check_scheduled = False
|
||||
|
||||
# Listeners for receiving messages from the back-end.
|
||||
self._message_handlers["cura.proto.Layer"] = self._onLayerMessage
|
||||
self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage
|
||||
@ -271,17 +290,16 @@ class CuraEngineBackend(QObject, Backend):
|
||||
return
|
||||
|
||||
if job.getResult() == StartSliceJob.StartJobResult.SettingError:
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if Application.getInstance().platformActivity:
|
||||
extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()))
|
||||
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 = global_container_stack.getErrorKeys()
|
||||
error_keys = self._global_container_stack.getErrorKeys()
|
||||
error_labels = set()
|
||||
for key in error_keys:
|
||||
for stack in [global_container_stack] + extruders: #Search all container stacks for the definition of this setting. Some are only in an extruder stack.
|
||||
for stack in [self._global_container_stack] + extruders: #Search all container stacks for the definition of this setting. Some are only in an extruder stack.
|
||||
definitions = stack.getBottom().findDefinitions(key = key)
|
||||
if definitions:
|
||||
break #Found it! No need to continue search.
|
||||
@ -420,9 +438,24 @@ class CuraEngineBackend(QObject, Backend):
|
||||
# With manually having to slice, we want to clear the old invalid layer data.
|
||||
self._clearLayerData()
|
||||
|
||||
## A setting has changed, so check if we must reslice.
|
||||
# \param instance The setting instance that has changed.
|
||||
# \param property The property of the setting instance that has changed.
|
||||
def _onSettingChanged(self, instance, property):
|
||||
if property == "value": # Only reslice if the value has changed.
|
||||
self.needsSlicing()
|
||||
self._onChanged()
|
||||
|
||||
elif property == "validationState":
|
||||
if self._use_timer:
|
||||
self._is_error_check_scheduled = True
|
||||
self._change_timer.stop()
|
||||
|
||||
def _onStackErrorCheckFinished(self):
|
||||
self.needsSlicing()
|
||||
self._onChanged()
|
||||
self._is_error_check_scheduled = False
|
||||
if self._need_slicing:
|
||||
self.needsSlicing()
|
||||
self._onChanged()
|
||||
|
||||
## Called when a sliced layer data message is received from the engine.
|
||||
#
|
||||
@ -515,7 +548,12 @@ class CuraEngineBackend(QObject, Backend):
|
||||
def _onChanged(self, *args, **kwargs):
|
||||
self.needsSlicing()
|
||||
if self._use_timer:
|
||||
self._change_timer.start()
|
||||
# if the error check is scheduled, wait for the error check finish signal to trigger auto-slice,
|
||||
# otherwise business as usual
|
||||
if self._is_error_check_scheduled:
|
||||
self._change_timer.stop()
|
||||
else:
|
||||
self._change_timer.start()
|
||||
|
||||
## Called when the back-end connects to the front-end.
|
||||
def _onBackendConnected(self):
|
||||
@ -575,6 +613,41 @@ class CuraEngineBackend(QObject, Backend):
|
||||
Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait())
|
||||
self._process = None
|
||||
|
||||
## Called when the global container stack changes
|
||||
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(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
||||
|
||||
for extruder in extruders:
|
||||
extruder.propertyChanged.disconnect(self._onSettingChanged)
|
||||
|
||||
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
|
||||
if self._global_container_stack:
|
||||
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
|
||||
self._global_container_stack.containersChanged.connect(self._onChanged)
|
||||
extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
||||
for extruder in extruders:
|
||||
extruder.propertyChanged.connect(self._onSettingChanged)
|
||||
self._onActiveExtruderChanged()
|
||||
self._onChanged()
|
||||
|
||||
def _onActiveExtruderChanged(self):
|
||||
if self._global_container_stack:
|
||||
# Connect all extruders of the active machine. This might cause a few connects that have already happend,
|
||||
# but that shouldn't cause issues as only new / unique connections are added.
|
||||
extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
||||
for extruder in extruders:
|
||||
extruder.propertyChanged.connect(self._onSettingChanged)
|
||||
if self._active_extruder_stack:
|
||||
self._active_extruder_stack.containersChanged.disconnect(self._onChanged)
|
||||
|
||||
self._active_extruder_stack = ExtruderManager.getInstance().getActiveExtruderStack()
|
||||
if self._active_extruder_stack:
|
||||
self._active_extruder_stack.containersChanged.connect(self._onChanged)
|
||||
|
||||
def _onProcessLayersFinished(self, job):
|
||||
self._process_layers_job = None
|
||||
|
||||
|
@ -12,7 +12,9 @@ UM.Dialog
|
||||
id: base;
|
||||
|
||||
width: 500 * Screen.devicePixelRatio;
|
||||
minimumWidth: 500 * Screen.devicePixelRatio;
|
||||
height: 100 * Screen.devicePixelRatio;
|
||||
minimumHeight: 100 * Screen.devicePixelRatio;
|
||||
|
||||
visible: true;
|
||||
modality: Qt.ApplicationModal;
|
||||
|
@ -19,6 +19,7 @@ import platform
|
||||
import glob
|
||||
import time
|
||||
import os.path
|
||||
import serial.tools.list_ports
|
||||
from UM.Extension import Extension
|
||||
|
||||
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||
@ -252,24 +253,13 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
||||
# \param only_list_usb If true, only usb ports are listed
|
||||
def getSerialPortList(self, only_list_usb = False):
|
||||
base_list = []
|
||||
if platform.system() == "Windows":
|
||||
import winreg # type: ignore @UnresolvedImport
|
||||
try:
|
||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
|
||||
i = 0
|
||||
while True:
|
||||
values = winreg.EnumValue(key, i)
|
||||
if not only_list_usb or "USBSER" or "VCP" in values[0]:
|
||||
base_list += [values[1]]
|
||||
i += 1
|
||||
except Exception as e:
|
||||
pass
|
||||
else:
|
||||
if only_list_usb:
|
||||
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.usb*") + glob.glob("/dev/tty.wchusb*") + glob.glob("/dev/cu.wchusb*")
|
||||
base_list = filter(lambda s: "Bluetooth" not in s, base_list) # Filter because mac sometimes puts them in the list
|
||||
else:
|
||||
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/tty.wchusb*") + glob.glob("/dev/cu.wchusb*") + glob.glob("/dev/rfcomm*") + glob.glob("/dev/serial/by-id/*")
|
||||
for port in serial.tools.list_ports.comports():
|
||||
if not isinstance(port, tuple):
|
||||
port = (port.device, port.description, port.hwid)
|
||||
if only_list_usb and not port[2].startswith("USB"):
|
||||
continue
|
||||
base_list += [port[0]]
|
||||
|
||||
return list(base_list)
|
||||
|
||||
_instance = None # type: "USBPrinterOutputDeviceManager"
|
||||
|
@ -701,7 +701,7 @@
|
||||
},
|
||||
"roofing_line_width":
|
||||
{
|
||||
"label": "Top Surface Infill Line Width",
|
||||
"label": "Top Surface Skin Line Width",
|
||||
"description": "Width of a single line of the areas at the top of the print.",
|
||||
"unit": "mm",
|
||||
"minimum_value": "0.001",
|
||||
@ -949,7 +949,7 @@
|
||||
},
|
||||
"roofing_extruder_nr":
|
||||
{
|
||||
"label": "Top Surface Infill Extruder",
|
||||
"label": "Top Surface Skin Extruder",
|
||||
"description": "The extruder train used for printing the top most skin. This is used in multi-extrusion.",
|
||||
"type": "optional_extruder",
|
||||
"default_value": "-1",
|
||||
@ -962,20 +962,20 @@
|
||||
},
|
||||
"roofing_layer_count":
|
||||
{
|
||||
"label": "Top Surface Infill Layers",
|
||||
"label": "Top Surface Skin Layers",
|
||||
"description": "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces.",
|
||||
"default_value": 0,
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "top_layers - 1",
|
||||
"type": "int",
|
||||
"value": "0 if infill_sparse_density == 100 else 1",
|
||||
"value": "0",
|
||||
"limit_to_extruder": "roofing_extruder_nr",
|
||||
"settable_per_mesh": true,
|
||||
"enabled": "top_layers > 0"
|
||||
},
|
||||
"roofing_pattern":
|
||||
{
|
||||
"label": "Top Surface Infill Pattern",
|
||||
"label": "Top Surface Skin Pattern",
|
||||
"description": "The pattern of the top most layers.",
|
||||
"type": "enum",
|
||||
"options":
|
||||
@ -992,8 +992,8 @@
|
||||
},
|
||||
"roofing_angles":
|
||||
{
|
||||
"label": "Top Surface Infill Line Directions",
|
||||
"description": "A list of integer line directions to use when the top surface infill layers use the lines or zig zag pattern. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees).",
|
||||
"label": "Top Surface Skin Line Directions",
|
||||
"description": "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees).",
|
||||
"type": "[int]",
|
||||
"default_value": "[ ]",
|
||||
"value": "skin_angles",
|
||||
@ -1088,6 +1088,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"top_reference_wall":
|
||||
{
|
||||
"label": "Top Reference Wall",
|
||||
"description": "The number of the wall of the layers above a layer to consider as infill for that layer. Reducing this number reduces the skin on slanted top faces of the input model. Increasing this number causes walls on consecutive layers to be supported better. Zero means the outline of the layer is used.",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "wall_line_count",
|
||||
"default_value": 2,
|
||||
"type": "int",
|
||||
"value": "wall_line_count",
|
||||
"limit_to_extruder": "top_bottom_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"bottom_reference_wall":
|
||||
{
|
||||
"label": "Bottom Reference Wall",
|
||||
"description": "The number of the wall of the layers below a layer to consider as infill for that layer. Reducing this number reduces the skin on overhanging faces of the input model. Increasing this number causes bridges to attach better to the walls of the previous layer. Zero means the outline of the layer is used.",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "wall_line_count",
|
||||
"default_value": 0,
|
||||
"type": "int",
|
||||
"limit_to_extruder": "top_bottom_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"top_bottom_pattern":
|
||||
{
|
||||
"label": "Top/Bottom Pattern",
|
||||
@ -2079,8 +2102,8 @@
|
||||
},
|
||||
"speed_roofing":
|
||||
{
|
||||
"label": "Roofing Speed",
|
||||
"description": "The speed at which roofing layers are printed.",
|
||||
"label": "Top Surface Skin Speed",
|
||||
"description": "The speed at which top surface skin layers are printed.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"minimum_value": "0.1",
|
||||
@ -2434,8 +2457,8 @@
|
||||
},
|
||||
"acceleration_roofing":
|
||||
{
|
||||
"label": "Roofing Acceleration",
|
||||
"description": "The acceleration with which roofing layers are printed.",
|
||||
"label": "Top Surface Skin Acceleration",
|
||||
"description": "The acceleration with which top surface skin layers are printed.",
|
||||
"unit": "mm/s²",
|
||||
"type": "float",
|
||||
"minimum_value": "0.1",
|
||||
@ -2738,8 +2761,8 @@
|
||||
},
|
||||
"jerk_roofing":
|
||||
{
|
||||
"label": "Roofing Jerk",
|
||||
"description": "The maximum instantaneous velocity change with which roofing layers are printed.",
|
||||
"label": "Top Surface Skin Jerk",
|
||||
"description": "The maximum instantaneous velocity change with which top surface skin layers are printed.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"minimum_value": "0.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user