Merge branch 'master' into feature_sync_button

This commit is contained in:
Diego Prado Gesto 2018-03-13 13:54:22 +01:00
commit 2bf6d071d1
44 changed files with 678 additions and 317 deletions

View file

@ -216,11 +216,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
archive = zipfile.ZipFile(file_name, "r")
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
# A few lists of containers in this project files.
# When loading the global stack file, it may be associated with those containers, which may or may not be
# in Cura already, so we need to provide them as alternative search lists.
instance_container_list = []
resolve_strategy_keys = ["machine", "material", "quality_changes"]
self._resolve_strategies = {k: None for k in resolve_strategy_keys}
containers_found_dict = {k: False for k in resolve_strategy_keys}
@ -307,34 +302,34 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
container_info = ContainerInfo(instance_container_file_name, serialized, parser)
instance_container_info_dict[container_id] = container_info
instance_container = InstanceContainer(container_id)
# Deserialize InstanceContainer by converting read data from bytes to string
instance_container.deserialize(serialized, file_name = instance_container_file_name)
instance_container_list.append(instance_container)
container_type = instance_container.getMetaDataEntry("type")
container_type = parser["metadata"]["type"]
if container_type == "quality_changes":
quality_changes_info_list.append(container_info)
if not parser.has_option("metadata", "extruder"):
if not parser.has_option("metadata", "position"):
self._machine_info.quality_changes_info.name = parser["general"]["name"]
self._machine_info.quality_changes_info.global_info = container_info
else:
position = parser["metadata"]["position"]
self._machine_info.quality_changes_info.extruder_info_dict[position] = container_info
quality_name = instance_container.getName()
num_settings_overriden_by_quality_changes += len(instance_container._instances)
quality_name = parser["general"]["name"]
values = parser["values"] if parser.has_section("values") else dict()
num_settings_overriden_by_quality_changes += len(values)
# Check if quality changes already exists.
quality_changes = self._container_registry.findInstanceContainers(id = container_id)
if quality_changes:
containers_found_dict["quality_changes"] = True
# Check if there really is a conflict by comparing the values
instance_container = InstanceContainer(container_id)
instance_container.deserialize(serialized, file_name = instance_container_file_name)
if quality_changes[0] != instance_container:
quality_changes_conflict = True
elif container_type == "quality":
if not quality_name:
quality_name = instance_container.getName()
quality_name = parser["general"]["name"]
elif container_type == "user":
num_user_settings += len(instance_container._instances)
num_user_settings += len(parser["values"])
elif container_type in self._ignored_instance_container_types:
# Ignore certain instance container types
Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type)
@ -453,15 +448,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
machine_conflict = True
break
if self._machine_info.quality_changes_info is not None:
for quality_changes_info in quality_changes_info_list:
if not quality_changes_info.parser.has_option("metadata", "extruder"):
continue
extruder_definition_id = quality_changes_info.parser["metadata"]["extruder"]
extruder_definition_metadata = self._container_registry.findDefinitionContainersMetadata(id = extruder_definition_id)[0]
position = extruder_definition_metadata["position"]
self._machine_info.quality_changes_info.extruder_info_dict[position] = quality_changes_info
num_visible_settings = 0
try:
temp_preferences = Preferences()
@ -739,7 +725,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(global_stack)
machine_definition_for_quality = self._container_registry.findDefinitionContainers(id = machine_definition_id_for_quality)[0]
extruder_dict_for_quality = machine_definition_for_quality.getMetaDataEntry("machine_extruder_trains")
quality_changes_info = self._machine_info.quality_changes_info
quality_changes_quality_type = quality_changes_info.global_info.parser["metadata"]["quality_type"]
@ -752,13 +737,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
quality_changes_name = self._container_registry.uniqueName(quality_changes_name)
for position, container_info in container_info_dict.items():
extruder_definition_id = None
extruder_stack = None
if position is not None:
extruder_definition_id = extruder_dict_for_quality[position]
extruder_stack = global_stack.extruders[position]
container = quality_manager._createQualityChanges(quality_changes_quality_type,
quality_changes_name,
global_stack, extruder_definition_id)
global_stack, extruder_stack)
container_info.container = container
container.setDirty(True)
self._container_registry.addContainer(container)
@ -781,18 +765,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
container_info = quality_changes_info.extruder_info_dict[position]
container_info.container = container
for position, container_info in quality_changes_info.extruder_info_dict.items():
container_info.definition_id = extruder_dict_for_quality[position]
# If there is no quality changes for any extruder, create one.
if not quality_changes_info.extruder_info_dict:
container_info = ContainerInfo(None, None, None)
quality_changes_info.extruder_info_dict["0"] = container_info
extruder_definition_id = extruder_dict_for_quality["0"]
container_info.definition_id = extruder_definition_id
extruder_stack = global_stack.extruders["0"]
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
global_stack, extruder_definition_id)
global_stack, extruder_stack)
container_info.container = container
container.setDirty(True)
self._container_registry.addContainer(container)
@ -818,9 +798,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
continue
if container_info.container is None:
extruder_definition_id = extruder_dict_for_quality[position]
extruder_stack = global_stack.extruders[position]
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
global_stack, extruder_definition_id)
global_stack, extruder_stack)
container_info.container = container
for key, value in container_info.parser["values"].items():

View file

@ -94,6 +94,8 @@ class CuraEngineBackend(QObject, Backend):
self._onGlobalStackChanged()
Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)
# extruder enable / disable. Actually wanted to use machine manager here, but the initialization order causes it to crash
ExtruderManager.getInstance().extrudersChanged.connect(self._extruderChanged)
# A flag indicating if an error check was scheduled
# If so, we will stop the auto-slice timer and start upon the error check
@ -782,3 +784,9 @@ class CuraEngineBackend(QObject, Backend):
def tickle(self):
if self._use_timer:
self._change_timer.start()
def _extruderChanged(self):
for build_plate_number in range(Application.getInstance().getMultiBuildPlateModel().maxBuildPlate + 1):
if build_plate_number not in self._build_plates_to_be_sliced:
self._build_plates_to_be_sliced.append(build_plate_number)
self._invokeSlice()

View file

@ -81,7 +81,8 @@ class ProcessSlicedLayersJob(Job):
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
new_node = CuraSceneNode()
# The no_setting_override is here because adding the SettingOverrideDecorator will trigger a reslice
new_node = CuraSceneNode(no_setting_override = True)
new_node.addDecorator(BuildPlateDecorator(self._build_plate_number))
# Force garbage collection.

View file

@ -129,8 +129,10 @@ class StartSliceJob(Job):
self.setResult(StartJobResult.MaterialIncompatible)
return
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
for position, extruder_stack in stack.extruders.items():
material = extruder_stack.findContainer({"type": "material"})
if not extruder_stack.isEnabled:
continue
if material:
if material.getMetaDataEntry("compatible") == False:
self.setResult(StartJobResult.MaterialIncompatible)
@ -189,11 +191,18 @@ class StartSliceJob(Job):
if per_object_stack:
is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS)
if node.callDecoration("getBuildPlateNumber") == self._build_plate_number:
if not getattr(node, "_outside_buildarea", False) or is_non_printing_mesh:
temp_list.append(node)
if not is_non_printing_mesh:
has_printing_mesh = True
# Find a reason not to add the node
if node.callDecoration("getBuildPlateNumber") != self._build_plate_number:
continue
if getattr(node, "_outside_buildarea", False) and not is_non_printing_mesh:
continue
node_position = node.callDecoration("getActiveExtruderPosition")
if not stack.extruders[str(node_position)].isEnabled:
continue
temp_list.append(node)
if not is_non_printing_mesh:
has_printing_mesh = True
Job.yieldThread()
@ -269,9 +278,15 @@ class StartSliceJob(Job):
# \return A dictionary of replacement tokens to the values they should be
# replaced with.
def _buildReplacementTokens(self, stack) -> dict:
default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
result = {}
for key in stack.getAllKeys():
result[key] = stack.getProperty(key, "value")
setting_type = stack.getProperty(key, "type")
value = stack.getProperty(key, "value")
if setting_type == "extruder" and value == -1:
# replace with the default value
value = default_extruder_position
result[key] = value
Job.yieldThread()
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
@ -377,11 +392,11 @@ class StartSliceJob(Job):
# limit_to_extruder property.
def _buildGlobalInheritsStackMessage(self, stack):
for key in stack.getAllKeys():
extruder = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
if extruder >= 0: #Set to a specific extruder.
extruder_position = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
if extruder_position >= 0: # Set to a specific extruder.
setting_extruder = self._slice_message.addRepeatedMessage("limit_to_extruder")
setting_extruder.name = key
setting_extruder.extruder = extruder
setting_extruder.extruder = extruder_position
Job.yieldThread()
## Check if a node has per object settings and ensure that they are set correctly in the message

