Merge pull request #817 from Ultimaker/feature_multi_materialsnozzles

Multiextrusion support for materials and nozzles
This commit is contained in:
Jaime van Kessel 2016-06-22 17:05:17 +02:00 committed by GitHub
commit 1e40d98fd7
7 changed files with 140 additions and 53 deletions

View File

@ -111,7 +111,7 @@ class ExtruderManager(QObject):
## Creates a container stack for an extruder train.
#
# The container stack has an extruder definition at the bottom, which is
# linked to a machine definition. Then it has a nozzle profile, a material
# linked to a machine definition. Then it has a variant profile, a material
# profile, a quality profile and a user profile, in that order.
#
# The resulting container stack is added to the registry.
@ -136,31 +136,31 @@ class ExtruderManager(QObject):
container_stack.addMetaDataEntry("position", position)
container_stack.addContainer(extruder_definition)
#Find the nozzle to use for this extruder.
nozzle = container_registry.getEmptyInstanceContainer()
if machine_definition.getMetaDataEntry("has_nozzles", default = "False") == "True":
#First add any nozzle. Later, overwrite with preference if the preference is valid.
nozzles = container_registry.findInstanceContainers(machine = machine_id, type = "nozzle")
if len(nozzles) >= 1:
nozzle = nozzles[0]
preferred_nozzle_id = machine_definition.getMetaDataEntry("preferred_nozzle")
if preferred_nozzle_id:
preferred_nozzles = container_registry.findInstanceContainers(id = preferred_nozzle_id, type = "nozzle")
if len(preferred_nozzles) >= 1:
nozzle = preferred_nozzles[0]
#Find the variant to use for this extruder.
variant = container_registry.getEmptyInstanceContainer()
if machine_definition.getMetaDataEntry("has_variants"):
#First add any variant. Later, overwrite with preference if the preference is valid.
variants = container_registry.findInstanceContainers(definition = machine_id, type = "variant")
if len(variants) >= 1:
variant = variants[0]
preferred_variant_id = machine_definition.getMetaDataEntry("preferred_variant")
if preferred_variant_id:
preferred_variants = container_registry.findInstanceContainers(id = preferred_variant_id, type = "variant")
if len(preferred_variants) >= 1:
variant = preferred_variants[0]
else:
UM.Logger.log("w", "The preferred nozzle \"%s\" of machine %s doesn't exist or is not a nozzle profile.", preferred_nozzle_id, machine_id)
#And leave it at the default nozzle.
container_stack.addContainer(nozzle)
UM.Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id)
#And leave it at the default variant.
container_stack.addContainer(variant)
#Find a material to use for this nozzle.
#Find a material to use for this variant.
material = container_registry.getEmptyInstanceContainer()
if machine_definition.getMetaDataEntry("has_materials", default = "False") == "True":
if machine_definition.getMetaDataEntry("has_materials"):
#First add any material. Later, overwrite with preference if the preference is valid.
if machine_definition.getMetaDataEntry("has_nozzle_materials", default = "False") == "True":
materials = container_registry.findInstanceContainers(type = "material", machine = machine_id, nozzle = nozzle.getId())
if machine_definition.getMetaDataEntry("has_variant_materials", default = "False") == "True":
materials = container_registry.findInstanceContainers(type = "material", definition = machine_id, variant = variant.getId())
else:
materials = container_registry.findInstanceContainers(type = "material", machine = machine_id)
materials = container_registry.findInstanceContainers(type = "material", definition = machine_id)
if len(materials) >= 1:
material = materials[0]
preferred_material_id = machine_definition.getMetaDataEntry("preferred_material")
@ -175,7 +175,7 @@ class ExtruderManager(QObject):
#Find a quality to use for this extruder.
quality = container_registry.getEmptyInstanceContainer()
#First add any quality. Later, overwrite with preference if the preference is valid.
qualities = container_registry.findInstanceContainers(type = "quality")
if len(qualities) >= 1:

View File

@ -46,12 +46,17 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
self._add_global = False
self._active_extruder_stack = None
#Listen to changes.
manager = cura.ExtruderManager.ExtruderManager.getInstance()
manager.extrudersChanged.connect(self._updateExtruders) #When the list of extruders changes in general.
UM.Application.globalContainerStackChanged.connect(self._updateExtruders) #When the current machine changes.
UM.Application.getInstance().globalContainerStackChanged.connect(self._updateExtruders) #When the current machine changes.
self._updateExtruders()
manager.activeExtruderChanged.connect(self._onActiveExtruderChanged)
self._onActiveExtruderChanged()
def setAddGlobal(self, add):
if add != self._add_global:
self._add_global = add
@ -63,6 +68,25 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
def addGlobal(self):
return self._add_global
def _onActiveExtruderChanged(self):
manager = cura.ExtruderManager.ExtruderManager.getInstance()
active_extruder_stack = manager.getActiveExtruderStack()
if self._active_extruder_stack != active_extruder_stack:
if self._active_extruder_stack:
self._active_extruder_stack.containersChanged.disconnect(self._onExtruderStackContainersChanged)
if active_extruder_stack:
# Update the model when the material container is changed
active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged)
self._active_extruder_stack = active_extruder_stack
def _onExtruderStackContainersChanged(self, container):
if container.getMetaDataEntry("type") == "material":
self._updateExtruders()
modelChanged = pyqtSignal()
## Update the list of extruders.
#
# This should be called whenever the list of extruders changes.
@ -85,7 +109,10 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
self.appendItem(item)
for extruder in manager.getMachineExtruders(global_container_stack.getBottom().getId()):
extruder_name = extruder.getName()
material = extruder.findContainer({ "type": "material" })
if material:
extruder_name = "%s (%s)" % (material.getName(), extruder_name)
position = extruder.getBottom().getMetaDataEntry("position", default = "0") #Position in the definition.
try:
position = int(position)
@ -95,10 +122,11 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
colour = material.getMetaDataEntry("color_code", default = default_colour) if material else default_colour
item = { #Construct an item with only the relevant information.
"id": extruder.getId(),
"name": extruder.getName(),
"name": extruder_name,
"colour": colour,
"index": position
}
self.appendItem(item)
self.sort(lambda item: item["index"])
self.modelChanged.emit()

View File

@ -376,11 +376,16 @@ class MachineManagerModel(QObject):
return
old_material = self._active_container_stack.findContainer({"type":"material"})
old_quality = self._active_container_stack.findContainer({"type": "quality"})
if old_material:
material_index = self._active_container_stack.getContainerIndex(old_material)
self._active_container_stack.replaceContainer(material_index, containers[0])
self.setActiveQuality(self._updateQualityContainer(self._active_container_stack.getBottom(), containers[0]).id)
preferred_quality_name = None
if old_quality:
preferred_quality_name = old_quality.getName()
self.setActiveQuality(self._updateQualityContainer(self._global_container_stack.getBottom(), containers[0], preferred_quality_name).id)
@pyqtSlot(str)
def setActiveVariant(self, variant_id):
@ -389,11 +394,16 @@ class MachineManagerModel(QObject):
return
old_variant = self._active_container_stack.findContainer({"type": "variant"})
old_material = self._active_container_stack.findContainer({"type": "material"})
if old_variant:
variant_index = self._active_container_stack.getContainerIndex(old_variant)
self._active_container_stack.replaceContainer(variant_index, containers[0])
self.setActiveMaterial(self._updateMaterialContainer(self._active_container_stack.getBottom(), containers[0]).id)
preferred_material = None
if old_material:
preferred_material = old_material.getId()
self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material).id)
@pyqtSlot(str)
def setActiveQuality(self, quality_id):
@ -503,7 +513,7 @@ class MachineManagerModel(QObject):
return self._empty_variant_container
def _updateMaterialContainer(self, definition, variant_container = None):
def _updateMaterialContainer(self, definition, variant_container = None, preferred_material = None):
if not definition.getMetaDataEntry("has_materials"):
return self._empty_material_container
@ -517,7 +527,8 @@ class MachineManagerModel(QObject):
else:
search_criteria["definition"] = "fdmprinter"
preferred_material = definition.getMetaDataEntry("preferred_material")
if not preferred_material:
preferred_material = definition.getMetaDataEntry("preferred_material")
if preferred_material:
search_criteria["id"] = preferred_material
@ -527,7 +538,7 @@ class MachineManagerModel(QObject):
return self._empty_material_container
def _updateQualityContainer(self, definition, material_container = None):
def _updateQualityContainer(self, definition, material_container = None, preferred_quality_name = None):
search_criteria = { "type": "quality" }
if definition.getMetaDataEntry("has_machine_quality"):
@ -538,9 +549,12 @@ class MachineManagerModel(QObject):
else:
search_criteria["definition"] = "fdmprinter"
preferred_quality = definition.getMetaDataEntry("preferred_quality")
if preferred_quality:
search_criteria["id"] = preferred_quality
if preferred_quality_name:
search_criteria["name"] = preferred_quality_name
else:
preferred_quality = definition.getMetaDataEntry("preferred_quality")
if preferred_quality:
search_criteria["id"] = preferred_quality
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
if containers:

