mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 14:37:29 -06:00
Merge branch 'master' into cura_containerstack
This commit is contained in:
commit
c42d092b0f
24 changed files with 1157 additions and 472 deletions
|
@ -108,6 +108,7 @@ class CuraApplication(QtApplication):
|
|||
UserInstanceContainer = Resources.UserType + 6
|
||||
MachineStack = Resources.UserType + 7
|
||||
ExtruderStack = Resources.UserType + 8
|
||||
DefinitionChangesContainer = Resources.UserType + 9
|
||||
|
||||
Q_ENUMS(ResourceTypes)
|
||||
|
||||
|
@ -153,6 +154,7 @@ class CuraApplication(QtApplication):
|
|||
Resources.addStorageType(self.ResourceTypes.UserInstanceContainer, "user")
|
||||
Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders")
|
||||
Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances")
|
||||
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
|
||||
|
||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer)
|
||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.VariantInstanceContainer)
|
||||
|
@ -160,6 +162,7 @@ class CuraApplication(QtApplication):
|
|||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.UserInstanceContainer)
|
||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.ExtruderStack)
|
||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.MachineStack)
|
||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.DefinitionChangesContainer)
|
||||
|
||||
## Initialise the version upgrade manager with Cura's storage paths.
|
||||
import UM.VersionUpgradeManager #Needs to be here to prevent circular dependencies.
|
||||
|
@ -415,7 +418,7 @@ class CuraApplication(QtApplication):
|
|||
elif instance_type == "variant":
|
||||
path = Resources.getStoragePath(self.ResourceTypes.VariantInstanceContainer, file_name)
|
||||
elif instance_type == "definition_changes":
|
||||
path = Resources.getStoragePath(self.ResourceTypes.MachineStack, file_name)
|
||||
path = Resources.getStoragePath(self.ResourceTypes.DefinitionChangesContainer, file_name)
|
||||
|
||||
if path:
|
||||
instance.setPath(path)
|
||||
|
|
|
@ -144,6 +144,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
items.append(item)
|
||||
changed = True
|
||||
|
||||
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
|
||||
manager = ExtruderManager.getInstance()
|
||||
for extruder in manager.getMachineExtruders(global_container_stack.getId()):
|
||||
extruder_name = extruder.getName()
|
||||
|
@ -154,6 +155,9 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
position = int(position)
|
||||
except ValueError: #Not a proper int.
|
||||
position = -1
|
||||
if position >= machine_extruder_count:
|
||||
continue
|
||||
|
||||
default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0]
|
||||
color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color
|
||||
item = { #Construct an item with only the relevant information.
|
||||
|
|
|
@ -495,6 +495,17 @@ class MachineManager(QObject):
|
|||
|
||||
return result
|
||||
|
||||
@pyqtProperty("QVariantList", notify = activeVariantChanged)
|
||||
def activeMaterialIds(self):
|
||||
result = []
|
||||
if ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() is not None:
|
||||
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks():
|
||||
variant_container = stack.findContainer({"type": "variant"})
|
||||
if variant_container and variant_container != self._empty_variant_container:
|
||||
result.append(variant_container.getId())
|
||||
|
||||
return result
|
||||
|
||||
@pyqtProperty("QVariantList", notify = activeMaterialChanged)
|
||||
def activeMaterialNames(self):
|
||||
result = []
|
||||
|
|
|
@ -13,9 +13,9 @@ from UM.Resources import Resources
|
|||
from UM.Settings.Validator import ValidatorState #To find if a setting is in an error state. We can't slice then.
|
||||
from UM.Platform import Platform
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Qt.Duration import DurationFormat
|
||||
from PyQt5.QtCore import QObject, pyqtSlot
|
||||
|
||||
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from . import ProcessSlicedLayersJob
|
||||
from . import StartSliceJob
|
||||
|
@ -442,6 +442,15 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self.backendStateChange.emit(BackendState.Done)
|
||||
self.processingProgress.emit(1.0)
|
||||
|
||||
for line in self._scene.gcode_list:
|
||||
replaced = line.replace("{print_time}", str(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601)))
|
||||
replaced = replaced.replace("{filament_amount}", str(Application.getInstance().getPrintInformation().materialLengths))
|
||||
replaced = replaced.replace("{filament_weight}", str(Application.getInstance().getPrintInformation().materialWeights))
|
||||
replaced = replaced.replace("{filament_cost}", str(Application.getInstance().getPrintInformation().materialCosts))
|
||||
replaced = replaced.replace("{jobname}", str(Application.getInstance().getPrintInformation().jobName))
|
||||
|
||||
self._scene.gcode_list[self._scene.gcode_list.index(line)] = replaced
|
||||
|
||||
self._slicing = False
|
||||
self._need_slicing = False
|
||||
Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import numpy
|
||||
from string import Formatter
|
||||
from enum import IntEnum
|
||||
import time
|
||||
|
||||
from UM.Job import Job
|
||||
from UM.Application import Application
|
||||
|
@ -240,6 +241,13 @@ class StartSliceJob(Job):
|
|||
print_temperature_settings = {"material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"}
|
||||
settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings))
|
||||
|
||||
settings["print_bed_temperature"] = settings["material_bed_temperature"]
|
||||
settings["print_temperature"] = settings["material_print_temperature"]
|
||||
|
||||
settings["time"] = time.strftime('%H:%M:%S')
|
||||
settings["date"] = time.strftime('%d-%m-%Y')
|
||||
settings["day"] = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][int(time.strftime('%w'))]
|
||||
|
||||
for key, value in settings.items(): #Add all submessages for each individual setting.
|
||||
setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
|
||||
setting_message.name = key
|
||||
|
|
247
plugins/MachineSettingsAction/MachineSettingsAction.py
Normal file → Executable file
247
plugins/MachineSettingsAction/MachineSettingsAction.py
Normal file → Executable file
|
@ -7,12 +7,15 @@ from UM.FlameProfiler import pyqtSlot
|
|||
from cura.MachineAction import MachineAction
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Logger import Logger
|
||||
|
||||
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
|
||||
import UM.i18n
|
||||
catalog = UM.i18n.i18nCatalog("cura")
|
||||
|
@ -25,36 +28,81 @@ class MachineSettingsAction(MachineAction):
|
|||
super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
|
||||
self._qml_url = "MachineSettingsAction.qml"
|
||||
|
||||
self._global_container_stack = None
|
||||
self._container_index = 0
|
||||
self._extruder_container_index = 0
|
||||
|
||||
self._container_registry = ContainerRegistry.getInstance()
|
||||
self._container_registry.containerAdded.connect(self._onContainerAdded)
|
||||
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
|
||||
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
||||
|
||||
self._backend = Application.getInstance().getBackend()
|
||||
|
||||
def _onContainerAdded(self, container):
|
||||
# Add this action as a supported action to all machine definitions
|
||||
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
|
||||
Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
|
||||
|
||||
def _onContainerRemoved(self, container):
|
||||
# Remove definition_changes containers when a stack is removed
|
||||
if container.getMetaDataEntry("type") in ["machine", "extruder_train"]:
|
||||
definition_changes_container = container.findContainer({"type": "definition_changes"})
|
||||
if not definition_changes_container:
|
||||
return
|
||||
|
||||
self._container_registry.removeContainer(definition_changes_container.getId())
|
||||
|
||||
def _reset(self):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if not global_container_stack:
|
||||
if not self._global_container_stack:
|
||||
return
|
||||
|
||||
# Make sure there is a definition_changes container to store the machine settings
|
||||
definition_changes_container = global_container_stack.findContainer({"type": "definition_changes"})
|
||||
definition_changes_container = self._global_container_stack.findContainer({"type": "definition_changes"})
|
||||
if not definition_changes_container:
|
||||
definition_changes_container = self._createDefinitionChangesContainer(global_container_stack)
|
||||
definition_changes_container = self._createDefinitionChangesContainer(self._global_container_stack, self._global_container_stack.getName() + "_settings")
|
||||
|
||||
# Notify the UI in which container to store the machine settings data
|
||||
container_index = global_container_stack.getContainerIndex(definition_changes_container)
|
||||
container_index = self._global_container_stack.getContainerIndex(definition_changes_container)
|
||||
if container_index != self._container_index:
|
||||
self._container_index = container_index
|
||||
self.containerIndexChanged.emit()
|
||||
|
||||
def _createDefinitionChangesContainer(self, global_container_stack, container_index = None):
|
||||
definition_changes_container = InstanceContainer(global_container_stack.getName() + "_settings")
|
||||
definition = global_container_stack.getBottom()
|
||||
# Disable autoslicing while the machineaction is showing
|
||||
self._backend.disableTimer()
|
||||
|
||||
@pyqtSlot()
|
||||
def onFinishAction(self):
|
||||
# Restore autoslicing when the machineaction is dismissed
|
||||
if self._backend.determineAutoSlicing():
|
||||
self._backend.tickle()
|
||||
|
||||
def _onActiveExtruderStackChanged(self):
|
||||
extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
|
||||
if not self._global_container_stack or not extruder_container_stack:
|
||||
return
|
||||
|
||||
# Make sure there is a definition_changes container to store the machine settings
|
||||
definition_changes_container = extruder_container_stack.findContainer({"type": "definition_changes"})
|
||||
if not definition_changes_container:
|
||||
definition_changes_container = self._createDefinitionChangesContainer(extruder_container_stack, extruder_container_stack.getId() + "_settings")
|
||||
|
||||
# Notify the UI in which container to store the machine settings data
|
||||
container_index = extruder_container_stack.getContainerIndex(definition_changes_container)
|
||||
if container_index != self._extruder_container_index:
|
||||
self._extruder_container_index = container_index
|
||||
self.extruderContainerIndexChanged.emit()
|
||||
|
||||
def _createDefinitionChangesContainer(self, container_stack, container_name, container_index = None):
|
||||
definition_changes_container = InstanceContainer(container_name)
|
||||
definition = container_stack.getBottom()
|
||||
definition_changes_container.setDefinition(definition)
|
||||
definition_changes_container.addMetaDataEntry("type", "definition_changes")
|
||||
|
||||
self._container_registry.addContainer(definition_changes_container)
|
||||
# Insert definition_changes between the definition and the variant
|
||||
global_container_stack.insertContainer(-1, definition_changes_container)
|
||||
container_stack.insertContainer(-1, definition_changes_container)
|
||||
|
||||
return definition_changes_container
|
||||
|
||||
|
@ -64,15 +112,129 @@ class MachineSettingsAction(MachineAction):
|
|||
def containerIndex(self):
|
||||
return self._container_index
|
||||
|
||||
def _onContainerAdded(self, container):
|
||||
# Add this action as a supported action to all machine definitions
|
||||
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
|
||||
if container.getProperty("machine_extruder_count", "value") > 1:
|
||||
# Multiextruder printers are not currently supported
|
||||
Logger.log("d", "Not attaching MachineSettingsAction to %s; Multi-extrusion printers are not supported", container.getId())
|
||||
return
|
||||
extruderContainerIndexChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(int, notify = extruderContainerIndexChanged)
|
||||
def extruderContainerIndex(self):
|
||||
return self._extruder_container_index
|
||||
|
||||
|
||||
def _onGlobalContainerChanged(self):
|
||||
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
|
||||
# This additional emit is needed because we cannot connect a UM.Signal directly to a pyqtSignal
|
||||
self.globalContainerChanged.emit()
|
||||
|
||||
globalContainerChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(int, notify = globalContainerChanged)
|
||||
def definedExtruderCount(self):
|
||||
if not self._global_container_stack:
|
||||
return 0
|
||||
|
||||
return len(self._global_container_stack.getMetaDataEntry("machine_extruder_trains"))
|
||||
|
||||
@pyqtSlot(int)
|
||||
def setMachineExtruderCount(self, extruder_count):
|
||||
machine_manager = Application.getInstance().getMachineManager()
|
||||
extruder_manager = ExtruderManager.getInstance()
|
||||
|
||||
definition_changes_container = self._global_container_stack.findContainer({"type": "definition_changes"})
|
||||
if not self._global_container_stack or not definition_changes_container:
|
||||
return
|
||||
|
||||
previous_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
|
||||
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.activeVariantIds[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)
|
||||
|
||||
# Check to see if any features are set to print with an extruder that will no longer exist
|
||||
for setting_key in ["adhesion_extruder_nr", "support_extruder_nr", "support_extruder_nr_layer_0", "support_infill_extruder_nr", "support_interface_extruder_nr"]:
|
||||
if int(self._global_container_stack.getProperty(setting_key, "value")) > extruder_count -1:
|
||||
Logger.log("i", "Lowering %s setting to match number of extruders", setting_key)
|
||||
self._global_container_stack.getTop().setProperty(setting_key, "value", extruder_count -1)
|
||||
|
||||
# Check to see if any objects are set to print with an extruder that will no longer exist
|
||||
root_node = Application.getInstance().getController().getScene().getRoot()
|
||||
for node in DepthFirstIterator(root_node):
|
||||
if node.getMeshData():
|
||||
extruder_nr = node.callDecoration("getActiveExtruderPosition")
|
||||
|
||||
if extruder_nr is not None and int(extruder_nr) > extruder_count - 1:
|
||||
node.callDecoration("setActiveExtruder", extruder_manager.getExtruderStack(extruder_count - 1).getId())
|
||||
|
||||
definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count)
|
||||
self.forceUpdate()
|
||||
|
||||
if extruder_count > 1:
|
||||
# Multiextrusion
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
# 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)
|
||||
|
||||
Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
|
||||
|
||||
@pyqtSlot()
|
||||
def forceUpdate(self):
|
||||
|
@ -83,34 +245,35 @@ class MachineSettingsAction(MachineAction):
|
|||
@pyqtSlot()
|
||||
def updateHasMaterialsMetadata(self):
|
||||
# Updates the has_materials metadata flag after switching gcode flavor
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack:
|
||||
definition = global_container_stack.getBottom()
|
||||
if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
|
||||
has_materials = global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
|
||||
if not self._global_container_stack:
|
||||
return
|
||||
|
||||
material_container = global_container_stack.findContainer({"type": "material"})
|
||||
material_index = global_container_stack.getContainerIndex(material_container)
|
||||
definition = self._global_container_stack.getBottom()
|
||||
if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
|
||||
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
|
||||
|
||||
if has_materials:
|
||||
if "has_materials" in global_container_stack.getMetaData():
|
||||
global_container_stack.setMetaDataEntry("has_materials", True)
|
||||
else:
|
||||
global_container_stack.addMetaDataEntry("has_materials", True)
|
||||
material_container = self._global_container_stack.findContainer({"type": "material"})
|
||||
material_index = self._global_container_stack.getContainerIndex(material_container)
|
||||
|
||||
# Set the material container to a sane default
|
||||
if material_container.getId() == "empty_material":
|
||||
search_criteria = { "type": "material", "definition": "fdmprinter", "id": "*pla*" }
|
||||
containers = self._container_registry.findInstanceContainers(**search_criteria)
|
||||
if containers:
|
||||
global_container_stack.replaceContainer(material_index, containers[0])
|
||||
if has_materials:
|
||||
if "has_materials" in self._global_container_stack.getMetaData():
|
||||
self._global_container_stack.setMetaDataEntry("has_materials", True)
|
||||
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.
|
||||
if "has_materials" in global_container_stack.getMetaData():
|
||||
global_container_stack.removeMetaDataEntry("has_materials")
|
||||
self._global_container_stack.addMetaDataEntry("has_materials", True)
|
||||
|
||||
empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0]
|
||||
global_container_stack.replaceContainer(material_index, empty_material)
|
||||
# Set the material container to a sane default
|
||||
if material_container.getId() == "empty_material":
|
||||
search_criteria = { "type": "material", "definition": "fdmprinter", "id": "*pla*" }
|
||||
containers = self._container_registry.findInstanceContainers(**search_criteria)
|
||||
if containers:
|
||||
self._global_container_stack.replaceContainer(material_index, 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.
|
||||
if "has_materials" in self._global_container_stack.getMetaData():
|
||||
self._global_container_stack.removeMetaDataEntry("has_materials")
|
||||
|
||||
Application.getInstance().globalContainerStackChanged.emit()
|
||||
empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0]
|
||||
self._global_container_stack.replaceContainer(material_index, empty_material)
|
||||
|
||||
Application.getInstance().globalContainerStackChanged.emit()
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,10 @@ _removed_settings = { #Settings that were removed in 2.5.
|
|||
"start_layers_at_same_position"
|
||||
}
|
||||
|
||||
_split_settings = { #These settings should be copied to all settings it was split into.
|
||||
"support_interface_line_distance": {"support_roof_line_distance", "support_bottom_line_distance"}
|
||||
}
|
||||
|
||||
## A collection of functions that convert the configuration of the user in Cura
|
||||
# 2.4 to a configuration for Cura 2.5.
|
||||
#
|
||||
|
@ -42,8 +46,16 @@ class VersionUpgrade24to25(VersionUpgrade):
|
|||
#Remove settings from the visible_settings.
|
||||
if parser.has_section("general") and "visible_settings" in parser["general"]:
|
||||
visible_settings = parser["general"]["visible_settings"].split(";")
|
||||
visible_settings = filter(lambda setting: setting not in _removed_settings, visible_settings)
|
||||
parser["general"]["visible_settings"] = ";".join(visible_settings)
|
||||
new_visible_settings = []
|
||||
for setting in visible_settings:
|
||||
if setting in _removed_settings:
|
||||
continue #Skip.
|
||||
if setting in _split_settings:
|
||||
for replaced_setting in _split_settings[setting]:
|
||||
new_visible_settings.append(replaced_setting)
|
||||
continue #Don't add the original.
|
||||
new_visible_settings.append(setting) #No special handling, so just add the original visible setting back.
|
||||
parser["general"]["visible_settings"] = ";".join(new_visible_settings)
|
||||
|
||||
#Change the version number in the file.
|
||||
if parser.has_section("general"): #It better have!
|
||||
|
@ -66,6 +78,10 @@ class VersionUpgrade24to25(VersionUpgrade):
|
|||
if parser.has_section("values"):
|
||||
for removed_setting in (_removed_settings & parser["values"].keys()): #Both in keys that need to be removed and in keys present in the file.
|
||||
del parser["values"][removed_setting]
|
||||
for replaced_setting in (_split_settings.keys() & parser["values"].keys()):
|
||||
for replacement in _split_settings[replaced_setting]:
|
||||
parser["values"][replacement] = parser["values"][replaced_setting] #Copy to replacement before removing the original!
|
||||
del replaced_setting
|
||||
|
||||
#Change the version number in the file.
|
||||
if parser.has_section("general"):
|
||||
|
|
|
@ -10,6 +10,17 @@
|
|||
"category": "Custom",
|
||||
"file_formats": "text/x-gcode",
|
||||
"has_materials": true,
|
||||
"machine_extruder_trains":
|
||||
{
|
||||
"0": "custom_extruder_1",
|
||||
"1": "custom_extruder_2",
|
||||
"2": "custom_extruder_3",
|
||||
"3": "custom_extruder_4",
|
||||
"4": "custom_extruder_5",
|
||||
"5": "custom_extruder_6",
|
||||
"6": "custom_extruder_7",
|
||||
"7": "custom_extruder_8"
|
||||
},
|
||||
"first_start_actions": ["MachineSettingsAction"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,18 @@
|
|||
"settable_per_meshgroup": false,
|
||||
"settable_globally": false
|
||||
},
|
||||
"machine_nozzle_size":
|
||||
{
|
||||
"label": "Nozzle Diameter",
|
||||
"description": "The inner diameter of the nozzle. Change this setting when using a non-standard nozzle size.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.4,
|
||||
"minimum_value": "0.001",
|
||||
"maximum_value_warning": "10",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"machine_nozzle_offset_x":
|
||||
{
|
||||
"label": "Nozzle X Offset",
|
||||
|
|
|
@ -3235,7 +3235,7 @@
|
|||
"support_bottom_stair_step_height":
|
||||
{
|
||||
"label": "Support Stair Step Height",
|
||||
"description": "The height of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures.",
|
||||
"description": "The height of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures. Set to zero to turn off the stair-like behaviour.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.3,
|
||||
|
@ -3245,6 +3245,19 @@
|
|||
"enabled": "support_enable",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"support_bottom_stair_step_width":
|
||||
{
|
||||
"label": "Support Stair Step Maximum Width",
|
||||
"description": "The maximum width of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0,
|
||||
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "10.0",
|
||||
"enabled": "support_enable",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"support_join_distance":
|
||||
{
|
||||
"label": "Support Join Distance",
|
||||
|
|
17
resources/extruders/custom_extruder_1.def.json
Normal file
17
resources/extruders/custom_extruder_1.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_1",
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 0,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_2.def.json
Normal file
17
resources/extruders/custom_extruder_2.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_2",
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 1,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_3.def.json
Normal file
17
resources/extruders/custom_extruder_3.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_3",
|
||||
"version": 2,
|
||||
"name": "Extruder 3",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "2"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 2,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_4.def.json
Normal file
17
resources/extruders/custom_extruder_4.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_4",
|
||||
"version": 2,
|
||||
"name": "Extruder 4",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "3"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 3,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_5.def.json
Normal file
17
resources/extruders/custom_extruder_5.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_5",
|
||||
"version": 2,
|
||||
"name": "Extruder 5",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "4"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 4,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_6.def.json
Normal file
17
resources/extruders/custom_extruder_6.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_6",
|
||||
"version": 2,
|
||||
"name": "Extruder 6",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "5"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 5,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_7.def.json
Normal file
17
resources/extruders/custom_extruder_7.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_7",
|
||||
"version": 2,
|
||||
"name": "Extruder 7",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "6"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 6,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
17
resources/extruders/custom_extruder_8.def.json
Normal file
17
resources/extruders/custom_extruder_8.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "custom_extruder_8",
|
||||
"version": 2,
|
||||
"name": "Extruder 8",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "custom",
|
||||
"position": "7"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 7,
|
||||
"maximum_value": "7"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -180,7 +180,7 @@ UM.Dialog
|
|||
anchors.bottom:parent.bottom
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Text
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Printer Name:")
|
||||
anchors.verticalCenter: machineName.verticalCenter
|
||||
|
|
|
@ -126,9 +126,11 @@ UM.PreferencesPage
|
|||
text: catalog.i18nc("@label","Interface")
|
||||
}
|
||||
|
||||
Row
|
||||
GridLayout
|
||||
{
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
id: interfaceGrid
|
||||
columns: 4
|
||||
|
||||
Label
|
||||
{
|
||||
id: languageLabel
|
||||
|
@ -189,94 +191,79 @@ UM.PreferencesPage
|
|||
{
|
||||
id: currencyLabel
|
||||
text: catalog.i18nc("@label","Currency:")
|
||||
anchors.verticalCenter: languageComboBox.verticalCenter
|
||||
anchors.verticalCenter: currencyField.verticalCenter
|
||||
}
|
||||
|
||||
TextField
|
||||
{
|
||||
id: currencyField
|
||||
text: UM.Preferences.getValue("cura/currency")
|
||||
onTextChanged: UM.Preferences.setValue("cura/currency", text)
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: themeLabel
|
||||
text: catalog.i18nc("@label","Theme:")
|
||||
anchors.verticalCenter: themeComboBox.verticalCenter
|
||||
}
|
||||
|
||||
ComboBox
|
||||
{
|
||||
id: themeComboBox
|
||||
|
||||
model: ListModel
|
||||
{
|
||||
id: themeList
|
||||
|
||||
Component.onCompleted: {
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "Ultimaker"), code: "cura" })
|
||||
}
|
||||
}
|
||||
|
||||
currentIndex:
|
||||
{
|
||||
var code = UM.Preferences.getValue("general/theme");
|
||||
for(var i = 0; i < themeList.count; ++i)
|
||||
{
|
||||
if(model.get(i).code == code)
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: UM.Preferences.setValue("general/theme", model.get(index).code)
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
// Because ListModel is stupid and does not allow using qsTr() for values.
|
||||
for(var i = 0; i < themeList.count; ++i)
|
||||
{
|
||||
themeList.setProperty(i, "text", catalog.i18n(themeList.get(i).text));
|
||||
}
|
||||
|
||||
// Glorious hack time. ComboBox does not update the text properly after changing the
|
||||
// model. So change the indices around to force it to update.
|
||||
currentIndex += 1;
|
||||
currentIndex -= 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
|
||||
|
||||
|
||||
Label
|
||||
{
|
||||
id: languageCaption
|
||||
|
||||
//: Language change warning
|
||||
text: catalog.i18nc("@label", "You will need to restart the application for language changes to have effect.")
|
||||
text: catalog.i18nc("@label", "You will need to restart the application for these changes to have effect.")
|
||||
wrapMode: Text.WordWrap
|
||||
font.italic: true
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
//: Spacer
|
||||
height: UM.Theme.getSize("default_margin").height
|
||||
width: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
|
||||
Row
|
||||
{
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
Label
|
||||
{
|
||||
id: themeLabel
|
||||
text: catalog.i18nc("@label","Theme:")
|
||||
anchors.verticalCenter: themeComboBox.verticalCenter
|
||||
}
|
||||
|
||||
ComboBox
|
||||
{
|
||||
id: themeComboBox
|
||||
model: ListModel
|
||||
{
|
||||
id: themeList
|
||||
|
||||
Component.onCompleted: {
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "Ultimaker"), code: "cura" })
|
||||
}
|
||||
}
|
||||
|
||||
currentIndex:
|
||||
{
|
||||
var code = UM.Preferences.getValue("general/theme");
|
||||
for(var i = 0; i < themeList.count; ++i)
|
||||
{
|
||||
if(model.get(i).code == code)
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: UM.Preferences.setValue("general/theme", model.get(index).code)
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
// Because ListModel is stupid and does not allow using qsTr() for values.
|
||||
for(var i = 0; i < themeList.count; ++i)
|
||||
{
|
||||
themeList.setProperty(i, "text", catalog.i18n(themeList.get(i).text));
|
||||
}
|
||||
|
||||
// Glorious hack time. ComboBox does not update the text properly after changing the
|
||||
// model. So change the indices around to force it to update.
|
||||
currentIndex += 1;
|
||||
currentIndex -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: themeCaption
|
||||
|
||||
//: Theme change warning
|
||||
text: catalog.i18nc("@label", "You will need to restart the application for theme changes to have effect.")
|
||||
wrapMode: Text.WordWrap
|
||||
font.italic: true
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
//: Spacer
|
||||
|
|
|
@ -179,7 +179,7 @@ Item
|
|||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
enabled:
|
||||
{
|
||||
if(!ExtruderManager.activeExtruderStackId && ExtruderManager.extruderCount > 0)
|
||||
if(!ExtruderManager.activeExtruderStackId && machineExtruderCount.properties.value > 1)
|
||||
{
|
||||
// disable all controls on the global tab, except categories
|
||||
return model.type == "category"
|
||||
|
|
|
@ -19,7 +19,7 @@ Item
|
|||
property Action configureSettings;
|
||||
property variant minimumPrintTime: PrintInformation.minimumPrintTime;
|
||||
property variant maximumPrintTime: PrintInformation.maximumPrintTime;
|
||||
property bool settingsEnabled: ExtruderManager.activeExtruderStackId || ExtruderManager.extruderCount == 0
|
||||
property bool settingsEnabled: ExtruderManager.activeExtruderStackId || machineExtruderCount.properties.value == 1
|
||||
|
||||
Component.onCompleted: PrintInformation.enabled = true
|
||||
Component.onDestruction: PrintInformation.enabled = false
|
||||
|
|
|
@ -247,7 +247,7 @@
|
|||
},
|
||||
|
||||
"sizes": {
|
||||
"window_minimum_size": [70, 54],
|
||||
"window_minimum_size": [70, 50],
|
||||
"window_margin": [1.0, 1.0],
|
||||
"default_margin": [1.0, 1.0],
|
||||
"default_lining": [0.08, 0.08],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue