Browse Source

CURA-5090 speedups by using qtimers on updating mostly visual elements

Jack Ha 7 years ago
parent
commit
e3dd7a449d

+ 1 - 1
cura/BuildVolume.py

@@ -136,6 +136,7 @@ class BuildVolume(SceneNode):
                 if active_extruder_changed is not None:
                     node.callDecoration("getActiveExtruderChangedSignal").disconnect(self._updateDisallowedAreasAndRebuild)
                 node.decoratorsChanged.disconnect(self._updateNodeListeners)
+            self._updateDisallowedAreasAndRebuild()  # make sure we didn't miss anything before we updated the node listeners
 
             self._scene_objects = new_scene_objects
             self._onSettingPropertyChanged("print_sequence", "value")  # Create fake event, so right settings are triggered.
@@ -150,7 +151,6 @@ class BuildVolume(SceneNode):
         active_extruder_changed = node.callDecoration("getActiveExtruderChangedSignal")
         if active_extruder_changed is not None:
             active_extruder_changed.connect(self._updateDisallowedAreasAndRebuild)
-            self._updateDisallowedAreasAndRebuild()
 
     def setWidth(self, width):
         if width is not None:

+ 12 - 3
cura/CuraApplication.py

@@ -4,7 +4,7 @@
 #Type hinting.
 from typing import Dict
 
-from PyQt5.QtCore import QObject
+from PyQt5.QtCore import QObject, QTimer
 from PyQt5.QtNetwork import QLocalServer
 from PyQt5.QtNetwork import QLocalSocket
 
@@ -283,10 +283,15 @@ class CuraApplication(QtApplication):
         self._preferred_mimetype = ""
         self._i18n_catalog = i18nCatalog("cura")
 
-        self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
+        self._update_platform_activity_timer = QTimer()
+        self._update_platform_activity_timer.setInterval(500)
+        self._update_platform_activity_timer.setSingleShot(True)
+        self._update_platform_activity_timer.timeout.connect(self.updatePlatformActivity)
+
+        self.getController().getScene().sceneChanged.connect(self.updatePlatformActivityDelayed)
         self.getController().toolOperationStopped.connect(self._onToolOperationStopped)
         self.getController().contextMenuRequested.connect(self._onContextMenuRequested)
-        self.getCuraSceneController().activeBuildPlateChanged.connect(self.updatePlatformActivity)
+        self.getCuraSceneController().activeBuildPlateChanged.connect(self.updatePlatformActivityDelayed)
 
         Resources.addType(self.ResourceTypes.QmlFiles, "qml")
         Resources.addType(self.ResourceTypes.Firmware, "firmware")
@@ -1061,6 +1066,10 @@ class CuraApplication(QtApplication):
     def getSceneBoundingBoxString(self):
         return self._i18n_catalog.i18nc("@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm.", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()}
 
+    def updatePlatformActivityDelayed(self, node = None):
+        if node is not None and node.getMeshData() is not None:
+            self._update_platform_activity_timer.start()
+
     ##  Update scene bounding box for current build plate
     def updatePlatformActivity(self, node = None):
         count = 0

+ 10 - 2
cura/Machines/Models/MultiBuildPlateModel.py

@@ -1,7 +1,7 @@
 # Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
-from PyQt5.QtCore import pyqtSignal, pyqtProperty
+from PyQt5.QtCore import QTimer, pyqtSignal, pyqtProperty
 
 from UM.Application import Application
 from UM.Scene.Selection import Selection
@@ -21,8 +21,13 @@ class MultiBuildPlateModel(ListModel):
     def __init__(self, parent = None):
         super().__init__(parent)
 
+        self._update_timer = QTimer()
+        self._update_timer.setInterval(100)
+        self._update_timer.setSingleShot(True)
+        self._update_timer.timeout.connect(self._updateSelectedObjectBuildPlateNumbers)
+
         self._application = Application.getInstance()
-        self._application.getController().getScene().sceneChanged.connect(self._updateSelectedObjectBuildPlateNumbers)
+        self._application.getController().getScene().sceneChanged.connect(self._updateSelectedObjectBuildPlateNumbersDelayed)
         Selection.selectionChanged.connect(self._updateSelectedObjectBuildPlateNumbers)
 
         self._max_build_plate = 1  # default
@@ -45,6 +50,9 @@ class MultiBuildPlateModel(ListModel):
     def activeBuildPlate(self):
         return self._active_build_plate
 
+    def _updateSelectedObjectBuildPlateNumbersDelayed(self, *args):
+        self._update_timer.start()
+
     def _updateSelectedObjectBuildPlateNumbers(self, *args):
         result = set()
         for node in Selection.getAllSelectedObjects():

+ 15 - 2
cura/ObjectsModel.py

@@ -1,3 +1,8 @@
+# Copyright (c) 2018 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.Qt.ListModel import ListModel
 from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@@ -14,8 +19,13 @@ class ObjectsModel(ListModel):
     def __init__(self):
         super().__init__()
 
-        Application.getInstance().getController().getScene().sceneChanged.connect(self._update)
-        Preferences.getInstance().preferenceChanged.connect(self._update)
+        Application.getInstance().getController().getScene().sceneChanged.connect(self._updateDelayed)
+        Preferences.getInstance().preferenceChanged.connect(self._updateDelayed)
+
+        self._update_timer = QTimer()
+        self._update_timer.setInterval(100)
+        self._update_timer.setSingleShot(True)
+        self._update_timer.timeout.connect(self._update)
 
         self._build_plate_number = -1
 
@@ -23,6 +33,9 @@ class ObjectsModel(ListModel):
         self._build_plate_number = nr
         self._update()
 
+    def _updateDelayed(self, *args):
+        self._update_timer.start()
+
     def _update(self, *args):
         nodes = []
         filter_current_build_plate = Preferences.getInstance().getValue("view/filter_current_build_plate")

+ 20 - 1
cura/Scene/ConvexHullDecorator.py

@@ -1,6 +1,8 @@
 # Copyright (c) 2016 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
@@ -22,6 +24,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
 
         self._global_stack = None
 
+        # Make sure the timer is created on the main thread
+        self._recompute_convex_hull_timer = None
+        Application.getInstance().callLater(self.createRecomputeConvexHullTimer)
+
         self._raft_thickness = 0.0
         # For raft thickness, DRY
         self._build_volume = Application.getInstance().getBuildVolume()
@@ -33,6 +39,12 @@ class ConvexHullDecorator(SceneNodeDecorator):
 
         self._onGlobalStackChanged()
 
+    def createRecomputeConvexHullTimer(self):
+        self._recompute_convex_hull_timer = QTimer()
+        self._recompute_convex_hull_timer.setInterval(200)
+        self._recompute_convex_hull_timer.setSingleShot(True)
+        self._recompute_convex_hull_timer.timeout.connect(self.recomputeConvexHull)
+
     def setNode(self, node):
         previous_node = self._node
         # Disconnect from previous node signals
@@ -99,6 +111,12 @@ class ConvexHullDecorator(SceneNodeDecorator):
                 return self._compute2DConvexHull()
         return None
 
+    def recomputeConvexHullDelayed(self):
+        if self._recompute_convex_hull_timer is not None:
+            self._recompute_convex_hull_timer.start()
+        else:
+            self.recomputeConvexHull()
+
     def recomputeConvexHull(self):
         controller = Application.getInstance().getController()
         root = controller.getScene().getRoot()
@@ -279,7 +297,8 @@ class ConvexHullDecorator(SceneNodeDecorator):
 
     def _onChanged(self, *args):
         self._raft_thickness = self._build_volume.getRaftThickness()
-        self.recomputeConvexHull()
+        if not args or args[0] == self._node:
+            self.recomputeConvexHullDelayed()
 
     def _onGlobalStackChanged(self):
         if self._global_stack:

+ 4 - 3
plugins/SimulationView/SimulationView.py

@@ -158,9 +158,10 @@ class SimulationView(View):
         return self._nozzle_node
 
     def _onSceneChanged(self, node):
-        self.setActivity(False)
-        self.calculateMaxLayers()
-        self.calculateMaxPathsOnLayer(self._current_layer_num)
+        if node.getMeshData() is not None:
+            self.setActivity(False)
+            self.calculateMaxLayers()
+            self.calculateMaxPathsOnLayer(self._current_layer_num)
 
     def isBusy(self):
         return self._busy