mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-14 18:05:55 +08:00
Merge branch 'master' into feature_enable_disable_extruder
This commit is contained in:
commit
859ac88357
@ -102,6 +102,13 @@ class MaterialManager(QObject):
|
||||
# GUID -> material group list
|
||||
self._guid_material_groups_map = defaultdict(list)
|
||||
for root_material_id, material_group in self._material_group_map.items():
|
||||
# This can happen when we are updating with incomplete data.
|
||||
if material_group.root_material_node is None:
|
||||
Logger.log("e", "Missing root material node for [%s]. Probably caused by update using incomplete data."
|
||||
" Check all related signals for further debugging.",
|
||||
material_group.name)
|
||||
# Do nothing here, we wait for a next signal to trigger an update.
|
||||
return
|
||||
guid = material_group.root_material_node.metadata["GUID"]
|
||||
self._guid_material_groups_map[guid].append(material_group)
|
||||
|
||||
|
@ -40,8 +40,6 @@ class BaseMaterialsModel(ListModel):
|
||||
self._extruder_position = 0
|
||||
self._extruder_stack = None
|
||||
|
||||
self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack)
|
||||
|
||||
def _updateExtruderStack(self):
|
||||
global_stack = self._machine_manager.activeMachine
|
||||
if global_stack is None:
|
||||
|
@ -6,6 +6,7 @@ from UM.Application import Application
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Signal import postponeSignals, CompressTechnique
|
||||
from UM.Settings.ContainerStack import ContainerStack
|
||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
@ -434,6 +435,24 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
# \param file_name
|
||||
@call_on_qt_thread
|
||||
def read(self, file_name):
|
||||
container_registry = ContainerRegistry.getInstance()
|
||||
signals = [container_registry.containerAdded,
|
||||
container_registry.containerRemoved,
|
||||
container_registry.containerMetaDataChanged]
|
||||
#
|
||||
# We now have different managers updating their lookup tables upon container changes. It is critical to make
|
||||
# sure that the managers have a complete set of data when they update.
|
||||
#
|
||||
# In project loading, lots of the container-related signals are loosely emitted, which can create timing gaps
|
||||
# for incomplete data update or other kinds of issues to happen.
|
||||
#
|
||||
# To avoid this, we postpone all signals so they don't get emitted immediately. But, please also be aware that,
|
||||
# because of this, do not expect to have the latest data in the lookup tables in project loading.
|
||||
#
|
||||
with postponeSignals(*signals, compress = CompressTechnique.CompressSingle):
|
||||
return self._read(file_name)
|
||||
|
||||
def _read(self, file_name):
|
||||
archive = zipfile.ZipFile(file_name, "r")
|
||||
|
||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||
|
@ -1,14 +1,15 @@
|
||||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Workspace.WorkspaceWriter import WorkspaceWriter
|
||||
import configparser
|
||||
from io import StringIO
|
||||
import zipfile
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Logger import Logger
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
import zipfile
|
||||
from io import StringIO
|
||||
import configparser
|
||||
from UM.Workspace.WorkspaceWriter import WorkspaceWriter
|
||||
|
||||
|
||||
class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
||||
@ -16,7 +17,10 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
||||
super().__init__()
|
||||
|
||||
def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode):
|
||||
mesh_writer = Application.getInstance().getMeshFileHandler().getWriter("3MFWriter")
|
||||
application = Application.getInstance()
|
||||
machine_manager = application.getMachineManager()
|
||||
|
||||
mesh_writer = application.getMeshFileHandler().getWriter("3MFWriter")
|
||||
|
||||
if not mesh_writer: # We need to have the 3mf mesh writer, otherwise we can't save the entire workspace
|
||||
return False
|
||||
@ -29,17 +33,17 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
||||
if archive is None: # This happens if there was no mesh data to write.
|
||||
archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED)
|
||||
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
global_stack = machine_manager.activeMachine
|
||||
|
||||
# Add global container stack data to the archive.
|
||||
self._writeContainerToArchive(global_container_stack, archive)
|
||||
self._writeContainerToArchive(global_stack, archive)
|
||||
|
||||
# Also write all containers in the stack to the file
|
||||
for container in global_container_stack.getContainers():
|
||||
for container in global_stack.getContainers():
|
||||
self._writeContainerToArchive(container, archive)
|
||||
|
||||
# Check if the machine has extruders and save all that data as well.
|
||||
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()):
|
||||
for extruder_stack in global_stack.extruders.values():
|
||||
self._writeContainerToArchive(extruder_stack, archive)
|
||||
for container in extruder_stack.getContainers():
|
||||
self._writeContainerToArchive(container, archive)
|
||||
@ -59,9 +63,9 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
||||
version_file = zipfile.ZipInfo("Cura/version.ini")
|
||||
version_config_parser = configparser.ConfigParser(interpolation = None)
|
||||
version_config_parser.add_section("versions")
|
||||
version_config_parser.set("versions", "cura_version", Application.getInstance().getVersion())
|
||||
version_config_parser.set("versions", "build_type", Application.getInstance().getBuildType())
|
||||
version_config_parser.set("versions", "is_debug_mode", str(Application.getInstance().getIsDebugMode()))
|
||||
version_config_parser.set("versions", "cura_version", application.getVersion())
|
||||
version_config_parser.set("versions", "build_type", application.getBuildType())
|
||||
version_config_parser.set("versions", "is_debug_mode", str(application.getIsDebugMode()))
|
||||
|
||||
version_file_string = StringIO()
|
||||
version_config_parser.write(version_file_string)
|
||||
@ -85,7 +89,8 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
||||
# Some containers have a base file, which should then be the file to use.
|
||||
if "base_file" in container.getMetaData():
|
||||
base_file = container.getMetaDataEntry("base_file")
|
||||
container = ContainerRegistry.getInstance().findContainers(id = base_file)[0]
|
||||
if base_file != container.getId():
|
||||
container = ContainerRegistry.getInstance().findContainers(id = base_file)[0]
|
||||
|
||||
file_name = "Cura/%s.%s" % (container.getId(), file_suffix)
|
||||
|
||||
|
@ -2,17 +2,15 @@
|
||||
# under the terms of the AGPLv3 or higher
|
||||
|
||||
from ..Script import Script
|
||||
#from UM.Logger import Logger
|
||||
# from cura.Settings.ExtruderManager import ExtruderManager
|
||||
|
||||
class ColorChange(Script):
|
||||
class FilamentChange(Script):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name":"Color Change",
|
||||
"key": "ColorChange",
|
||||
"name":"Filament Change",
|
||||
"key": "FilamentChange",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
@ -60,17 +58,17 @@ class ColorChange(Script):
|
||||
if later_retract is not None and later_retract > 0.:
|
||||
color_change = color_change + (" L%.2f" % later_retract)
|
||||
|
||||
color_change = color_change + " ; Generated by ColorChange plugin"
|
||||
color_change = color_change + " ; Generated by FilamentChange plugin"
|
||||
|
||||
layer_targets = layer_nums.split(',')
|
||||
layer_targets = layer_nums.split(",")
|
||||
if len(layer_targets) > 0:
|
||||
for layer_num in layer_targets:
|
||||
layer_num = int( layer_num.strip() )
|
||||
layer_num = int(layer_num.strip())
|
||||
if layer_num < len(data):
|
||||
layer = data[ layer_num - 1 ]
|
||||
layer = data[layer_num - 1]
|
||||
lines = layer.split("\n")
|
||||
lines.insert(2, color_change )
|
||||
final_line = "\n".join( lines )
|
||||
data[ layer_num - 1 ] = final_line
|
||||
lines.insert(2, color_change)
|
||||
final_line = "\n".join(lines)
|
||||
data[layer_num - 1] = final_line
|
||||
|
||||
return data
|
@ -93,13 +93,15 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
|
||||
self._gcode = gcode_list
|
||||
|
||||
is_job_sent = True
|
||||
if len(self._printers) > 1:
|
||||
self._spawnPrinterSelectionDialog()
|
||||
else:
|
||||
self.sendPrintJob()
|
||||
is_job_sent = self.sendPrintJob()
|
||||
|
||||
# Notify the UI that a switch to the print monitor should happen
|
||||
Application.getInstance().getController().setActiveStage("MonitorStage")
|
||||
if is_job_sent:
|
||||
Application.getInstance().getController().setActiveStage("MonitorStage")
|
||||
|
||||
def _spawnPrinterSelectionDialog(self):
|
||||
if self._printer_selection_dialog is None:
|
||||
@ -121,7 +123,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
i18n_catalog.i18nc("@info:status",
|
||||
"Sending new jobs (temporarily) blocked, still sending the previous print job."))
|
||||
self._error_message.show()
|
||||
return
|
||||
return False
|
||||
|
||||
self._sending_gcode = True
|
||||
|
||||
@ -134,7 +136,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
compressed_gcode = self._compressGCode()
|
||||
if compressed_gcode is None:
|
||||
# Abort was called.
|
||||
return
|
||||
return False
|
||||
|
||||
parts = []
|
||||
|
||||
@ -152,6 +154,8 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
|
||||
self._latest_reply_handler = self.postFormWithParts("print_jobs/", parts, onFinished=self._onPostPrintJobFinished, onProgress=self._onUploadPrintJobProgress)
|
||||
|
||||
return True
|
||||
|
||||
@pyqtProperty(QObject, notify=activePrinterChanged)
|
||||
def activePrinter(self) -> Optional["PrinterOutputModel"]:
|
||||
return self._active_printer
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Logger import Logger
|
||||
@ -17,7 +17,7 @@ from .avr_isp import stk500v2, intelHex
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
|
||||
|
||||
from serial import Serial, SerialException
|
||||
from serial import Serial, SerialException, SerialTimeoutException
|
||||
from threading import Thread
|
||||
from time import time, sleep
|
||||
from queue import Queue
|
||||
@ -266,8 +266,11 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||
command = (command + "\n").encode()
|
||||
if not command.endswith(b"\n"):
|
||||
command += b"\n"
|
||||
self._serial.write(b"\n")
|
||||
self._serial.write(command)
|
||||
try:
|
||||
self._serial.write(b"\n")
|
||||
self._serial.write(command)
|
||||
except SerialTimeoutException:
|
||||
Logger.log("w", "Timeout when sending command to printer via USB.")
|
||||
|
||||
def _update(self):
|
||||
while self._connection_state == ConnectionState.connected and self._serial is not None:
|
||||
|
@ -200,18 +200,25 @@ class XmlMaterialProfile(InstanceContainer):
|
||||
## Begin Settings Block
|
||||
builder.start("settings")
|
||||
|
||||
if self.getDefinition().getId() == "fdmprinter":
|
||||
if self.getMetaDataEntry("definition") == "fdmprinter":
|
||||
for instance in self.findInstances():
|
||||
self._addSettingElement(builder, instance)
|
||||
|
||||
machine_container_map = {}
|
||||
machine_nozzle_map = {}
|
||||
|
||||
variant_manager = CuraApplication.getInstance()._variant_manager
|
||||
variant_manager = CuraApplication.getInstance().getVariantManager()
|
||||
material_manager = CuraApplication.getInstance().getMaterialManager()
|
||||
|
||||
root_material_id = self.getMetaDataEntry("base_file") # if basefile is self.getId, this is a basefile.
|
||||
material_group = material_manager.getMaterialGroup(root_material_id)
|
||||
|
||||
all_containers = []
|
||||
for node in [material_group.root_material_node] + material_group.derived_material_node_list:
|
||||
all_containers.append(node.getContainer())
|
||||
|
||||
all_containers = registry.findInstanceContainers(GUID = self.getMetaDataEntry("GUID"), base_file = self.getId())
|
||||
for container in all_containers:
|
||||
definition_id = container.getDefinition().getId()
|
||||
definition_id = container.getMetaDataEntry("definition")
|
||||
if definition_id == "fdmprinter":
|
||||
continue
|
||||
|
||||
@ -233,7 +240,8 @@ class XmlMaterialProfile(InstanceContainer):
|
||||
product_id_map = self.getProductIdMap()
|
||||
|
||||
for definition_id, container in machine_container_map.items():
|
||||
definition = container.getDefinition()
|
||||
definition_id = container.getMetaDataEntry("definition")
|
||||
definition_metadata = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = definition_id)[0]
|
||||
|
||||
product = definition_id
|
||||
for product_name, product_id_list in product_id_map.items():
|
||||
@ -243,13 +251,14 @@ class XmlMaterialProfile(InstanceContainer):
|
||||
|
||||
builder.start("machine")
|
||||
builder.start("machine_identifier", {
|
||||
"manufacturer": container.getMetaDataEntry("machine_manufacturer", definition.getMetaDataEntry("manufacturer", "Unknown")),
|
||||
"manufacturer": container.getMetaDataEntry("machine_manufacturer",
|
||||
definition_metadata.get("manufacturer", "Unknown")),
|
||||
"product": product
|
||||
})
|
||||
builder.end("machine_identifier")
|
||||
|
||||
for instance in container.findInstances():
|
||||
if self.getDefinition().getId() == "fdmprinter" and self.getInstance(instance.definition.key) and self.getProperty(instance.definition.key, "value") == instance.value:
|
||||
if self.getMetaDataEntry("definition") == "fdmprinter" and self.getInstance(instance.definition.key) and self.getProperty(instance.definition.key, "value") == instance.value:
|
||||
# If the settings match that of the base profile, just skip since we inherit the base profile.
|
||||
continue
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user