From 27de74848d75a9cb2107f0b9a110714c75ec237a Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Wed, 24 Jun 2015 13:44:36 +0200 Subject: [PATCH 01/18] Restyling of the save to toolpath button Fixes #54 --- resources/qml/SaveButton.qml | 301 ++++++++++++++++--------------- resources/qml/Sidebar.qml | 15 +- resources/themes/cura/theme.json | 14 +- 3 files changed, 176 insertions(+), 154 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 07bc0a9ccc..e45d5b07b6 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -8,7 +8,7 @@ import QtQuick.Layouts 1.1 import UM 1.0 as UM -Button { +Rectangle { id: base; property Action saveAction; @@ -16,8 +16,6 @@ Button { property real progress: UM.Backend.progress; Behavior on progress { NumberAnimation { duration: 250; } } - enabled: progress >= 0.95; - property string currentDevice: "local_file" property bool defaultOverride: false; property bool defaultAmbiguous: false; @@ -25,9 +23,6 @@ Button { property variant printDuration: PrintInformation.currentPrintTime; property real printMaterialAmount: PrintInformation.materialAmount; - iconSource: UM.Theme.icons[Printer.outputDevices[base.currentDevice].icon]; - tooltip: Printer.outputDevices[base.currentDevice].description; - Connections { target: Printer; onOutputDevicesChanged: { @@ -51,161 +46,183 @@ Button { } } - style: ButtonStyle { - background: UM.AngledCornerRectangle { - implicitWidth: control.width; - implicitHeight: control.height; + Rectangle{ + id: background + implicitWidth: base.width; + implicitHeight: parent.height; + color: UM.Theme.colors.save_button_background; + border.width: UM.Theme.sizes.save_button_border.width + border.color: UM.Theme.colors.save_button_border - color: UM.Theme.colors.save_button_border; - cornerSize: UM.Theme.sizes.default_margin.width; + Rectangle { + id: infoBox + width: parent.width - UM.Theme.sizes.default_margin.width * 2; + height: UM.Theme.sizes.save_button_slicing_bar.height - UM.AngledCornerRectangle { - anchors.fill: parent; - anchors.margins: UM.Theme.sizes.save_button_border.width; - cornerSize: UM.Theme.sizes.default_margin.width; - color: UM.Theme.colors.save_button; - } + anchors.top: parent.top + anchors.topMargin: UM.Theme.sizes.default_margin.height; + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.default_margin.width; - UM.AngledCornerRectangle { - anchors { - left: parent.left; - top: parent.top; - bottom: parent.bottom; - } - - width: Math.max(parent.height + (parent.width - parent.height) * control.progress, parent.height); - cornerSize: UM.Theme.sizes.default_margin.width; - - color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active; - Behavior on color { ColorAnimation { duration: 50; } } - } - - UM.AngledCornerRectangle { - anchors.left: parent.left; - width: parent.height + UM.Theme.sizes.save_button_border.width; - height: parent.height; - cornerSize: UM.Theme.sizes.default_margin.width; - color: UM.Theme.colors.save_button; - } - - UM.AngledCornerRectangle { - anchors.left: parent.left; - width: parent.height + UM.Theme.sizes.save_button_border.width; - height: parent.height; - cornerSize: UM.Theme.sizes.default_margin.width; - - color: UM.Theme.colors.save_button; - } - - UM.AngledCornerRectangle { - id: icon; - - anchors.left: parent.left; - width: parent.height; - height: parent.height; - cornerSize: UM.Theme.sizes.default_margin.width; - color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active; - Behavior on color { ColorAnimation { duration: 50; } } - - Image { - anchors.centerIn: parent; - - width: UM.Theme.sizes.button_icon.width; - height: UM.Theme.sizes.button_icon.height; - - sourceSize.width: width; - sourceSize.height: height; - - source: control.iconSource; - } - } - } - - label: Column { + border.width: UM.Theme.sizes.save_button_border.width + border.color: UM.Theme.colors.save_button_border + color: UM.Theme.colors.save_button_estimated_text_background; Label { id: label; - anchors.left: parent.left; - anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width; - - color: UM.Theme.colors.save_button_text; - font: UM.Theme.fonts.default; - - text: control.text; + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width; + visible: base.progress >= 0 && base.progress < 0.99 ? false : true + color: UM.Theme.colors.save_button_estimated_text; + font: UM.Theme.fonts.small; + text: + if(base.progress < 0) { + //: Save button label + return qsTr("Please load a 3D model"); + } else if (base.progress < 0.99) { + //: Save button label + return qsTr("Calculating Print-time"); + } else if (base.progress > 0.99){ + //: Save button label + return qsTr("Estimated Print-time"); + } else if (base.progress == null){ + return qsTr(""); + } } Label { - anchors.left: parent.left; - anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width; - - color: UM.Theme.colors.save_button_text; - font: UM.Theme.fonts.default; - - text: (!control.printDuration || !control.printDuration.valid) ? "" : control.printDuration.getDisplayString(UM.DurationFormat.Long) + id: printDurationLabel + anchors.verticalCenter: parent.verticalCenter + anchors.left: label.right; + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width; + color: UM.Theme.colors.save_button_printtime_text; + font: UM.Theme.fonts.small; + visible: base.progress < 0.99 ? false : true + text: (!base.printDuration || !base.printDuration.valid) ? "" : base.printDuration.getDisplayString(UM.DurationFormat.Long); } Label { - anchors.left: parent.left; - anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width; - - color: UM.Theme.colors.save_button_text; - font: UM.Theme.fonts.default; - + id: printMaterialLabel + anchors.verticalCenter: parent.verticalCenter + anchors.left: printDurationLabel.right; + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width; + color: UM.Theme.colors.save_button_printtime_text; + font: UM.Theme.fonts.small; + visible: base.progress < 0.99 ? false : true //: Print material amount save button label - text: control.printMaterialAmount < 0 ? "" : qsTr("%1m material").arg(control.printMaterialAmount); + text: base.printMaterialAmount < 0 ? "" : qsTr("%1m material").arg(base.printMaterialAmount); } } - } + Rectangle { + id: infoBoxOverlay + anchors { + left: infoBox.left; + top: infoBox.top; + bottom: infoBox.bottom; + } + width: Math.max(infoBox.width * base.progress); + color: UM.Theme.colors.save_button_active + visible: base.progress > 0.99 ? false : true + } - MouseArea { - anchors.fill: parent; + Button { + id: saveToButton + anchors.top: infoBox.bottom + anchors.topMargin: UM.Theme.sizes.save_button_text_margin.height; + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.default_margin.width; + tooltip: '' + enabled: progress >= 0.99; - acceptedButtons: Qt.RightButton; - - onClicked: devicesMenu.popup(); - } - - Menu { - id: devicesMenu; - - Instantiator { - model: Printer.outputDeviceNames; - MenuItem { - text: Printer.outputDevices[modelData].description; - checkable: true; - checked: base.defaultAmbiguous ? false : modelData == base.currentDevice; - exclusiveGroup: devicesMenuGroup; - onTriggered: { - base.defaultOverride = true; - base.currentDevice = modelData; - if(base.defaultAmbiguous) { - base.defaultAmbiguous = false; - Printer.writeToOutputDevice(modelData); + width: infoBox.width/6*4.5 + height: UM.Theme.sizes.save_button_save_to_button.height + style: ButtonStyle { + background: Rectangle { + color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active; + Label { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + color: UM.Theme.colors.save_button_safe_to_text; + font: UM.Theme.fonts.sidebar_save_to; + text: Printer.outputDevices[base.currentDevice].description; } } } - onObjectAdded: devicesMenu.insertItem(index, object) - onObjectRemoved: devicesMenu.removeItem(object) + onClicked: + if(base.defaultAmbiguous) { + devicesMenu.popup(); + } else { + Printer.writeToOutputDevice(base.currentDevice); + } } - ExclusiveGroup { id: devicesMenuGroup; } - } + Button { + id: deviceSelectionMenu; + anchors.top: infoBox.bottom + anchors.topMargin: UM.Theme.sizes.save_button_text_margin.height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.sizes.default_margin.width; + tooltip: '' - text: { - if(base.progress < 0) { - //: Save button label - return qsTr("Please load a 3D model"); - } else if (base.progress < 0.95) { - //: Save button label - return qsTr("Calculating Print-time"); - } else { - //: Save button label - return qsTr("Estimated Print-time"); + width: infoBox.width/6*1.3 - UM.Theme.sizes.save_button_text_margin.height; + height: UM.Theme.sizes.save_button_save_to_button.height + + style: ButtonStyle { + background: Rectangle { + color: UM.Theme.colors.save_button_background; + border.width: control.hovered ? UM.Theme.sizes.save_button_border.width : 0 + border.color: UM.Theme.colors.save_button_border + Rectangle { + id: deviceSelectionIcon + color: UM.Theme.colors.save_button_background; + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width / 2; + anchors.verticalCenter: parent.verticalCenter; + width: parent.height - UM.Theme.sizes.save_button_text_margin.width ; + height: parent.height - UM.Theme.sizes.save_button_text_margin.width; + UM.RecolorImage { + anchors.centerIn: parent; + width: parent.width; + height: parent.height; + sourceSize.width: width; + sourceSize.height: height; + color: UM.Theme.colors.save_button_active + source: UM.Theme.icons[Printer.outputDevices[base.currentDevice].icon]; + } + } + Label { + id: deviceSelectionArrow + anchors.right: parent.right; + anchors.rightMargin: UM.Theme.sizes.save_button_text_margin.height + anchors.verticalCenter: parent.verticalCenter; + text: "▼"; + font: UM.Theme.fonts.tiny; + color: UM.Theme.colors.save_button_active; + } + } + } + + menu: Menu { + id: devicesMenu; + Instantiator { + model: Printer.outputDeviceNames; + MenuItem { + text: Printer.outputDevices[modelData].description; + checkable: true; + checked: base.defaultAmbiguous ? false : modelData == base.currentDevice; + exclusiveGroup: devicesMenuGroup; + onTriggered: { + base.defaultOverride = true; + base.currentDevice = modelData; + if(base.defaultAmbiguous) { + base.defaultAmbiguous = false; + Printer.writeToOutputDevice(modelData); + } + } + } + onObjectAdded: devicesMenu.insertItem(index, object) + onObjectRemoved: devicesMenu.removeItem(object) + } + ExclusiveGroup { id: devicesMenuGroup; } + } } } - - onClicked: { - if(base.defaultAmbiguous) { - devicesMenu.popup(); - } else { - Printer.writeToOutputDevice(base.currentDevice); - } - } -} +} \ No newline at end of file diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index a40f1fdcb3..23ddfe4ed7 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -8,15 +8,13 @@ import QtQuick.Layouts 1.1 import UM 1.0 as UM -UM.AngledCornerRectangle { +Rectangle { id: base; property Action addMachineAction; property Action configureMachinesAction; property alias saveAction: saveButton.saveAction; - cornerSize: UM.Theme.sizes.default_margin.width; - color: UM.Theme.colors.sidebar; function showTooltip(item, position, text) { @@ -41,7 +39,6 @@ UM.AngledCornerRectangle { ColumnLayout { anchors.fill: parent; anchors.topMargin: UM.Theme.sizes.default_margin.height; - anchors.bottomMargin: UM.Theme.sizes.window_margin.height; spacing: UM.Theme.sizes.default_margin.height; @@ -75,7 +72,7 @@ UM.AngledCornerRectangle { property Item sidebar: base; onLoaded: - { + { if(item) { item.configureSettings = base.configureMachinesAction; @@ -93,13 +90,11 @@ UM.AngledCornerRectangle { SaveButton { id: saveButton; - Layout.preferredWidth: base.width - UM.Theme.sizes.default_margin.width * 2; - Layout.preferredHeight: UM.Theme.sizes.button.height; - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter; + implicitWidth: base.width + implicitHeight: UM.Theme.sizes.save_button_text_margin.height * 2 + UM.Theme.sizes.save_button_slicing_bar.height + UM.Theme.sizes.save_button_save_to_button.height + UM.Theme.sizes.default_margin.height } - } - + SidebarTooltip { id: tooltip; } diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 1e34028046..88a236d7ce 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -27,6 +27,10 @@ "capitalize": true, "family": "Roboto" }, + "sidebar_save_to": { + "size": 1.0, + "family": "Roboto" + }, "timeslider_time": { "size": 1.0, "bold": true, @@ -105,12 +109,15 @@ "tooltip": [255, 225, 146, 255], - "save_button": [255, 255, 255, 255], "save_button_border": [205, 202, 201, 255], "save_button_inactive": [205, 202, 201, 255], "save_button_active": [12, 159, 227, 255], "save_button_active_hover": [34, 150, 190, 255], - "save_button_text": [35, 35, 35, 255], + "save_button_safe_to_text": [255, 255, 255, 255], + "save_button_estimated_text": [140, 144, 154, 255], + "save_button_estimated_text_background": [255, 255, 255, 255], + "save_button_printtime_text": [12, 169, 227, 255], + "save_button_background": [249, 249, 249, 255], "message": [205, 202, 201, 255], "message_text": [35, 35, 35, 255], @@ -153,7 +160,10 @@ "tooltip_margins": [1.0, 1.0], "save_button_border": [0.06, 0.06], + "save_button_text_margin": [0.6, 0.6], + "save_button_slicing_bar": [0.0, 2.2], "save_button_label_margin": [0.5, 0.5], + "save_button_save_to_button": [0.3, 2.7], "message": [30.0, 5.0], "message_close": [1.25, 1.25] From 492f6309b0c1b928265cc8a32499318bce3d1d04 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 14:51:45 +0200 Subject: [PATCH 02/18] If we skip an object because it does not have a bounding box, retrigger the change timer This causes the platform physics to run again a few ms later so that we actually do not stop trying to push objects apart until everything is correctly updated Fixes Asana issue 33694499624771 --- cura/PlatformPhysics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index d7276c9773..444fe2d3cc 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -49,6 +49,7 @@ class PlatformPhysics: bbox = node.getBoundingBox() if not bbox or not bbox.isValid(): + self._change_timer.start() continue # Mark the node as outside the build volume if the bounding box test fails. From d0287b97d77a3d79cce807dabb153018e98b453c Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Wed, 24 Jun 2015 16:11:25 +0200 Subject: [PATCH 03/18] lowers the printbed so the mesh and grid no longer z-fight Lowers the height of the printbed of the Ultimaker Original platvorm mesh by 1 mm Fixes #66 --- resources/meshes/ultimaker_platform.stl | Bin 174284 -> 174284 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/meshes/ultimaker_platform.stl b/resources/meshes/ultimaker_platform.stl index cd8893143e69a7c66e1403b69a7679d8a75e3f5b..e81aeefb04fb9adf008cb71280b8cb1051b6bfef 100644 GIT binary patch delta 51813 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 UkafOjawo{RV-Pe=TY*SXQSyHqp`H9Xl9JpU3q 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 oo$R9yMCcw)O Date: Wed, 24 Jun 2015 16:02:05 +0200 Subject: [PATCH 04/18] Update setting ranges to reflect those that are used in the current Cura Fixes Asana issue 35497030487594 --- resources/settings/fdmprinter.json | 141 ++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 22 deletions(-) diff --git a/resources/settings/fdmprinter.json b/resources/settings/fdmprinter.json index 42bee91167..35fae31182 100644 --- a/resources/settings/fdmprinter.json +++ b/resources/settings/fdmprinter.json @@ -41,9 +41,9 @@ "unit": "mm", "type": "float", "default": 0.1, - "min_value": 0.00001, + "min_value": 0.0001, "min_value_warning": 0.04, - "max_value_warning": 2.0, + "max_value_warning": 0.32, "always_visible": true, "children": { "layer_height_0": { @@ -52,9 +52,9 @@ "unit": "mm", "type": "float", "default": 0.3, - "min_value": 0.0, + "min_value": 0.0001, "min_value_warning": 0.04, - "max_value_warning": 2.0, + "max_value_warning": 0.32, "visible": false } } @@ -66,7 +66,8 @@ "type": "float", "default": 0.8, "min_value": 0.0, - "max_value": 5.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "children": { "wall_thickness": { "label": "Wall Thickness", @@ -74,9 +75,8 @@ "unit": "mm", "default": 0.8, "min_value": 0.0, - "max_value": 5.0, - "min_value_warning": 0.4, - "max_value_warning": 2.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "type": "float", "visible": false, @@ -84,6 +84,7 @@ "wall_line_count": { "label": "Wall Line Count", "description": "Number of shell lines. This these lines are called perimeter lines in other tools and impact the strength and structural integrity of your print.", + "min_value": 0, "default": 2, "type": "int", "visible": false, @@ -93,6 +94,9 @@ "label": "Wall Line Width", "description": "Width of a single shell line. Each line of the shell will be printed with this width in mind.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false, @@ -103,6 +107,9 @@ "label": "First Wall Line Width", "description": "Width of the outermost shell line. By printing a thinner outermost wall line you can print higher details with a larger nozzle.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -111,6 +118,9 @@ "label": "Other Walls Line Width", "description": "Width of a single shell line for all shell lines except the outermost one.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -119,6 +129,9 @@ "label": "Skirt line width", "description": "Width of a single skirt line.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -127,6 +140,9 @@ "label": "Top/bottom line width", "description": "Width of a single top/bottom printed line. Which are used to fill up the top/bottom areas of a print.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -135,6 +151,9 @@ "label": "Infill line width", "description": "Width of the inner infill printed lines.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -143,6 +162,9 @@ "label": "Support line width", "description": "Width of the printed support structures lines.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -168,6 +190,7 @@ "label": "Top Thickness", "description": "This controls the thickness of the top layers. The number of solid layers printed is calculated from the layer thickness and this value. Having this value be a multiple of the layer thickness makes sense. And keep it nearto your wall thickness to make an evenly strong part.", "unit": "mm", + "min_value": 0.0, "default": 0.8, "type": "float", "visible": false, @@ -176,6 +199,7 @@ "top_layers": { "label": "Top Layers", "description": "This controls the amount of top layers.", + "min_value": 0, "default": 4, "type": "int", "visible": false, @@ -187,6 +211,7 @@ "label": "Bottom Thickness", "description": "This controls the thickness of the bottom layers. The number of solid layers printed is calculated from the layer thickness and this value. Having this value be a multiple of the layer thickness makes sense. And keep it near to your wall thickness to make an evenly strong part.", "unit": "mm", + "min_value": 0.0, "default": 0.8, "type": "float", "visible": false, @@ -195,6 +220,7 @@ "bottom_layers": { "label": "Bottom Layers", "description": "This controls the amount of bottom layers.", + "min_value": 0, "default": 4, "type": "int", "visible": false, @@ -256,18 +282,18 @@ "description": "The temperature used for printing. Set at 0 to pre-heat yourself. For PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required.", "unit": "°C", "type": "float", - "default": 220, - "min_value": 10, - "max_value": 340 + "default": 210, + "min_value": 0, + "max_value_warning": 260 }, "material_bed_temperature": { "label": "Bed Temperature", "description": "The temperature used for the heated printer bed. Set at 0 to pre-heat it yourself.", "unit": "°C", "type": "float", - "default": 70, + "default": 60, "min_value": 0, - "max_value": 340 + "max_value_warning": 260 }, "material_diameter": { "label": "Diameter", @@ -275,8 +301,8 @@ "unit": "mm", "type": "float", "default": 2.85, - "min_value": 0.4, - "max_value": 5.0 + "min_value_warning": 0.4, + "max_value_warning": 3.5 }, "material_flow": { "label": "Flow", @@ -285,7 +311,8 @@ "default": 100.0, "type": "float", "min_value": 5.0, - "max_value": 300.0 + "min_value_warning": 50.0, + "max_value_warning": 150.0 }, "retraction_enable": { "label": "Enable Retraction", @@ -299,7 +326,8 @@ "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", "unit": "mm/s", "type": "float", - "default": 25.0, + "min_value": 0.1, + "default": 40.0, "visible": false, "inherit": false, @@ -309,6 +337,7 @@ "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", "unit": "mm/s", "type": "float", + "min_value": 0.1, "default": 25.0, "visible": false }, @@ -317,6 +346,7 @@ "description": "The speed at which the filament is pushed back after retraction.", "unit": "mm/s", "type": "float", + "min_value": 0.1, "default": 25.0, "visible": false } @@ -327,6 +357,7 @@ "description": "The amount of retraction: Set at 0 for no retraction at all. A value of 4.5mm seems to generate good results for 3mm filament in Bowden-tube fed printers.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 4.5, "visible": false, "inherit": false @@ -336,7 +367,8 @@ "description": "The minimum distance of travel needed for a retraction to happen at all. This helps ensure you do not get a lot of retractions in a small area.", "unit": "mm", "type": "float", - "default": 4.5, + "min_value": 0.0, + "default": 1.5, "visible": false, "inherit": false }, @@ -353,6 +385,7 @@ "description": "The minimum amount of extrusion that needs to happen between retractions. If a retraction should happen before this minimum is reached, it will be ignored. This avoids retracting repeatedly on the same piece of filament as that can flatten the filament and cause grinding issues.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.02, "visible": false, "inherit": false @@ -362,6 +395,7 @@ "description": "Whenever a retraction is done, the head is lifted by this amount to travel over the print. A value of 0.075 works well. This feature has a lot of positive effect on delta towers.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.0, "visible": false, "inherit": false @@ -380,6 +414,8 @@ "description": "The speed at which printing happens. A well-adjusted Ultimaker can reach 150mm/s, but for good quality prints you will want to print slower. Printing speed depends on a lot of factors, so you will need to experiment with optimal settings for this.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "children": { @@ -388,6 +424,8 @@ "description": "The speed at which infill parts are printed. Printing the infill faster can greatly reduce printing time, but this can negatively affect print quality.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "visible": false }, @@ -396,6 +434,8 @@ "description": "The speed at which shell is printed. Printing the outer shell at a lower speed improves the final skin quality.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "visible": false, @@ -405,6 +445,8 @@ "description": "The speed at which outer shell is printed. Printing the outer shell at a lower speed improves the final skin quality. However, having a large difference between the inner shell speed and the outer shell speed will effect quality in a negative way.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "visible": false }, @@ -413,6 +455,8 @@ "description": "The speed at which all inner shells are printed. Printing the inner shell fasster than the outer shell will reduce printing time. It is good to set this in between the outer shell speed and the infill speed.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "visible": false } @@ -423,6 +467,8 @@ "description": "Speed at which top/bottom parts are printed. Printing the top/bottom faster can greatly reduce printing time, but this can negatively affect print quality.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "visible": false }, @@ -431,6 +477,8 @@ "description": "The speed at which exterior support is printed. Printing exterior supports at higher speeds can greatly improve printing time. And the surface quality of exterior support is usually not important, so higher speeds can be used.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, "default": 50.0, "visible": false, "inherit_function": "speed_wall_0" @@ -442,6 +490,8 @@ "description": "The speed at which travel moves are done. A well-built Ultimaker can reach speeds of 250mm/s. But some machines might have misaligned layers then.", "unit": "mm/s", "type": "float", + "min_value": 0.1, + "max_value_warning": 300.0, "default": 150.0 }, "speed_layer_0": { @@ -449,6 +499,7 @@ "description": "The print speed for the bottom layer: You want to print the first layer slower so it sticks to the printer bed better.", "unit": "mm/s", "type": "float", + "min_value": 0.1, "default": 15.0, "visible": false, @@ -458,6 +509,7 @@ "description": "The speed at which the skirt and brim are printed. Normally this is done at the initial layer speed. But sometimes you want to print the skirt at a different speed.", "unit": "mm/s", "type": "float", + "min_value": 0.1, "default": 15.0, "visible": false } @@ -467,6 +519,7 @@ "label": "Amount of Slower Layers", "description": "The first few layers are printed slower then the rest of the object, this to get better adhesion to the printer bed and improve the overall success rate of prints. The speed is gradually increased over these layers. 4 layers of speed-up is generally right for most materials and printers.", "type": "int", + "min_value": 0, "default": 4, "visible": false } @@ -482,6 +535,8 @@ "description": "This controls how densely filled the insides of your print will be. For a solid part use 100%, for an hollow part use 0%. A value around 20% is usually enough. This won't affect the outside of the print and only adjusts how strong the part becomes.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 20.0, "children": { @@ -504,6 +559,7 @@ "description": "Distance between the printed infill lines.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 2.0, "visible": false, "inherit_function": "(infill_line_width * 100) / parent_value" @@ -515,6 +571,8 @@ "description": "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 15.0, "visible": false }, @@ -523,6 +581,7 @@ "description": "The thickness of the sparse infill. This is rounded to a multiple of the layerheight and used to print the sparse-infill in fewer, thicker layers to save printing time.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.1, "visible": false, @@ -556,6 +615,8 @@ "description": "Fan speed used for the print cooling fan on the printer head.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 100.0, "visible": false, "inherit_function": "100.0 if parent_value else 0.0", @@ -566,6 +627,8 @@ "description": "Normally the fan runs at the minimum fan speed. If the layer is slowed down due to minimum layer time, the fan speed adjusts between minimum and maximum fan speed.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 100.0, "visible": false }, @@ -574,6 +637,8 @@ "description": "Normally the fan runs at the minimum fan speed. If the layer is slowed down due to minimum layer time, the fan speed adjusts between minimum and maximum fan speed.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 100.0, "visible": false } @@ -586,6 +651,7 @@ "description": "The height at which the fan is turned on completely. For the layers below this the fan speed is scaled linearly with the fan off for the first layer.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.5, "visible": false, @@ -594,6 +660,7 @@ "label": "Fan Full on at Layer", "description": "The layer number at which the fan is turned on completely. For the layers below this the fan speed is scaled linearly with the fan off for the first layer.", "type": "int", + "min_value": 0, "default": 4, "visible": false, "inherit_function": "int((parent_value - layer_height_0 + 0.001) / layer_height)" @@ -605,6 +672,7 @@ "description": "The minimum time spent in a layer: Gives the layer time to cool down before the next one is put on top. If a layer would print in less time, then the printer will slow down to make sure it has spent at least this many seconds printing the layer.", "unit": "sec", "type": "float", + "min_value": 0.0, "default": 5.0, "visible": false }, @@ -613,6 +681,7 @@ "description": "The minimum time spent in a layer which will cause the fan to be at minmum speed. The fan speed increases linearly from maximal fan speed for layers taking minimal layer time to minimal fan speed for layers taking the time specified here.", "unit": "sec", "type": "float", + "min_value": 0.0, "default": 10.0, "visible": false }, @@ -621,6 +690,7 @@ "description": "The minimum layer time can cause the print to slow down so much it starts to droop. The minimum feedrate protects against this. Even if a print gets slowed down it will never be slower than this minimum speed.", "unit": "mm/s", "type": "float", + "min_value": 0.0, "default": 10.0, "visible": false }, @@ -649,7 +719,6 @@ "description": "Where to place support structures. The placement can be restricted such that the support structures won't rest on the model, which could otherwise cause scarring.", "type": "enum", "options": [ - "None", "Touching Buildplate", "Everywhere" ], @@ -665,6 +734,8 @@ "description": "The maximum angle of overhangs for which support will be added. With 0 degrees being horizontal, and 90 degrees being vertical.", "unit": "°", "type": "float", + "min_value": 0.0, + "max_value": 90.0, "default": 60.0, "visible": false, "active_if": { @@ -677,6 +748,8 @@ "description": "Distance of the support structure from the print, in the X/Y directions. 0.7mm typically gives a nice distance from the print so the support does not stick to the surface.", "unit": "mm", "type": "float", + "min_value": 0.0, + "max_value_warning": 10.0, "default": 0.7, "visible": false, "active_if": { @@ -689,6 +762,8 @@ "description": "Distance from the top/bottom of the support to the print. A small gap here makes it easier to remove the support but makes the print a bit uglier. 0.15mm allows for easier separation of the support structure.", "unit": "mm", "type": "float", + "min_value": 0.0, + "max_value_warning": 10.0, "default": 0.15, "visible": false, "active_if": { @@ -700,6 +775,8 @@ "label": "Top Distance", "description": "Distance from the top of the support to the print.", "unit": "mm", + "min_value": 0.0, + "max_value_warning": 10.0, "default": 0.15, "type": "float", "visible": false, @@ -712,6 +789,8 @@ "label": "Bottom Distance", "description": "Distance from the print to the bottom of the support.", "unit": "mm", + "min_value": 0.0, + "max_value_warning": 10.0, "default": 0.15, "type": "float", "visible": false, @@ -798,6 +877,8 @@ "description": "The angle of the rooftop of a tower. Larger angles mean more pointy towers. ", "unit": "°", "type": "int", + "min_value": 0, + "max_value": 90, "default": 65, "visible": false, "active_if": { @@ -837,6 +918,8 @@ "description": "The amount of infill structure in the support, less infill gives weaker support which is easier to remove.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 15, "visible": false, "active_if": { @@ -850,6 +933,7 @@ "description": "Distance between the printed support lines.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 2.66, "visible": false, "active_if": { @@ -882,6 +966,8 @@ "label": "Skirt Line Count", "description": "The skirt is a line drawn around the first layer of the. This helps to prime your extruder, and to see if the object fits on your platform. Setting this to 0 will disable the skirt. Multiple skirt lines can help to prime your extruder better for small objects.", "type": "int", + "min_value": 0, + "max_value_warning": 100, "default": 1, "active_if": { "setting": "adhesion_type", @@ -893,6 +979,7 @@ "description": "The horizontal distance between the skirt and the first layer of the print.\nThis is the minimum distance, multiple skirt lines will extend outwards from this distance.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 3.0, "active_if": { "setting": "adhesion_type", @@ -904,7 +991,8 @@ "description": "The minimum length of the skirt. If this minimum length is not reached, more skirt lines will be added to reach this minimum length. Note: If the line count is set to 0 this is ignored.", "unit": "mm", "type": "float", - "default": 250, + "min_value": 0.0, + "default": 250.0, "active_if": { "setting": "adhesion_type", "value": "None" @@ -914,7 +1002,9 @@ "label": "Brim Line Count", "description": "The amount of lines used for a brim: More lines means a larger brim which sticks better, but this also makes your effective print area smaller.", "type": "int", - "default": 10, + "min_value": 0, + "max_value_warning": 100, + "default": 20, "active_if": { "setting": "adhesion_type", "value": "Brim" @@ -925,6 +1015,7 @@ "description": "If the raft is enabled, this is the extra raft area around the object which is also given a raft. Increasing this margin will create a stronger raft while using more material and leaving less area for your print.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 5.0, "active_if": { "setting": "adhesion_type", @@ -936,7 +1027,8 @@ "description": "The distance between the raft lines. The first 2 layers of the raft have this amount of spacing between the raft lines.", "unit": "mm", "type": "float", - "default": 5.0, + "min_value": 0.0, + "default": 3.0, "active_if": { "setting": "adhesion_type", "value": "Raft" @@ -947,6 +1039,7 @@ "description": "Layer thickness of the first raft layer. This should be a thick layer which sticks firmly to the printer bed.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.3, "active_if": { "setting": "adhesion_type", @@ -980,6 +1073,7 @@ "description": "Thickness of the 2nd raft layer.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.27, "active_if": { "setting": "adhesion_type", @@ -991,6 +1085,7 @@ "description": "Width of the 2nd raft layer lines. These lines should be thinner than the first layer, but strong enough to attach the object to.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.4, "active_if": { "setting": "adhesion_type", @@ -1002,6 +1097,7 @@ "description": "The gap between the final raft layer and the first layer of the object. Only the first layer is raised by this amount to lower the bonding between the raft layer and the object. Makes it easier to peel off the raft.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.22, "active_if": { "setting": "adhesion_type", @@ -1012,6 +1108,7 @@ "label": "Raft Surface Layers", "description": "The number of surface layers on top of the 2nd raft layer. These are fully filled layers that the object sits on. 2 layers usually works fine.", "type": "int", + "min_value": 0, "default": 2, "active_if": { "setting": "adhesion_type", From ca2c1037e149bdc85e63ee95806b0e3a41cfd114 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 17:00:33 +0200 Subject: [PATCH 05/18] Do not hide enable retraction check box even if all children are visible Fixes Asana issue 38958940640341 --- resources/settings/fdmprinter.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/settings/fdmprinter.json b/resources/settings/fdmprinter.json index 35fae31182..351f92b480 100644 --- a/resources/settings/fdmprinter.json +++ b/resources/settings/fdmprinter.json @@ -319,6 +319,7 @@ "description": "Retract the filament when the nozzle is moving over a non-printed area. Details about the retraction can be configured in the advanced tab.", "type": "boolean", "default": true, + "always_visible": true, "children": { "retraction_speed": { From 5f2d76aca9c48d9e874d0dfffccf238e41157270 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 17:01:13 +0200 Subject: [PATCH 06/18] Update UMO start/end gcode to reflect what is used in Cura 15.04 Fixes Asana issue 38958940640350 --- resources/settings/ultimaker_original.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/resources/settings/ultimaker_original.json b/resources/settings/ultimaker_original.json index ab8f0290a9..360bbbe6b6 100644 --- a/resources/settings/ultimaker_original.json +++ b/resources/settings/ultimaker_original.json @@ -19,7 +19,14 @@ "machine_nozzle_gantry_distance": { "default": 55 }, "machine_nozzle_offset_x_1": { "default": 18.0 }, "machine_nozzle_offset_y_1": { "default": 0.0 }, - "machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" } + "machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" }, + + "machine_start_gcode": { + "default": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." + }, + "machine_end_gcode": { + "default": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" + } }, "categories": { From 22fecc4cd0d8bd3af48d303bf2b452a5a65c7ccf Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 10:43:24 -0700 Subject: [PATCH 07/18] Properly add and set the window icon --- cura/CuraApplication.py | 4 +++- resources/images/cura-icon.png | Bin 0 -> 2145 bytes 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 resources/images/cura-icon.png diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 1fb243ab0a..718f7f1e38 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -36,7 +36,7 @@ from . import PrintInformation from . import CuraActions from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty -from PyQt5.QtGui import QColor +from PyQt5.QtGui import QColor, QIcon import platform import sys @@ -52,6 +52,8 @@ class CuraApplication(QtApplication): super().__init__(name = "cura", version = "15.05.95") + self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png"))) + self.setRequiredPlugins([ "CuraEngineBackend", "MeshView", diff --git a/resources/images/cura-icon.png b/resources/images/cura-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ecfe0d1e4efe064ae9e5154e423d15b303fa4dd2 GIT binary patch literal 2145 zcmWkwc|6o#7ycS##u8%*$(EY2HI#m%R5Mi8m?XSYVk{F9M%fL`s4R)_mVFIlDdZJl z!cfXGS+n%ZI+Cq0k#z>|ckbtN?z!iA&NDdMeML z2f+Cw#)Szw0so8Uwoq_{Ly56q4D&O);ST`j13cp^HICZ?LHPh*dqA+u{o6or za4_nQ?_Ga47r)ym(tVGt<@1LDKxo4JvXN~__EL6)x09V>J9ch@b3WpGiD<@uQ8#0B z?4l)vm;53er6Dc*vozJ~{H#afa(0d_oKNHPZW3KIHe_b0}%Qj7hcQx(4 zmRa-|h&X-Nf*z^Y8kKisSY+zM)kCiZ{aDDvT1Y+nYpVs{t*r%@900`)_@4zJ`(OvJ zMin6(&=T-tFRsIi1R32OYS0_V-G^`Mfsi!G?Mp^Ko3V6)`lQ{`41 z(qLvF!t1yN9*JpGj`*!Rcz2#8|UfJ%Dr0Htso%c(%L_rd(WR%+ z%8XUW5SfGsyZ4@`AlCXqfY%0uqiiX`=hjbb;u|uUM?JKuf4_{F5(-zJD%am2rRzx= zhRvFiIi+KJR)71bwjyH8JAz5M+xDva3UJ62d|TCd3E7 zBE*k>gNtA>RWV&TBXqWuyA9uG_vUY{&y>zz{P~WQe^n{XOI6=e0&HLSPYU4;0>gcU z7YUs{0r}=v27=2=TLo6k$Ul3%d|Q>mGkvy(0r1{HR7>)nzvLc|g%QB^B{h(a3D zuvtPhh2`4#Y&*n%A~AElhuHoFu!mYxW+L0%83rW@)3TMv>%F67-j1VZ1WQMt%9F(A z%2oAS+lp~o^lMfpW`F5Jry-Yh&OgDN^{grO@}(_AzlR;V)?q+IHhCbgpsvt6~3ET#~FL7*HA3*YF#m(sO;%3-yoxMdM%VPH0D)=bAn453R;;g z)@!-xUGiPhPK^&YO2M3+Z{6(Pd}(U2d|8Ft zWpTO(yW|TXTZ*y@uk9#AHM)U!xsy|pBcB24r2Q3fG3))^-h?5hNHwI9!*BA&W9S_> z+Oz%o=f$6V|6Z5=3D?HERys-BH2gA{<|lU#dHb~`_H%n^CchSbn94WYKK_TfkG@%V z4KAy)HD6*)tM1PXo09m5rDyJ3+I)KJY_H@r#9AAEE39^#UMoCACd)P7k!N9*0)re7aV7KHIjN!F zah04!89yW+M&+gWss-cK0K@6K>&J4r*N>APuSg8@~nx+USHQn9`(~cWWutFtyjYh(Q_IN z9jGAY{>i}Z`6C1X_CzqeyKXndxqq(6p;McbyZwV`0swZo#&^~aSlnIqpM;$@-lNPW zKG)#;3|<%Nk4m19H!^``Vjhh0F&WjgK)0B&Nh(#84g}_qKCRM^wbj z)8=A>e2^2hIi4iK@?$xNjY)KP)x4CEd7&vTUwl~&Gl<=BNn)v%CKxs$#t*mBn18-w ziRBXusk?PtA18qh5jW;ukwSB4$1o=AQc`l0~ZC?)leROR-1>P!b^hqKzjjL zkc3K&0yp@#N;ljOQuK(%lMK~92xfJ#E`aeg^<^ MW8CG+i_Q=K4@tB4iU0rr literal 0 HcmV?d00001 From 753e9826e0824c96b4288417d29ec56a490a24d7 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 10:47:04 -0700 Subject: [PATCH 08/18] Bump version to 15.05.96 --- cura/CuraApplication.py | 2 +- installer.nsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 718f7f1e38..56a43dfc24 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -50,7 +50,7 @@ class CuraApplication(QtApplication): if not hasattr(sys, "frozen"): Resources.addResourcePath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")) - super().__init__(name = "cura", version = "15.05.95") + super().__init__(name = "cura", version = "15.05.96") self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png"))) diff --git a/installer.nsi b/installer.nsi index b5adb4b572..54dd23a14d 100644 --- a/installer.nsi +++ b/installer.nsi @@ -1,5 +1,5 @@ !ifndef VERSION - !define VERSION '15.05.95' + !define VERSION '15.05.96' !endif ; The name of the installer From 2182163cbf2a81c4d532b2f1ad620132fd9e9d66 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 10:51:44 -0700 Subject: [PATCH 09/18] Use the application as source for the shortcut icon --- installer.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer.nsi b/installer.nsi index 54dd23a14d..e9d02fcaa4 100644 --- a/installer.nsi +++ b/installer.nsi @@ -92,7 +92,7 @@ Section "Cura ${VERSION}" CreateDirectory "$SMPROGRAMS\Cura ${VERSION}" CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Uninstall Cura ${VERSION}.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk" "$INSTDIR\Cura.exe" '' "$INSTDIR\resources\cura.ico" 0 + CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk" "$INSTDIR\Cura.exe" '' "$INSTDIR\Cura.exe" 0 SectionEnd From 55118c184bcc1d7f3e3d1be1ebe063d43fe7ae2c Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 10:54:15 -0700 Subject: [PATCH 10/18] Properly run the vcredist installer in quiet mode --- installer.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer.nsi b/installer.nsi index e9d02fcaa4..35c7fcb596 100644 --- a/installer.nsi +++ b/installer.nsi @@ -107,7 +107,7 @@ Section "Install Visual Studio 2010 Redistributable" File "vcredist_2010_20110908_x86.exe" IfSilent +2 - ExecWait '"$INSTDIR\vcredist_2010_20110908_x86.exe" /silent /norestart' + ExecWait '"$INSTDIR\vcredist_2010_20110908_x86.exe" /q /norestart' SectionEnd From 6d21ff40f538652ff013b124cd9492f1d19919da Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 10:55:21 -0700 Subject: [PATCH 11/18] Switch to using a proper windows application --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 1c82f07653..7204eedbf7 100644 --- a/setup.py +++ b/setup.py @@ -47,8 +47,8 @@ setup(name="Cura", url="http://software.ultimaker.com/", license="GNU AFFERO GENERAL PUBLIC LICENSE (AGPL)", scripts=["cura_app.py"], - #windows=[{"script": "printer.py", "dest_name": "Cura"}], - console=[{"script": "cura_app.py"}], + windows=[{"script": "cura_app.py", "dest_name": "Cura", "icon_resources": [(1, "icons/cura.ico")]}], + #console=[{"script": "cura_app.py"}], options={"py2exe": {"skip_archive": False, "includes": includes}}) print("Coping Cura plugins.") From 1f167987cbc6d9125e74f0766d39cfb49cbe2504 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 24 Jun 2015 10:58:42 -0700 Subject: [PATCH 12/18] Exclude ConsoleLogger and MLP* and OBJWriter plugins from the windows installer ConsoleLogger causes problems with the proper windows build and the other three are not currently working. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7204eedbf7..43074ab177 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ setup(name="Cura", options={"py2exe": {"skip_archive": False, "includes": includes}}) print("Coping Cura plugins.") -shutil.copytree(os.path.dirname(UM.__file__) + "/../plugins", "dist/plugins") +shutil.copytree(os.path.dirname(UM.__file__) + "/../plugins", "dist/plugins", ignore = shutil.ignore_patterns("ConsoleLogger", "OBJWriter", "MLPWriter", "MLPReader")) for path in os.listdir("plugins"): shutil.copytree("plugins/" + path, "dist/plugins/" + path) print("Coping resources.") From fa242bd02109f58729d1d37761e0d66c81f41bf5 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 25 Jun 2015 11:54:38 +0200 Subject: [PATCH 13/18] Remove sidebar right margin Contributes to Ultimaker/Uranium#24 --- resources/qml/Cura.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 9756b3550f..226f4f59a9 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -272,7 +272,6 @@ UM.MainWindow { top: parent.top; bottom: parent.bottom; right: parent.right; - rightMargin: UM.Theme.sizes.window_margin.width; } width: UM.Theme.sizes.panel.width; From ad68111c0cac4bc9bd4d705b9f6951a0b9dc175f Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 25 Jun 2015 11:55:56 +0200 Subject: [PATCH 14/18] Disable the low/high quality slicing and slider settings if we are not in simple mode Contributes to #11 --- cura/PrintInformation.py | 24 ++++++++++++++++++++++-- resources/qml/SidebarSimple.qml | 3 +++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index fdd835e9a0..d0346fbbb5 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -38,6 +38,8 @@ class PrintInformation(QObject): def __init__(self, parent = None): super().__init__(parent) + self._enabled = False + self._minimum_print_time = Duration(None, self) self._current_print_time = Duration(None, self) self._maximum_print_time = Duration(None, self) @@ -103,6 +105,21 @@ class PrintInformation(QObject): def timeQualityValue(self): return self._time_quality_value + def setEnabled(self, enabled): + if enabled != self._enabled: + self._enabled = enabled + + if self._enabled: + self._updateTimeQualitySettings() + self._onSlicingStarted() + + self.enabledChanged.emit() + + enabledChanged = pyqtSignal() + @pyqtProperty(bool, fset = setEnabled, notify = enabledChanged) + def enabled(self): + return self._enabled + @pyqtSlot(int) def setTimeQualityValue(self, value): if value != self._time_quality_value: @@ -132,7 +149,10 @@ class PrintInformation(QObject): self._material_amount = round(amount / 10) / 100 self.materialAmountChanged.emit() - if self._slice_reason != self.SliceReason.SettingChanged: + if not self._enabled: + return + + if self._slice_reason != self.SliceReason.SettingChanged or not self._minimum_print_time.valid or not self._maximum_print_time.valid: self._slice_pass = self.SlicePass.LowQualitySettings self._backend.slice(settings = self._low_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False) else: @@ -166,7 +186,7 @@ class PrintInformation(QObject): self._slice_reason = self.SliceReason.ActiveMachineChanged def _updateTimeQualitySettings(self): - if not self._current_settings: + if not self._current_settings or not self._enabled: return if not self._low_quality_settings: diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 1b41da7d6f..c27f992031 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -20,6 +20,9 @@ Item { property variant minimumPrintTime: PrintInformation.minimumPrintTime; property variant maximumPrintTime: PrintInformation.maximumPrintTime; + Component.onCompleted: PrintInformation.enabled = true + Component.onDestruction: PrintInformation.enabled = false + ColumnLayout { anchors.fill: parent; From 1c9ed0d5de3f6a17474c826bbc65462328d62e48 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 25 Jun 2015 12:06:05 +0200 Subject: [PATCH 15/18] Move initial layer thickness from layer height children into category This makes it possible to have a different initial layer height. Fixes Asana issue 38958940640338 --- resources/settings/fdmprinter.json | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/resources/settings/fdmprinter.json b/resources/settings/fdmprinter.json index 351f92b480..ca5785d046 100644 --- a/resources/settings/fdmprinter.json +++ b/resources/settings/fdmprinter.json @@ -44,20 +44,17 @@ "min_value": 0.0001, "min_value_warning": 0.04, "max_value_warning": 0.32, - "always_visible": true, - "children": { - "layer_height_0": { - "label": "Initial Layer Thickness", - "description": "The layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier.", - "unit": "mm", - "type": "float", - "default": 0.3, - "min_value": 0.0001, - "min_value_warning": 0.04, - "max_value_warning": 0.32, - "visible": false - } - } + }, + "layer_height_0": { + "label": "Initial Layer Thickness", + "description": "The layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier.", + "unit": "mm", + "type": "float", + "default": 0.3, + "min_value": 0.0001, + "min_value_warning": 0.04, + "max_value_warning": 0.32, + "visible": false }, "shell_thickness": { "label": "Shell Thickness", From 254f86faf75d0490e6e119ffd00e22ff5df7c397 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 25 Jun 2015 12:17:59 +0200 Subject: [PATCH 16/18] Fix the JSON file after moving the initial layer height setting Contributes to Asana issue 38958940640338 --- resources/settings/fdmprinter.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/settings/fdmprinter.json b/resources/settings/fdmprinter.json index ca5785d046..914a05f698 100644 --- a/resources/settings/fdmprinter.json +++ b/resources/settings/fdmprinter.json @@ -43,7 +43,7 @@ "default": 0.1, "min_value": 0.0001, "min_value_warning": 0.04, - "max_value_warning": 0.32, + "max_value_warning": 0.32 }, "layer_height_0": { "label": "Initial Layer Thickness", From 8ca0e8eef2595a88136103b469f6529209f0b8d4 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 25 Jun 2015 13:53:33 +0200 Subject: [PATCH 17/18] Account for skirt size and disallowed areas to set the scale to max size Contributes to Asana issue 37107676459484 --- cura/BuildVolume.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 97a3888c6e..cf085bfe61 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -42,6 +42,9 @@ class BuildVolume(SceneNode): def setDepth(self, depth): self._depth = depth + def getDisallowedAreas(self): + return self._disallowed_areas + def setDisallowedAreas(self, areas): self._disallowed_areas = areas @@ -109,19 +112,43 @@ class BuildVolume(SceneNode): v = self._grid_mesh.getVertex(n) self._grid_mesh.setVertexUVCoordinates(n, v[0], v[2]) + disallowed_area_size = 0 if self._disallowed_areas: mb = MeshBuilder() - for area in self._disallowed_areas: + for polygon in self._disallowed_areas: + points = polygon.getPoints() mb.addQuad( - area[0], - area[1], - area[2], - area[3], + Vector(points[0, 0], 0.1, points[0, 1]), + Vector(points[1, 0], 0.1, points[1, 1]), + Vector(points[2, 0], 0.1, points[2, 1]), + Vector(points[3, 0], 0.1, points[3, 1]), color = Color(174, 174, 174, 255) ) + # Find the largest disallowed area to exclude it from the maximum scale bounds + size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1])) + disallowed_area_size = max(size, disallowed_area_size) self._disallowed_area_mesh = mb.getData() else: self._disallowed_area_mesh = None self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD)) + + settings = Application.getInstance().getActiveMachine() + + skirt_size = 0.0 + if settings.getSettingValueByKey("adhesion_type") == "None": + skirt_size = settings.getSettingValueByKey("skirt_line_count") * settings.getSettingValueByKey("skirt_line_width") + settings.getSettingValueByKey("skirt_gap") + elif settings.getSettingValueByKey("adhesion_type") == "Brim": + skirt_size = settings.getSettingValueByKey("brim_line_count") * settings.getSettingValueByKey("skirt_line_width") + else: + skirt_size = settings.getSettingValueByKey("skirt_line_width") + + skirt_size += settings.getSettingValueByKey("skirt_line_width") + + scale_to_max_bounds = AxisAlignedBox( + minimum = Vector(minW + skirt_size, minH, minD + skirt_size + disallowed_area_size), + maximum = Vector(maxW - skirt_size, maxH, maxD - skirt_size - disallowed_area_size) + ) + + Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds From 886dac57817dc570483863332e66c746fb06bd17 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 25 Jun 2015 13:54:36 +0200 Subject: [PATCH 18/18] Store the disallowed areas as polygons and use those to test for intersection This prevents issues when trying to print larger things Contributes to Asana issue 37107676459484 --- cura/CuraApplication.py | 15 +++------------ cura/PlatformPhysics.py | 13 +++++++++---- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 56a43dfc24..2d388ce78c 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -18,6 +18,7 @@ from UM.Preferences import Preferences from UM.Message import Message from UM.PluginRegistry import PluginRegistry from UM.JobQueue import JobQueue +from UM.Math.Polygon import Polygon from UM.Scene.BoxRenderer import BoxRenderer from UM.Scene.Selection import Selection @@ -466,23 +467,13 @@ class CuraApplication(QtApplication): disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas") areas = [] if disallowed_areas: - for area in disallowed_areas: - polygon = [] - polygon.append(Vector(area[0][0], 0.2, area[0][1])) - polygon.append(Vector(area[1][0], 0.2, area[1][1])) - polygon.append(Vector(area[2][0], 0.2, area[2][1])) - polygon.append(Vector(area[3][0], 0.2, area[3][1])) - areas.append(polygon) + areas.append(Polygon(numpy.array(area, numpy.float32))) + self._volume.setDisallowedAreas(areas) self._volume.rebuild() - if self.getController().getTool("ScaleTool"): - bbox = self._volume.getBoundingBox() - bbox.setBottom(0.0) - self.getController().getTool("ScaleTool").setMaximumBounds(bbox) - offset = machine.getSettingValueByKey("machine_platform_offset") if offset: self._platform.setPosition(Vector(offset[0], offset[1], offset[2])) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 444fe2d3cc..9dcd15ad54 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -94,14 +94,19 @@ class PlatformPhysics: move_vector.setX(overlap[0] * 1.1) move_vector.setZ(overlap[1] * 1.1) + if hasattr(node, "_convex_hull"): + # Check for collisions between disallowed areas and the object + for area in self._build_volume.getDisallowedAreas(): + overlap = node._convex_hull.intersectsPolygon(area) + if overlap is None: + continue + + node._outside_buildarea = True + if move_vector != Vector(): op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector) op.push() - if node.getBoundingBox().intersectsBox(self._build_volume.getBoundingBox()) == AxisAlignedBox.IntersectionResult.FullIntersection: - op = ScaleToBoundsOperation(node, self._build_volume.getBoundingBox()) - op.push() - def _onToolOperationStarted(self, tool): self._enabled = False