diff --git a/.gitignore b/.gitignore index 72ba4bf565..f60e268711 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ docs/html *.log resources/i18n/en resources/i18n/x-test +resources/firmware # Editors and IDEs. *kdev* diff --git a/cura/Extruder.py b/cura/Extruder.py new file mode 100644 index 0000000000..5f74bd036f --- /dev/null +++ b/cura/Extruder.py @@ -0,0 +1,88 @@ +# Copyright (c) 2016 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import re #To parse container registry names to increment the duplicates-resolving number. + +import UM.Application #To link the stack to the global container stack. +import UM.Settings.ContainerRegistry #To search for nozzles, materials, etc. +import UM.Settings.ContainerStack #To create a container stack for this extruder. + +class Extruder: + ## Creates a new extruder from the specified definition container. + # + # \param definition The definition container defining this extruder. + def __init__(self, definition): + self._definition = definition + + container_registry = UM.Settings.ContainerRegistry.getInstance() + + #Find the nozzles that fit on this extruder. + self._nozzles = container_registry.findInstanceContainers(type = "nozzle", definitions = "*," + definition.getId() + ",*") #Extruder needs to be delimited by either a comma or the end of string. + self._nozzles += container_registry.findInstanceContainers(type = "nozzle", definitions = "*," + definition.getId()) + self._nozzles += container_registry.findInstanceContainers(type = "nozzle", definitions = definition.getId() + ",*") + self._nozzles += container_registry.findInstanceContainers(type = "nozzle", definitions = definition.getId()) + + #Create a container stack for this extruder. + self._container_stack = UM.Settings.ContainerStack(self._uniqueName(self._definition.getId())) + self._container_stack.addMetaDataEntry("type", "extruder_train") + self._container_stack.addContainer(self._definition) + + #Find the nozzle to use for this extruder. + self._nozzle = container_registry.getEmptyInstanceContainer() + if len(self._nozzles) >= 1: #First add any extruder. Later, overwrite with preference if the preference is valid. + self._nozzle = self._nozzles[0] + preferred_nozzle_id = self._definition.getMetaDataEntry("preferred_nozzle") + if preferred_nozzle_id: + for nozzle in self._nozzles: + if nozzle.getId() == preferred_nozzle_id: + self._nozzle = nozzle + break + self._container_stack.addContainer(self._nozzle) + + #Find a material to use for this nozzle. + self._material = container_registry.getEmptyInstanceContainer() + all_materials = container_registry.findInstanceContainers(type = "material") + if len(all_materials) >= 1: + self._material = all_materials[0] + preferred_material_id = self._definition.getMetaDataEntry("preferred_material") + if preferred_material_id: + preferred_material = container_registry.findInstanceContainers(type = "material", id = preferred_material_id.lower()) + if len(preferred_material) >= 1: + self._material = preferred_material[0] + self._container_stack.addContainer(self._material) + + #Find a quality to use for this extruder. + self._quality = container_registry.getEmptyInstanceContainer() + all_qualities = container_registry.findInstanceContainers(type = "quality") + if len(all_qualities) >= 1: + self._quality = all_qualities[0] + preferred_quality_id = self._definition.getMetaDataEntry("preferred_quality") + if preferred_quality_id: + preferred_quality = container_registry.findInstanceContainers(type = "quality", id = preferred_quality_id.lower()) + if len(preferred_quality) >= 1: + self._quality = preferred_quality[0] + self._container_stack.addContainer(self._quality) + + self._container_stack.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) + + ## Finds a unique name for an extruder stack. + # + # \param extruder An extruder definition to design a name for. + # \return A name for an extruder stack that is unique and reasonably + # human-readable. + def _uniqueName(self, extruder): + container_registry = UM.Settings.ContainerRegistry.getInstance() + + name = extruder.getName().strip() + num_check = re.compile("(.*?)\s*#\d$").match(name) + if num_check: #There is a number in the name. + name = num_check.group(1) #Filter out the number. + if name == "": #Wait, that deleted everything! + name = "Extruder" + unique_name = name + + i = 1 + while container_registry.findContainers(id = unique_name) or container_registry.findContainers(name = unique_name): #A container already has this name. + i += 1 #Try next numbering. + unique_name = "%s #%d" % (name, i) #Fill name like this: "Extruder #2". + return unique_name \ No newline at end of file diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index c99ac4be00..4d95a9008d 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -3,6 +3,7 @@ import re +from cura.Extruder import Extruder #The individual extruders managed by this manager. from UM.Application import Application #To get the global container stack to find the current machine. from UM.Logger import Logger from UM.Settings.ContainerStack import ContainerStack #To create container stacks for each extruder. @@ -17,81 +18,29 @@ from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers class ExtruderManager: ## Registers listeners and such to listen to changes to the extruders. def __init__(self): - self._extruderDefinitions = [] #Extruder definitions for the current machine. - self._nozzles = {} #Nozzle instances for each extruder. - self._extruderTrains = [] #Container stacks for each of the extruder trains. + self._extruders = [] #Extruders for the current machine. Application.getInstance().getGlobalContainerStack().containersChanged.connect(self._reloadExtruders) #When the current machine changes, we need to reload all extruders belonging to the new machine. + self._reloadExtruders() ## (Re)loads all extruders of the currently active machine. # # This looks at the global container stack to see which machine is active. - # Then it loads the extruder definitions for that machine and the variants - # of those definitions. Then it puts the new extruder definitions in the - # appropriate place in the container stacks. + # Then it loads the extruders for that machine and loads each of them in a + # list of extruders. def _reloadExtruders(self): - self._extruderDefinitions = [] - self._nozzles = {} - self._extruderTrains = [] + self._extruders = [] global_container_stack = Application.getInstance().getGlobalContainerStack() if not global_container_stack: #No machine has been added yet. return #Then leave them empty! - #Fill the list of extruder trains. + #Get the extruder definitions belonging to the current machine. machine = global_container_stack.getBottom() extruder_train_ids = machine.getMetaData("machine_extruder_trains") for extruder_train_id in extruder_train_ids: - extruders = ContainerRegistry.getInstance().findDefinitionContainers(id = extruder_train_id) #Should be only 1 definition if IDs are unique, but add the whole list anyway. - if not extruders: #Empty list or error. + extruder_definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = extruder_train_id) #Should be only 1 definition if IDs are unique, but add the whole list anyway. + if not extruder_definitions: #Empty list or error. Logger.log("w", "Machine definition %s refers to an extruder train \"%s\", but no such extruder was found.", machine.getId(), extruder_train_id) continue - self._extruderDefinitions += extruders - - #Fill the nozzles for each of the extruder trains. - for extruder in self._extruderDefinitions: - self._nozzles[extruder.id] = [] - all_nozzles = ContainerRegistry.getInstance().findInstanceContainers(type="nozzle") - for nozzle in all_nozzles: - extruders = nozzle.getMetaDataEntry("definitions").split(",").strip() - for extruder_id in extruders: - self._nozzles[extruder_id] = nozzle - - #Create the extruder train container stacks. - for extruder in self._extruderDefinitions: - self._extruderTrains.append(self._createContainerStack(extruder)) - - ## Creates a container stack for the specified extruder. - # - # This fills in the specified extruder as base definition, then a nozzle - # that fits in that extruder train, then a material that fits through that - # nozzle, then a quality profile that can be used with that material, and - # finally an empty user profile. - # - # \param extruder The extruder to create the container stack for. - # \return A container stack with the specified extruder as base. - def _createContainerStack(self, extruder): - container_stack = ContainerStack(self._uniqueName(extruder)) - #TODO: Fill the container stack. - return container_stack - - ## Finds a unique name for an extruder stack. - # - # \param extruder Extruder to design a name for. - # \return A name for an extruder stack that is unique and reasonably - # human-readable. - def _uniqueName(self, extruder): - container_registry = ContainerRegistry.getInstance() - - name = extruder.getName().strip() - num_check = re.compile("(.*?)\s*#\d$").match(name) - if(num_check): #There is a number in the name. - name = num_check.group(1) #Filter out the number. - if name == "": #Wait, that deleted everything! - name = "Extruder" - unique_name = name - - i = 1 - while(container_registry.findContainers(id = unique_name) or container_registry.findContainers(name = unique_name)): #A container already has this name. - i += 1 #Try next numbering. - unique_name = "%s #%d" % (name, i) #Fill name like this: "Extruder #2". - return unique_name \ No newline at end of file + for extruder_definition in extruder_definitions: + self._extruders.append(Extruder(extruder_definition)) \ No newline at end of file