View File

@ -10,9 +10,11 @@ from UM.View.Renderer import Renderer
from UM.View.GL.OpenGL import OpenGL
from cura.ExtrudersModel import ExtrudersModel
import math
## Standard view for mesh models.
## Standard view for mesh models.
class SolidView(View):
def __init__(self):
super().__init__()
@ -22,6 +24,8 @@ class SolidView(View):
self._enabled_shader = None
self._disabled_shader = None
self._extruders_model = ExtrudersModel()
def beginRendering(self):
scene = self.getController().getScene()
renderer = self.getRenderer()
@ -50,15 +54,37 @@ class SolidView(View):
# TODO: Find a better way to handle this
#if node.getBoundingBoxMesh():
# renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines)
uniforms = {}
if self._extruders_model.rowCount() > 0:
# 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_color = self._extruders_model.getItem(extruder_index)["colour"]
try:
# Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
# an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
uniforms["diffuse_color"] = [
int(extruder_color[1:3], 16) / 255,
int(extruder_color[3:5], 16) / 255,
int(extruder_color[5:7], 16) / 255,
1.0
]
except:
pass
if hasattr(node, "_outside_buildarea"):
if node._outside_buildarea:
renderer.queueNode(node, shader = self._disabled_shader)
else:
renderer.queueNode(node, shader = self._enabled_shader)
renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms)
else:
renderer.queueNode(node, material = self._enabled_shader)
renderer.queueNode(node, material = self._enabled_shader, uniforms = uniforms)
if node.callDecoration("isGroup"):
renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines)
renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = Renderer.RenderLines)
def endRendering(self):
pass

View File

@ -13,7 +13,7 @@ Column
id: base;
property int totalHeightHeader: childrenRect.height
property int currentExtruderIndex;
property int currentExtruderIndex: -1;
spacing: UM.Theme.getSize("default_margin").height
@ -50,7 +50,7 @@ Column
text: Cura.MachineManager.activeMachineName;
height: UM.Theme.getSize("setting_control").height
tooltip: Cura.MachineManager.activeMachineName;
tooltip: Cura.MachineManager.activeMachineName
anchors.verticalCenter: parent.verticalCenter
style: UM.Theme.styles.sidebar_header_button
@ -111,14 +111,25 @@ Column
model: Cura.ExtrudersModel { id: extrudersModel; addGlobal: true }
Connections
{
target: Cura.MachineManager
onGlobalContainerChanged:
{
base.currentExtruderIndex = -1;
ExtruderManager.setActiveExtruderIndex(index);
}
}
delegate: Button
{
height: ListView.view.height
width: ListView.view.width / extrudersModel.rowCount()
text: model.name
exclusiveGroup: extruderMenuGroup;
checkable: true;
tooltip: model.name
exclusiveGroup: extruderMenuGroup
checkable: true
checked: base.currentExtruderIndex == index
onClicked:
@ -144,6 +155,7 @@ Column
Rectangle
{
id: swatch
visible: index > -1
height: UM.Theme.getSize("setting_control").height / 2
width: height
anchors.left: parent.left
@ -158,8 +170,8 @@ Column
Label
{
anchors.verticalCenter: parent.verticalCenter
anchors.left: swatch.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width / 2
anchors.left: swatch.visible ? swatch.right : parent.left
anchors.leftMargin: swatch.visible ? UM.Theme.getSize("default_margin").width / 2 : UM.Theme.getSize("default_margin").width
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width / 2
@ -216,6 +228,7 @@ Column
text: Cura.MachineManager.activeVariantName
tooltip: Cura.MachineManager.activeVariantName;
visible: Cura.MachineManager.hasVariants
enabled: !extrudersList.visible || base.currentExtruderIndex > -1
height: UM.Theme.getSize("setting_control").height
width: materialSelection.visible ? (parent.width - UM.Theme.getSize("default_margin").width) / 2 : parent.width
@ -260,6 +273,7 @@ Column
text: Cura.MachineManager.activeMaterialName
tooltip: Cura.MachineManager.activeMaterialName
visible: Cura.MachineManager.hasMaterials
enabled: !extrudersList.visible || base.currentExtruderIndex > -1
height: UM.Theme.getSize("setting_control").height
width: variantSelection.visible ? (parent.width - UM.Theme.getSize("default_margin").width) / 2 : parent.width

View File

@ -319,11 +319,13 @@ Item
id: extruderModel
Component.onCompleted: populateExtruderModel()
}
Connections
//: Invisible list used to populate the extrudelModel
ListView
{
id: machineChange
target: Cura.MachineManager
onGlobalContainerChanged: populateExtruderModel()
id: extruders
model: Cura.ExtrudersModel { onModelChanged: populateExtruderModel() }
visible: false
}
}
@ -331,11 +333,13 @@ Item
{
extruderModel.clear();
extruderModel.append({
text: catalog.i18nc("@label", "Don't print support")
text: catalog.i18nc("@label", "Don't print support"),
color: ""
})
for(var extruder = 0; extruder < machineExtruderCount.properties.value ; extruder++) {
for(var extruderNr = 0; extruderNr < extruders.model.rowCount() ; extruderNr++) {
extruderModel.append({
text: catalog.i18nc("@label", "Print using Extruder %1").arg(extruder + 1)
text: catalog.i18nc("@label", "Print using %1").arg(extruders.model.getItem(extruderNr).name),
color: extruders.model.getItem(extruderNr).colour
})
}
}

View File

@ -11,9 +11,10 @@ QtObject {
property Component sidebar_header_button: Component {
ButtonStyle {
background: Rectangle {
color: Theme.getColor("setting_control")
color: control.enabled ? Theme.getColor("setting_control") : Theme.getColor("setting_control_disabled")
border.width: Theme.getSize("default_lining").width
border.color: control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border")
border.color: !control.enabled ? Theme.getColor("setting_control_disabled_border") :
control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border")
UM.RecolorImage {
id: downArrow
anchors.verticalCenter: parent.verticalCenter
@ -23,12 +24,12 @@ QtObject {
height: Theme.getSize("standard_arrow").height
sourceSize.width: width
sourceSize.height: width
color: Theme.getColor("setting_category_text")
color: control.enabled ? Theme.getColor("setting_category_text") : Theme.getColor("setting_control_disabled_text")
source: Theme.getIcon("arrow_bottom")
}
Label {
id: sidebarComboBoxLabel
color: Theme.getColor("setting_control_text")
color: control.enabled ? Theme.getColor("setting_control_text") : Theme.getColor("setting_control_disabled_text")
text: control.text;
elide: Text.ElideRight;
anchors.left: parent.left;