Browse Source

Merge remote-tracking branch 'origin/5.9'

Erwan MATHIEU 3 months ago
parent
commit
0286c6dda8

+ 8 - 4
cura/BuildVolume.py

@@ -252,19 +252,23 @@ class BuildVolume(SceneNode):
         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,

+ 7 - 10
cura/CuraApplication.py

@@ -1895,23 +1895,20 @@ class CuraApplication(QtApplication):
                 def on_finish(response):
                     content_disposition_header_key = QByteArray("content-disposition".encode())
 
-                    if not response.hasRawHeader(content_disposition_header_key):
-                        Logger.log("w", "Could not find Content-Disposition header in response from {0}".format(
-                            model_url.url()))
-                        # Use the last part of the url as the filename, and assume it is an STL file
-                        filename = model_url.path().split("/")[-1] + ".stl"
-                    else:
+                    filename = model_url.path().split("/")[-1] + ".stl"
+
+                    if response.hasRawHeader(content_disposition_header_key):
                         # content_disposition is in the format
                         # ```
-                        # content_disposition attachment; "filename=[FILENAME]"
+                        # content_disposition attachment; filename="[FILENAME]"
                         # ```
                         # Use a regex to extract the filename
                         content_disposition = str(response.rawHeader(content_disposition_header_key).data(),
                                                   encoding='utf-8')
-                        content_disposition_match = re.match(r'attachment; filename="(?P<filename>.*)"',
+                        content_disposition_match = re.match(r'attachment; filename=(?P<filename>.*)',
                                                              content_disposition)
-                        assert content_disposition_match is not None
-                        filename = content_disposition_match.group("filename")
+                        if content_disposition_match is not None:
+                            filename = content_disposition_match.group("filename").strip("\"")
 
                     tmp = tempfile.NamedTemporaryFile(suffix=filename, delete=False)
                     with open(tmp.name, "wb") as f:

+ 6 - 5
cura/Settings/ExtruderStack.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2024 UltiMaker
 # Cura is released under the terms of the LGPLv3 or higher.
 
 from typing import Any, Dict, TYPE_CHECKING, Optional
@@ -12,11 +12,8 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext
 from UM.Util import parseBool
 
-import cura.CuraApplication
-
 from . import Exceptions
 from .CuraContainerStack import CuraContainerStack, _ContainerIndexes
-from .ExtruderManager import ExtruderManager
 
 if TYPE_CHECKING:
     from cura.Settings.GlobalStack import GlobalStack
@@ -141,7 +138,11 @@ class ExtruderStack(CuraContainerStack):
                 context.popContainer()
             return result
 
-        limit_to_extruder = super().getProperty(key, "limit_to_extruder", context)
+        if not context:
+            context = PropertyEvaluationContext(self)
+        if "extruder_position" not in context.context:
+            context.context["extruder_position"] = super().getProperty(key, "limit_to_extruder", context)
+        limit_to_extruder = context.context["extruder_position"]
         if limit_to_extruder is not None:
             limit_to_extruder = str(limit_to_extruder)
 

+ 1 - 1
cura/Settings/MachineManager.py

@@ -398,7 +398,7 @@ class MachineManager(QObject):
                 self.setVariantByName(extruder.getMetaDataEntry("position"), machine_node.preferred_variant_name)
                 variant_node = machine_node.variants.get(machine_node.preferred_variant_name)
 
-            material_node = variant_node.materials.get(extruder.material.getMetaDataEntry("base_file"))
+            material_node = variant_node.materials.get(extruder.material.getMetaDataEntry("base_file")) if variant_node else None
             if material_node is None:
                 Logger.log("w", "An extruder has an unknown material, switching it to the preferred material")
                 if not self.setMaterialById(extruder.getMetaDataEntry("position"), machine_node.preferred_material):

+ 2 - 0
cura/UI/CuraSplashScreen.py

@@ -1,5 +1,6 @@
 # Copyright (c) 2020 Ultimaker B.V.
 # Uranium is released under the terms of the LGPLv3 or higher.
+import math
 
 from PyQt6.QtCore import Qt, QCoreApplication, QTimer
 from PyQt6.QtGui import QPixmap, QColor, QFont, QPen, QPainter
@@ -51,6 +52,7 @@ class CuraSplashScreen(QSplashScreen):
         self._last_update_time = time.time()
         # Since we don't know how much time actually passed, check how many intervals of 50 we had.
         self._loading_image_rotation_angle -= 10 * (time_since_last_update * 1000 / 50)
+        self._loading_image_rotation_angle = math.fmod(self._loading_image_rotation_angle, 360)
         self.repaint()
 
     # Override the mousePressEvent so the splashscreen doesn't disappear when clicked

+ 1 - 2
cura/UI/WelcomePagesModel.py

@@ -217,8 +217,7 @@ class WelcomePagesModel(ListModel):
     def _getBuiltinWelcomePagePath(page_filename: str) -> QUrl:
         """Convenience function to get QUrl path to pages that's located in "resources/qml/WelcomePages"."""
         from cura.CuraApplication import CuraApplication
-        return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
-                                                    os.path.join("WelcomePages", page_filename)))
+        return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "WelcomePages", page_filename))
 
     # FIXME: HACKs for optimization that we don't update the model every time the active machine gets changed.
     def _onActiveMachineChanged(self) -> None:

