Skip to content

Commit

Permalink
Merge branch '5.9' into revert_sparse_infill_strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
HellAholic authored Nov 13, 2024
2 parents 16706f6 + e026cd8 commit c204993
Show file tree
Hide file tree
Showing 151 changed files with 7,850 additions and 6,802 deletions.
27 changes: 20 additions & 7 deletions conandata.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
version: "5.9.0-beta.1"
version: "5.9.0"
requirements:
- "cura_resources/5.9.0-beta.1"
- "uranium/5.9.0-beta.1"
- "curaengine/5.9.0-beta.1"
- "cura_binary_data/5.9.0-beta.1"
- "fdm_materials/5.9.0-beta.1"
- "cura_resources/5.9.0"
- "uranium/5.9.0"
- "curaengine/5.9.0"
- "cura_binary_data/5.9.0"
- "fdm_materials/5.9.0"
- "dulcificum/0.2.1"
- "pysavitar/5.3.0"
- "pynest2d/5.3.0"
- "native_cad_plugin/2.0.0"
requirements_internal:
- "fdm_materials/5.9.0-beta.1"
- "fdm_materials/5.9.0"
- "cura_private_data/(latest)@internal/testing"
urls:
default:
Expand Down Expand Up @@ -124,6 +124,19 @@ pyinstaller:
Windows: "./icons/Cura.ico"
Macos: "./icons/cura.icns"
Linux: "./icons/cura-128.png"
blacklist:
- [ "assimp" ]
- [ "qt", "charts" ]
- [ "qt", "coap" ]
- [ "qt", "data", "vis" ]
- [ "qt", "lab", "animat" ]
- [ "qt", "mqtt" ]
- [ "qt", "net", "auth" ]
- [ "qt", "quick3d" ]
- [ "qt", "timeline" ]
- [ "qt", "virt", "key" ]
- [ "qt", "wayland", "compos" ]
- [ "qt", "5", "compat" ]
pycharm_targets:
- jinja_path: .run_templates/pycharm_cura_run.run.xml.jinja
module_name: Cura
Expand Down
79 changes: 78 additions & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,62 @@ def _generate_cura_version(self, location):
python_installs=self._python_installs(),
))

def _delete_unwanted_binaries(self, root):
dynamic_binary_file_exts = [".so", ".dylib", ".dll", ".pyd", ".pyi"]
prohibited = [
"qt5compat",
"qtcharts",
"qtcoap",
"qtdatavis3d",
"qtlottie",
"qtmqtt",
"qtnetworkauth",
"qtquick3d",
"qtquick3dphysics",
"qtquicktimeline",
"qtvirtualkeyboard",
"qtwayland"
]
forbiddens = [x.encode() for x in prohibited]
to_remove_files = []
to_remove_dirs = []
for root, dir_, files in os.walk(root):
for filename in files:
if not any([(x in filename) for x in dynamic_binary_file_exts]):
continue
pathname = os.path.join(root, filename)
still_exist = True
for forbidden in prohibited:
if forbidden.lower() in str(pathname).lower():
to_remove_files.append(pathname)
still_exist = False
break
if not still_exist:
continue
with open(pathname, "rb") as file:
bytez = file.read().lower()
for forbidden in forbiddens:
if bytez.find(forbidden) >= 0:
to_remove_files.append(pathname)
for dirname in dir_:
for forbidden in prohibited:
if forbidden.lower() == str(dirname).lower():
pathname = os.path.join(root, dirname)
to_remove_dirs.append(pathname)
break
for file in to_remove_files:
try:
os.remove(file)
print(f"deleted file: {file}")
except Exception as ex:
print(f"WARNING: Attempt to delete file {file} results in: {str(ex)}")
for dir_ in to_remove_dirs:
try:
rmdir(self, dir_)
print(f"deleted dir_: {dir_}")
except Exception as ex:
print(f"WARNING: Attempt to delete folder {dir_} results in: {str(ex)}")

def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, entitlements_file):
pyinstaller_metadata = self.conan_data["pyinstaller"]
datas = []
Expand Down Expand Up @@ -281,13 +337,27 @@ def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, e
version = self.conf.get("user.cura:version", default = self.version, check_type = str)
cura_version = Version(version)

# filter all binary files in binaries on the blacklist
blacklist = pyinstaller_metadata["blacklist"]
filtered_binaries = [b for b in binaries if not any([all([(part in b[0].lower()) for part in parts]) for parts in blacklist])]

# In case the installer isn't actually pyinstaller (Windows at the moment), outright remove the offending files:
specifically_delete = set(binaries) - set(filtered_binaries)
for (unwanted_path, _) in specifically_delete:
try:
os.remove(unwanted_path)
print(f"delete: {unwanted_path}")
except Exception as ex:
print(f"WARNING: Attempt to delete binary {unwanted_path} results in: {str(ex)}")

# Write the actual file:
with open(os.path.join(location, "UltiMaker-Cura.spec"), "w") as f:
f.write(pyinstaller.render(
name = str(self.options.display_name).replace(" ", "-"),
display_name = self._app_name,
entrypoint = entrypoint_location,
datas = datas,
binaries = binaries,
binaries = filtered_binaries,
venv_script_path = str(self._script_dir),
hiddenimports = pyinstaller_metadata["hiddenimports"],
collect_all = pyinstaller_metadata["collect_all"],
Expand Down Expand Up @@ -405,8 +475,10 @@ def generate(self):

for dependency in self.dependencies.host.values():
for bindir in dependency.cpp_info.bindirs:
self._delete_unwanted_binaries(bindir)
copy(self, "*.dll", bindir, str(self._site_packages), keep_path = False)
for libdir in dependency.cpp_info.libdirs:
self._delete_unwanted_binaries(libdir)
copy(self, "*.pyd", libdir, str(self._site_packages), keep_path = False)
copy(self, "*.pyi", libdir, str(self._site_packages), keep_path = False)
copy(self, "*.dylib", libdir, str(self._base_dir.joinpath("lib")), keep_path = False)
Expand Down Expand Up @@ -496,6 +568,11 @@ def deploy(self):

self._generate_cura_version(os.path.join(self._site_packages, "cura"))

self._delete_unwanted_binaries(self._site_packages)
self._delete_unwanted_binaries(self.package_folder)
self._delete_unwanted_binaries(self._base_dir)
self._delete_unwanted_binaries(self._share_dir)

entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "MacOS", "cura.entitlements"))
self._generate_pyinstaller_spec(location = self._base_dir,
entrypoint_location = "'{}'".format(os.path.join(self.package_folder, self.cpp_info.bindirs[0], self.conan_data["pyinstaller"]["runinfo"]["entrypoint"])).replace("\\", "\\\\"),
Expand Down
12 changes: 8 additions & 4 deletions cura/BuildVolume.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,19 +252,23 @@ def render(self, renderer):
if not self.getMeshData() or not self.isVisible():
return True

theme = self._application.getTheme()
if not self._shader:
self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader"))
self._grid_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "grid.shader"))
theme = self._application.getTheme()
self._grid_shader.setUniformValue("u_plateColor", Color(*theme.getColor("buildplate").getRgb()))
self._grid_shader.setUniformValue("u_gridColor0", Color(*theme.getColor("buildplate_grid").getRgb()))
self._grid_shader.setUniformValue("u_gridColor1", Color(*theme.getColor("buildplate_grid_minor").getRgb()))

plate_color = Color(*theme.getColor("buildplate").getRgb())
if self._global_container_stack.getMetaDataEntry("has_textured_buildplate", False):
plate_color.setA(0.5)
self._grid_shader.setUniformValue("u_plateColor", plate_color)

renderer.queueNode(self, mode = RenderBatch.RenderMode.Lines)
renderer.queueNode(self, mesh = self._origin_mesh, backface_cull = True)
renderer.queueNode(self, mesh = self._grid_mesh, shader = self._grid_shader, backface_cull = True)
renderer.queueNode(self, mesh = self._grid_mesh, shader = self._grid_shader, backface_cull = True, transparent = True, sort = -10)
if self._disallowed_area_mesh:
renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -9)
renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -5)

if self._error_mesh:
renderer.queueNode(self, mesh=self._error_mesh, shader=self._shader, transparent=True,
Expand Down
10 changes: 2 additions & 8 deletions cura/PrinterOutput/FormatMaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,12 @@ class FormatMaps:
"asa": {"name": "ASA", "guid": "f79bc612-21eb-482e-ad6c-87d75bdde066"},
"nylon12-cf": {"name": "Nylon 12 CF", "guid": "3c6f2877-71cc-4760-84e6-4b89ab243e3b"},
"nylon-cf": {"name": "Nylon CF", "guid": "17abb865-ca73-4ccd-aeda-38e294c9c60b"},
"nylon": {"name": "Nylon", "guid": "9475b03d-fd19-48a2-b7b5-be1fb46abb02"},
"pc": {"name": "PC", "guid": "62414577-94d1-490d-b1e4-7ef3ec40db02"},
"petg": {"name": "PETG", "guid": "2d004bbd-d1bb-47f8-beac-b066702d5273"},
"pet": {"name": "PETG", "guid": "2d004bbd-d1bb-47f8-beac-b066702d5273"},
"pla": {"name": "PLA", "guid": "abb9c58e-1f56-48d1-bd8f-055fde3a5b56"},
"pva": {"name": "PVA", "guid": "add51ef2-86eb-4c39-afd5-5586564f0715"},
"wss1": {"name": "RapidRinse", "guid": "a140ef8f-4f26-4e73-abe0-cfc29d6d1024"},
"sr30": {"name": "SR-30", "guid": "77873465-83a9-4283-bc44-4e542b8eb3eb"},
"bvoh": {"name": "BVOH", "guid": "923e604c-8432-4b09-96aa-9bbbd42207f4"},
"cpe": {"name": "CPE", "guid": "da1872c1-b991-4795-80ad-bdac0f131726"},
"hips": {"name": "HIPS", "guid": "a468d86a-220c-47eb-99a5-bbb47e514eb0"},
"tpu": {"name": "TPU 95A", "guid": "19baa6a9-94ff-478b-b4a1-8157b74358d2"},
"im-pla": {"name": "Tough", "guid": "96fca5d9-0371-4516-9e96-8e8182677f3c"}
"im-pla": {"name": "Tough", "guid": "de031137-a8ca-4a72-bd1b-17bb964033ad"}
# /!\ When changing this list, make sure the changes are reported accordingly on Digital Factory
}

Expand Down
1 change: 1 addition & 0 deletions packaging/AppImage-builder/AppImageBuilder.yml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ AppDir:
QT_PLUGIN_PATH: "$APPDIR/qt/plugins"
QML2_IMPORT_PATH: "$APPDIR/qt/qml"
QT_QPA_PLATFORMTHEME: xdgdesktopportal
QT_QPA_PLATFORM: xcb
GDK_PIXBUF_MODULEDIR: $APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
GDK_PIXBUF_MODULE_FILE: $APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders.cache
path_mappings:
Expand Down
1 change: 0 additions & 1 deletion plugins/3MFReader/ThreeMFWorkspaceReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,6 @@ def _updateActiveMachine(self, global_stack):
return
machine_manager.setQualityChangesGroup(quality_changes_group, no_dialog = True)
else:
self._quality_type_to_apply = self._quality_type_to_apply.lower() if self._quality_type_to_apply else None
quality_group_dict = container_tree.getCurrentQualityGroups()
if self._quality_type_to_apply in quality_group_dict:
quality_group = quality_group_dict[self._quality_type_to_apply]
Expand Down
12 changes: 12 additions & 0 deletions plugins/CuraEngineBackend/CuraEngineBackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ def __init__(self) -> None:
"""

super().__init__()
self._init_done = False
self._immediate_slice_after_init = False

# Find out where the engine is located, and how it is called.
# This depends on how Cura is packaged and which OS we are running on.
executable_name = "CuraEngine"
Expand Down Expand Up @@ -268,6 +271,10 @@ def initialize(self) -> None:
self._machine_error_checker = application.getMachineErrorChecker()
self._machine_error_checker.errorCheckFinished.connect(self._onStackErrorCheckFinished)

self._init_done = True
if self._immediate_slice_after_init:
self.slice()

def close(self) -> None:
"""Terminate the engine process.
Expand Down Expand Up @@ -342,6 +349,11 @@ def getLatestSnapshot(self) -> Optional[QImage]:
def slice(self) -> None:
"""Perform a slice of the scene."""

if not self._init_done:
self._immediate_slice_after_init = True
return
self._immediate_slice_after_init = False

self._createSnapshot()

self.startPlugins()
Expand Down
15 changes: 10 additions & 5 deletions plugins/DigitalLibrary/src/DigitalFactoryApiClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def getListOfFilesInProject(self, library_project_id: str, on_finished: Callable
url = "{}/projects/{}/files".format(self.CURA_API_ROOT, library_project_id)
self._http.get(url,
scope = self._scope,
callback = self._parseCallback(on_finished, DigitalFactoryFileResponse, failed),
callback = self._parseCallback(on_finished, DigitalFactoryFileResponse, failed, default_values = {'username': ''}),
error_callback = failed,
timeout = self.DEFAULT_REQUEST_TIMEOUT)

Expand All @@ -205,7 +205,8 @@ def _parseCallback(self,
Callable[[List[CloudApiClientModel]], Any]],
model: Type[CloudApiClientModel],
on_error: Optional[Callable] = None,
pagination_manager: Optional[PaginationManager] = None) -> Callable[[QNetworkReply], None]:
pagination_manager: Optional[PaginationManager] = None,
default_values: Dict[str, str] = None) -> Callable[[QNetworkReply], None]:

"""
Creates a callback function so that it includes the parsing of the response into the correct model.
Expand Down Expand Up @@ -234,7 +235,7 @@ def parse(reply: QNetworkReply) -> None:
if status_code >= 300 and on_error is not None:
on_error()
else:
self._parseModels(response, on_finished, model, pagination_manager = pagination_manager)
self._parseModels(response, on_finished, model, pagination_manager = pagination_manager, default_values = default_values)

self._anti_gc_callbacks.append(parse)
return parse
Expand Down Expand Up @@ -262,7 +263,8 @@ def _parseModels(self,
on_finished: Union[Callable[[CloudApiClientModel], Any],
Callable[[List[CloudApiClientModel]], Any]],
model_class: Type[CloudApiClientModel],
pagination_manager: Optional[PaginationManager] = None) -> None:
pagination_manager: Optional[PaginationManager] = None,
default_values: Dict[str, str] = None) -> None:
"""Parses the given models and calls the correct callback depending on the result.
:param response: The response from the server, after being converted to a dict.
Expand All @@ -279,7 +281,10 @@ def _parseModels(self,
if "links" in response and pagination_manager:
pagination_manager.setLinks(response["links"])
if isinstance(data, list):
results = [model_class(**c) for c in data] # type: List[CloudApiClientModel]
results = [] # type: List[CloudApiClientModel]
for model_data in data:
complete_model_data = (default_values | model_data) if default_values is not None else model_data
results.append(model_class(**complete_model_data))
on_finished_list = cast(Callable[[List[CloudApiClientModel]], Any], on_finished)
on_finished_list(results)
else:
Expand Down
6 changes: 2 additions & 4 deletions plugins/MakerbotWriter/MakerbotWriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,13 @@ def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode=MeshWriter.
match file_format:
case "application/x-makerbot-sketch":
filename, filedata = "print.gcode", gcode_text_io.getvalue()
self._PNG_FORMATS = self._PNG_FORMAT
case "application/x-makerbot":
filename, filedata = "print.jsontoolpath", du.gcode_2_miracle_jtp(gcode_text_io.getvalue())
self._PNG_FORMATS = self._PNG_FORMAT + self._PNG_FORMAT_METHOD
case _:
raise Exception("Unsupported Mime type")

png_files = []
for png_format in self._PNG_FORMATS:
for png_format in (self._PNG_FORMAT + self._PNG_FORMAT_METHOD):
width, height, prefix = png_format["width"], png_format["height"], png_format["prefix"]
thumbnail_buffer = self._createThumbnail(width, height)
if thumbnail_buffer is None:
Expand Down Expand Up @@ -252,7 +250,7 @@ def _getMeta(self, root_nodes: List[SceneNode]) -> Tuple[Dict[str, any], str]:
meta["preferences"] = dict()
bounds = application.getBuildVolume().getBoundingBox()
meta["preferences"]["instance0"] = {
"machineBounds": [bounds.right, bounds.back, bounds.left, bounds.front] if bounds is not None else None,
"machineBounds": [bounds.right, bounds.front, bounds.left, bounds.back] if bounds is not None else None,
"printMode": CuraApplication.getInstance().getIntentManager().currentIntentCategory,
}

Expand Down
14 changes: 12 additions & 2 deletions plugins/SimulationView/SimulationView.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,19 @@ def cumulativeLineDuration(self) -> List[float]:
polylines = self.getLayerData()
if polylines is not None:
for polyline in polylines.polygons:
for line_duration in list((polyline.lineLengths / polyline.lineFeedrates)[0]):
for line_index in range(len(polyline.lineLengths)):
line_length = polyline.lineLengths[line_index]
line_feedrate = polyline.lineFeedrates[line_index][0]

if line_feedrate > 0.0:
line_duration = line_length / line_feedrate
else:
# Something is wrong with this line, set an arbitrary non-null duration
line_duration = 0.1

total_duration += line_duration / SimulationView.SIMULATION_FACTOR
self._cumulative_line_duration.append(total_duration)

# for tool change we add an extra tool path
self._cumulative_line_duration.append(total_duration)
# set current cached layer
Expand Down Expand Up @@ -583,7 +593,7 @@ def calculateColorSchemeLimits(self) -> None:
self._max_thickness = sys.float_info.min
self._min_flow_rate = sys.float_info.max
self._max_flow_rate = sys.float_info.min
self._cumulative_line_duration = {}
self._cumulative_line_duration = []

# The colour scheme is only influenced by the visible lines, so filter the lines by if they should be visible.
visible_line_types = []
Expand Down
4 changes: 2 additions & 2 deletions plugins/SimulationView/layers3d.shader
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ geometry41core =
((v_prev_line_type[0] != 1) && (v_line_type[0] == 1)) ||
((v_prev_line_type[0] != 4) && (v_line_type[0] == 4))
)) {
float w = size_x;
float h = size_y;
float w = max(0.05, size_x);
float h = max(0.05, size_y);

myEmitVertex(v_vertex[0] + vec3( w, h, w), u_starts_color, normalize(vec3( 1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, w, 0.0))); // Front-top-left
myEmitVertex(v_vertex[0] + vec3(-w, h, w), u_starts_color, normalize(vec3(-1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, w, 0.0))); // Front-top-right
Expand Down
Loading

0 comments on commit c204993

Please sign in to comment.