mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-11-02 20:52:20 -07:00
Merge branch 'master' into feature_sync_button
This commit is contained in:
commit
2bf6d071d1
44 changed files with 678 additions and 317 deletions
|
|
@ -216,11 +216,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
archive = zipfile.ZipFile(file_name, "r")
|
||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||
|
||||
# A few lists of containers in this project files.
|
||||
# When loading the global stack file, it may be associated with those containers, which may or may not be
|
||||
# in Cura already, so we need to provide them as alternative search lists.
|
||||
instance_container_list = []
|
||||
|
||||
resolve_strategy_keys = ["machine", "material", "quality_changes"]
|
||||
self._resolve_strategies = {k: None for k in resolve_strategy_keys}
|
||||
containers_found_dict = {k: False for k in resolve_strategy_keys}
|
||||
|
|
@ -307,34 +302,34 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
container_info = ContainerInfo(instance_container_file_name, serialized, parser)
|
||||
instance_container_info_dict[container_id] = container_info
|
||||
|
||||
instance_container = InstanceContainer(container_id)
|
||||
|
||||
# Deserialize InstanceContainer by converting read data from bytes to string
|
||||
instance_container.deserialize(serialized, file_name = instance_container_file_name)
|
||||
instance_container_list.append(instance_container)
|
||||
|
||||
container_type = instance_container.getMetaDataEntry("type")
|
||||
container_type = parser["metadata"]["type"]
|
||||
if container_type == "quality_changes":
|
||||
quality_changes_info_list.append(container_info)
|
||||
|
||||
if not parser.has_option("metadata", "extruder"):
|
||||
if not parser.has_option("metadata", "position"):
|
||||
self._machine_info.quality_changes_info.name = parser["general"]["name"]
|
||||
self._machine_info.quality_changes_info.global_info = container_info
|
||||
else:
|
||||
position = parser["metadata"]["position"]
|
||||
self._machine_info.quality_changes_info.extruder_info_dict[position] = container_info
|
||||
|
||||
quality_name = instance_container.getName()
|
||||
num_settings_overriden_by_quality_changes += len(instance_container._instances)
|
||||
quality_name = parser["general"]["name"]
|
||||
values = parser["values"] if parser.has_section("values") else dict()
|
||||
num_settings_overriden_by_quality_changes += len(values)
|
||||
# Check if quality changes already exists.
|
||||
quality_changes = self._container_registry.findInstanceContainers(id = container_id)
|
||||
if quality_changes:
|
||||
containers_found_dict["quality_changes"] = True
|
||||
# Check if there really is a conflict by comparing the values
|
||||
instance_container = InstanceContainer(container_id)
|
||||
instance_container.deserialize(serialized, file_name = instance_container_file_name)
|
||||
if quality_changes[0] != instance_container:
|
||||
quality_changes_conflict = True
|
||||
elif container_type == "quality":
|
||||
if not quality_name:
|
||||
quality_name = instance_container.getName()
|
||||
quality_name = parser["general"]["name"]
|
||||
elif container_type == "user":
|
||||
num_user_settings += len(instance_container._instances)
|
||||
num_user_settings += len(parser["values"])
|
||||
elif container_type in self._ignored_instance_container_types:
|
||||
# Ignore certain instance container types
|
||||
Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type)
|
||||
|
|
@ -453,15 +448,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
machine_conflict = True
|
||||
break
|
||||
|
||||
if self._machine_info.quality_changes_info is not None:
|
||||
for quality_changes_info in quality_changes_info_list:
|
||||
if not quality_changes_info.parser.has_option("metadata", "extruder"):
|
||||
continue
|
||||
extruder_definition_id = quality_changes_info.parser["metadata"]["extruder"]
|
||||
extruder_definition_metadata = self._container_registry.findDefinitionContainersMetadata(id = extruder_definition_id)[0]
|
||||
position = extruder_definition_metadata["position"]
|
||||
self._machine_info.quality_changes_info.extruder_info_dict[position] = quality_changes_info
|
||||
|
||||
num_visible_settings = 0
|
||||
try:
|
||||
temp_preferences = Preferences()
|
||||
|
|
@ -739,7 +725,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
|
||||
machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(global_stack)
|
||||
machine_definition_for_quality = self._container_registry.findDefinitionContainers(id = machine_definition_id_for_quality)[0]
|
||||
extruder_dict_for_quality = machine_definition_for_quality.getMetaDataEntry("machine_extruder_trains")
|
||||
|
||||
quality_changes_info = self._machine_info.quality_changes_info
|
||||
quality_changes_quality_type = quality_changes_info.global_info.parser["metadata"]["quality_type"]
|
||||
|
|
@ -752,13 +737,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
quality_changes_name = self._container_registry.uniqueName(quality_changes_name)
|
||||
for position, container_info in container_info_dict.items():
|
||||
extruder_definition_id = None
|
||||
extruder_stack = None
|
||||
if position is not None:
|
||||
extruder_definition_id = extruder_dict_for_quality[position]
|
||||
|
||||
extruder_stack = global_stack.extruders[position]
|
||||
container = quality_manager._createQualityChanges(quality_changes_quality_type,
|
||||
quality_changes_name,
|
||||
global_stack, extruder_definition_id)
|
||||
global_stack, extruder_stack)
|
||||
container_info.container = container
|
||||
container.setDirty(True)
|
||||
self._container_registry.addContainer(container)
|
||||
|
|
@ -781,18 +765,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
container_info = quality_changes_info.extruder_info_dict[position]
|
||||
container_info.container = container
|
||||
|
||||
for position, container_info in quality_changes_info.extruder_info_dict.items():
|
||||
container_info.definition_id = extruder_dict_for_quality[position]
|
||||
|
||||
# If there is no quality changes for any extruder, create one.
|
||||
if not quality_changes_info.extruder_info_dict:
|
||||
container_info = ContainerInfo(None, None, None)
|
||||
quality_changes_info.extruder_info_dict["0"] = container_info
|
||||
extruder_definition_id = extruder_dict_for_quality["0"]
|
||||
container_info.definition_id = extruder_definition_id
|
||||
extruder_stack = global_stack.extruders["0"]
|
||||
|
||||
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
|
||||
global_stack, extruder_definition_id)
|
||||
global_stack, extruder_stack)
|
||||
container_info.container = container
|
||||
container.setDirty(True)
|
||||
self._container_registry.addContainer(container)
|
||||
|
|
@ -818,9 +798,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
continue
|
||||
|
||||
if container_info.container is None:
|
||||
extruder_definition_id = extruder_dict_for_quality[position]
|
||||
extruder_stack = global_stack.extruders[position]
|
||||
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
|
||||
global_stack, extruder_definition_id)
|
||||
global_stack, extruder_stack)
|
||||
container_info.container = container
|
||||
|
||||
for key, value in container_info.parser["values"].items():
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._onGlobalStackChanged()
|
||||
|
||||
Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)
|
||||
# extruder enable / disable. Actually wanted to use machine manager here, but the initialization order causes it to crash
|
||||
ExtruderManager.getInstance().extrudersChanged.connect(self._extruderChanged)
|
||||
|
||||
# A flag indicating if an error check was scheduled
|
||||
# If so, we will stop the auto-slice timer and start upon the error check
|
||||
|
|
@ -782,3 +784,9 @@ class CuraEngineBackend(QObject, Backend):
|
|||
def tickle(self):
|
||||
if self._use_timer:
|
||||
self._change_timer.start()
|
||||
|
||||
def _extruderChanged(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)
|
||||
self._invokeSlice()
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ class ProcessSlicedLayersJob(Job):
|
|||
|
||||
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
|
||||
|
||||
new_node = CuraSceneNode()
|
||||
# The no_setting_override is here because adding the SettingOverrideDecorator will trigger a reslice
|
||||
new_node = CuraSceneNode(no_setting_override = True)
|
||||
new_node.addDecorator(BuildPlateDecorator(self._build_plate_number))
|
||||
|
||||
# Force garbage collection.
|
||||
|
|
|
|||
|
|
@ -129,8 +129,10 @@ class StartSliceJob(Job):
|
|||
self.setResult(StartJobResult.MaterialIncompatible)
|
||||
return
|
||||
|
||||
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
|
||||
for position, extruder_stack in stack.extruders.items():
|
||||
material = extruder_stack.findContainer({"type": "material"})
|
||||
if not extruder_stack.isEnabled:
|
||||
continue
|
||||
if material:
|
||||
if material.getMetaDataEntry("compatible") == False:
|
||||
self.setResult(StartJobResult.MaterialIncompatible)
|
||||
|
|
@ -189,11 +191,18 @@ class StartSliceJob(Job):
|
|||
if per_object_stack:
|
||||
is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS)
|
||||
|
||||
if node.callDecoration("getBuildPlateNumber") == self._build_plate_number:
|
||||
if not getattr(node, "_outside_buildarea", False) or is_non_printing_mesh:
|
||||
temp_list.append(node)
|
||||
if not is_non_printing_mesh:
|
||||
has_printing_mesh = True
|
||||
# Find a reason not to add the node
|
||||
if node.callDecoration("getBuildPlateNumber") != self._build_plate_number:
|
||||
continue
|
||||
if getattr(node, "_outside_buildarea", False) and not is_non_printing_mesh:
|
||||
continue
|
||||
node_position = node.callDecoration("getActiveExtruderPosition")
|
||||
if not stack.extruders[str(node_position)].isEnabled:
|
||||
continue
|
||||
|
||||
temp_list.append(node)
|
||||
if not is_non_printing_mesh:
|
||||
has_printing_mesh = True
|
||||
|
||||
Job.yieldThread()
|
||||
|
||||
|
|
@ -269,9 +278,15 @@ class StartSliceJob(Job):
|
|||
# \return A dictionary of replacement tokens to the values they should be
|
||||
# replaced with.
|
||||
def _buildReplacementTokens(self, stack) -> dict:
|
||||
default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
|
||||
result = {}
|
||||
for key in stack.getAllKeys():
|
||||
result[key] = stack.getProperty(key, "value")
|
||||
setting_type = stack.getProperty(key, "type")
|
||||
value = stack.getProperty(key, "value")
|
||||
if setting_type == "extruder" and value == -1:
|
||||
# replace with the default value
|
||||
value = default_extruder_position
|
||||
result[key] = value
|
||||
Job.yieldThread()
|
||||
|
||||
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
|
||||
|
|
@ -377,11 +392,11 @@ class StartSliceJob(Job):
|
|||
# limit_to_extruder property.
|
||||
def _buildGlobalInheritsStackMessage(self, stack):
|
||||
for key in stack.getAllKeys():
|
||||
extruder = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
|
||||
if extruder >= 0: #Set to a specific extruder.
|
||||
extruder_position = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
|
||||
if extruder_position >= 0: # Set to a specific extruder.
|
||||
setting_extruder = self._slice_message.addRepeatedMessage("limit_to_extruder")
|
||||
setting_extruder.name = key
|
||||
setting_extruder.extruder = extruder
|
||||
setting_extruder.extruder = extruder_position
|
||||
Job.yieldThread()
|
||||
|
||||
## Check if a node has per object settings and ensure that they are set correctly in the message
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ Cura.MachineAction
|
|||
height: childrenRect.height
|
||||
width: childrenRect.width
|
||||
text: machineExtruderCountProvider.properties.description
|
||||
visible: extruderCountModel.count >= 2
|
||||
|
||||
Row
|
||||
{
|
||||
|
|
|
|||
|
|
@ -173,7 +173,10 @@ class PostProcessingPlugin(QObject, Extension):
|
|||
Logger.log("d", "Creating post processing plugin view.")
|
||||
|
||||
## Load all scripts in the scripts folders
|
||||
for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Preferences)]:
|
||||
# The PostProcessingPlugin path is for built-in scripts.
|
||||
# The Resources path is where the user should store custom scripts.
|
||||
# The Preferences path is legacy, where the user may previously have stored scripts.
|
||||
for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Resources), Resources.getStoragePath(Resources.Preferences)]:
|
||||
path = os.path.join(root, "scripts")
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -78,17 +78,13 @@ class SolidView(View):
|
|||
|
||||
for node in DepthFirstIterator(scene.getRoot()):
|
||||
if not node.render(renderer):
|
||||
if node.getMeshData() and node.isVisible():
|
||||
if node.getMeshData() and node.isVisible() and not node.callDecoration("getLayerData"):
|
||||
uniforms = {}
|
||||
shade_factor = 1.0
|
||||
|
||||
per_mesh_stack = node.callDecoration("getStack")
|
||||
|
||||
# Get color to render this mesh in from ExtrudersModel
|
||||
extruder_index = 0
|
||||
extruder_id = node.callDecoration("getActiveExtruder")
|
||||
if extruder_id:
|
||||
extruder_index = max(0, self._extruders_model.find("id", extruder_id))
|
||||
extruder_index = int(node.callDecoration("getActiveExtruderPosition"))
|
||||
|
||||
# Use the support extruder instead of the active extruder if this is a support_mesh
|
||||
if per_mesh_stack:
|
||||
|
|
|
|||
|
|
@ -301,8 +301,8 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
self._updatePrintJob(print_job, print_job_data)
|
||||
|
||||
if print_job.state != "queued": # Print job should be assigned to a printer.
|
||||
if print_job.state == "failed":
|
||||
# Print job was failed, so don't attach it to a printer.
|
||||
if print_job.state in ["failed", "finished", "aborted"]:
|
||||
# Print job was already completed, so don't attach it to a printer.
|
||||
printer = None
|
||||
else:
|
||||
printer = self._getPrinterByKey(print_job_data["printer_uuid"])
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ upgrade = VersionUpgrade32to33.VersionUpgrade32to33()
|
|||
def getMetaData():
|
||||
return {
|
||||
"version_upgrade": {
|
||||
# From To Upgrade function
|
||||
# From To Upgrade function
|
||||
("definition_changes", 2000004): ("definition_changes", 3000004, upgrade.upgradeInstanceContainer),
|
||||
("quality_changes", 2000004): ("quality_changes", 3000004, upgrade.upgradeQualityChanges),
|
||||
("user", 2000004): ("user", 3000004, upgrade.upgradeInstanceContainer)
|
||||
("quality_changes", 2000004): ("quality_changes", 3000004, upgrade.upgradeQualityChanges),
|
||||
("user", 2000004): ("user", 3000004, upgrade.upgradeInstanceContainer)
|
||||
},
|
||||
"sources": {
|
||||
"definition_changes": {
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
self._addSettingElement(builder, instance)
|
||||
|
||||
machine_container_map = {}
|
||||
machine_nozzle_map = {}
|
||||
machine_variant_map = {}
|
||||
|
||||
variant_manager = CuraApplication.getInstance().getVariantManager()
|
||||
material_manager = CuraApplication.getInstance().getMaterialManager()
|
||||
|
|
@ -225,13 +225,14 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
if definition_id not in machine_container_map:
|
||||
machine_container_map[definition_id] = container
|
||||
|
||||
if definition_id not in machine_nozzle_map:
|
||||
machine_nozzle_map[definition_id] = {}
|
||||
if definition_id not in machine_variant_map:
|
||||
machine_variant_map[definition_id] = {}
|
||||
|
||||
variant_name = container.getMetaDataEntry("variant_name")
|
||||
if variant_name:
|
||||
machine_nozzle_map[definition_id][variant_name] = variant_manager.getVariantNode(definition_id,
|
||||
variant_name)
|
||||
variant_dict = {"variant_node": variant_manager.getVariantNode(definition_id, variant_name),
|
||||
"material_container": container}
|
||||
machine_variant_map[definition_id][variant_name] = variant_dict
|
||||
continue
|
||||
|
||||
machine_container_map[definition_id] = container
|
||||
|
|
@ -265,28 +266,60 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
self._addSettingElement(builder, instance)
|
||||
|
||||
# Find all hotend sub-profiles corresponding to this material and machine and add them to this profile.
|
||||
for hotend_name, variant_node in machine_nozzle_map[definition_id].items():
|
||||
# The hotend identifier is not the containers name, but its "name".
|
||||
builder.start("hotend", {"id": hotend_name})
|
||||
buildplate_dict = {}
|
||||
for variant_name, variant_dict in machine_variant_map[definition_id].items():
|
||||
variant_type = variant_dict["variant_node"].metadata["hardware_type"]
|
||||
from cura.Machines.VariantManager import VariantType
|
||||
variant_type = VariantType(variant_type)
|
||||
if variant_type == VariantType.NOZZLE:
|
||||
# The hotend identifier is not the containers name, but its "name".
|
||||
builder.start("hotend", {"id": variant_name})
|
||||
|
||||
# Compatible is a special case, as it's added as a meta data entry (instead of an instance).
|
||||
compatible = variant_node.metadata.get("compatible")
|
||||
if compatible is not None:
|
||||
builder.start("setting", {"key": "hardware compatible"})
|
||||
if compatible:
|
||||
builder.data("yes")
|
||||
else:
|
||||
builder.data("no")
|
||||
builder.end("setting")
|
||||
# Compatible is a special case, as it's added as a meta data entry (instead of an instance).
|
||||
material_container = variant_dict["material_container"]
|
||||
compatible = container.getMetaDataEntry("compatible")
|
||||
if compatible is not None:
|
||||
builder.start("setting", {"key": "hardware compatible"})
|
||||
if compatible:
|
||||
builder.data("yes")
|
||||
else:
|
||||
builder.data("no")
|
||||
builder.end("setting")
|
||||
|
||||
for instance in variant_node.getContainer().findInstances():
|
||||
if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
|
||||
# If the settings match that of the machine profile, just skip since we inherit the machine profile.
|
||||
continue
|
||||
for instance in material_container.findInstances():
|
||||
if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
|
||||
# If the settings match that of the machine profile, just skip since we inherit the machine profile.
|
||||
continue
|
||||
|
||||
self._addSettingElement(builder, instance)
|
||||
self._addSettingElement(builder, instance)
|
||||
|
||||
builder.end("hotend")
|
||||
if material_container.getMetaDataEntry("buildplate_compatible") and not buildplate_dict:
|
||||
buildplate_dict["buildplate_compatible"] = material_container.getMetaDataEntry("buildplate_compatible")
|
||||
buildplate_dict["buildplate_recommended"] = material_container.getMetaDataEntry("buildplate_recommended")
|
||||
buildplate_dict["material_container"] = material_container
|
||||
|
||||
builder.end("hotend")
|
||||
|
||||
if buildplate_dict:
|
||||
for variant_name in buildplate_dict["buildplate_compatible"]:
|
||||
builder.start("buildplate", {"id": variant_name})
|
||||
|
||||
material_container = buildplate_dict["material_container"]
|
||||
buildplate_compatible_dict = material_container.getMetaDataEntry("buildplate_compatible")
|
||||
buildplate_recommended_dict = material_container.getMetaDataEntry("buildplate_recommended")
|
||||
if buildplate_compatible_dict:
|
||||
compatible = buildplate_compatible_dict[variant_name]
|
||||
recommended = buildplate_recommended_dict[variant_name]
|
||||
|
||||
builder.start("setting", {"key": "hardware compatible"})
|
||||
builder.data("yes" if compatible else "no")
|
||||
builder.end("setting")
|
||||
|
||||
builder.start("setting", {"key": "hardware recommended"})
|
||||
builder.data("yes" if recommended else "no")
|
||||
builder.end("setting")
|
||||
|
||||
builder.end("buildplate")
|
||||
|
||||
builder.end("machine")
|
||||
|
||||
|
|
@ -617,7 +650,8 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
|
||||
from cura.Machines.VariantManager import VariantType
|
||||
variant_manager = CuraApplication.getInstance().getVariantManager()
|
||||
variant_node = variant_manager.getVariantNode(machine_id, buildplate_id)
|
||||
variant_node = variant_manager.getVariantNode(machine_id, buildplate_id,
|
||||
variant_type = VariantType.BUILD_PLATE)
|
||||
if not variant_node:
|
||||
continue
|
||||
|
||||
|
|
@ -841,6 +875,8 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
continue
|
||||
|
||||
settings = buildplate.iterfind("./um:setting", cls.__namespaces)
|
||||
buildplate_compatibility = True
|
||||
buildplate_recommended = True
|
||||
for entry in settings:
|
||||
key = entry.get("key")
|
||||
if key == "hardware compatible":
|
||||
|
|
@ -848,8 +884,8 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
elif key == "hardware recommended":
|
||||
buildplate_recommended = cls._parseCompatibleValue(entry.text)
|
||||
|
||||
buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_map["buildplate_compatible"]
|
||||
buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_map["buildplate_recommended"]
|
||||
buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_compatibility
|
||||
buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_recommended
|
||||
|
||||
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
|
||||
hotend_name = hotend.get("id")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue