Merge branch 'feature_intent_container_tree' of https://github.com/Ultimaker/Cura into feature_intent_container_tree

This commit is contained in:
Remco Burema 2019-08-15 16:47:29 +02:00
commit 9374934d72
4 changed files with 21 additions and 103 deletions

View file

@ -8,7 +8,7 @@ from UM.Settings.Interfaces import ContainerInterface
from cura.Machines.MachineNode import MachineNode
from typing import Dict
import time
## This class contains a look-up tree for which containers are available at
# which stages of configuration.
#
@ -32,12 +32,15 @@ class ContainerTree:
## Builds the initial container tree.
def _loadAll(self):
Logger.log("i", "Building container tree.")
start_time = time.time()
all_stacks = ContainerRegistry.getInstance().findContainerStacks()
for stack in all_stacks:
definition_id = stack.definition.getId()
if definition_id not in self.machines:
self.machines[definition_id] = MachineNode(definition_id)
Logger.log("d", "Building the container tree took %s seconds", time.time() - start_time)
## When a printer gets added, we need to build up the tree for that container.
def _machineAdded(self, definition_container: ContainerInterface):
if not isinstance(definition_container, DefinitionContainer):

View file

@ -83,71 +83,6 @@ class MaterialManager(QObject):
self._favorites = set(cura.CuraApplication.CuraApplication.getInstance().getPreferences().getValue("cura/favorite_materials").split(";"))
self.materialsUpdated.emit()
def __addMaterialMetadataIntoLookupTree(self, material_metadata: Dict[str, Any]) -> None:
material_id = material_metadata["id"]
# We don't store empty material in the lookup tables
if material_id == "empty_material":
return
root_material_id = material_metadata["base_file"]
definition = material_metadata["definition"]
approximate_diameter = str(material_metadata["approximate_diameter"])
if approximate_diameter not in self._diameter_machine_nozzle_buildplate_material_map:
self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] = {}
machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[
approximate_diameter]
if definition not in machine_nozzle_buildplate_material_map:
machine_nozzle_buildplate_material_map[definition] = MaterialNode()
# This is a list of information regarding the intermediate nodes:
# nozzle -> buildplate
nozzle_name = material_metadata.get("variant_name")
buildplate_name = material_metadata.get("buildplate_name")
intermediate_node_info_list = [(nozzle_name, VariantType.NOZZLE),
(buildplate_name, VariantType.BUILD_PLATE),
]
variant_manager = cura.CuraApplication.CuraApplication.getInstance().getVariantManager()
machine_node = machine_nozzle_buildplate_material_map[definition]
current_node = machine_node
current_intermediate_node_info_idx = 0
error_message = None # type: Optional[str]
while current_intermediate_node_info_idx < len(intermediate_node_info_list):
variant_name, variant_type = intermediate_node_info_list[current_intermediate_node_info_idx]
if variant_name is not None:
# The new material has a specific variant, so it needs to be added to that specific branch in the tree.
variant = variant_manager.getVariantNode(definition, variant_name, variant_type)
if variant is None:
error_message = "Material {id} contains a variant {name} that does not exist.".format(
id = material_metadata["id"], name = variant_name)
break
# Update the current node to advance to a more specific branch
if variant_name not in current_node.children_map:
current_node.children_map[variant_name] = MaterialNode()
current_node = current_node.children_map[variant_name]
current_intermediate_node_info_idx += 1
if error_message is not None:
Logger.log("e", "%s It will not be added into the material lookup tree.", error_message)
CuraContainerRegistry.getInstance().addWrongContainerId(material_metadata["id"])
return
# Add the material to the current tree node, which is the deepest (the most specific) branch we can find.
# Sanity check: Make sure that there is no duplicated materials.
if root_material_id in current_node.material_map:
Logger.log("e", "Duplicated material [%s] with root ID [%s]. It has already been added.",
material_id, root_material_id)
ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id)
return
current_node.material_map[root_material_id] = MaterialNode(material_metadata)
def getMaterialGroup(self, root_material_id: str) -> Optional[MaterialGroup]:
return self._material_group_map.get(root_material_id)
@ -190,41 +125,22 @@ class MaterialManager(QObject):
#
def getMaterialNode(self, machine_definition_id: str, nozzle_name: Optional[str],
buildplate_name: Optional[str], diameter: float, root_material_id: str) -> Optional["MaterialNode"]:
# round the diameter to get the approximate diameter
rounded_diameter = str(round(diameter))
if rounded_diameter not in self._diameter_machine_nozzle_buildplate_material_map:
Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s]) for root material id [%s]",
diameter, rounded_diameter, root_material_id)
container_tree = ContainerTree.getInstance()
machine_node = container_tree.machines.get(machine_definition_id)
if machine_node is None:
Logger.log("w", "Could not find machine with definition %s in the container tree", machine_definition_id)
return None
# If there are nozzle materials, get the nozzle-specific material
machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[rounded_diameter] # type: Dict[str, MaterialNode]
machine_node = machine_nozzle_buildplate_material_map.get(machine_definition_id)
nozzle_node = None
buildplate_node = None
variant_node = machine_node.variants.get(nozzle_name)
if variant_node is None:
Logger.log("w", "Could not find variant %s for machine with definition %s in the container tree", nozzle_name, machine_definition_id )
return None
# Fallback for "fdmprinter" if the machine-specific materials cannot be found
if machine_node is None:
machine_node = machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id)
if machine_node is not None and nozzle_name is not None and nozzle_name in machine_node.children_map:
nozzle_node = machine_node.children_map[nozzle_name]
if nozzle_node is not None and buildplate_name is not None and buildplate_name in nozzle_node.children_map:
buildplate_node = nozzle_node.children_map[buildplate_name]
material_node = variant_node.materials.get(root_material_id)
# Fallback mechanism of finding materials:
# 1. buildplate-specific material
# 2. nozzle-specific material
# 3. machine-specific material
# 4. generic material (for fdmprinter)
nodes_to_check = [buildplate_node, nozzle_node, machine_node,
machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id)]
material_node = None
for node in nodes_to_check:
if node is not None:
material_node = node.material_map.get(root_material_id)
if material_node:
break
if material_node is None:
Logger.log("w", "Could not find material %s for machine with definition %s and variant %s in the container tree", root_material_id, machine_definition_id, nozzle_name)
return None
return material_node