View file

@ -244,6 +244,7 @@ Cura.MachineAction
height: childrenRect.height
width: childrenRect.width
text: machineExtruderCountProvider.properties.description
visible: extruderCountModel.count >= 2
Row
{

View file

@ -173,7 +173,10 @@ class PostProcessingPlugin(QObject, Extension):
Logger.log("d", "Creating post processing plugin view.")
## Load all scripts in the scripts folders
for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Preferences)]:
# The PostProcessingPlugin path is for built-in scripts.
# The Resources path is where the user should store custom scripts.
# The Preferences path is legacy, where the user may previously have stored scripts.
for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Resources), Resources.getStoragePath(Resources.Preferences)]:
path = os.path.join(root, "scripts")
if not os.path.isdir(path):
try:

View file

@ -78,17 +78,13 @@ class SolidView(View):
for node in DepthFirstIterator(scene.getRoot()):
if not node.render(renderer):
if node.getMeshData() and node.isVisible():
if node.getMeshData() and node.isVisible() and not node.callDecoration("getLayerData"):
uniforms = {}
shade_factor = 1.0
per_mesh_stack = node.callDecoration("getStack")
# 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_index = int(node.callDecoration("getActiveExtruderPosition"))
# Use the support extruder instead of the active extruder if this is a support_mesh
if per_mesh_stack:

View file

@ -301,8 +301,8 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._updatePrintJob(print_job, print_job_data)
if print_job.state != "queued": # Print job should be assigned to a printer.
if print_job.state == "failed":
# Print job was failed, so don't attach it to a printer.
if print_job.state in ["failed", "finished", "aborted"]:
# Print job was already completed, so don't attach it to a printer.
printer = None
else:
printer = self._getPrinterByKey(print_job_data["printer_uuid"])

View file