+ 2 - 2
plugins/SimulationView/layers3d.shader

@@ -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

+ 40 - 4
plugins/SliceInfoPlugin/SliceInfo.py

@@ -1,11 +1,12 @@
 # Copyright (c) 2023 UltiMaker
 # Cura is released under the terms of the LGPLv3 or higher.
+import datetime
 
 import json
 import os
 import platform
 import time
-from typing import Optional, Set, TYPE_CHECKING
+from typing import Any, Optional, Set, TYPE_CHECKING
 
 from PyQt6.QtCore import pyqtSlot, QObject
 from PyQt6.QtNetwork import QNetworkRequest
@@ -33,7 +34,18 @@ class SliceInfo(QObject, Extension):
     no model files are being sent (Just a SHA256 hash of the model).
     """
 
-    info_url = "https://stats.ultimaker.com/api/cura"
+    info_url = "https://statistics.ultimaker.com/api/v2/cura/slice"
+
+    _adjust_flattened_names = {
+        "extruders_extruder": "extruders",
+        "extruders_settings": "extruders",
+        "models_model": "models",
+        "models_transformation_data": "models_transformation",
+        "print_settings_": "",
+        "print_times": "print_time",
+        "active_machine_": "",
+        "slice_uuid": "slice_id",
+    }
 
     def __init__(self, parent = None):
         QObject.__init__(self, parent)
@@ -112,6 +124,26 @@ class SliceInfo(QObject, Extension):
 
         return list(sorted(user_modified_setting_keys))
 
+    def _flattenData(self, data: Any, result: dict, current_flat_key: Optional[str] = None, lift_list: bool = False) -> None:
+        if isinstance(data, dict):
+            for key, value in data.items():
+                total_flat_key = key if current_flat_key is None else f"{current_flat_key}_{key}"
+                self._flattenData(value, result, total_flat_key, lift_list)
+        elif isinstance(data, list):
+            for item in data:
+                self._flattenData(item, result, current_flat_key, True)
+        else:
+            actual_flat_key = current_flat_key.lower()
+            for key, value in self._adjust_flattened_names.items():
+                if actual_flat_key.startswith(key):
+                    actual_flat_key = actual_flat_key.replace(key, value)
+            if lift_list:
+                if actual_flat_key not in result:
+                    result[actual_flat_key] = []
+                result[actual_flat_key].append(data)
+            else:
+                result[actual_flat_key] = data
+
     def _onWriteStarted(self, output_device):
         try:
             if not self._application.getPreferences().getValue("info/send_slice_info"):
@@ -125,8 +157,7 @@ class SliceInfo(QObject, Extension):
             global_stack = machine_manager.activeMachine
 
             data = dict()  # The data that we're going to submit.
-            data["time_stamp"] = time.time()
-            data["schema_version"] = 0
+            data["schema_version"] = 1000
             data["cura_version"] = self._application.getVersion()
             data["cura_build_type"] = ApplicationMetadata.CuraBuildType
             org_id = user_profile.get("organization_id", None) if user_profile else None
@@ -298,6 +329,11 @@ class SliceInfo(QObject, Extension):
                 "time_backend": int(round(time_backend)),
             }
 
+            # Massage data into format used in the DB:
+            flat_data = dict()
+            self._flattenData(data, flat_data)
+            data = flat_data
+
             # Convert data to bytes
             binary_data = json.dumps(data).encode("utf-8")
 

+ 1 - 1
resources/conandata.yml

@@ -1 +1 @@
-version: "5.9.0-beta.2"
+version: "5.9.0"

+ 1 - 0
resources/definitions/ankermake_m5.def.json

@@ -10,6 +10,7 @@
         "file_formats": "text/x-gcode",
         "platform": "ankermake_m5_platform.obj",
         "has_machine_quality": true,
+        "has_textured_buildplate": true,
         "machine_extruder_trains": { "0": "ankermake_m5_extruder_0" },
         "platform_texture": "ankermake_m5.png",
         "preferred_material": "generic_pla",

Some files were not shown because too many files changed in this diff