VariantManager.py 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from collections import OrderedDict
  4. from typing import Optional
  5. from UM.Logger import Logger
  6. from UM.Settings.ContainerRegistry import ContainerRegistry
  7. from cura.Machines.ContainerNode import ContainerNode
  8. from cura.Settings.GlobalStack import GlobalStack
  9. class VariantType:
  10. BUILD_PLATE = "buildplate"
  11. NOZZLE = "nozzle"
  12. ALL_VARIANT_TYPES = (VariantType.BUILD_PLATE, VariantType.NOZZLE)
  13. #
  14. # VariantManager is THE place to look for a specific variant. It maintains a variant lookup table with the following
  15. # structure:
  16. #
  17. # [machine_definition_id] -> [variant_type] -> [variant_name] -> ContainerNode(metadata / container)
  18. # Example: "ultimaker3" -> "buildplate" -> "Glass" (if present) -> ContainerNode
  19. # -> ...
  20. # -> "nozzle" -> "AA 0.4"
  21. # -> "BB 0.8"
  22. # -> ...
  23. #
  24. # Note that the "container" field is not loaded in the beginning because it would defeat the purpose of lazy-loading.
  25. # A container is loaded when getVariant() is called to load a variant InstanceContainer.
  26. #
  27. class VariantManager:
  28. def __init__(self, container_registry):
  29. self._container_registry = container_registry # type: ContainerRegistry
  30. self._machine_to_variant_dict_map = dict() # <machine_type> -> <variant_dict>
  31. self._exclude_variant_id_list = ["empty_variant"]
  32. #
  33. # Initializes the VariantManager including:
  34. # - initializing the variant lookup table based on the metadata in ContainerRegistry.
  35. #
  36. def initialize(self):
  37. self._machine_to_variant_dict_map = OrderedDict()
  38. # Cache all variants from the container registry to a variant map for better searching and organization.
  39. variant_metadata_list = self._container_registry.findContainersMetadata(type = "variant")
  40. for variant_metadata in variant_metadata_list:
  41. if variant_metadata["id"] in self._exclude_variant_id_list:
  42. Logger.log("d", "Exclude variant [%s]", variant_metadata["id"])
  43. continue
  44. variant_name = variant_metadata["name"]
  45. variant_definition = variant_metadata["definition"]
  46. if variant_definition not in self._machine_to_variant_dict_map:
  47. self._machine_to_variant_dict_map[variant_definition] = OrderedDict()
  48. for variant_type in ALL_VARIANT_TYPES:
  49. self._machine_to_variant_dict_map[variant_definition][variant_type] = dict()
  50. variant_type = variant_metadata["hardware_type"]
  51. variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type]
  52. if variant_name in variant_dict:
  53. # ERROR: duplicated variant name.
  54. raise RuntimeError("Found duplicated variant name [%s], type [%s] for machine [%s]" %
  55. (variant_name, variant_type, variant_definition))
  56. variant_dict[variant_name] = ContainerNode(metadata = variant_metadata)
  57. #
  58. # Gets the variant InstanceContainer with the given information.
  59. # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present.
  60. #
  61. def getVariantNode(self, machine_definition_id: str, variant_name: str,
  62. variant_type: Optional[str] = VariantType.NOZZLE) -> Optional["ContainerNode"]:
  63. return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name)
  64. def getVariantNodes(self, machine: "GlobalStack",
  65. variant_type: Optional[str] = VariantType.NOZZLE) -> dict:
  66. machine_definition_id = machine.definition.getId()
  67. return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {})