mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-18 04:07:57 -06:00
Implement lazy loading for machine nodes
Should be completely transparent. It'll fail the unit tests though because it now pretends that all printers have machine nodes. Contributes to issue CURA-6793.
This commit is contained in:
parent
0238f65e6a
commit
4ffda015db
2 changed files with 31 additions and 38 deletions
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry # To listen to containers being added.
|
from UM.Settings.ContainerRegistry import ContainerRegistry # To listen to containers being added.
|
||||||
from UM.Settings.Interfaces import ContainerInterface
|
|
||||||
from UM.Signal import Signal
|
from UM.Signal import Signal
|
||||||
import cura.CuraApplication # Imported like this to prevent circular dependencies.
|
import cura.CuraApplication # Imported like this to prevent circular dependencies.
|
||||||
from cura.Machines.MachineNode import MachineNode
|
from cura.Machines.MachineNode import MachineNode
|
||||||
|
@ -11,7 +10,6 @@ from cura.Settings.GlobalStack import GlobalStack # To listen only to global st
|
||||||
|
|
||||||
from typing import Dict, List, TYPE_CHECKING
|
from typing import Dict, List, TYPE_CHECKING
|
||||||
import time
|
import time
|
||||||
import UM.FlameProfiler
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from cura.Machines.QualityGroup import QualityGroup
|
from cura.Machines.QualityGroup import QualityGroup
|
||||||
|
@ -38,13 +36,9 @@ class ContainerTree:
|
||||||
return cls.__instance
|
return cls.__instance
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.machines = {} # type: Dict[str, MachineNode] # Mapping from definition ID to machine nodes.
|
self.machines = self.MachineNodeMap() # Mapping from definition ID to machine nodes with lazy loading.
|
||||||
self.materialsChanged = Signal() # Emitted when any of the material nodes in the tree got changed.
|
self.materialsChanged = Signal() # Emitted when any of the material nodes in the tree got changed.
|
||||||
|
|
||||||
container_registry = ContainerRegistry.getInstance()
|
|
||||||
container_registry.containerAdded.connect(self._machineAdded)
|
|
||||||
self._loadAll()
|
|
||||||
|
|
||||||
## Get the quality groups available for the currently activated printer.
|
## Get the quality groups available for the currently activated printer.
|
||||||
#
|
#
|
||||||
# This contains all quality groups, enabled or disabled. To check whether
|
# This contains all quality groups, enabled or disabled. To check whether
|
||||||
|
@ -76,19 +70,6 @@ class ContainerTree:
|
||||||
extruder_enabled = [extruder.isEnabled for extruder in global_stack.extruderList]
|
extruder_enabled = [extruder.isEnabled for extruder in global_stack.extruderList]
|
||||||
return self.machines[global_stack.definition.getId()].getQualityChangesGroups(variant_names, material_bases, extruder_enabled)
|
return self.machines[global_stack.definition.getId()].getQualityChangesGroups(variant_names, material_bases, extruder_enabled)
|
||||||
|
|
||||||
# Add a machine node by the id of it's definition.
|
|
||||||
# This is automatically called by the _machineAdded function, but it's sometimes needed to add a machine node
|
|
||||||
# faster than would have been done when waiting on any signals (for instance; when creating an entirely new machine)
|
|
||||||
@UM.FlameProfiler.profile
|
|
||||||
def addMachineNodeByDefinitionId(self, definition_id: str) -> None:
|
|
||||||
if definition_id in self.machines:
|
|
||||||
return # Already have this definition ID.
|
|
||||||
|
|
||||||
start_time = time.time()
|
|
||||||
self.machines[definition_id] = MachineNode(definition_id)
|
|
||||||
self.machines[definition_id].materialsChanged.connect(self.materialsChanged)
|
|
||||||
Logger.log("d", "Adding container tree for {definition_id} took {duration} seconds.".format(definition_id = definition_id, duration = time.time() - start_time))
|
|
||||||
|
|
||||||
## Builds the initial container tree.
|
## Builds the initial container tree.
|
||||||
def _loadAll(self):
|
def _loadAll(self):
|
||||||
Logger.log("i", "Building container tree.")
|
Logger.log("i", "Building container tree.")
|
||||||
|
@ -97,26 +78,15 @@ class ContainerTree:
|
||||||
for stack in all_stacks:
|
for stack in all_stacks:
|
||||||
if not isinstance(stack, GlobalStack):
|
if not isinstance(stack, GlobalStack):
|
||||||
continue # Only want to load global stacks. We don't need to create a tree for extruder definitions.
|
continue # Only want to load global stacks. We don't need to create a tree for extruder definitions.
|
||||||
definition_id = stack.definition.getId()
|
_ = self.machines[stack.definition.getId()] # TODO: Load this lazily.
|
||||||
if definition_id not in self.machines:
|
|
||||||
definition_start_time = time.time()
|
|
||||||
self.machines[definition_id] = MachineNode(definition_id)
|
|
||||||
self.machines[definition_id].materialsChanged.connect(self.materialsChanged)
|
|
||||||
Logger.log("d", "Adding container tree for {definition_id} took {duration} seconds.".format(definition_id = definition_id, duration = time.time() - definition_start_time))
|
|
||||||
|
|
||||||
Logger.log("d", "Building the container tree took %s seconds", time.time() - start_time)
|
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, container_stack: ContainerInterface) -> None:
|
|
||||||
if not isinstance(container_stack, GlobalStack):
|
|
||||||
return # Not our concern.
|
|
||||||
self.addMachineNodeByDefinitionId(container_stack.definition.getId())
|
|
||||||
|
|
||||||
## For debugging purposes, visualise the entire container tree as it stands
|
## For debugging purposes, visualise the entire container tree as it stands
|
||||||
# now.
|
# now.
|
||||||
def _visualise_tree(self) -> str:
|
def _visualise_tree(self) -> str:
|
||||||
lines = ["% CONTAINER TREE"] # Start with array and then combine into string, for performance.
|
lines = ["% CONTAINER TREE"] # Start with array and then combine into string, for performance.
|
||||||
for machine in self.machines.values():
|
for machine in self.machines.machines.values():
|
||||||
lines.append(" # " + machine.container_id)
|
lines.append(" # " + machine.container_id)
|
||||||
for variant in machine.variants.values():
|
for variant in machine.variants.values():
|
||||||
lines.append(" * " + variant.container_id)
|
lines.append(" * " + variant.container_id)
|
||||||
|
@ -127,3 +97,30 @@ class ContainerTree:
|
||||||
for intent in quality.intents.values():
|
for intent in quality.intents.values():
|
||||||
lines.append(" . " + intent.container_id)
|
lines.append(" . " + intent.container_id)
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
## Dictionary-like object that contains the machines.
|
||||||
|
#
|
||||||
|
# This handles the lazy loading of MachineNodes.
|
||||||
|
class MachineNodeMap:
|
||||||
|
def __init__(self):
|
||||||
|
self.machines = {}
|
||||||
|
|
||||||
|
## Returns whether a printer with a certain definition ID exists. This
|
||||||
|
# is regardless of whether or not the printer is loaded yet.
|
||||||
|
# \param definition_id The definition to look for.
|
||||||
|
# \return Whether or not a printer definition exists with that name.
|
||||||
|
def __contains__(self, definition_id: str) -> bool:
|
||||||
|
return len(ContainerRegistry.getInstance().findInstanceContainersMetadata(id = definition_id)) == 0
|
||||||
|
|
||||||
|
## Returns a machine node for the specified definition ID.
|
||||||
|
#
|
||||||
|
# If the machine node wasn't loaded yet, this will load it lazily.
|
||||||
|
# \param definition_id The definition to look for.
|
||||||
|
# \return A machine node for that definition.
|
||||||
|
def __getitem__(self, definition_id: str) -> MachineNode:
|
||||||
|
if definition_id not in self.machines:
|
||||||
|
start_time = time.time()
|
||||||
|
self.machines[definition_id] = MachineNode(definition_id)
|
||||||
|
self.machines[definition_id].materialsChanged.connect(ContainerTree.getInstance().materialsChanged)
|
||||||
|
Logger.log("d", "Adding container tree for {definition_id} took {duration} seconds.".format(definition_id = definition_id, duration = time.time() - start_time))
|
||||||
|
return self.machines[definition_id]
|
|
@ -37,10 +37,6 @@ class CuraStackBuilder:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
machine_definition = definitions[0]
|
machine_definition = definitions[0]
|
||||||
# The container tree listens to the containerAdded signal to add the definition and build the tree,
|
|
||||||
# but that signal is emitted with a delay which might not have passed yet.
|
|
||||||
# Therefore we must make sure that it's manually added here.
|
|
||||||
container_tree.addMachineNodeByDefinitionId(machine_definition.getId())
|
|
||||||
machine_node = container_tree.machines[machine_definition.getId()]
|
machine_node = container_tree.machines[machine_definition.getId()]
|
||||||
|
|
||||||
generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName())
|
generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue