Merge pull request #2685 from Ultimaker/container_stack_improvements

Container stack improvements
This commit is contained in:
ChrisTerBeke 2017-11-17 13:09:54 +01:00 committed by ChrisTerBeke
parent da14ce5bef
commit 657a91c525
43 changed files with 556 additions and 836 deletions

View file

@ -107,20 +107,13 @@ class ThreeMFReader(MeshReader):
um_node.addDecorator(SettingOverrideDecorator())
global_container_stack = Application.getInstance().getGlobalContainerStack()
# Ensure the correct next container for the SettingOverride decorator is set.
if global_container_stack:
multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
default_stack = ExtruderManager.getInstance().getExtruderStack(0)
# Ensure that all extruder data is reset
if not multi_extrusion:
default_stack_id = global_container_stack.getId()
else:
default_stack = ExtruderManager.getInstance().getExtruderStack(0)
if default_stack:
default_stack_id = default_stack.getId()
else:
default_stack_id = global_container_stack.getId()
um_node.callDecoration("setActiveExtruder", default_stack_id)
if default_stack:
um_node.callDecoration("setActiveExtruder", default_stack.getId())
# Get the definition & set it
definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom())
@ -139,7 +132,7 @@ class ThreeMFReader(MeshReader):
else:
Logger.log("w", "Unable to find extruder in position %s", setting_value)
continue
setting_container.setProperty(key,"value", setting_value)
setting_container.setProperty(key, "value", setting_value)
if len(um_node.getChildren()) > 0:
group_decorator = GroupDecorator()

View file

@ -644,9 +644,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# Get the stack(s) saved in the workspace.
Logger.log("d", "Workspace loading is checking stacks containers...")
# --
# load global stack file
try:
stack = None
if self._resolve_strategies["machine"] == "override":
container_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original)
stack = container_stacks[0]
@ -682,12 +683,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._container_registry.addContainer(stack)
containers_added.append(stack)
else:
Logger.log("e", "Resolve strategy of %s for machine is not supported",
self._resolve_strategies["machine"])
Logger.log("e", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
# Create a new definition_changes container if it was empty
if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer():
stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack._id + "_settings"))
stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings"))
global_stack = stack
Job.yieldThread()
except:
@ -697,16 +697,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._container_registry.removeContainer(container.getId())
return
#
# Use the number of extruders from the global stack instead of the number of extruder stacks this project file
# contains. The Custom FDM Printer can have multiple extruders, but the actual number of extruders in used is
# defined in the global stack.
# Because for single-extrusion machines, there won't be an extruder stack, so relying on the the extruder count
# in the global stack can avoid problems in those cases.
#
extruder_count_from_global_stack = global_stack.getProperty("machine_extruder_count", "value")
# --
# load extruder stack files
try:
for extruder_stack_file in extruder_stack_files:
@ -749,9 +739,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# Create a new definition_changes container if it was empty
if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer():
stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack._id + "_settings"))
if global_stack.getProperty("machine_extruder_count", "value") > 1:
extruder_stacks.append(stack)
stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings"))
extruder_stacks.append(stack)
# If not extruder stacks were saved in the project file (pre 3.1) create one manually
# We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this
if not extruder_stacks:
self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder")
except:
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
# Something went really wrong. Try to remove any data that we added.
@ -784,7 +780,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
for stack in [global_stack] + extruder_stacks:
stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container)
#
# Replacing the old containers if resolve is "new".
# When resolve is "new", some containers will get renamed, so all the other containers that reference to those
# MUST get updated too.

View file

@ -87,7 +87,7 @@ class ThreeMFWriter(MeshWriter):
if stack is not None:
changed_setting_keys = set(stack.getTop().getAllKeys())
# Ensure that we save the extruder used for this object.
# Ensure that we save the extruder used for this object in a multi-extrusion setup
if stack.getProperty("machine_extruder_count", "value") > 1:
changed_setting_keys.add("extruder_nr")

View file

