Skip to content

Commit facf0b7

Browse files
authored
Merge branch 'main' into PostProcessing_InsertAtLayerChange_update
2 parents c91862f + ee021f7 commit facf0b7

File tree

213 files changed

+7865
-581
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

213 files changed

+7865
-581
lines changed

.github/ISSUE_TEMPLATE/SlicingCrash.yaml

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,25 @@ body:
55
- type: markdown
66
attributes:
77
value: |
8-
### ✨Try our improved Cura 5.7
9-
Before filling out the report below, we want you to try the latest Cura 5.7.
10-
This version of Cura has become significantly more reliable and has an updated slicing engine that will automatically send a report to the Cura Team for analysis.
11-
#### [You can find the downloads here](https://github.com/Ultimaker/Cura/releases/latest) ####
12-
If you still encounter a crash you are still welcome to report the issue so we can use your model as a test case, you can find instructions on how to do that below.
8+
### ✨Are you stuck? Have you tried these two things?
9+
1- Are you on a Cura version lower than Cura 5.7? We really recommend updating because it resolves a lot of slicing crashes!
10+
2- Have you tried fixing the model with software that repairs 3d files and makes them watertight?
11+
Are you seeing spots and dots on your model? That is Cura indicating that your model is not watertight.
12+
You can try doing a quick [Mesh Fix with the Meshtools Plugin](https://marketplace.ultimaker.com/app/cura/plugins/fieldofview/MeshTools) or other mesh editing software.
1313
14-
### Project File
15-
**⚠️ Before you continue, we need your project file to troubleshoot a slicing crash.**
16-
It contains the printer and settings we need for troubleshooting.
14+
If you still encounter a crash you are welcome to report the issue so we can use your model as a test case.
15+
You can find instructions on how to share your model in a Package for Technical Support below.
1716
18-
![Alt Text](https://user-images.githubusercontent.com/40423138/240616958-5a9751f2-bd34-4808-9752-6fde2e27516e.gif)
19-
20-
To save a project file go to File -> Save project.
21-
Please make sure to .zip your project file.
22-
For big files, you may need to use [WeTransfer](https://wetransfer.com/) or similar file-sharing sites.
23-
24-
🤔 Before you share, please think to yourself. Is this a model that can be shared?
25-
Unfortunately we cannot help if this file is missing.
26-
Do you have the project file? Than let's continue ⬇️
27-
28-
### Questions
17+
🤔 Before you share, please think to yourself. Is this a model that can be shared on the internet?
18+
**Unfortunately, we cannot help if this file is missing.**
19+
20+
### Questions
2921
- type: input
3022
attributes:
3123
label: Cura Version
32-
placeholder: 5.6.0
24+
description: We work hard on improving our slicing crashes. If you are not on the latest version of Cura, [you can download it here](https://github.com/Ultimaker/Cura/releases/latest)
3325
validations:
3426
required: true
35-
- type: markdown
36-
attributes:
37-
value: |
38-
We work hard on improving our slicing crashes. Our most recent release is 5.7.1.
39-
If you are not on the latest version of Cura, [you can download it here](https://github.com/Ultimaker/Cura/releases/latest)
4027
- type: input
4128
attributes:
4229
label: Operating System
@@ -50,27 +37,13 @@ body:
5037
description: Which printer was selected in Cura?
5138
validations:
5239
required: true
53-
- type: input
54-
attributes:
55-
label: Name abnormal settings
56-
description: Are there any settings that you might have changed that caused the crash? Does your model slice when you select the default profiles?
57-
placeholder:
58-
validations:
59-
- type: input
60-
attributes:
61-
label: Describe model location
62-
description: Does your model slice if you rotate the model 90 degrees or if you move it away from the center of the buildplate?
63-
placeholder:
64-
validations:
65-
- type: input
66-
attributes:
67-
label: Describe your model
68-
description: Have you sliced your model succesfully before? Is it watertight? Have you tried doing a quick [Mesh Fix with the Meshtools Plugin](https://marketplace.ultimaker.com/app/cura/plugins/fieldofview/MeshTools)?
69-
validations:
70-
required: true
40+
7141
- type: textarea
7242
attributes:
73-
label: Add your .zip here ⬇️
74-
description: You can add the zip file and additional information that is relevant to the issue in the comments below.
43+
label: Describe your problem and add the package for technical support as a .zip here ⬇️
44+
description: |
45+
If you still have Cura open with your crash > Click on Help on top bar > Click on Export Package For Technical Support > Compress the file into a zip > Add the file here to your GitHub issue 🔗
46+
47+
If you closed Cura, please open Cura to recreate the crash> Select your printer > Load your model > Select your print settings > Click on Help on top bar > Click on Export Package For Technical Support > Compress the file into a zip > Add the file here to your GitHub issue 🔗
7548
validations:
7649
required: true

.github/workflows/nightly-stable.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: Nightly build - stable release
22
run-name: Nightly build - stable release
33

4-
on:
5-
schedule:
6-
# Daily at 5:15 CET
7-
- cron: '15 4 * * *'
4+
# on:
5+
# schedule:
6+
# # Daily at 5:15 CET
7+
# - cron: '15 4 * * *'
88

99
jobs:
1010
build-nightly:

.github/workflows/nightly-testing.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: Nightly build - dev release
22
run-name: Nightly build - dev release
33

4-
on:
5-
schedule:
6-
# Daily at 4:15 CET
7-
- cron: '15 3 * * *'
4+
# on:
5+
# schedule:
6+
# # Daily at 4:15 CET
7+
# - cron: '15 3 * * *'
88

99
jobs:
1010
build-nightly:

conandata.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ requirements:
66
- "cura_binary_data/5.11.0-alpha.0@ultimaker/testing"
77
- "fdm_materials/5.11.0-alpha.0@ultimaker/testing"
88
- "dulcificum/5.10.0"
9-
- "pysavitar/5.10.0"
9+
- "pysavitar/5.11.0-alpha.0"
1010
- "pynest2d/5.10.0"
1111
requirements_internal:
1212
- "fdm_materials/5.11.0-alpha.0@ultimaker/testing"
13-
- "cura_private_data/5.10.0-alpha.0@internal/testing"
13+
- "cura_private_data/5.11.0-alpha.0@internal/testing"
1414
requirements_enterprise:
1515
- "native_cad_plugin/2.0.0"
1616
urls:

conanfile.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import json
12
import os
23
import requests
34
import yaml
45
import tempfile
56
import tarfile
7+
from datetime import datetime
68
from io import StringIO
79
from pathlib import Path
810
from git import Repo
@@ -562,6 +564,30 @@ def layout(self):
562564
self.cpp.package.bindirs = ["bin"]
563565
self.cpp.package.resdirs = ["resources", "plugins", "packaging"]
564566

567+
def _make_internal_distinct(self):
568+
test_colors_path = Path(self.source_folder, "resources", "themes", "daily_test_colors.json")
569+
if not test_colors_path.exists():
570+
print(f"Could not find '{str(test_colors_path)}'. Won't generate rotating colors for alpha builds.")
571+
return
572+
if "alpha" in self.version:
573+
with test_colors_path.open("r") as test_colors_file:
574+
test_colors = json.load(test_colors_file)
575+
biweekly_day = (datetime.now() - datetime(2025, 3, 14)).days % len(test_colors)
576+
for theme_dir in Path(self.source_folder, "resources", "themes").iterdir():
577+
if not theme_dir.is_dir():
578+
continue
579+
theme_path = Path(theme_dir, "theme.json")
580+
if not theme_path.exists():
581+
print(f"('Colorize-by-day' alpha builds): Skipping {str(theme_path)}, could not find file.")
582+
continue
583+
with theme_path.open("r") as theme_file:
584+
theme = json.load(theme_file)
585+
if theme["colors"]:
586+
theme["colors"]["main_window_header_background"] = test_colors[biweekly_day]
587+
with theme_path.open("w") as theme_file:
588+
json.dump(theme, theme_file)
589+
test_colors_path.unlink()
590+
565591
def generate(self):
566592
copy(self, "cura_app.py", self.source_folder, str(self._script_dir))
567593

@@ -581,6 +607,9 @@ def generate(self):
581607
copy(self, "bundled_*.json", native_cad_plugin.resdirs[1],
582608
str(Path(self.source_folder, "resources", "bundled_packages")), keep_path = False)
583609

610+
# Make internal versions built on different days distinct, so people don't get confused while testing.
611+
self._make_internal_distinct()
612+
584613
# Copy resources of cura_binary_data
585614
cura_binary_data = self.dependencies["cura_binary_data"].cpp_info
586615
copy(self, "*", cura_binary_data.resdirs[0], str(self._share_dir.joinpath("cura")), keep_path = True)

cura/API/Backups.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018 Ultimaker B.V.
1+
# Copyright (c) 2025 UltiMaker
22
# Cura is released under the terms of the LGPLv3 or higher.
33
from typing import Tuple, Optional, TYPE_CHECKING, Dict, Any
44

@@ -9,14 +9,10 @@
99

1010

1111
class Backups:
12-
"""The back-ups API provides a version-proof bridge between Cura's
13-
14-
BackupManager and plug-ins that hook into it.
12+
"""The back-ups API provides a version-proof bridge between Cura's BackupManager and plug-ins that hook into it.
1513
1614
Usage:
17-
1815
.. code-block:: python
19-
2016
from cura.API import CuraAPI
2117
api = CuraAPI()
2218
api.backups.createBackup()
@@ -26,19 +22,22 @@ class Backups:
2622
def __init__(self, application: "CuraApplication") -> None:
2723
self.manager = BackupsManager(application)
2824

29-
def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]:
25+
def createBackup(self, available_remote_plugins: frozenset[str] = frozenset()) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]:
3026
"""Create a new back-up using the BackupsManager.
3127
3228
:return: Tuple containing a ZIP file with the back-up data and a dict with metadata about the back-up.
3329
"""
3430

35-
return self.manager.createBackup()
31+
return self.manager.createBackup(available_remote_plugins)
3632

37-
def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any]) -> None:
33+
def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any], auto_close: bool = True) -> None:
3834
"""Restore a back-up using the BackupsManager.
3935
4036
:param zip_file: A ZIP file containing the actual back-up data.
4137
:param meta_data: Some metadata needed for restoring a back-up, like the Cura version number.
4238
"""
4339

