Skip to content

Commit

Permalink
Merge branch 'main' into CURA-10004_fix_crash_small_rotations
Browse files Browse the repository at this point in the history
  • Loading branch information
saumyaj3 authored Sep 18, 2023
2 parents 9334447 + d2b7f31 commit 47b4320
Show file tree
Hide file tree
Showing 670 changed files with 17,585 additions and 1,369 deletions.
41 changes: 33 additions & 8 deletions .github/workflows/installers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ on:
type: boolean

schedule:
# Daily at 5:20 CET
- cron: '20 4 * * *'
# Daily at 5:15 CET
- cron: '15 3 * * *'

env:
CURA_CONAN_VERSION: ${{ inputs.cura_conan_version || 'cura/latest@ultimaker/testing' }}
Expand All @@ -41,10 +41,32 @@ env:
STAGING: ${{ inputs.staging || false }}

jobs:
default-values:
runs-on: ubuntu-latest
outputs:
cura_conan_version: ${{ steps.default.outputs.cura_conan_version }}

steps:
- name: Output default values
id: default
shell: python
run: |
import os
cura_conan_version = "cura/latest@ultimaker/testing" if "${{ github.event.inputs.cura_conan_version }}" == "" else "${{ github.event.inputs.cura_conan_version }}"
output_env = os.environ["GITHUB_OUTPUT"]
content = ""
if os.path.exists(output_env):
with open(output_env, "r") as f:
content = f.read()
with open(output_env, "w") as f:
f.write(content)
f.writelines(f"cura_conan_version={cura_conan_version}\n")
windows-installer:
uses: ./.github/workflows/windows.yml
needs: [ default-values ]
with:
cura_conan_version: ${{ github.event.inputs.CURA_CONAN_VERSION }}
cura_conan_version: ${{ needs.default-values.outputs.cura_conan_version }}
conan_args: ${{ github.event.inputs.conan_args }}
enterprise: ${{ github.event.inputs.enterprise == 'true' }}
staging: ${{ github.event.inputs.staging == 'true' }}
Expand All @@ -54,8 +76,9 @@ jobs:

linux-installer:
uses: ./.github/workflows/linux.yml
needs: [ default-values ]
with:
cura_conan_version: ${{ github.event.inputs.CURA_CONAN_VERSION }}
cura_conan_version: ${{ needs.default-values.outputs.cura_conan_version }}
conan_args: ${{ github.event.inputs.conan_args }}
enterprise: ${{ github.event.inputs.enterprise == 'true' }}
staging: ${{ github.event.inputs.staging == 'true' }}
Expand All @@ -65,8 +88,9 @@ jobs:

macos-installer:
uses: ./.github/workflows/macos.yml
needs: [ default-values ]
with:
cura_conan_version: ${{ github.event.inputs.CURA_CONAN_VERSION }}
cura_conan_version: ${{ needs.default-values.outputs.cura_conan_version }}
conan_args: ${{ github.event.inputs.conan_args }}
enterprise: ${{ github.event.inputs.enterprise == 'true' }}
staging: ${{ github.event.inputs.staging == 'true' }}
Expand All @@ -76,8 +100,9 @@ jobs:

macos-arm-installer:
uses: ./.github/workflows/macos.yml
needs: [ default-values ]
with:
cura_conan_version: ${{ github.event.inputs.CURA_CONAN_VERSION }}
cura_conan_version: ${{ needs.default-values.outputs.cura_conan_version }}
conan_args: ${{ github.event.inputs.conan_args }}
enterprise: ${{ github.event.inputs.enterprise == 'true' }}
staging: ${{ github.event.inputs.staging == 'true' }}
Expand All @@ -87,7 +112,7 @@ jobs:

# Run and update nightly release when the nightly input is set to true or if the schedule is triggered
update-nightly-release:
if: ${{ always() && (! cancelled()) && contains(needs.*.result, 'success') && (! contains(needs.*.result, 'failure')) && (inputs.nightly || github.event_name == 'schedule') }}
if: ${{ inputs.nightly || github.event_name == 'schedule' }}
runs-on: ubuntu-latest
needs: [ windows-installer, linux-installer, macos-installer, macos-arm-installer ]
steps:
Expand Down Expand Up @@ -208,7 +233,7 @@ jobs:
name: ${{ steps.filename.outputs.MAC_ARM_DMG }}-dmg
path: installers