@ -8,10 +8,10 @@ upgrade = VersionUpgrade32to33.VersionUpgrade32to33()
def getMetaData():
return {
"version_upgrade": {
# From To Upgrade function
# From To Upgrade function
("definition_changes", 2000004): ("definition_changes", 3000004, upgrade.upgradeInstanceContainer),
("quality_changes", 2000004): ("quality_changes", 3000004, upgrade.upgradeQualityChanges),
("user", 2000004): ("user", 3000004, upgrade.upgradeInstanceContainer)
("quality_changes", 2000004): ("quality_changes", 3000004, upgrade.upgradeQualityChanges),
("user", 2000004): ("user", 3000004, upgrade.upgradeInstanceContainer)
},
"sources": {
"definition_changes": {

View file

@ -205,7 +205,7 @@ class XmlMaterialProfile(InstanceContainer):
self._addSettingElement(builder, instance)
machine_container_map = {}
machine_nozzle_map = {}
machine_variant_map = {}
variant_manager = CuraApplication.getInstance().getVariantManager()
material_manager = CuraApplication.getInstance().getMaterialManager()
@ -225,13 +225,14 @@ class XmlMaterialProfile(InstanceContainer):
if definition_id not in machine_container_map:
machine_container_map[definition_id] = container
if definition_id not in machine_nozzle_map:
machine_nozzle_map[definition_id] = {}
if definition_id not in machine_variant_map:
machine_variant_map[definition_id] = {}
variant_name = container.getMetaDataEntry("variant_name")
if variant_name:
machine_nozzle_map[definition_id][variant_name] = variant_manager.getVariantNode(definition_id,
variant_name)
variant_dict = {"variant_node": variant_manager.getVariantNode(definition_id, variant_name),
"material_container": container}
machine_variant_map[definition_id][variant_name] = variant_dict
continue
machine_container_map[definition_id] = container
@ -265,28 +266,60 @@ class XmlMaterialProfile(InstanceContainer):
self._addSettingElement(builder, instance)
# Find all hotend sub-profiles corresponding to this material and machine and add them to this profile.
for hotend_name, variant_node in machine_nozzle_map[definition_id].items():
# The hotend identifier is not the containers name, but its "name".
builder.start("hotend", {"id": hotend_name})
buildplate_dict = {}
for variant_name, variant_dict in machine_variant_map[definition_id].items():
variant_type = variant_dict["variant_node"].metadata["hardware_type"]
from cura.Machines.VariantManager import VariantType
variant_type = VariantType(variant_type)
if variant_type == VariantType.NOZZLE:
# The hotend identifier is not the containers name, but its "name".
builder.start("hotend", {"id": variant_name})
# Compatible is a special case, as it's added as a meta data entry (instead of an instance).
compatible = variant_node.metadata.get("compatible")
if compatible is not None:
builder.start("setting", {"key": "hardware compatible"})
if compatible:
builder.data("yes")
else:
builder.data("no")
builder.end("setting")
# Compatible is a special case, as it's added as a meta data entry (instead of an instance).
material_container = variant_dict["material_container"]
compatible = container.getMetaDataEntry("compatible")
if compatible is not None:
builder.start("setting", {"key": "hardware compatible"})
if compatible:
builder.data("yes")
else:
builder.data("no")
builder.end("setting")
for instance in variant_node.getContainer().findInstances():
if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
# If the settings match that of the machine profile, just skip since we inherit the machine profile.
continue
for instance in material_container.findInstances():
if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
# If the settings match that of the machine profile, just skip since we inherit the machine profile.
continue
self._addSettingElement(builder, instance)
self._addSettingElement(builder, instance)
builder.end("hotend")
if material_container.getMetaDataEntry("buildplate_compatible") and not buildplate_dict:
buildplate_dict["buildplate_compatible"] = material_container.getMetaDataEntry("buildplate_compatible")
buildplate_dict["buildplate_recommended"] = material_container.getMetaDataEntry("buildplate_recommended")
buildplate_dict["material_container"] = material_container
builder.end("hotend")
if buildplate_dict:
for variant_name in buildplate_dict["buildplate_compatible"]:
builder.start("buildplate", {"id": variant_name})
material_container = buildplate_dict["material_container"]
buildplate_compatible_dict = material_container.getMetaDataEntry("buildplate_compatible")
buildplate_recommended_dict = material_container.getMetaDataEntry("buildplate_recommended")
if buildplate_compatible_dict:
compatible = buildplate_compatible_dict[variant_name]
recommended = buildplate_recommended_dict[variant_name]
builder.start("setting", {"key": "hardware compatible"})
builder.data("yes" if compatible else "no")
builder.end("setting")
builder.start("setting", {"key": "hardware recommended"})
builder.data("yes" if recommended else "no")
builder.end("setting")
builder.end("buildplate")
builder.end("machine")
@ -617,7 +650,8 @@ class XmlMaterialProfile(InstanceContainer):
from cura.Machines.VariantManager import VariantType
variant_manager = CuraApplication.getInstance().getVariantManager()
variant_node = variant_manager.getVariantNode(machine_id, buildplate_id)
variant_node = variant_manager.getVariantNode(machine_id, buildplate_id,
variant_type = VariantType.BUILD_PLATE)
if not variant_node:
continue
@ -841,6 +875,8 @@ class XmlMaterialProfile(InstanceContainer):
continue
settings = buildplate.iterfind("./um:setting", cls.__namespaces)
buildplate_compatibility = True
buildplate_recommended = True
for entry in settings:
key = entry.get("key")
if key == "hardware compatible":
@ -848,8 +884,8 @@ class XmlMaterialProfile(InstanceContainer):
elif key == "hardware recommended":
buildplate_recommended = cls._parseCompatibleValue(entry.text)
buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_map["buildplate_compatible"]
buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_map["buildplate_recommended"]
buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_compatibility
buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_recommended
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
hotend_name = hotend.get("id")