44-
return self.manager.restoreBackup(zip_file, meta_data)
40+
return self.manager.restoreBackup(zip_file, meta_data, auto_close=auto_close)
41+
42+
def shouldReinstallDownloadablePlugins(self) -> bool:
43+
return self.manager.shouldReinstallDownloadablePlugins()

cura/API/Interface/Settings.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from dataclasses import asdict
55

6-
from typing import cast, Dict, TYPE_CHECKING
6+
from typing import cast, Dict, TYPE_CHECKING, Any
77

88
from UM.Settings.InstanceContainer import InstanceContainer
99
from UM.Settings.SettingFunction import SettingFunction
@@ -54,6 +54,15 @@ def getContextMenuItems(self) -> list:
5454

5555
return self.application.getSidebarCustomMenuItems()
5656

57+
def getAllGlobalSettings(self) -> Dict[str, Any]:
58+
global_stack = cast(GlobalStack, self.application.getGlobalContainerStack())
59+
60+
all_settings = {}
61+
for setting in global_stack.getAllKeys():
62+
all_settings[setting] = self._retrieveValue(global_stack, setting)
63+
64+
return all_settings
65+
5766
def getSliceMetadata(self) -> Dict[str, Dict[str, Dict[str, str]]]:
5867
"""Get all changed settings and all settings. For each extruder and the global stack"""
5968
print_information = self.application.getPrintInformation()
@@ -71,24 +80,16 @@ def getSliceMetadata(self) -> Dict[str, Dict[str, Dict[str, str]]]:
7180
"quality": asdict(machine_manager.activeQualityDisplayNameMap()),
7281
}
7382

74-
def _retrieveValue(container: InstanceContainer, setting_: str):
75-
value_ = container.getProperty(setting_, "value")
76-
for _ in range(0, 1024): # Prevent possibly endless loop by not using a limit.
77-
if not isinstance(value_, SettingFunction):
78-
return value_ # Success!
79-
value_ = value_(container)
80-
return 0 # Fallback value after breaking possibly endless loop.
81-
8283
global_stack = cast(GlobalStack, self.application.getGlobalContainerStack())
8384

8485
# Add global user or quality changes
8586
global_flattened_changes = InstanceContainer.createMergedInstanceContainer(global_stack.userChanges, global_stack.qualityChanges)
8687
for setting in global_flattened_changes.getAllKeys():
87-
settings["global"]["changes"][setting] = _retrieveValue(global_flattened_changes, setting)
88+
settings["global"]["changes"][setting] = self._retrieveValue(global_flattened_changes, setting)
8889

8990
# Get global all settings values without user or quality changes
9091
for setting in global_stack.getAllKeys():
91-
settings["global"]["all_settings"][setting] = _retrieveValue(global_stack, setting)
92+
settings["global"]["all_settings"][setting] = self._retrieveValue(global_stack, setting)
9293

9394
for i, extruder in enumerate(global_stack.extruderList):
9495
# Add extruder fields to settings dictionary
@@ -100,10 +101,19 @@ def _retrieveValue(container: InstanceContainer, setting_: str):
100101
# Add extruder user or quality changes
101102
extruder_flattened_changes = InstanceContainer.createMergedInstanceContainer(extruder.userChanges, extruder.qualityChanges)
102103
for setting in extruder_flattened_changes.getAllKeys():
103-
settings[f"extruder_{i}"]["changes"][setting] = _retrieveValue(extruder_flattened_changes, setting)
104+
settings[f"extruder_{i}"]["changes"][setting] = self._retrieveValue(extruder_flattened_changes, setting)
104105

105106
# Get extruder all settings values without user or quality changes
106107
for setting in extruder.getAllKeys():
107-
settings[f"extruder_{i}"]["all_settings"][setting] = _retrieveValue(extruder, setting)
108+
settings[f"extruder_{i}"]["all_settings"][setting] = self._retrieveValue(extruder, setting)
108109

109110
return settings
111+
112+
@staticmethod
113+
def _retrieveValue(container: InstanceContainer, setting_: str):
114+
value_ = container.getProperty(setting_, "value")
115+
for _ in range(0, 1024): # Prevent possibly endless loop by not using a limit.
116+
if not isinstance(value_, SettingFunction):
117+
return value_ # Success!
118+
value_ = value_(container)
119+
return 0 # Fallback value after breaking possibly endless loop.

0 commit comments

Comments
 (0)