mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
CURA-4557 it's now a small button next to the job spec when one of the warping materials is selected
This commit is contained in:
parent
25bf7a6aba
commit
d8d226c0d6
6 changed files with 190 additions and 57 deletions
|
@ -1,13 +1,16 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, pyqtProperty
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Tool import Tool
|
||||
from UM.Extension import Extension
|
||||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
@ -17,35 +20,34 @@ SHRINKAGE_THRESHOLD = 0.5
|
|||
WARNING_SIZE_XY = 150
|
||||
WARNING_SIZE_Z = 100
|
||||
|
||||
# Use this when actual shrinkage data is not in fdm_materials yet
|
||||
MATERIALS_LOOKUP = {
|
||||
"generic_abs": 1,
|
||||
"generic_pc": 1,
|
||||
"generic_pp": 1,
|
||||
"generic_cpe_plus": 1
|
||||
}
|
||||
|
||||
|
||||
class ModelChecker(QObject, Extension):
|
||||
|
||||
needCheckChanged = pyqtSignal()
|
||||
|
||||
class ModelChecker(Tool):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self._last_known_tool_id = None
|
||||
self._button_view = None
|
||||
self._need_checks = False
|
||||
|
||||
self._controller.activeToolChanged.connect(self._onActiveToolChanged)
|
||||
Application.getInstance().initializationFinished.connect(self.bindSignals)
|
||||
|
||||
def bindSignals(self):
|
||||
Application.getInstance().getMachineManager().rootMaterialChanged.connect(self._onChanged)
|
||||
|
||||
def checkObjectsForShrinkage(self, nodes_to_check):
|
||||
material_shrinkage = self.getMaterialShrinkage()
|
||||
|
||||
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
|
||||
|
||||
# Get all shrinkage values of materials used
|
||||
for extruder_position, extruder in global_container_stack.extruders.items():
|
||||
shrinkage = extruder.material.getProperty("material_shrinkage_percentage", "value")
|
||||
if shrinkage is None:
|
||||
shrinkage = 0
|
||||
if shrinkage > SHRINKAGE_THRESHOLD:
|
||||
need_check = True
|
||||
material_shrinkage[extruder_position] = shrinkage
|
||||
|
||||
# Check if we can bail out fast
|
||||
if not need_check:
|
||||
return
|
||||
|
||||
# Check node material shrinkage and bounding box size
|
||||
for node in nodes_to_check:
|
||||
|
@ -64,7 +66,7 @@ class ModelChecker(Tool):
|
|||
for node in DepthFirstIterator(scene.getRoot()):
|
||||
if node.callDecoration("isSliceable"):
|
||||
nodes_to_check.append(node)
|
||||
return self.checkObjects(nodes_to_check)
|
||||
return self.checkObjectsForShrinkage(nodes_to_check)
|
||||
|
||||
## Display warning message
|
||||
def showWarningMessage(self, warning_nodes):
|
||||
|
@ -82,23 +84,77 @@ class ModelChecker(Tool):
|
|||
def showHappyMessage(self):
|
||||
happy_message = Message(catalog.i18nc(
|
||||
"@info:status",
|
||||
"The Model Checker did not detect any problems with your model / print setup combination."),
|
||||
"The Model Checker did not detect any problems with your model / chosen materials 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():
|
||||
## Creates the view used by show popup. The view is saved because of the fairly aggressive garbage collection.
|
||||
def _createView(self):
|
||||
Logger.log("d", "Creating model checker view.")
|
||||
|
||||
# Create the plugin dialog component
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath("ModelChecker"), "ModelChecker.qml")
|
||||
self._button_view = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
|
||||
# The qml is only the button
|
||||
Application.getInstance().addAdditionalComponent("jobSpecsButton", self._button_view)
|
||||
|
||||
Logger.log("d", "Model checker view created.")
|
||||
|
||||
def _onChanged(self, *args):
|
||||
if self._button_view is None:
|
||||
self._createView()
|
||||
old_need_checks = self._need_checks
|
||||
self._need_checks = self.calculateNeedCheck()
|
||||
if old_need_checks != self._need_checks:
|
||||
self.needCheckChanged.emit()
|
||||
|
||||
@pyqtSlot()
|
||||
def runChecks(self):
|
||||
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)
|
||||
|
||||
# TODO: use this if branch feature_model_check is merged in fdm_materials to master
|
||||
# def getMaterialShrinkage(self):
|
||||
# global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
# if global_container_stack is None:
|
||||
# return {}
|
||||
#
|
||||
# material_shrinkage = {}
|
||||
# # Get all shrinkage values of materials used
|
||||
# for extruder_position, extruder in global_container_stack.extruders.items():
|
||||
# shrinkage = extruder.material.getProperty("material_shrinkage_percentage", "value")
|
||||
# if shrinkage is None:
|
||||
# shrinkage = 0
|
||||
# material_shrinkage[extruder_position] = shrinkage
|
||||
# return material_shrinkage
|
||||
|
||||
def getMaterialShrinkage(self):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack is None:
|
||||
return {}
|
||||
|
||||
material_shrinkage = {}
|
||||
# Get all shrinkage values of materials used
|
||||
for extruder_position, extruder in global_container_stack.extruders.items():
|
||||
base_file = extruder.material.getMetaDataEntry("base_file")
|
||||
shrinkage = MATERIALS_LOOKUP.get(base_file, 0)
|
||||
material_shrinkage[extruder_position] = shrinkage
|
||||
return material_shrinkage
|
||||
|
||||
@pyqtProperty(bool, notify = needCheckChanged)
|
||||
def needCheck(self):
|
||||
return self._need_checks
|
||||
|
||||
def calculateNeedCheck(self):
|
||||
need_check = False
|
||||
|
||||
for shrinkage in self.getMaterialShrinkage().values():
|
||||
if shrinkage > SHRINKAGE_THRESHOLD:
|
||||
need_check = True
|
||||
|
||||
return need_check
|
||||
|
|
47
plugins/ModelChecker/ModelChecker.qml
Normal file
47
plugins/ModelChecker/ModelChecker.qml
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
Button
|
||||
{
|
||||
id: modelCheckerButton
|
||||
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
|
||||
visible: manager.needCheck
|
||||
tooltip: catalog.i18nc("@info:tooltip", "Check current setup for known problems.")
|
||||
onClicked: manager.runChecks()
|
||||
|
||||
//anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
|
||||
//anchors.right: parent.right
|
||||
//anchors.verticalCenter: parent.verticalCenter
|
||||
width: UM.Theme.getSize("save_button_specs_icons").width
|
||||
height: UM.Theme.getSize("save_button_specs_icons").height
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Item
|
||||
{
|
||||
UM.RecolorImage
|
||||
{
|
||||
width: UM.Theme.getSize("save_button_specs_icons").width;
|
||||
height: UM.Theme.getSize("save_button_specs_icons").height;
|
||||
sourceSize.width: width;
|
||||
sourceSize.height: width;
|
||||
color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene");
|
||||
source: "model_checker.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,14 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# This example is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import ModelChecker
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("uranium")
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData():
|
||||
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
|
||||
}
|
||||
}
|
||||
return {}
|
||||
|
||||
def register(app):
|
||||
return { "tool": ModelChecker.ModelChecker() }
|
||||
return { "extension": ModelChecker.ModelChecker() }
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="30px" height="30px" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>ModelChecker</title>
|
||||
<g id="ModelChecker" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<polygon id="Rectangle-3" fill="#000000" points="19 11 30 8 30 24 19 27"></polygon>
|
||||
<g id="ModelChecker" stroke="none" fill="none">
|
||||
<polygon fill="#000000" points="19 11 30 8 30 24 19 27"></polygon>
|
||||
<path d="M10,19 C5.581722,19 2,15.418278 2,11 C2,6.581722 5.581722,3 10,3 C14.418278,3 18,6.581722 18,11 C18,15.418278 14.418278,19 10,19 Z M10,17 C13.3137085,17 16,14.3137085 16,11 C16,7.6862915 13.3137085,5 10,5 C6.6862915,5 4,7.6862915 4,11 C4,14.3137085 6.6862915,17 10,17 Z" id="Combined-Shape" fill="#000000"></path>
|
||||
<polygon id="Polygon" fill="#000000" points="4.2 15 6 16.8 1.8 21 0 19.2"></polygon>
|
||||
<polygon fill="#000000" points="4.2 15 6 16.8 1.8 21 0 19.2"></polygon>
|
||||
<path d="M18.7333454,8.81666365 C18.2107269,6.71940704 16.9524304,4.91317986 15.248379,3.68790525 L18,3 L30,6 L18.7333454,8.81666365 Z M17,16.6573343 L17,27 L6,24 L6,19.0644804 C7.20495897,19.6632939 8.56315852,20 10,20 C12.8272661,20 15.3500445,18.6963331 17,16.6573343 Z" id="Combined-Shape" fill="#000000"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -124,15 +124,50 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: additionalComponentsRow
|
||||
anchors.top: jobNameRow.bottom
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: boundingSpec
|
||||
anchors.top: jobNameRow.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.right: additionalComponentsRow.left
|
||||
anchors.rightMargin:
|
||||
{
|
||||
if (additionalComponentsRow.width > 0)
|
||||
{
|
||||
return UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
height: UM.Theme.getSize("jobspecs_line").height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font: UM.Theme.getFont("small")
|
||||
color: UM.Theme.getColor("text_scene")
|
||||
text: CuraApplication.getSceneBoundingBoxString
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
base.addAdditionalComponents("jobSpecsButton")
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: CuraApplication
|
||||
onAdditionalComponentsChanged: base.addAdditionalComponents("jobSpecsButton")
|
||||
}
|
||||
|
||||
function addAdditionalComponents (areaId) {
|
||||
if(areaId == "jobSpecsButton") {
|
||||
for (var component in CuraApplication.additionalComponents["jobSpecsButton"]) {
|
||||
CuraApplication.additionalComponents["jobSpecsButton"][component].parent = additionalComponentsRow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -411,6 +411,8 @@
|
|||
"save_button_save_to_button": [0.3, 2.7],
|
||||
"save_button_specs_icons": [1.4, 1.4],
|
||||
|
||||
"job_specs_button": [2.7, 2.7],
|
||||
|
||||
"monitor_preheat_temperature_control": [4.5, 2.0],
|
||||
|
||||
"modal_window_minimum": [60.0, 45],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue