From 1aba1cfe6ab319c31d17f215c77afa278bee258a Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Mar 2018 16:30:11 +0100 Subject: CURA-4557 model checker is now a tool, click to activate --- plugins/ModelChecker/ModelChecker.py | 102 ++++++++++++++++++----------------- plugins/ModelChecker/__init__.py | 28 +++++----- plugins/ModelChecker/plugin.json | 6 +-- 3 files changed, 69 insertions(+), 67 deletions(-) (limited to 'plugins/ModelChecker') diff --git a/plugins/ModelChecker/ModelChecker.py b/plugins/ModelChecker/ModelChecker.py index b4c79387a8..0ae9cc5d01 100644 --- a/plugins/ModelChecker/ModelChecker.py +++ b/plugins/ModelChecker/ModelChecker.py @@ -5,7 +5,7 @@ from PyQt5.QtCore import QTimer from cura.Scene.CuraSceneNode import CuraSceneNode from UM.Application import Application -from UM.Extension import Extension +from UM.Tool import Tool from UM.Message import Message from UM.i18n import i18nCatalog from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -17,31 +17,20 @@ SHRINKAGE_THRESHOLD = 0.5 WARNING_SIZE_XY = 150 WARNING_SIZE_Z = 100 -MESSAGE_LIFETIME = 10 - -class ModelChecker(Extension): +class ModelChecker(Tool): def __init__(self): super().__init__() - self._update_timer = QTimer() - self._update_timer.setInterval(2000) - self._update_timer.setSingleShot(True) - self._update_timer.timeout.connect(self.checkObjects) - - self._nodes_to_check = set() - - self._warning_model_names = set() # Collect the names of models so we show the next warning with timeout - - Application.getInstance().initializationFinished.connect(self.bindSignals) + self._last_known_tool_id = None - def bindSignals(self): - Application.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged) - Application.getInstance().getMachineManager().rootMaterialChanged.connect(self._checkAllSliceableNodes) + self._controller.activeToolChanged.connect(self._onActiveToolChanged) - def checkObjects(self): + def checkObjects(self, nodes_to_check): warning_nodes = [] global_container_stack = Application.getInstance().getGlobalContainerStack() + if global_container_stack is None: + return [] material_shrinkage = {} need_check = False @@ -59,42 +48,57 @@ class ModelChecker(Extension): return # Check node material shrinkage and bounding box size - for node in self._nodes_to_check: + for node in nodes_to_check: node_extruder_position = node.callDecoration("getActiveExtruderPosition") if material_shrinkage[node_extruder_position] > SHRINKAGE_THRESHOLD: bbox = node.getBoundingBox() if bbox.width >= WARNING_SIZE_XY or bbox.depth >= WARNING_SIZE_XY or bbox.height >= WARNING_SIZE_Z: warning_nodes.append(node) - self._nodes_to_check = set() - - # Display warning message - if warning_nodes: - message_lifetime = MESSAGE_LIFETIME - for node in warning_nodes: - if node.getName() not in self._warning_model_names: - message_lifetime = 0 # infinite - self._warning_model_names.add(node.getName()) - caution_message = Message(catalog.i18nc( - "@info:warning", - "Some models may not be printed optimal due to object size and material chosen [%s].\n" - "Tips that may be useful to improve the print quality:\n" - "1) Use rounded corners\n" - "2) Turn the fan off (only if the are no tiny details on the model)\n" - "3) Use a different material") % ", ".join([n.getName() for n in warning_nodes]), - lifetime = message_lifetime, - title = catalog.i18nc("@info:title", "Model Warning")) - caution_message.show() - - def _onSceneChanged(self, source): - if isinstance(source, CuraSceneNode) and source.callDecoration("isSliceable"): - self._nodes_to_check.add(source) - self._update_timer.start() - - def _checkAllSliceableNodes(self, *args): - # Add all scene nodes + + return warning_nodes + + def checkAllSliceableNodes(self): + # Add all sliceable scene nodes to check scene = Application.getInstance().getController().getScene() + nodes_to_check = [] for node in DepthFirstIterator(scene.getRoot()): if node.callDecoration("isSliceable"): - self._nodes_to_check.add(node) - if self._nodes_to_check: - self._update_timer.start() + nodes_to_check.append(node) + return self.checkObjects(nodes_to_check) + + ## Display warning message + def showWarningMessage(self, warning_nodes): + caution_message = Message(catalog.i18nc( + "@info:status", + "Some models may not be printed optimal due to object size and material chosen [%s].\n" + "Tips that may be useful to improve the print quality:\n" + "1) Use rounded corners\n" + "2) Turn the fan off (only if the are no tiny details on the model)\n" + "3) Use a different material") % ", ".join([n.getName() for n in warning_nodes]), + lifetime = 0, + title = catalog.i18nc("@info:title", "Model Checker Warning")) + caution_message.show() + + def showHappyMessage(self): + happy_message = Message(catalog.i18nc( + "@info:status", + "The Model Checker did not detect any problems with your model / print setup combination."), + lifetime = 5, + title = catalog.i18nc("@info:title", "Model Checker")) + happy_message.show() + + def _onActiveToolChanged(self): + active_tool = self.getController().getActiveTool() + if active_tool is None: + return + active_tool_id = active_tool.getPluginId() + if active_tool_id != self.getPluginId(): + self._last_known_tool_id = active_tool_id + if active_tool_id == self.getPluginId(): + warning_nodes = self.checkAllSliceableNodes() + if warning_nodes: + self.showWarningMessage(warning_nodes) + else: + self.showHappyMessage() + if self._last_known_tool_id is not None: + self.getController().setActiveTool(self._last_known_tool_id) diff --git a/plugins/ModelChecker/__init__.py b/plugins/ModelChecker/__init__.py index ae4aa7d0c0..b2b8587a7a 100644 --- a/plugins/ModelChecker/__init__.py +++ b/plugins/ModelChecker/__init__.py @@ -3,21 +3,19 @@ from . import ModelChecker -## Defines additional metadata for the plug-in. -# -# Some types of plug-ins require additional metadata, such as which file types -# they are able to read or the name of the tool they define. In the case of -# the "Extension" type plug-in, there is no additional metadata though. +from UM.i18n import i18nCatalog +i18n_catalog = i18nCatalog("uranium") + + def getMetaData(): - return {} + return { + "tool": { + "name": i18n_catalog.i18nc("@label", "Model Checker"), + "description": i18n_catalog.i18nc("@info:tooltip", "Checks models and print configuration for possible printing issues and give suggestions."), + "icon": "model_checker.svg", + "weight": 10 + } + } -## Lets Uranium know that this plug-in exists. -# -# This is called when starting the application to find out which plug-ins -# exist and what their types are. We need to return a dictionary mapping from -# strings representing plug-in types (in this case "extension") to objects -# that inherit from PluginObject. -# -# \param app The application that the plug-in needs to register with. def register(app): - return {"extension": ModelChecker.ModelChecker()} + return { "tool": ModelChecker.ModelChecker() } diff --git a/plugins/ModelChecker/plugin.json b/plugins/ModelChecker/plugin.json index db8819a325..a9190adcaa 100644 --- a/plugins/ModelChecker/plugin.json +++ b/plugins/ModelChecker/plugin.json @@ -1,8 +1,8 @@ { "name": "Model Checker", - "author": "Ultimaker", + "author": "Ultimaker B.V.", "version": "0.1", "api": 4, - "description": "Checks models for possible printing issues and give suggestions.", - "catalog": "cura" + "description": "Checks models and print configuration for possible printing issues and give suggestions.", + "i18n-catalog": "cura" } -- cgit v1.2.3