Просмотр исходного кода

Merge branch 'master' into libArachne_rebased

Ghostkeeper 4 лет назад
Родитель
Сommit
0fd4d303ad

+ 4 - 3
.github/workflows/cicd.yml → .github/workflows/ci.yml

@@ -1,5 +1,5 @@
 ---
-name: CI/CD
+name: CI
 on:
   push:
     branches:
@@ -10,11 +10,12 @@ on:
   pull_request:
 jobs:
   build:
-    name: Build and test
     runs-on: ubuntu-latest
     container: ultimaker/cura-build-environment
     steps:
     - name: Checkout Cura
       uses: actions/checkout@v2
-    - name: Build and test
+    - name: Build
       run: docker/build.sh
+    - name: Test
+      run: docker/test.sh

+ 6 - 1
CMakeLists.txt

@@ -16,6 +16,8 @@ if(CURA_DEBUGMODE)
     set(_cura_debugmode "ON")
 endif()
 
+option(GENERATE_TRANSLATIONS "Should the translations be generated?" ON)
+
 set(CURA_APP_NAME "cura" CACHE STRING "Short name of Cura, used for configuration folder")
 set(CURA_APP_DISPLAY_NAME "Ultimaker Cura" CACHE STRING "Display name of Cura")
 set(CURA_VERSION "master" CACHE STRING "Version name of Cura")
@@ -24,6 +26,7 @@ set(CURA_CLOUD_API_ROOT "" CACHE STRING "Alternative Cura cloud API root")
 set(CURA_CLOUD_API_VERSION "" CACHE STRING "Alternative Cura cloud API version")
 set(CURA_CLOUD_ACCOUNT_API_ROOT "" CACHE STRING "Alternative Cura cloud account API version")
 set(CURA_MARKETPLACE_ROOT "" CACHE STRING "Alternative Marketplace location")
+set(CURA_DIGITAL_FACTORY_URL "" CACHE STRING "Alternative Digital Factory location")
 
 configure_file(${CMAKE_SOURCE_DIR}/cura.desktop.in ${CMAKE_BINARY_DIR}/cura.desktop @ONLY)
 
@@ -50,7 +53,9 @@ if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
     # Extract Strings
     add_custom_target(extract-messages ${URANIUM_SCRIPTS_DIR}/extract-messages ${CMAKE_SOURCE_DIR} cura)
     # Build Translations
-    CREATE_TRANSLATION_TARGETS()
+    if(${GENERATE_TRANSLATIONS})
+        CREATE_TRANSLATION_TARGETS()
+    endif()
 endif()
 
 

+ 8 - 2
cmake/CuraPluginInstall.cmake

@@ -9,6 +9,8 @@
 # form of "a;b;c" or "a,b,c". By default all plugins will be installed.
 #
 
+option(PRINT_PLUGIN_LIST "Should the list of plugins that are installed be printed?" ON)
+
 # FIXME: Remove the code for CMake <3.12 once we have switched over completely.
 # FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
 # module is copied from the CMake repository here so in CMake <3.12 we can still use it.
@@ -81,7 +83,9 @@ foreach(_plugin_json_path ${_plugin_json_list})
     endif()
 
     if(_add_plugin)
-        message(STATUS "[+] PLUGIN TO INSTALL: ${_rel_plugin_dir}")
+        if(${PRINT_PLUGIN_LIST})
+            message(STATUS "[+] PLUGIN TO INSTALL: ${_rel_plugin_dir}")
+        endif()
         get_filename_component(_rel_plugin_parent_dir ${_rel_plugin_dir} DIRECTORY)
         install(DIRECTORY ${_rel_plugin_dir}
                 DESTINATION lib${LIB_SUFFIX}/cura/${_rel_plugin_parent_dir}
@@ -90,7 +94,9 @@ foreach(_plugin_json_path ${_plugin_json_list})
                 )
         list(APPEND _install_plugin_list ${_plugin_dir})
     elseif(_is_no_install_plugin)
-        message(STATUS "[-] PLUGIN TO REMOVE : ${_rel_plugin_dir}")
+        if(${PRINT_PLUGIN_LIST})
+            message(STATUS "[-] PLUGIN TO REMOVE : ${_rel_plugin_dir}")
+        endif()
         execute_process(COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mod_bundled_packages_json.py
                         -d ${CMAKE_CURRENT_SOURCE_DIR}/resources/bundled_packages
                         ${_plugin_dir_name}

+ 8 - 7
cmake/CuraTests.cmake

@@ -49,6 +49,14 @@ function(cura_add_test)
     endif()
 endfunction()
 
+
+#Add code style test.
+add_test(
+    NAME "code-style"
+    COMMAND ${Python3_EXECUTABLE} run_mypy.py
+    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+)
+
 #Add test for import statements which are not compatible with all builds
 add_test(
     NAME "invalid-imports"
@@ -67,13 +75,6 @@ foreach(_plugin ${_plugins})
     endif()
 endforeach()
 
-#Add code style test.
-add_test(
-    NAME "code-style"
-    COMMAND ${Python3_EXECUTABLE} run_mypy.py
-    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-)
-
 #Add test for whether the shortcut alt-keys are unique in every translation.
 add_test(
     NAME "shortcut-keys"

+ 4 - 1
cura/CrashHandler.py

@@ -250,7 +250,10 @@ class CrashHandler:
 
                 scope.set_context("plugins", self.data["plugins"])
 
-                scope.set_user({"id": str(uuid.getnode())})
+                user_id = uuid.getnode()  # On all of Cura's supported platforms, this returns the MAC address which is pseudonymical information (!= anonymous).
+                user_id %= 2 ** 16  # So to make it anonymous, apply a bitmask selecting only the last 16 bits.
+                                    # This prevents it from being traceable to a specific user but still gives somewhat of an idea of whether it's just the same user hitting the same crash over and over again, or if it's widespread.
+                scope.set_user({"id": str(user_id)})
 
         return group
 

+ 1 - 1
cura/CuraActions.py

@@ -40,7 +40,7 @@ class CuraActions(QObject):
 
     @pyqtSlot()
     def openBugReportPage(self) -> None:
-        event = CallFunctionEvent(self._openUrl, [QUrl("https://github.com/Ultimaker/Cura/issues")], {})
+        event = CallFunctionEvent(self._openUrl, [QUrl("https://github.com/Ultimaker/Cura/issues/new/choose")], {})
         cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
 
     @pyqtSlot()

+ 5 - 2
cura/CuraApplication.py

@@ -126,7 +126,7 @@ class CuraApplication(QtApplication):
     # SettingVersion represents the set of settings available in the machine/extruder definitions.
     # You need to make sure that this version number needs to be increased if there is any non-backwards-compatible
     # changes of the settings.
-    SettingVersion = 15
+    SettingVersion = 16
 
     Created = False
 
@@ -1725,7 +1725,7 @@ class CuraApplication(QtApplication):
         :param project_mode: How to handle project files. Either None(default): Follow user preference, "open_as_model"
          or "open_as_project". This parameter is only considered if the file is a project file.
         """
-
+        Logger.log("i", "Attempting to read file %s", file.toString())
         if not file.isValid():
             return
 
@@ -1799,6 +1799,9 @@ class CuraApplication(QtApplication):
             return
 
         nodes = job.getResult()
+        if nodes is None:
+            Logger.error("Read mesh job returned None. Mesh loading must have failed.")
+            return
         file_name = job.getFileName()
         file_name_lower = file_name.lower()
         file_extension = file_name_lower.split(".")[-1]

+ 2 - 1
cura/CuraVersion.py.in

@@ -9,4 +9,5 @@ CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False
 CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@"
 CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@"
 CuraCloudAccountAPIRoot = "@CURA_CLOUD_ACCOUNT_API_ROOT@"
-CuraMarketplaceRoot = "@CURA_MARKETPLACE_ROOT@"
+CuraMarketplaceRoot = "@CURA_MARKETPLACE_ROOT@"
+CuraDigitalFactoryURL = "@CURA_DIGITAL_FACTORY_URL@"

+ 9 - 3
cura/Machines/Models/QualityManagementModel.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Ultimaker B.V.
+# Copyright (c) 2020 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 from typing import Any, cast, Dict, Optional, TYPE_CHECKING
@@ -132,7 +132,7 @@ class QualityManagementModel(ListModel):
         for metadata in quality_changes_group.metadata_per_extruder.values():
             extruder_container = cast(InstanceContainer, container_registry.findContainers(id = metadata["id"])[0])
             extruder_container.setName(new_name)
-        global_container = cast(InstanceContainer, container_registry.findContainers(id=quality_changes_group.metadata_for_global["id"])[0])
+        global_container = cast(InstanceContainer, container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])[0])
         global_container.setName(new_name)
 
         quality_changes_group.name = new_name
@@ -164,10 +164,16 @@ class QualityManagementModel(ListModel):
         quality_group = quality_model_item["quality_group"]
         quality_changes_group = quality_model_item["quality_changes_group"]
         if quality_changes_group is None:
-            # Create global quality changes only.
             new_quality_changes = self._createQualityChanges(quality_group.quality_type, intent_category, new_name,
                                                              global_stack, extruder_stack = None)
             container_registry.addContainer(new_quality_changes)
+
+            for extruder in global_stack.extruderList:
+                new_extruder_quality_changes = self._createQualityChanges(quality_group.quality_type, intent_category,
+                                                                          new_name,
+                                                                          global_stack, extruder_stack = extruder)
+
+                container_registry.addContainer(new_extruder_quality_changes)
         else:
             for metadata in [quality_changes_group.metadata_for_global] + list(quality_changes_group.metadata_per_extruder.values()):
                 containers = container_registry.findContainers(id = metadata["id"])

+ 43 - 14
cura/Scene/ConvexHullDecorator.py

@@ -1,11 +1,10 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2020 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 from PyQt5.QtCore import QTimer
 
 from UM.Application import Application
 from UM.Math.Polygon import Polygon
-
 from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
 from UM.Settings.ContainerRegistry import ContainerRegistry
 
@@ -50,8 +49,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
         self._build_volume.raftThicknessChanged.connect(self._onChanged)
 
         CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
-        CuraApplication.getInstance().getController().toolOperationStarted.connect(self._onChanged)
-        CuraApplication.getInstance().getController().toolOperationStopped.connect(self._onChanged)
+        controller = CuraApplication.getInstance().getController()
+        controller.toolOperationStarted.connect(self._onChanged)
+        controller.toolOperationStopped.connect(self._onChanged)
+        #CuraApplication.getInstance().sceneBoundingBoxChanged.connect(self._onChanged)
 
         self._root = Application.getInstance().getController().getScene().getRoot()
 
@@ -188,7 +189,6 @@ class ConvexHullDecorator(SceneNodeDecorator):
 
     def recomputeConvexHullDelayed(self) -> None:
         """The same as recomputeConvexHull, but using a timer if it was set."""
-
         if self._recompute_convex_hull_timer is not None:
             self._recompute_convex_hull_timer.start()
         else:
@@ -263,16 +263,17 @@ class ConvexHullDecorator(SceneNodeDecorator):
             return offset_hull
 
         else:
+            convex_hull = Polygon([])
             offset_hull = Polygon([])
             mesh = self._node.getMeshData()
             if mesh is None:
                 return Polygon([])  # Node has no mesh data, so just return an empty Polygon.
 
-            world_transform = self._node.getWorldTransformation(copy= False)
+            world_transform = self._node.getWorldTransformation(copy = False)
 
             # Check the cache
             if mesh is self._2d_convex_hull_mesh and world_transform == self._2d_convex_hull_mesh_world_transform:
-                return self._2d_convex_hull_mesh_result
+                return self._offsetHull(self._2d_convex_hull_mesh_result)
 
             vertex_data = mesh.getConvexHullTransformedVertices(world_transform)
             # Don't use data below 0.
@@ -307,7 +308,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
             # Store the result in the cache
             self._2d_convex_hull_mesh = mesh
             self._2d_convex_hull_mesh_world_transform = world_transform
-            self._2d_convex_hull_mesh_result = offset_hull
+            self._2d_convex_hull_mesh_result = convex_hull
 
             return offset_hull
 
@@ -379,12 +380,41 @@ class ConvexHullDecorator(SceneNodeDecorator):
         :return: New Polygon instance that is offset with everything that
         influences the collision area.
         """
-
+        # Shrinkage compensation.
+        if not self._global_stack:  # Should never happen.
+            return convex_hull
+        scale_factor = self._global_stack.getProperty("material_shrinkage_percentage", "value") / 100.0
+        result = convex_hull
+        if scale_factor != 1.0 and not self.getNode().callDecoration("isGroup"):
+            center = None
+            if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time":
+                # Find the root node that's placed in the scene; the root of the mesh group.
+                ancestor = self.getNode()
+                while ancestor.getParent() != self._root:
+                    ancestor = ancestor.getParent()
+                center = ancestor.getBoundingBox().center
+            else:
+                # Find the bounding box of the entire scene, which is all one mesh group then.
+                aabb = None
+                for printed_node in self._root.getChildren():
+                    if not printed_node.callDecoration("isSliceable") and not printed_node.callDecoration("isGroup"):
+                        continue  # Not a printed node.
+                    if aabb is None:
+                        aabb = printed_node.getBoundingBox()
+                    else:
+                        aabb = aabb + printed_node.getBoundingBox()
+                if aabb:
+                    center = aabb.center
+            if center:
+                result = convex_hull.scale(scale_factor, [center.x, center.z])  # Yes, use Z instead of Y. Mixed conventions there with how the OpenGL coordinates are transmitted.
+
+        # Horizontal expansion.
         horizontal_expansion = max(
             self._getSettingProperty("xy_offset", "value"),
             self._getSettingProperty("xy_offset_layer_0", "value")
         )
 
+        # Mold.
         mold_width = 0
         if self._getSettingProperty("mold_enabled", "value"):
             mold_width = self._getSettingProperty("mold_width", "value")
@@ -396,14 +426,13 @@ class ConvexHullDecorator(SceneNodeDecorator):
                 [hull_offset, hull_offset],
                 [hull_offset, -hull_offset]
             ], numpy.float32))
-            return convex_hull.getMinkowskiHull(expansion_polygon)
+            return result.getMinkowskiHull(expansion_polygon)
         else:
-            return convex_hull
+            return result
 
     def _onChanged(self, *args) -> None:
         self._raft_thickness = self._build_volume.getRaftThickness()
-        if not args or args[0] == self._node:
-            self.recomputeConvexHullDelayed()
+        self.recomputeConvexHullDelayed()
 
     def _onGlobalStackChanged(self) -> None:
         if self._global_stack:
@@ -469,7 +498,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
         "adhesion_type", "raft_margin", "print_sequence",
         "skirt_gap", "skirt_line_count", "skirt_brim_line_width", "skirt_distance", "brim_line_count"]
 
-    _influencing_settings = {"xy_offset", "xy_offset_layer_0", "mold_enabled", "mold_width", "anti_overhang_mesh", "infill_mesh", "cutting_mesh"}
+    _influencing_settings = {"xy_offset", "xy_offset_layer_0", "mold_enabled", "mold_width", "anti_overhang_mesh", "infill_mesh", "cutting_mesh", "material_shrinkage_percentage"}
     """Settings that change the convex hull.
 
     If these settings change, the convex hull should be recalculated.

Некоторые файлы не были показаны из-за большого количества измененных файлов