@ -159,13 +159,9 @@ class StartSliceJob(Job):
self._buildGlobalSettingsMessage(stack)
self._buildGlobalInheritsStackMessage(stack)
# Only add extruder stacks if there are multiple extruders
# Single extruder machines only use the global stack to store setting values
if stack.getProperty("machine_extruder_count", "value") > 1:
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
self._buildExtruderMessage(extruder_stack)
else:
self._buildExtruderMessageFromGlobalStack(stack)
# Build messages for extruder stacks
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
self._buildExtruderMessage(extruder_stack)
for group in object_groups:
group_message = self._slice_message.addRepeatedMessage("object_lists")
@ -251,19 +247,6 @@ class StartSliceJob(Job):
setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
Job.yieldThread()
## Create extruder message from global stack
def _buildExtruderMessageFromGlobalStack(self, stack):
message = self._slice_message.addRepeatedMessage("extruders")
for key in stack.getAllKeys():
# Do not send settings that are not settable_per_extruder.
if not stack.getProperty(key, "settable_per_extruder"):
continue
setting = message.getMessage("settings").addRepeatedMessage("settings")
setting.name = key
setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
Job.yieldThread()
## Sends all global settings to the engine.
#
# The settings are taken from the global stack. This does not include any

View file

@ -116,8 +116,7 @@ class MachineSettingsAction(MachineAction):
@pyqtSlot(int)
def setMachineExtruderCount(self, extruder_count):
machine_manager = Application.getInstance().getMachineManager()
extruder_manager = ExtruderManager.getInstance()
extruder_manager = Application.getInstance().getExtruderManager()
definition_changes_container = self._global_container_stack.definitionChanges
if not self._global_container_stack or definition_changes_container == self._empty_container:
@ -127,34 +126,6 @@ class MachineSettingsAction(MachineAction):
if extruder_count == previous_extruder_count:
return
extruder_material_id = None
extruder_variant_id = None
if extruder_count == 1:
# Get the material and variant of the first extruder before setting the number extruders to 1
if machine_manager.hasMaterials:
extruder_material_id = machine_manager.allActiveMaterialIds[extruder_manager.extruderIds["0"]]
if machine_manager.hasVariants:
extruder_variant_id = machine_manager.allActiveVariantIds[extruder_manager.extruderIds["0"]]
# Copy any settable_per_extruder setting value from the extruders to the global stack
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
extruder_stacks.reverse() # make sure the first extruder is done last, so its settings override any higher extruder settings
global_user_container = self._global_container_stack.getTop()
for extruder_stack in extruder_stacks:
extruder_index = extruder_stack.getMetaDataEntry("position")
extruder_user_container = extruder_stack.getTop()
for setting_instance in extruder_user_container.findInstances():
setting_key = setting_instance.definition.key
settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder")
if settable_per_extruder:
limit_to_extruder = self._global_container_stack.getProperty(setting_key, "limit_to_extruder")
if limit_to_extruder == "-1" or limit_to_extruder == extruder_index:
global_user_container.setProperty(setting_key, "value", extruder_user_container.getProperty(setting_key, "value"))
extruder_user_container.removeInstance(setting_key)
# reset all extruder number settings whose value is no longer valid
for setting_instance in self._global_container_stack.userChanges.findInstances():
setting_key = setting_instance.definition.key
@ -177,52 +148,29 @@ class MachineSettingsAction(MachineAction):
definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count)
if extruder_count > 1:
# Multiextrusion
# Make sure one of the extruder stacks is active
extruder_manager.setActiveExtruderIndex(0)
# Make sure one of the extruder stacks is active
if extruder_manager.activeExtruderIndex == -1:
extruder_manager.setActiveExtruderIndex(0)
# Move settable_per_extruder values out of the global container
# After CURA-4482 this should not be the case anymore, but we still want to support older project files.
global_user_container = self._global_container_stack.getTop()
# Move settable_per_extruder values out of the global container
if previous_extruder_count == 1:
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
global_user_container = self._global_container_stack.getTop()
if previous_extruder_count == 1:
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
global_user_container = self._global_container_stack.getTop()
for setting_instance in global_user_container.findInstances():
setting_key = setting_instance.definition.key
settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder")
if settable_per_extruder:
limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder"))
extruder_stack = extruder_stacks[max(0, limit_to_extruder)]
extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
global_user_container.removeInstance(setting_key)
else:
# Single extrusion
for setting_instance in global_user_container.findInstances():
setting_key = setting_instance.definition.key
settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder")
# Make sure the machine stack is active
if extruder_manager.activeExtruderIndex > -1:
extruder_manager.setActiveExtruderIndex(-1)
# Restore material and variant on global stack
# MachineManager._onGlobalContainerChanged removes the global material and variant of multiextruder machines
if extruder_material_id or extruder_variant_id:
# Prevent the DiscardOrKeepProfileChangesDialog from popping up (twice) if there are user changes
# The dialog is not relevant here, since we're restoring the previous situation as good as possible
preferences = Preferences.getInstance()
choice_on_profile_override = preferences.getValue("cura/choice_on_profile_override")
preferences.setValue("cura/choice_on_profile_override", "always_keep")
if extruder_material_id:
machine_manager.setActiveMaterial(extruder_material_id)
if extruder_variant_id:
machine_manager.setActiveVariant(extruder_variant_id)
preferences.setValue("cura/choice_on_profile_override", choice_on_profile_override)
if settable_per_extruder:
limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder"))
extruder_stack = extruder_stacks[max(0, limit_to_extruder)]
extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
global_user_container.removeInstance(setting_key)
self.forceUpdate()
@pyqtSlot()
def forceUpdate(self):
# Force rebuilding the build volume by reloading the global container stack.
@ -275,16 +223,13 @@ class MachineSettingsAction(MachineAction):
if not self._global_container_stack.getMetaDataEntry("has_materials", False):
return
machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
if machine_extruder_count > 1:
material = ExtruderManager.getInstance().getActiveExtruderStack().material
else:
material = self._global_container_stack.material
material = ExtruderManager.getInstance().getActiveExtruderStack().material
material_diameter = material.getProperty("material_diameter", "value")
if not material_diameter: # in case of "empty" material
if not material_diameter:
# in case of "empty" material
material_diameter = 0
material_approximate_diameter = str(round(material_diameter))
material_approximate_diameter = str(round(material_diameter))
definition_changes = self._global_container_stack.definitionChanges
machine_diameter = definition_changes.getProperty("material_diameter", "value")
if not machine_diameter:
@ -294,10 +239,7 @@ class MachineSettingsAction(MachineAction):
if material_approximate_diameter != machine_approximate_diameter:
Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.")
if machine_extruder_count > 1:
stacks = ExtruderManager.getInstance().getExtruderStacks()
else:
stacks = [self._global_container_stack]
stacks = ExtruderManager.getInstance().getExtruderStacks()
if self._global_container_stack.getMetaDataEntry("has_machine_materials", False):
materials_definition = self._global_container_stack.definition.getId()
@ -338,7 +280,7 @@ class MachineSettingsAction(MachineAction):
search_criteria["id"] = stack.getMetaDataEntry("preferred_material")
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:
# Preferrd material with new diameter is not found, search for any material
# Preferred material with new diameter is not found, search for any material
search_criteria.pop("id", None)
materials = self._container_registry.findInstanceContainers(**search_criteria)
if not materials:

View file

@ -78,31 +78,26 @@ class PerObjectSettingsTool(Tool):
def _onGlobalContainerChanged(self):
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
# used for enabling or disabling per extruder settings per object
self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
# Ensure that all extruder data is reset
if not self._multi_extrusion:
default_stack_id = global_container_stack.getId()
else:
default_stack = ExtruderManager.getInstance().getExtruderStack(0)
if default_stack:
default_stack_id = default_stack.getId()
else:
default_stack_id = global_container_stack.getId()
extruder_stack = ExtruderManager.getInstance().getExtruderStack(0)
root_node = Application.getInstance().getController().getScene().getRoot()
for node in DepthFirstIterator(root_node):
new_stack_id = default_stack_id
# Get position of old extruder stack for this node
old_extruder_pos = node.callDecoration("getActiveExtruderPosition")
if old_extruder_pos is not None:
# Fetch current (new) extruder stack at position
new_stack = ExtruderManager.getInstance().getExtruderStack(old_extruder_pos)
if new_stack:
new_stack_id = new_stack.getId()
node.callDecoration("setActiveExtruder", new_stack_id)
if extruder_stack:
root_node = Application.getInstance().getController().getScene().getRoot()
for node in DepthFirstIterator(root_node):
new_stack_id = extruder_stack.getId()
# Get position of old extruder stack for this node
old_extruder_pos = node.callDecoration("getActiveExtruderPosition")
if old_extruder_pos is not None:
# Fetch current (new) extruder stack at position
new_stack = ExtruderManager.getInstance().getExtruderStack(old_extruder_pos)
if new_stack:
new_stack_id = new_stack.getId()
node.callDecoration("setActiveExtruder", new_stack_id)
self._updateEnabled()
self._updateEnabled()
def _updateEnabled(self):
selected_objects = Selection.getAllSelectedObjects()

View file

@ -87,15 +87,10 @@ class SliceInfo(Extension):
data["active_machine"] = {"definition_id": global_container_stack.definition.getId(), "manufacturer": global_container_stack.definition.getMetaData().get("manufacturer","")}
# add extruder specific data to slice info
data["extruders"] = []
extruder_count = len(global_container_stack.extruders)
extruders = []
if extruder_count > 1:
extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()))
extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position"))
if not extruders:
extruders = [global_container_stack]
extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()))
extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position"))
for extruder in extruders:
extruder_dict = dict()

View file

@ -46,19 +46,10 @@ class SolidView(View):
self._disabled_shader.setUniformValue("u_diffuseColor2", Color(*theme.getColor("model_unslicable_alt").getRgb()))
self._disabled_shader.setUniformValue("u_width", 50.0)
multi_extrusion = False
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
if multi_extrusion:
support_extruder_nr = global_container_stack.getProperty("support_extruder_nr", "value")
support_angle_stack = ExtruderManager.getInstance().getExtruderStack(support_extruder_nr)
if not support_angle_stack:
support_angle_stack = global_container_stack
else:
support_angle_stack = global_container_stack
support_extruder_nr = global_container_stack.getProperty("support_extruder_nr", "value")
support_angle_stack = ExtruderManager.getInstance().getExtruderStack(support_extruder_nr)
if Preferences.getInstance().getValue("view/show_overhang"):
angle = support_angle_stack.getProperty("support_angle", "value")
@ -71,33 +62,26 @@ class SolidView(View):
else:
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0)))
for node in DepthFirstIterator(scene.getRoot()):
if not node.render(renderer):
if node.getMeshData() and node.isVisible():
uniforms = {}
shade_factor = 1.0
if not multi_extrusion:
if global_container_stack:
material = global_container_stack.findContainer({ "type": "material" })
material_color = material.getMetaDataEntry("color_code", default = self._extruders_model.defaultColors[0]) if material else self._extruders_model.defaultColors[0]
else:
material_color = self._extruders_model.defaultColors[0]
else:
# 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))
try:
material_color = self._extruders_model.getItem(extruder_index)["color"]
except KeyError:
material_color = self._extruders_model.defaultColors[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))
try:
material_color = self._extruders_model.getItem(extruder_index)["color"]
except KeyError:
material_color = self._extruders_model.defaultColors[0]
if extruder_index != ExtruderManager.getInstance().activeExtruderIndex:
# Shade objects that are printed with the non-active extruder 25% darker
shade_factor = 0.6
if extruder_index != ExtruderManager.getInstance().activeExtruderIndex:
# Shade objects that are printed with the non-active extruder 25% darker
shade_factor = 0.6
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])

View file

@ -37,7 +37,7 @@ class UM2UpgradeSelection(MachineAction):
def setHasVariants(self, has_variants = True):
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
variant_container = global_container_stack.variant
variant_container = global_container_stack.extruders["0"].variant
variant_index = global_container_stack.getContainerIndex(variant_container)
if has_variants:
@ -52,7 +52,7 @@ class UM2UpgradeSelection(MachineAction):
search_criteria = { "type": "variant", "definition": "ultimaker2", "id": "*0.4*" }
containers = self._container_registry.findInstanceContainers(**search_criteria)
if containers:
global_container_stack.variant = containers[0]
global_container_stack.extruders["0"].variant = containers[0]
else:
# The metadata entry is stored in an ini, and ini files are parsed as strings only.
# Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.

View file

@ -549,7 +549,7 @@ class XmlMaterialProfile(InstanceContainer):
definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = machine_id)
if not definitions:
Logger.log("w", "No definition found for machine ID %s", machine_id)
# Logger.log("w", "No definition found for machine ID %s", machine_id)
continue
definition = definitions[0]