View file

@ -1,11 +1,10 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import TYPE_CHECKING, Optional, cast, Dict, List, Set
from typing import TYPE_CHECKING, Optional, Dict
from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
from UM.Logger import Logger
from UM.Util import parseBool
from UM.Settings.InstanceContainer import InstanceContainer
@ -117,7 +116,7 @@ class QualityManager(QObject):
nozzle_name = extruder.variant.getName()
material_base = extruder.material.getMetaDataEntry("base_file")
if nozzle_name not in machine_node.variants or material_base not in machine_node.variants[nozzle_name].materials:
# The printer has no variant/material-specific quality profiles. Return the global quality profiles.
# The printer has no variant/material-specific quality profiles. Use the global quality profiles.
qualities_per_type_per_extruder[extruder_nr] = machine_node.global_qualities
else:
# Use the actually specialised quality profiles.
@ -126,8 +125,8 @@ class QualityManager(QObject):
# Create the quality group for each available type.
quality_groups = {}
for quality_type, global_quality_node in machine_node.global_qualities.items():
quality_groups[quality_type].node_for_global = global_quality_node
quality_groups[quality_type] = QualityGroup(name = global_quality_node.getMetaDataEntry("name", "Unnamed profile"), quality_type = quality_type)
quality_groups[quality_type].node_for_global = global_quality_node
for extruder, qualities_per_type in qualities_per_type_per_extruder:
quality_groups[quality_type].nodes_for_extruders[extruder] = qualities_per_type[quality_type]

View file

@ -1253,7 +1253,7 @@ class MachineManager(QObject):
if self._global_container_stack is None:
return
if material_node:
self._global_container_stack.extruders[position].material = CuraContainerRegistry.getInstance().findContainers(id = material_node.container_id)
self._global_container_stack.extruders[position].material = CuraContainerRegistry.getInstance().findContainers(id = material_node.container_id)[0]
root_material_id = material_node.getMetaDataEntry("base_file", None)
else:
self._global_container_stack.extruders[position].material = empty_material_container