- name: Download acOS (ARM-64) pkg installer jobs artifacts
- name: Download MacOS (ARM-64) pkg installer jobs artifacts
uses: actions/download-artifact@v2
with:
name: ${{ steps.filename.outputs.MAC_ARM_PKG }}-pkg
Expand Down
6 changes: 6 additions & 0 deletions cura/BackendPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def __init__(self) -> None:
self._process = None
self._is_running = False
self._supported_slots: List[int] = []
self._use_plugin = True

def usePlugin(self) -> bool:
return self._use_plugin

def getSupportedSlots(self) -> List[int]:
return self._supported_slots
Expand Down Expand Up @@ -55,6 +59,8 @@ def start(self) -> bool:
:return: True if the plugin process started successfully, False otherwise.
"""
if not self.usePlugin():
return False
try:
# STDIN needs to be None because we provide no input, but communicate via a local socket instead.
# The NUL device sometimes doesn't exist on some computers.
Expand Down
19 changes: 17 additions & 2 deletions cura/Machines/MaterialNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def __init__(self, container_id: str, variant: "VariantNode") -> None:
my_metadata = container_registry.findContainersMetadata(id = container_id)[0]
self.base_file = my_metadata["base_file"]
self.material_type = my_metadata["material"]
self.brand = my_metadata["brand"]
self.guid = my_metadata["GUID"]
self._loadAll()
container_registry.containerRemoved.connect(self._onRemoved)
Expand Down Expand Up @@ -80,6 +81,7 @@ def _loadAll(self) -> None:
# such as "generic_pla_ultimaker_s5_AA_0.4". So we search with the "base_file" which is the material_root_id.
else:
qualities = container_registry.findInstanceContainersMetadata(type = "quality", definition = self.variant.machine.quality_definition, material = self.base_file)

if not qualities:
my_material_type = self.material_type
if self.variant.machine.has_variants:
Expand All @@ -89,9 +91,22 @@ def _loadAll(self) -> None:
else:
qualities_any_material = container_registry.findInstanceContainersMetadata(type = "quality", definition = self.variant.machine.quality_definition)

all_material_base_files = {material_metadata["base_file"] for material_metadata in container_registry.findInstanceContainersMetadata(type = "material", material = my_material_type)}
# First we attempt to find materials that have the same brand but not the right color
all_material_base_files_right_brand = {material_metadata["base_file"] for material_metadata in container_registry.findInstanceContainersMetadata(type = "material", material = my_material_type, brand = self.brand)}

right_brand_no_color_qualities = [quality for quality in qualities_any_material if quality.get("material") in all_material_base_files_right_brand]

qualities.extend((quality for quality in qualities_any_material if quality.get("material") in all_material_base_files))
if right_brand_no_color_qualities:
# We found qualties for materials with the right brand but not with the right color. Use those.
qualities.extend(right_brand_no_color_qualities)
else:
# Fall back to generic
all_material_base_files = {material_metadata["base_file"] for material_metadata in
container_registry.findInstanceContainersMetadata(type="material",
material=my_material_type)}
no_brand_no_color_qualities = (quality for quality in qualities_any_material if
quality.get("material") in all_material_base_files)
qualities.extend(no_brand_no_color_qualities)

if not qualities: # No quality profiles found. Go by GUID then.
my_guid = self.guid
Expand Down
4 changes: 4 additions & 0 deletions cura/Machines/Models/MaterialBrandsModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def _update(self):
if bool(container_node.getMetaDataEntry("removed", False)):
continue

# Ignore materials that are marked as not visible for whatever reason
if not bool(container_node.getMetaDataEntry("visible", True)):
continue

# Add brands we haven't seen yet to the dict, skipping generics
brand = container_node.getMetaDataEntry("brand", "")
if brand.lower() == "generic":
Expand Down
3 changes: 3 additions & 0 deletions cura/UltimakerCloud/CloudMaterialSync.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ def exportAll(self, file_path: QUrl, notify_progress: Optional["Signal"] = None)
continue
if metadata["id"] == "empty_material": # Don't export the empty material.
continue
# Ignore materials that are marked as not visible for whatever reason
if not bool(metadata.get("visible", True)):
continue
material = registry.findContainers(id = metadata["id"])[0]
suffix = registry.getMimeTypeForContainer(type(material)).preferredSuffix
filename = metadata["id"] + "." + suffix
Expand Down
22 changes: 18 additions & 4 deletions plugins/3MFReader/ThreeMFWorkspaceReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,8 @@ def _applyDefinitionChanges(self, global_stack, extruder_stack_dict):
if global_stack.getProperty(key, "settable_per_extruder"):
values_to_set_for_extruders[key] = value
else:
global_stack.definitionChanges.setProperty(key, "value", value)
if not self._settingIsFromMissingPackage(key, value):
global_stack.definitionChanges.setProperty(key, "value", value)

for position, extruder_stack in extruder_stack_dict.items():
if position not in self._machine_info.extruder_info_dict:
Expand All @@ -1109,7 +1110,8 @@ def _applyDefinitionChanges(self, global_stack, extruder_stack_dict):
extruder_stack.definitionChanges.setProperty(key, "value", value)
if parser is not None:
for key, value in parser["values"].items():
extruder_stack.definitionChanges.setProperty(key, "value", value)
if not self._settingIsFromMissingPackage(key, value):
extruder_stack.definitionChanges.setProperty(key, "value", value)

def _applyUserChanges(self, global_stack, extruder_stack_dict):
values_to_set_for_extruder_0 = {}
Expand All @@ -1119,7 +1121,8 @@ def _applyUserChanges(self, global_stack, extruder_stack_dict):
if global_stack.getProperty(key, "settable_per_extruder"):
values_to_set_for_extruder_0[key] = value
else:
global_stack.userChanges.setProperty(key, "value", value)
if not self._settingIsFromMissingPackage(key, value):
global_stack.userChanges.setProperty(key, "value", value)

for position, extruder_stack in extruder_stack_dict.items():
if position not in self._machine_info.extruder_info_dict:
Expand All @@ -1133,7 +1136,8 @@ def _applyUserChanges(self, global_stack, extruder_stack_dict):
extruder_stack.userChanges.setProperty(key, "value", value)
if parser is not None:
for key, value in parser["values"].items():
extruder_stack.userChanges.setProperty(key, "value", value)
if not self._settingIsFromMissingPackage(key, value):
extruder_stack.userChanges.setProperty(key, "value", value)

def _applyVariants(self, global_stack, extruder_stack_dict):
machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
Expand Down Expand Up @@ -1208,6 +1212,15 @@ def _applyChangesToMachine(self, global_stack, extruder_stack_dict):
if key not in _ignored_machine_network_metadata:
global_stack.setMetaDataEntry(key, value)

def _settingIsFromMissingPackage(self, key, value):
# Check if the key and value pair is from the missing package
for package in self._dialog.missingPackages:
if value.startswith("PLUGIN::"):
if (package['id'] + "@" + package['package_version']) in value:
Logger.log("w", f"Ignoring {key} value {value} from missing package")
return True
return False

def _updateActiveMachine(self, global_stack):
# Actually change the active machine.
machine_manager = Application.getInstance().getMachineManager()
Expand Down Expand Up @@ -1327,3 +1340,4 @@ def _filter_missing_package_metadata(package_metadata: List[Dict[str, str]]) ->
missing_packages.append(package)

return missing_packages

2 changes: 2 additions & 0 deletions plugins/CuraEngineBackend/StartSliceJob.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ def run(self) -> None:
self._buildExtruderMessage(extruder_stack)

for plugin in CuraApplication.getInstance().getBackendPlugins():
if not plugin.usePlugin():
continue
for slot in plugin.getSupportedSlots():
# Right now we just send the message for every slot that we support. A single plugin can support
# multiple slots
Expand Down
43 changes: 41 additions & 2 deletions plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//Copyright (c) 2022 Ultimaker B.V.
//Cura is released under the terms of the LGPLv3 or higher.

import QtQuick 2.2
import QtQuick 2.15
import QtQuick.Controls 2.15

import UM 1.5 as UM
Expand Down Expand Up @@ -234,10 +234,11 @@ Item
setDestroyed(true)
}
}

property int indexWithFocus: -1
delegate: Row
{
spacing: UM.Theme.getSize("default_margin").width
property var settingLoaderItem: settingLoader.item
Loader
{
id: settingLoader
Expand Down Expand Up @@ -340,6 +341,44 @@ Item
function onPropertiesChanged() { provider.forcePropertiesChanged() }
}

Connections
{
target: settingLoader.item
function onFocusReceived()
{

contents.indexWithFocus = index
contents.positionViewAtIndex(index, ListView.Contain)
}
function onSetActiveFocusToNextSetting(forward)
{
if (forward == undefined || forward)
{
contents.currentIndex = contents.indexWithFocus + 1
while(contents.currentItem && contents.currentItem.height <= 0)
{
contents.currentIndex++
}
if (contents.currentItem)
{
contents.currentItem.settingLoaderItem.focusItem.forceActiveFocus()
}
}
else
{
contents.currentIndex = contents.indexWithFocus - 1
while(contents.currentItem && contents.currentItem.height <= 0)
{
contents.currentIndex--
}
if (contents.currentItem)
{
contents.currentItem.settingLoaderItem.focusItem.forceActiveFocus()
}
}
}
}

Connections
{
target: UM.ActiveTool
Expand Down
2 changes: 1 addition & 1 deletion plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def _getLocalMaterials() -> Dict[str, LocalMaterial]:

result = {} # type: Dict[str, LocalMaterial]
all_materials = CuraApplication.getInstance().getContainerRegistry().findInstanceContainersMetadata(type = "material")
all_base_files = [material for material in all_materials if material["id"] == material.get("base_file")] # Don't send materials without base_file: The empty material doesn't need to be sent.
all_base_files = [material for material in all_materials if material["id"] == material.get("base_file") and material.get("visible", True)] # Don't send materials without base_file: The empty material doesn't need to be sent.

# Find the latest version of all material containers in the registry.
for material_metadata in all_base_files:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright (c) 2023 UltiMaker
# Cura is released under the terms of the LGPLv3 or higher.

import configparser
from typing import Tuple, List
import io
from UM.VersionUpgrade import VersionUpgrade
import re



class VersionUpgrade54to55(VersionUpgrade):
profile_regex = re.compile(
r"um\_(?P<machine>s(3|5|7))_(?P<core_type>aa|cc|bb)(?P<nozzle_size>0\.(6|4|8))_(?P<material>pla|petg|abs|cpe|cpe_plus|nylon|pc|petcf|tough_pla|tpu)_(?P<layer_height>0\.\d{1,2}mm)")

@staticmethod
def _isUpgradedUltimakerDefinitionId(definition_id: str) -> bool:
if definition_id.startswith("ultimaker_s5"):
return True
if definition_id.startswith("ultimaker_s3"):
return True
if definition_id.startswith("ultimaker_s7"):
return True

return False

@staticmethod
def _isBrandedMaterialID(material_id: str) -> bool:
return material_id.startswith("ultimaker_")

@staticmethod
def upgradeStack(serialized: str, filename: str) -> Tuple[List[str], List[str]]:
"""
Upgrades stacks to have the new version number.
:param serialized: The original contents of the stack.
:param filename: The original file name of the stack.
:return: A list of new file names, and a list of the new contents for
those files.
"""
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)

# Update version number.
if "general" not in parser:
parser["general"] = {}

extruder_definition_id = parser["containers"]["7"]
if parser["metadata"]["type"] == "extruder_train" and VersionUpgrade54to55._isUpgradedUltimakerDefinitionId(extruder_definition_id):
# We only need to update certain Ultimaker extruder ID's
material_id = parser["containers"]["4"]
quality_id = parser["containers"]["3"]
intent_id = parser["containers"]["2"]
if VersionUpgrade54to55._isBrandedMaterialID(material_id):
# We have an Ultimaker branded material ID, so we should change the intent & quality!

quality_id = VersionUpgrade54to55.profile_regex.sub(
r"um_\g<machine>_\g<core_type>\g<nozzle_size>_um-\g<material>_\g<layer_height>", quality_id)


intent_id = VersionUpgrade54to55.profile_regex.sub(
r"um_\g<machine>_\g<core_type>\g<nozzle_size>_um-\g<material>_\g<layer_height>", intent_id)

parser["containers"]["3"] = quality_id
parser["containers"]["2"] = intent_id

# We're not changing any settings, but we are changing how certain stacks are handled.
parser["general"]["version"] = "6"

result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
Loading

0 comments on commit 47b4320

Please sign in to comment.