mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-29 01:28:55 +08:00
Merge pull request #817 from Ultimaker/feature_multi_materialsnozzles
Multiextrusion support for materials and nozzles
This commit is contained in:
commit
1e40d98fd7
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user