Browse Source

Merge branch 'master' of github.com:Ultimaker/Cura into CURA-7122_Include_description_in_search_field

Jaime van Kessel 4 years ago
parent
commit
134d79608f

+ 2 - 0
cura/Arranging/ArrangeObjectsJob.py

@@ -1,5 +1,6 @@
 # Copyright (c) 2019 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
+from PyQt5.QtCore import QCoreApplication
 
 from UM.Application import Application
 from UM.Job import Job
@@ -94,6 +95,7 @@ class ArrangeObjectsJob(Job):
 
             status_message.setProgress((idx + 1) / len(nodes_arr) * 100)
             Job.yieldThread()
+            QCoreApplication.processEvents()
 
         grouped_operation.push()
 

+ 9 - 5
cura/BuildVolume.py

@@ -92,6 +92,8 @@ class BuildVolume(SceneNode):
         self._adhesion_type = None  # type: Any
         self._platform = Platform(self)
 
+        self._edge_disallowed_size = None
+
         self._build_volume_message = Message(catalog.i18nc("@info:status",
             "The build volume height has been reduced due to the value of the"
             " \"Print Sequence\" setting to prevent the gantry from colliding"
@@ -106,8 +108,6 @@ class BuildVolume(SceneNode):
 
         self._application.globalContainerStackChanged.connect(self._onStackChanged)
 
-        self._onStackChanged()
-
         self._engine_ready = False
         self._application.engineCreatedSignal.connect(self._onEngineCreated)
 
@@ -118,7 +118,7 @@ class BuildVolume(SceneNode):
         self._scene_objects = set()  # type: Set[SceneNode]
 
         self._scene_change_timer = QTimer()
-        self._scene_change_timer.setInterval(100)
+        self._scene_change_timer.setInterval(200)
         self._scene_change_timer.setSingleShot(True)
         self._scene_change_timer.timeout.connect(self._onSceneChangeTimerFinished)
 
@@ -747,6 +747,7 @@ class BuildVolume(SceneNode):
         self._error_areas = []
 
         used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
+        self._edge_disallowed_size = None  # Force a recalculation
         disallowed_border_size = self.getEdgeDisallowedSize()
 
         result_areas = self._computeDisallowedAreasStatic(disallowed_border_size, used_extruders)  # Normal machine disallowed areas can always be added.
@@ -1124,6 +1125,9 @@ class BuildVolume(SceneNode):
         if not self._global_container_stack or not self._global_container_stack.extruderList:
             return 0
 
+        if self._edge_disallowed_size is not None:
+            return self._edge_disallowed_size
+
         container_stack = self._global_container_stack
         used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
 
@@ -1139,8 +1143,8 @@ class BuildVolume(SceneNode):
         # Now combine our different pieces of data to get the final border size.
         # Support expansion is added to the bed adhesion, since the bed adhesion goes around support.
         # Support expansion is added to farthest shield distance, since the shields go around support.
-        border_size = max(move_from_wall_radius, support_expansion + farthest_shield_distance, support_expansion + bed_adhesion_size)
-        return border_size
+        self._edge_disallowed_size = max(move_from_wall_radius, support_expansion + farthest_shield_distance, support_expansion + bed_adhesion_size)
+        return self._edge_disallowed_size
 
     def _clamp(self, value, min_value, max_value):
         return max(min(value, max_value), min_value)

+ 19 - 5
cura/Machines/MachineErrorChecker.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2020 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 import time
@@ -14,6 +14,7 @@ from UM.Settings.Validator import ValidatorState
 
 import cura.CuraApplication
 
+
 class MachineErrorChecker(QObject):
     """This class performs setting error checks for the currently active machine.
 
@@ -50,6 +51,8 @@ class MachineErrorChecker(QObject):
         self._error_check_timer.setInterval(100)
         self._error_check_timer.setSingleShot(True)
 
+        self._keys_to_check = set()  # type: Set[str]
+
     def initialize(self) -> None:
         self._error_check_timer.timeout.connect(self._rescheduleCheck)
 
@@ -103,6 +106,7 @@ class MachineErrorChecker(QObject):
 
         if property_name != "value":
             return
+        self._keys_to_check.add(key)
         self.startErrorCheck()
 
     def startErrorCheck(self, *args: Any) -> None:
@@ -140,7 +144,10 @@ class MachineErrorChecker(QObject):
         # Populate the (stack, key) tuples to check
         self._stacks_and_keys_to_check = deque()
         for stack in global_stack.extruderList:
-            for key in stack.getAllKeys():
+            if not self._keys_to_check:
+                self._keys_to_check = stack.getAllKeys()
+
+            for key in self._keys_to_check:
                 self._stacks_and_keys_to_check.append((stack, key))
 
         self._application.callLater(self._checkStack)
@@ -181,18 +188,25 @@ class MachineErrorChecker(QObject):
                 validator = validator_type(key)
                 validation_state = validator(stack)
         if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError, ValidatorState.Invalid):
-            # Finish
-            self._setResult(True)
+            # Since we don't know if any of the settings we didn't check is has an error value, store the list for the
+            # next check.
+            keys_to_recheck = {setting_key for stack, setting_key in self._stacks_and_keys_to_check}
+            keys_to_recheck.add(key)
+            self._setResult(True, keys_to_recheck = keys_to_recheck)
             return
 
         # Schedule the check for the next key
         self._application.callLater(self._checkStack)
 
-    def _setResult(self, result: bool) -> None:
+    def _setResult(self, result: bool, keys_to_recheck = None) -> None:
         if result != self._has_errors:
             self._has_errors = result
             self.hasErrorUpdated.emit()
             self._machine_manager.stacksValidationChanged.emit()
+        if keys_to_recheck is None:
+            self._keys_to_check = set()
+        else:
+            self._keys_to_check = keys_to_recheck
         self._need_to_check = False
         self._check_in_progress = False
         self.needToWaitForResultChanged.emit()

+ 4 - 1
cura/MultiplyObjectsJob.py

@@ -4,6 +4,8 @@
 import copy
 from typing import List
 
+from PyQt5.QtCore import QCoreApplication
+
 from UM.Job import Job
 from UM.Operations.GroupedOperation import GroupedOperation
 from UM.Message import Message
@@ -93,8 +95,9 @@ class MultiplyObjectsJob(Job):
                 nodes.append(new_node)
                 current_progress += 1
                 status_message.setProgress((current_progress / total_progress) * 100)
+                QCoreApplication.processEvents()
                 Job.yieldThread()
-
+            QCoreApplication.processEvents()
             Job.yieldThread()
 
         if nodes:

+ 1 - 1
cura/PickingPass.py

@@ -54,7 +54,7 @@ class PickingPass(RenderPass):
         # Fill up the batch with objects that can be sliced. `
         for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
             if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
-                batch.addItem(node.getWorldTransformation(), node.getMeshData())
+                batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData())
 
         self.bind()
         batch.render(self._scene.getActiveCamera())

+ 2 - 2
cura/PreviewPass.py

@@ -114,12 +114,12 @@ class PreviewPass(RenderPass):
                             1.0]
                         uniforms["diffuse_color"] = prettier_color(diffuse_color)
                         uniforms["diffuse_color_2"] = diffuse_color2
-                        batch_support_mesh.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
+                        batch_support_mesh.addItem(node.getWorldTransformation(copy = False), node.getMeshData(), uniforms = uniforms)
                     else:
                         # Normal scene node
                         uniforms = {}
                         uniforms["diffuse_color"] = prettier_color(cast(CuraSceneNode, node).getDiffuseColor())
-                        batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
+                        batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData(), uniforms = uniforms)
 
         self.bind()
 

+ 6 - 11
cura/Scene/ConvexHullDecorator.py

@@ -53,6 +53,8 @@ class ConvexHullDecorator(SceneNodeDecorator):
         CuraApplication.getInstance().getController().toolOperationStarted.connect(self._onChanged)
         CuraApplication.getInstance().getController().toolOperationStopped.connect(self._onChanged)
 
+        self._root = Application.getInstance().getController().getScene().getRoot()
+
         self._onGlobalStackChanged()
 
     def createRecomputeConvexHullTimer(self) -> None:
@@ -198,23 +200,16 @@ class ConvexHullDecorator(SceneNodeDecorator):
             CuraApplication.getInstance().callLater(self.recomputeConvexHullDelayed)
 
     def recomputeConvexHull(self) -> None:
-        controller = Application.getInstance().getController()
-        root = controller.getScene().getRoot()
-        if self._node is None or controller.isToolOperationActive() or not self.__isDescendant(root, self._node):
-            # If the tool operation is still active, we need to compute the convex hull later after the controller is
-            # no longer active.
-            if controller.isToolOperationActive():
-                self.recomputeConvexHullDelayed()
-                return
-
+        if self._node is None or not self.__isDescendant(self._root, self._node):
             if self._convex_hull_node:
+                # Convex hull node still exists, but the node is removed or no longer in the scene.
                 self._convex_hull_node.setParent(None)
                 self._convex_hull_node = None
             return
 
         if self._convex_hull_node:
             self._convex_hull_node.setParent(None)
-        hull_node = ConvexHullNode.ConvexHullNode(self._node, self.getPrintingArea(), self._raft_thickness, root)
+        hull_node = ConvexHullNode.ConvexHullNode(self._node, self.getPrintingArea(), self._raft_thickness, self._root)
         self._convex_hull_node = hull_node
 
     def _onSettingValueChanged(self, key: str, property_name: str) -> None:
@@ -273,7 +268,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
             if mesh is None:
                 return Polygon([])  # Node has no mesh data, so just return an empty Polygon.
 
-            world_transform = self._node.getWorldTransformation()
+            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:

+ 21 - 18
cura/Scene/ConvexHullNode.py

@@ -57,13 +57,20 @@ class ConvexHullNode(SceneNode):
         self._hull = hull
         if self._hull:
             hull_mesh_builder = MeshBuilder()
+            if self._thickness == 0:
+                if hull_mesh_builder.addConvexPolygon(
+                    self._hull.getPoints()[::],  # bottom layer is reversed
+                    self._mesh_height, color = self._color):
 
-            if hull_mesh_builder.addConvexPolygonExtrusion(
-                self._hull.getPoints()[::-1],  # bottom layer is reversed
-                self._mesh_height - thickness, self._mesh_height, color = self._color):
+                    hull_mesh = hull_mesh_builder.build()
+                    self.setMeshData(hull_mesh)
+            else:
+                if hull_mesh_builder.addConvexPolygonExtrusion(
+                    self._hull.getPoints()[::-1],  # bottom layer is reversed
+                    self._mesh_height - thickness, self._mesh_height, color = self._color):
 
-                hull_mesh = hull_mesh_builder.build()
-                self.setMeshData(hull_mesh)
+                    hull_mesh = hull_mesh_builder.build()
+                    self.setMeshData(hull_mesh)
 
     def getHull(self):
         return self._hull
@@ -79,15 +86,15 @@ class ConvexHullNode(SceneNode):
             ConvexHullNode.shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "transparent_object.shader"))
             ConvexHullNode.shader.setUniformValue("u_diffuseColor", self._color)
             ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
-
-        if self.getParent():
-            if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate:
-                # The object itself (+ adhesion in one-at-a-time mode)
-                renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
-                if self._convex_hull_head_mesh:
-                    # The full head. Rendered as a hint to the user: If this area overlaps another object A; this object
-                    # cannot be printed after A, because the head would hit A while printing the current object
-                    renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
+        batch = renderer.getNamedBatch("convex_hull_node")
+        if not batch:
+            batch = renderer.createRenderBatch(transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
+            renderer.addRenderBatch(batch, name = "convex_hull_node")
+        batch.addItem(self.getWorldTransformation(copy = False), self.getMeshData())
+        if self._convex_hull_head_mesh:
+            # The full head. Rendered as a hint to the user: If this area overlaps another object A; this object
+            # cannot be printed after A, because the head would hit A while printing the current object
+            renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
 
         return True
 
@@ -97,7 +104,3 @@ class ConvexHullNode(SceneNode):
             convex_hull_head_builder = MeshBuilder()
             convex_hull_head_builder.addConvexPolygon(convex_hull_head.getPoints(), self._mesh_height - self._thickness)
             self._convex_hull_head_mesh = convex_hull_head_builder.build()
-
-        if not node:
-            return
-

+ 2 - 2
cura/Scene/CuraSceneNode.py

@@ -118,7 +118,7 @@ class CuraSceneNode(SceneNode):
 
         self._aabb = None
         if self._mesh_data:
-            self._aabb = self._mesh_data.getExtents(self.getWorldTransformation())
+            self._aabb = self._mesh_data.getExtents(self.getWorldTransformation(copy = False))
         else:  # If there is no mesh_data, use a bounding box that encompasses the local (0,0,0)
             position = self.getWorldPosition()
             self._aabb = AxisAlignedBox(minimum = position, maximum = position)
@@ -139,7 +139,7 @@ class CuraSceneNode(SceneNode):
         """Taken from SceneNode, but replaced SceneNode with CuraSceneNode"""
 
         copy = CuraSceneNode(no_setting_override = True)  # Setting override will be added later
-        copy.setTransformation(self.getLocalTransformation())
+        copy.setTransformation(self.getLocalTransformation(copy= False))
         copy.setMeshData(self._mesh_data)
         copy.setVisible(cast(bool, deepcopy(self._visible, memo)))
         copy._selectable = cast(bool, deepcopy(self._selectable, memo))

+ 31 - 30
cura/Settings/ExtruderManager.py

@@ -204,49 +204,50 @@ class ExtruderManager(QObject):
         # If no extruders are registered in the extruder manager yet, return an empty array
         if len(self.extruderIds) == 0:
             return []
+        number_active_extruders = len([extruder for extruder in self.getActiveExtruderStacks() if extruder.isEnabled])
 
         # Get the extruders of all printable meshes in the scene
-        meshes = [node for node in DepthFirstIterator(scene_root) if isinstance(node, SceneNode) and node.isSelectable()] #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+        nodes = [node for node in DepthFirstIterator(scene_root) if node.isSelectable() and not node.callDecoration("isAntiOverhangMesh") and not  node.callDecoration("isSupportMesh")] #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
 
-        # Exclude anti-overhang meshes
-        mesh_list = []
-        for mesh in meshes:
-            stack = mesh.callDecoration("getStack")
-            if stack is not None and (stack.getProperty("anti_overhang_mesh", "value") or stack.getProperty("support_mesh", "value")):
-                continue
-            mesh_list.append(mesh)
-
-        for mesh in mesh_list:
-            extruder_stack_id = mesh.callDecoration("getActiveExtruder")
+        for node in nodes:
+            extruder_stack_id = node.callDecoration("getActiveExtruder")
             if not extruder_stack_id:
                 # No per-object settings for this node
                 extruder_stack_id = self.extruderIds["0"]
             used_extruder_stack_ids.add(extruder_stack_id)
 
+            if len(used_extruder_stack_ids) == number_active_extruders:
+                # We're already done. Stop looking.
+                # Especially with a lot of models on the buildplate, this will speed up things rather dramatically.
+                break
+
             # Get whether any of them use support.
-            stack_to_use = mesh.callDecoration("getStack")  # if there is a per-mesh stack, we use it
+            stack_to_use = node.callDecoration("getStack")  # if there is a per-mesh stack, we use it
             if not stack_to_use:
                 # if there is no per-mesh stack, we use the build extruder for this mesh
                 stack_to_use = container_registry.findContainerStacks(id = extruder_stack_id)[0]
 
-            support_enabled |= stack_to_use.getProperty("support_enable", "value")
-            support_bottom_enabled |= stack_to_use.getProperty("support_bottom_enable", "value")
-            support_roof_enabled |= stack_to_use.getProperty("support_roof_enable", "value")
-
-            # Check limit to extruders
-            limit_to_extruder_feature_list = ["wall_0_extruder_nr",
-                                              "wall_x_extruder_nr",
-                                              "roofing_extruder_nr",
-                                              "top_bottom_extruder_nr",
-                                              "infill_extruder_nr",
-                                              ]
-            for extruder_nr_feature_name in limit_to_extruder_feature_list:
-                extruder_nr = int(global_stack.getProperty(extruder_nr_feature_name, "value"))
-                if extruder_nr == -1:
-                    continue
-                if str(extruder_nr) not in self.extruderIds:
-                    extruder_nr = int(self._application.getMachineManager().defaultExtruderPosition)
-                used_extruder_stack_ids.add(self.extruderIds[str(extruder_nr)])
+            if not support_enabled:
+                support_enabled |= stack_to_use.getProperty("support_enable", "value")
+            if not support_bottom_enabled:
+                support_bottom_enabled |= stack_to_use.getProperty("support_bottom_enable", "value")
+            if not support_roof_enabled:
+                support_roof_enabled |= stack_to_use.getProperty("support_roof_enable", "value")
+
+        # Check limit to extruders
+        limit_to_extruder_feature_list = ["wall_0_extruder_nr",
+                                          "wall_x_extruder_nr",
+                                          "roofing_extruder_nr",
+                                          "top_bottom_extruder_nr",
+                                          "infill_extruder_nr",
+                                          ]
+        for extruder_nr_feature_name in limit_to_extruder_feature_list:
+            extruder_nr = int(global_stack.getProperty(extruder_nr_feature_name, "value"))
+            if extruder_nr == -1:
+                continue
+            if str(extruder_nr) not in self.extruderIds:
+                extruder_nr = int(self._application.getMachineManager().defaultExtruderPosition)
+            used_extruder_stack_ids.add(self.extruderIds[str(extruder_nr)])
 
         # Check support extruders
         if support_enabled:

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