From 56454a9c7a894f3c2c7acc08e5347f0bdad008b4 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Mon, 8 Jun 2015 17:50:29 +0200 Subject: [PATCH 01/26] Add support for listing recent files Fixes Asana issue 33694049548880 --- cura/CuraApplication.py | 32 ++++++++++++++++++++++++++++++++ resources/qml/Cura.qml | 14 ++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 55e1e466a4..7668a62dae 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -17,6 +17,7 @@ from UM.Logger import Logger from UM.Preferences import Preferences from UM.Message import Message from UM.PluginRegistry import PluginRegistry +from UM.JobQueue import JobQueue from UM.Scene.BoxRenderer import BoxRenderer from UM.Scene.Selection import Selection @@ -71,6 +72,17 @@ class CuraApplication(QtApplication): Preferences.getInstance().addPreference("cura/active_machine", "") Preferences.getInstance().addPreference("cura/active_mode", "simple") + Preferences.getInstance().addPreference("cura/recent_files", "") + + JobQueue.getInstance().jobFinished.connect(self._onJobFinished) + + self._recent_files = [] + files = Preferences.getInstance().getValue("cura/recent_files").split(";") + for f in files: + if not os.path.isfile(f): + continue + + self._recent_files.append(f) ## Handle loading of all plugin types (and the backend explicitly) # \sa PluginRegistery @@ -305,6 +317,11 @@ class CuraApplication(QtApplication): return log + recentFilesChanged = pyqtSignal() + @pyqtProperty("QStringList", notify = recentFilesChanged) + def recentFiles(self): + return self._recent_files + outputDevicesChanged = pyqtSignal() @pyqtProperty("QVariantMap", notify = outputDevicesChanged) @@ -460,3 +477,18 @@ class CuraApplication(QtApplication): op = AddSceneNodeOperation(node, self.getController().getScene().getRoot()) op.push() + + def _onJobFinished(self, job): + if type(job) is not ReadMeshJob: + return + + f = job.getFileName() + if f in self._recent_files: + self._recent_files.remove(f) + + self._recent_files.insert(0, f) + if len(self._recent_files) > 10: + del self._recent_files[10] + + Preferences.getInstance().setValue("cura/recent_files", ";".join(self._recent_files)) + self.recentFilesChanged.emit() diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index a2eeba59cd..e0caf4d83d 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -25,6 +25,7 @@ UM.MainWindow { window: base Menu { + id: fileMenu //: File menu title: qsTr("&File"); @@ -33,6 +34,19 @@ UM.MainWindow { MenuSeparator { } + Instantiator { + model: Printer.recentFiles + MenuItem { + property url filePath: modelData; + text: (index + 1) + ". " + modelData.slice(modelData.lastIndexOf("/") + 1); + onTriggered: UM.MeshFileHandler.readLocalFile(filePath); + } + onObjectAdded: fileMenu.insertItem(index, object) + onObjectRemoved: fileMenu.removeItem(object) + } + + MenuSeparator { } + MenuItem { action: actions.quit; } } From fc33b340607fd0cf99db82ba722bc5531fd30b6e Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 9 Jun 2015 13:38:23 +0200 Subject: [PATCH 02/26] Save the state of collapsed/expanded categories Fixes Asana issue 36436828173802 --- cura/CuraApplication.py | 15 +++++++++++++++ resources/qml/SidebarAdvanced.qml | 9 ++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7668a62dae..43ce586e74 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -73,6 +73,7 @@ class CuraApplication(QtApplication): Preferences.getInstance().addPreference("cura/active_machine", "") Preferences.getInstance().addPreference("cura/active_mode", "simple") Preferences.getInstance().addPreference("cura/recent_files", "") + Preferences.getInstance().addPreference("cura/categories_expanded", "") JobQueue.getInstance().jobFinished.connect(self._onJobFinished) @@ -322,6 +323,20 @@ class CuraApplication(QtApplication): def recentFiles(self): return self._recent_files + @pyqtSlot("QStringList") + def setExpandedCategories(self, categories): + categories = list(set(categories)) + categories.sort() + joined = ";".join(categories) + if joined != Preferences.getInstance().getValue("cura/categories_expanded"): + Preferences.getInstance().setValue("cura/categories_expanded", joined) + self.expandedCategoriesChanged.emit() + + expandedCategoriesChanged = pyqtSignal() + @pyqtProperty("QStringList", notify = expandedCategoriesChanged) + def expandedCategories(self): + return Preferences.getInstance().getValue("cura/categories_expanded").split(";") + outputDevicesChanged = pyqtSignal() @pyqtProperty("QVariantMap", notify = outputDevicesChanged) diff --git a/resources/qml/SidebarAdvanced.qml b/resources/qml/SidebarAdvanced.qml index 7d0e391768..8a231aa53d 100644 --- a/resources/qml/SidebarAdvanced.qml +++ b/resources/qml/SidebarAdvanced.qml @@ -1,6 +1,13 @@ // Copyright (c) 2015 Ultimaker B.V. // Cura is released under the terms of the AGPLv3 or higher. +import QtQuick 2.0 + +import QtQuick.Controls 1.2 + import UM 1.0 as UM -UM.SettingView { } +UM.SettingView { + expandedCategories: Printer.expandedCategories; + onExpandedCategoriesChanged: Printer.setExpandedCategories(expandedCategories); +} From 5019a157a1a31b2c999cfd75f510785b74e47dd0 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 9 Jun 2015 05:22:28 -0700 Subject: [PATCH 03/26] Bump version to .95 --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 43ce586e74..5135a84471 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -49,7 +49,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.93") + super().__init__(name = "cura", version = "15.05.94") self.setRequiredPlugins([ "CuraEngineBackend", From da6b7c272cebe17a2b2045106eef664416b116ed Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 9 Jun 2015 05:23:37 -0700 Subject: [PATCH 04/26] Include VCRedist and add an option to run it during install Fixes Asana issue 34145139570660 --- installer.nsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/installer.nsi b/installer.nsi index 5bd18a929b..1259aeba7a 100644 --- a/installer.nsi +++ b/installer.nsi @@ -99,6 +99,15 @@ Function LaunchLink Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk"' FunctionEnd +Section "Install Visual Studio 2010 Redistributable" + SetOutPath "$INSTDIR" + File "vcredist_2010_x86.exe" + + IfSilent +2 + ExecWait '"$INSTDIR\vcredist_2010_x86.exe"' + +SectionEnd + ;Section "Install Arduino Drivers" ; ; Set output path to the driver directory. ; SetOutPath "$INSTDIR\drivers\" From aef2821464ba50958a323663cbfdd02e7f463cc2 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 9 Jun 2015 14:37:04 +0200 Subject: [PATCH 05/26] Update CHANGES file with changes since .93 --- CHANGES | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index e62253066b..f33001afd5 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,24 @@ Cura 15.06 is a new release built from the ground up on a completely new framework called Uranium. This framework has been designed to make it easier to extend Cura with additional functionality as well as provide a cleaner UI. +Changes since 15.05.93 +---------------------- + +* Fixed: No shortcuts for moving up/down layers in layer view. +* Fixed: Last view layers could not be scrolled through in layer view. +* Fixed: Files provided on command line would not actually show up on the build + platform. +* Fixed: Render a ghost of the selection in Layer view to make the actual object + position clear. +* Fixed: Showing a menu would clear the selection. +* Fixed: Size and scaling factor display for scale tool. +* Fixed: Missing background for additional tool controls. +* Fixed: Loading message times out when loading large files. +* Fixed: Show recent files in the file menu. +* Fixed: Windows installer will now install MSVC 2010 redistributable, to + prevent issues with missing DLL's. +* Fixed: Collapsed/expanded state of setting categories not stored. + Changes since 15.05.91 ---------------------- @@ -26,7 +44,8 @@ Changes since 15.05.91 * Fixed: Camera panning now works correctly instead of doing nothing. * Fixed: Camera would flip around center point at maximum rotation. * Fixed: Build platform grid blocked view from below objects. -* Fixed: Viewport on MacOSX with high-DPI screens was only taking 1/4th of the window +* Fixed: Viewport on MacOSX with high-DPI screens was only taking 1/4th of the +window Changes since 15.05.90 ---------------------- From 74cf0274214797bdfe5e1a1ddfeb25c37353249f Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Wed, 10 Jun 2015 14:40:46 +0200 Subject: [PATCH 06/26] Fix text wrapping and several other style issues of the About dialog Contributes to Ultimaker/Uranium#43 --- resources/qml/AboutDialog.qml | 72 ++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml index df2ecf4172..1ed9f5dd32 100644 --- a/resources/qml/AboutDialog.qml +++ b/resources/qml/AboutDialog.qml @@ -3,7 +3,6 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 -import QtQuick.Layouts 1.1 import QtQuick.Window 2.1 import UM 1.0 as UM @@ -12,48 +11,53 @@ UM.Dialog { id: base //: About dialog title - title: qsTr("About Cura"); + title: qsTr("About Cura") + minimumWidth: 400 + minimumHeight: 300 - ColumnLayout { - anchors.fill: parent; + Image { + id: logo + width: parent.width * 0.75 + height: width * (1/4.25) - Item { - Layout.fillWidth: true; - Layout.fillHeight: true; - } + source: UM.Theme.images.logo - Image { - Layout.alignment: Qt.AlignHCenter; - Layout.preferredWidth: parent.width * 0.75; - Layout.preferredHeight: width * (1/4.25); + sourceSize.width: width + sourceSize.height: height + anchors.centerIn: parent + anchors.verticalCenterOffset : -(height * 0.5) + } - source: UM.Theme.images.logo; + Label { + id: version - sourceSize.width: width; - sourceSize.height: height; - } + text: "Cura 15.06 Beta" + font: UM.Theme.fonts.large + anchors.horizontalCenter : logo.horizontalCenter + anchors.horizontalCenterOffset : (logo.width * 0.25) + anchors.top: logo.bottom + anchors.topMargin : 5 + } - Label { - Layout.alignment: Qt.AlignHCenter; + Label { + id: description + width: parent.width - text: "Cura 15.06 Beta"; - font: UM.Theme.fonts.large; - } + //: About dialog application description + text: qsTr("End-to-end solution for fused filament 3D printing.") + wrapMode: Text.WordWrap + anchors.top: version.bottom + anchors.topMargin : 10 + } - Label { - //: About dialog application description - text: qsTr("End-to-end solution for fused filament 3D printing.") - } + Label { + id: author_note + width: parent.width - Label { - //: About dialog application author note - text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.") - } - - Item { - Layout.fillWidth: true; - Layout.fillHeight: true; - } + //: About dialog application author note + text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.") + wrapMode: Text.WordWrap + anchors.top: description.bottom } rightButtons: Button { From 5f24b70453d11fa17f6b746afe425d6841c37dd8 Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Wed, 10 Jun 2015 14:57:37 +0200 Subject: [PATCH 07/26] Highlight Open button when no files are loaded This helps with first-run to make it clear where to start. Fixes #37 --- resources/qml/Cura.qml | 3 +- resources/themes/cura/styles.qml | 49 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index e0caf4d83d..8c5c43d83c 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -192,7 +192,7 @@ UM.MainWindow { id: openFileButton; iconSource: UM.Theme.icons.open; - style: UM.Theme.styles.tool_button; + style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button; anchors { top: parent.top; @@ -433,3 +433,4 @@ UM.MainWindow { Component.onCompleted: UM.Theme.load(UM.Resources.getPath(UM.Resources.ThemesLocation, "cura")) } + diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index b7db374da1..e6c08b381c 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -35,6 +35,55 @@ QtObject { } } + property Component open_file_button: Component { + ButtonStyle { + background: UM.AngledCornerRectangle { + implicitWidth: UM.Theme.sizes.button.width; + implicitHeight: UM.Theme.sizes.button.height; + color: { + if(control.hovered) { + return UM.Theme.colors.button_active_hover; + } else { + return UM.Theme.colors.button_active; + } + } + Behavior on color { ColorAnimation { duration: 50; } } + cornerSize: UM.Theme.sizes.default_margin.width; + + Rectangle { + anchors.bottom: parent.top; + + width: parent.width; + height: control.hovered ? label.height : 0; + Behavior on height { NumberAnimation { duration: 75; } } + + opacity: control.hovered ? 1.0 : 0.0; + Behavior on opacity { NumberAnimation { duration: 75; } } + + Label { + id: label + anchors.horizontalCenter: parent.horizontalCenter; + text: control.text; + font: UM.Theme.fonts.button_tooltip; + color: UM.Theme.colors.button_tooltip_text; + } + } + } + + label: Item { + Image { + anchors.centerIn: parent; + + source: control.iconSource; + width: UM.Theme.sizes.button_icon.width; + height: UM.Theme.sizes.button_icon.height; + + sourceSize: UM.Theme.sizes.button_icon; + } + } + } + } + property Component tool_button: Component { ButtonStyle { background: UM.AngledCornerRectangle { From 9d50b1fb26090237f5f38b30f7f028dd3c4c730b Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 10 Jun 2015 15:32:57 +0200 Subject: [PATCH 08/26] Correct name of UM Original+ --- resources/settings/ultimaker_original_plus.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/settings/ultimaker_original_plus.json b/resources/settings/ultimaker_original_plus.json index d0b04879db..9e5cf6370d 100644 --- a/resources/settings/ultimaker_original_plus.json +++ b/resources/settings/ultimaker_original_plus.json @@ -1,6 +1,6 @@ { "id": "ultimaker_original_plus", - "name": "Ultimaker Original Plus", + "name": "Ultimaker Original+", "icon": "icon_ultimaker.png", "platform": "ultimaker2_platform.obj", "platform_texture": "UltimakerPlusbackplate.png", From fa671225c829f7acc1efeac74d08535a4e7ccb06 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 10 Jun 2015 15:36:15 +0200 Subject: [PATCH 09/26] Update tool button styling for improved clarity Fixes #35 --- resources/themes/cura/styles.qml | 53 ++++++++++++++++++-------------- resources/themes/cura/theme.json | 6 ++-- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index e6c08b381c..3ca9ea6ea2 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -86,45 +86,52 @@ QtObject { property Component tool_button: Component { ButtonStyle { - background: UM.AngledCornerRectangle { - property bool down: control.pressed || (control.checkable && control.checked); - + background: Item { implicitWidth: UM.Theme.sizes.button.width; implicitHeight: UM.Theme.sizes.button.height; - color: { - if(!control.enabled) { - return UM.Theme.colors.button_disabled; - } else if(control.checkable && control.checked && control.hovered) { - return UM.Theme.colors.button_active_hover; - } else if(control.pressed || (control.checkable && control.checked)) { - return UM.Theme.colors.button_active; - } else if(control.hovered) { - return UM.Theme.colors.button_hover; - } else { - return UM.Theme.colors.button; - } - } - Behavior on color { ColorAnimation { duration: 50; } } - cornerSize: UM.Theme.sizes.default_margin.width; Rectangle { - anchors.bottom: parent.top; + anchors.bottom: parent.verticalCenter; width: parent.width; - height: control.hovered ? label.height : 0; - Behavior on height { NumberAnimation { duration: 75; } } + height: control.hovered ? parent.height / 2 + label.height : 0; + Behavior on height { NumberAnimation { duration: 100; } } opacity: control.hovered ? 1.0 : 0.0; - Behavior on opacity { NumberAnimation { duration: 75; } } + Behavior on opacity { NumberAnimation { duration: 100; } } Label { id: label anchors.horizontalCenter: parent.horizontalCenter; - text: control.text; + text: control.text.replace("&", ""); font: UM.Theme.fonts.button_tooltip; color: UM.Theme.colors.button_tooltip_text; } } + + UM.AngledCornerRectangle { + id: buttonFace; + + anchors.fill: parent; + + property bool down: control.pressed || (control.checkable && control.checked); + + color: { + if(!control.enabled) { + return UM.Theme.colors.button_disabled; + } else if(control.checkable && control.checked && control.hovered) { + return UM.Theme.colors.button_active_hover; + } else if(control.pressed || (control.checkable && control.checked)) { + return UM.Theme.colors.button_active; + } else if(control.hovered) { + return UM.Theme.colors.button_hover; + } else { + return UM.Theme.colors.button; + } + } + Behavior on color { ColorAnimation { duration: 50; } } + cornerSize: UM.Theme.sizes.default_margin.width; + } } label: Item { diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index eda2badd71..a99fcc7f55 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -57,10 +57,10 @@ "text_hover": [35, 35, 35, 255], "text_pressed": [12, 169, 227, 255], - "button": [205, 202, 201, 255], - "button_hover": [174, 174, 174, 255], + "button": [160, 163, 171, 255], + "button_hover": [140, 144, 154, 255], "button_active": [12, 169, 227, 255], - "button_active_hover": [34, 150, 190, 255], + "button_active_hover": [34, 150, 199, 255], "button_text": [255, 255, 255, 255], "button_disabled": [245, 245, 245, 255], "button_tooltip_text": [35, 35, 35, 255], From 9f1b6fc496118d208b59c2b959623cf2af6fd08c Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 10 Jun 2015 15:41:21 +0200 Subject: [PATCH 10/26] Use a darker text color for improved clarity Contributes to Asana Readability issue --- resources/themes/cura/theme.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index a99fcc7f55..caf6dc5358 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -52,8 +52,8 @@ "border": [205, 202, 201, 255], "secondary": [205, 202, 201, 255], - "text": [174, 174, 174, 255], - "text_inactive": [205, 202, 201, 255], + "text": [140, 144, 154, 255], + "text_inactive": [174, 174, 174, 255], "text_hover": [35, 35, 35, 255], "text_pressed": [12, 169, 227, 255], @@ -77,7 +77,7 @@ "setting_category_active_hover": [34, 150, 190, 255], "setting_category_text": [255, 255, 255, 255], - "setting_label": [174, 174, 174, 255], + "setting_label": [140, 144, 154, 255], "setting_control": [255, 255, 255, 255], "setting_control_highlight": [245, 245, 245, 255], "setting_control_border": [174, 174, 174, 255], @@ -98,7 +98,7 @@ "checkbox_hover": [245, 245, 245, 255], "checkbox_border": [174, 174, 174, 255], "checkbox_mark": [35, 35, 35, 255], - "checkbox_text": [174, 174, 174, 255], + "checkbox_text": [140, 144, 154, 255], "tooltip": [255, 225, 146, 255], From ff058bbfae0f11f0fb453e08b56984b9773c5db2 Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Thu, 11 Jun 2015 13:42:49 +0200 Subject: [PATCH 11/26] Changes icon size (within the buttons) to improve clarity Contributes to #43 --- resources/themes/cura/theme.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index eda2badd71..bfe36b5d97 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -133,7 +133,7 @@ "setting_unit_margin": [0.5, 0.5], "button": [4.25, 4.25], - "button_icon": [3.57, 3.57], + "button_icon": [2.9, 2.9], "scrollbar": [0.5, 0.5], From 4d1fdc92b31306ff659851b25396e29ae459057e Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Thu, 11 Jun 2015 14:41:52 +0200 Subject: [PATCH 12/26] Removes the default tooltips of the buttons to improve clarity Put the automatically added tooltips back to the default value (empty qSt) so the user doensn't sees two 'tooltips' Contributes to #43 --- resources/qml/Cura.qml | 4 ++-- resources/qml/Toolbar.qml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 8c5c43d83c..7067c88c12 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -193,7 +193,7 @@ UM.MainWindow { iconSource: UM.Theme.icons.open; style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button; - + tooltip: ''; anchors { top: parent.top; topMargin: UM.Theme.sizes.window_margin.height; @@ -232,7 +232,7 @@ UM.MainWindow { iconSource: UM.Theme.icons.viewmode; style: UM.Theme.styles.tool_button; - + tooltip: ''; menu: Menu { id: viewMenu; Instantiator { diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index e7cb0788c5..d5126db481 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -47,7 +47,6 @@ Item { Button { text: model.name; iconSource: UM.Theme.icons[model.icon]; - tooltip: model.description; checkable: true; checked: model.active; From 62558f47fafb9d783388238011f8fca938ffe145 Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Thu, 11 Jun 2015 15:56:09 +0200 Subject: [PATCH 13/26] makes the tooltip/label appear behind the button. Contributes to #43 --- resources/themes/cura/styles.qml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index e6c08b381c..cd66a79257 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -51,14 +51,15 @@ QtObject { cornerSize: UM.Theme.sizes.default_margin.width; Rectangle { - anchors.bottom: parent.top; + anchors.verticalCenter: parent.top; width: parent.width; - height: control.hovered ? label.height : 0; + height: control.hovered ? (label.height + 20) : 0; Behavior on height { NumberAnimation { duration: 75; } } opacity: control.hovered ? 1.0 : 0.0; Behavior on opacity { NumberAnimation { duration: 75; } } + z: -1; Label { id: label @@ -106,16 +107,16 @@ QtObject { } Behavior on color { ColorAnimation { duration: 50; } } cornerSize: UM.Theme.sizes.default_margin.width; - Rectangle { - anchors.bottom: parent.top; + anchors.verticalCenter: parent.top; width: parent.width; - height: control.hovered ? label.height : 0; + height: control.hovered ? (label.height + 20) : 0; Behavior on height { NumberAnimation { duration: 75; } } opacity: control.hovered ? 1.0 : 0.0; Behavior on opacity { NumberAnimation { duration: 75; } } + z: -1; Label { id: label From 0b9986d34b0c6257e8a5db86c3407c4dd94ae871 Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Thu, 11 Jun 2015 13:42:49 +0200 Subject: [PATCH 14/26] Changes icon size (within the buttons) to improve clarity Contributes to #43 --- resources/themes/cura/theme.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index caf6dc5358..9e5911e4e0 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -133,7 +133,7 @@ "setting_unit_margin": [0.5, 0.5], "button": [4.25, 4.25], - "button_icon": [3.57, 3.57], + "button_icon": [2.9, 2.9], "scrollbar": [0.5, 0.5], From 4bd5aeda6a2acc2f74288c2321d3a0f87d264650 Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Thu, 11 Jun 2015 14:41:52 +0200 Subject: [PATCH 15/26] Removes the default tooltips of the buttons to improve clarity Put the automatically added tooltips back to the default value (empty qSt) so the user doensn't sees two 'tooltips' Contributes to #43 --- resources/qml/Cura.qml | 4 ++-- resources/qml/Toolbar.qml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 8c5c43d83c..7067c88c12 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -193,7 +193,7 @@ UM.MainWindow { iconSource: UM.Theme.icons.open; style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button; - + tooltip: ''; anchors { top: parent.top; topMargin: UM.Theme.sizes.window_margin.height; @@ -232,7 +232,7 @@ UM.MainWindow { iconSource: UM.Theme.icons.viewmode; style: UM.Theme.styles.tool_button; - + tooltip: ''; menu: Menu { id: viewMenu; Instantiator { diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index e7cb0788c5..d5126db481 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -47,7 +47,6 @@ Item { Button { text: model.name; iconSource: UM.Theme.icons[model.icon]; - tooltip: model.description; checkable: true; checked: model.active; From aa0c18118b0d258b43cb617a206ce57101aa88ea Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Fri, 12 Jun 2015 12:19:23 +0200 Subject: [PATCH 16/26] Revert "makes the tooltip/label appear behind the button." This reverts commit 62558f47fafb9d783388238011f8fca938ffe145. --- resources/themes/cura/styles.qml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index cd66a79257..e6c08b381c 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -51,15 +51,14 @@ QtObject { cornerSize: UM.Theme.sizes.default_margin.width; Rectangle { - anchors.verticalCenter: parent.top; + anchors.bottom: parent.top; width: parent.width; - height: control.hovered ? (label.height + 20) : 0; + height: control.hovered ? label.height : 0; Behavior on height { NumberAnimation { duration: 75; } } opacity: control.hovered ? 1.0 : 0.0; Behavior on opacity { NumberAnimation { duration: 75; } } - z: -1; Label { id: label @@ -107,16 +106,16 @@ QtObject { } Behavior on color { ColorAnimation { duration: 50; } } cornerSize: UM.Theme.sizes.default_margin.width; + Rectangle { - anchors.verticalCenter: parent.top; + anchors.bottom: parent.top; width: parent.width; - height: control.hovered ? (label.height + 20) : 0; + height: control.hovered ? label.height : 0; Behavior on height { NumberAnimation { duration: 75; } } opacity: control.hovered ? 1.0 : 0.0; Behavior on opacity { NumberAnimation { duration: 75; } } - z: -1; Label { id: label From 8e6ab3a10b526b6b6767af712448eb95cd5ac0f7 Mon Sep 17 00:00:00 2001 From: derekhe Date: Sat, 13 Jun 2015 14:31:37 +0800 Subject: [PATCH 17/26] Add new cura description. Add build scripts url --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f311976ca1..acd87f1b0e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ Cura ==== -This is the source code of Cura. +This is the new, shiny, unreleased frontend for Cura. [daid/Cura](https://github.com/daid/Cura.git) is the old legacy Cura that everyone knows and loves/hates. + +We re-worked the whole GUI code at Ultimaker, because my old code started to become an unmaintainable ball of poo. Dependencies ------------ @@ -12,3 +14,8 @@ Dependencies This will be needed at runtime to perform the actual slicing. * PySerial Only required for USB printing support. + +Build scripts +------------- + +Please checkout [cura-build](https://github.com/Ultimaker/cura-build) From 6add467477dbc50d6bd9acb62195316f36d68e7f Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Mon, 15 Jun 2015 13:59:17 +0200 Subject: [PATCH 18/26] Makes the openfile button blue/active as long as there is no file loaded. This is to make the UI more intuitive. Contributes to #43 --- resources/themes/cura/styles.qml | 39 +++++++++++++++++--------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index 3ca9ea6ea2..3c2a392b8d 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -35,39 +35,42 @@ QtObject { } } - property Component open_file_button: Component { + property Component open_file_button: Component { ButtonStyle { - background: UM.AngledCornerRectangle { + background: Item { implicitWidth: UM.Theme.sizes.button.width; implicitHeight: UM.Theme.sizes.button.height; - color: { - if(control.hovered) { - return UM.Theme.colors.button_active_hover; - } else { - return UM.Theme.colors.button_active; - } - } - Behavior on color { ColorAnimation { duration: 50; } } - cornerSize: UM.Theme.sizes.default_margin.width; Rectangle { - anchors.bottom: parent.top; - + anchors.bottom: parent.verticalCenter; width: parent.width; - height: control.hovered ? label.height : 0; - Behavior on height { NumberAnimation { duration: 75; } } + height: control.hovered ? parent.height / 2 + label.height : 0; + Behavior on height { NumberAnimation { duration: 100; } } opacity: control.hovered ? 1.0 : 0.0; - Behavior on opacity { NumberAnimation { duration: 75; } } + Behavior on opacity { NumberAnimation { duration: 100; } } Label { - id: label + id: label; anchors.horizontalCenter: parent.horizontalCenter; - text: control.text; + text: control.text.replace("&", ""); font: UM.Theme.fonts.button_tooltip; color: UM.Theme.colors.button_tooltip_text; } } + + UM.AngledCornerRectangle { + anchors.fill: parent; + color: { + if(control.hovered) { + return UM.Theme.colors.button_active_hover; + } else { + return UM.Theme.colors.button_active; + } + } + Behavior on color { ColorAnimation { duration: 50; } } + cornerSize: UM.Theme.sizes.default_margin.width; + } } label: Item { From c11c80fa2461ea07925770cd1e437cf6fd043473 Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Mon, 15 Jun 2015 16:44:43 +0200 Subject: [PATCH 19/26] Defines the style of the progressbar Commits to #44 --- resources/themes/cura/styles.qml | 43 ++++++++++++++++++++++++++++++++ resources/themes/cura/theme.json | 7 ++++++ 2 files changed, 50 insertions(+) diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index 3c2a392b8d..43bbb8c400 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -151,6 +151,49 @@ QtObject { } } + + property Component progressbar: Component{ + ProgressBarStyle { + background: UM.AngledCornerRectangle { + anchors.fill: parent + anchors.left: parent.left + implicitWidth: UM.Theme.sizes.progressbar.width + implicitHeight: UM.Theme.sizes.progressbar.height + color: "transparent" + } + progress: UM.AngledCornerRectangle { + anchors.left: parent.left + anchors.fill: parent + cornerSize: UM.Theme.sizes.progressbar_control.height + color: UM.Theme.colors.progressbar_background + Item { + anchors.fill: parent + anchors.margins: UM.Theme.sizes.progressbar_margin.width + visible: control.indeterminate + Row { + Repeater { + UM.AngledCornerRectangle { + cornerSize: UM.Theme.sizes.progressbar_control.height + color: UM.Theme.colors.progressbar_control + width: UM.Theme.sizes.progressbar_control.width + height: UM.Theme.sizes.progressbar_control.height + } + model: 1 + } + SequentialAnimation on x { + id: xAnim + property int animEndPoint: UM.Theme.sizes.progressbar.width - UM.Theme.sizes.progressbar_control.width + running: control.indeterminate + loops: Animation.Infinite + NumberAnimation { from: 0; to: xAnim.animEndPoint; duration: 2000;} + NumberAnimation { from: xAnim.animEndPoint; to: 0; duration: 2000;} + } + } + } + } + } + } + property Component sidebar_category: Component { ButtonStyle { background: UM.AngledCornerRectangle { diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 9e5911e4e0..222b3008fe 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -88,6 +88,9 @@ "setting_validation_warning": [255, 186, 15, 255], "setting_validation_ok": [255, 255, 255, 255], + "progressbar_background": [245, 245, 245, 255], + "progressbar_control": [12, 169, 227, 255], + "slider_groove": [245, 245, 245, 255], "slider_groove_border": [205, 202, 201, 255], "slider_groove_fill": [205, 202, 201, 255], @@ -135,6 +138,10 @@ "button": [4.25, 4.25], "button_icon": [2.9, 2.9], + "progressbar": [26.0, 0.5], + "progressbar_control": [8.0, 0.5], + "progressbar_margin": [0.0, 0.0], + "scrollbar": [0.5, 0.5], "slider_groove": [0.5, 0.5], From cff6ae32a76ab710186d9925cb05dead39001ede Mon Sep 17 00:00:00 2001 From: Tamara Hogenhout Date: Mon, 15 Jun 2015 17:28:41 +0200 Subject: [PATCH 20/26] helps with making the messagestack adapt to the total size of messages + pogressbar Commits to #44 --- resources/themes/cura/theme.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 222b3008fe..1e34028046 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -140,7 +140,7 @@ "progressbar": [26.0, 0.5], "progressbar_control": [8.0, 0.5], - "progressbar_margin": [0.0, 0.0], + "progressbar_padding": [0.0, 1.0], "scrollbar": [0.5, 0.5], From 2aa2d4d1a8b85a475602adfbc827fa8fba55f356 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Jun 2015 12:36:39 +0200 Subject: [PATCH 21/26] Update generated protobuf protocol file as per CuraEngine changes Contributes to Ultimaker/Cura#52 --- plugins/CuraEngineBackend/Cura_pb2.py | 68 ++++++++++++++++++--------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/plugins/CuraEngineBackend/Cura_pb2.py b/plugins/CuraEngineBackend/Cura_pb2.py index cf95bd2832..f97aaafc4d 100644 --- a/plugins/CuraEngineBackend/Cura_pb2.py +++ b/plugins/CuraEngineBackend/Cura_pb2.py @@ -1,6 +1,3 @@ -# Copyright (c) 2015 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. - # Generated by the protocol buffer compiler. DO NOT EDIT! # source: Cura.proto @@ -21,7 +18,7 @@ _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='Cura.proto', package='Cura', - serialized_pb=_b('\n\nCura.proto\x12\x04\x43ura\"+\n\nObjectList\x12\x1d\n\x07objects\x18\x01 \x03(\x0b\x32\x0c.Cura.Object\"i\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12\x1f\n\x08settings\x18\x05 \x03(\x0b\x32\r.Cura.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"7\n\x10SlicedObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.Cura.SlicedObject\"7\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x1b\n\x06layers\x18\x02 \x03(\x0b\x32\x0b.Cura.Layer\"4\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x1f\n\x08polygons\x18\x02 \x03(\x0b\x32\r.Cura.Polygon\"\x9f\x01\n\x07Polygon\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.Cura.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\"b\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\".\n\x0bSettingList\x12\x1f\n\x08settings\x18\x01 \x03(\x0b\x32\r.Cura.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3') + serialized_pb=_b('\n\nCura.proto\x12\x04\x43ura\"+\n\nObjectList\x12\x1d\n\x07objects\x18\x01 \x03(\x0b\x32\x0c.Cura.Object\"i\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12\x1f\n\x08settings\x18\x05 \x03(\x0b\x32\r.Cura.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"7\n\x10SlicedObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.Cura.SlicedObject\"7\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x1b\n\x06layers\x18\x02 \x03(\x0b\x32\x0b.Cura.Layer\"W\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12\x1f\n\x08polygons\x18\x04 \x03(\x0b\x32\r.Cura.Polygon\"\xdb\x01\n\x07Polygon\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.Cura.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\".\n\x0bSettingList\x12\x1f\n\x08settings\x18\x01 \x03(\x0b\x32\r.Cura.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -57,11 +54,19 @@ _POLYGON_TYPE = _descriptor.EnumDescriptor( name='SkirtType', index=5, number=5, options=None, type=None), + _descriptor.EnumValueDescriptor( + name='InfillType', index=6, number=6, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SupportInfillType', index=7, number=7, + options=None, + type=None), ], containing_type=None, options=None, - serialized_start=430, - serialized_end=528, + serialized_start=486, + serialized_end=623, ) _sym_db.RegisterEnumDescriptor(_POLYGON_TYPE) @@ -266,8 +271,22 @@ _LAYER = _descriptor.Descriptor( is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( - name='polygons', full_name='Cura.Layer.polygons', index=1, - number=2, type=11, cpp_type=10, label=3, + name='height', full_name='Cura.Layer.height', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='thickness', full_name='Cura.Layer.thickness', index=2, + number=3, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='polygons', full_name='Cura.Layer.polygons', index=3, + number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -284,7 +303,7 @@ _LAYER = _descriptor.Descriptor( oneofs=[ ], serialized_start=314, - serialized_end=366, + serialized_end=401, ) @@ -309,6 +328,13 @@ _POLYGON = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), + _descriptor.FieldDescriptor( + name='line_width', full_name='Cura.Polygon.line_width', index=2, + number=3, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), ], extensions=[ ], @@ -321,8 +347,8 @@ _POLYGON = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=369, - serialized_end=528, + serialized_start=404, + serialized_end=623, ) @@ -358,8 +384,8 @@ _GCODELAYER = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=530, - serialized_end=568, + serialized_start=625, + serialized_end=663, ) @@ -402,8 +428,8 @@ _OBJECTPRINTTIME = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=570, - serialized_end=638, + serialized_start=665, + serialized_end=733, ) @@ -432,8 +458,8 @@ _SETTINGLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=640, - serialized_end=686, + serialized_start=735, + serialized_end=781, ) @@ -469,8 +495,8 @@ _SETTING = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=688, - serialized_end=726, + serialized_start=783, + serialized_end=821, ) @@ -499,8 +525,8 @@ _GCODEPREFIX = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=728, - serialized_end=755, + serialized_start=823, + serialized_end=850, ) _OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT From 9849283144e0d6287efa17b1d49b443e6747ba3c Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Jun 2015 13:11:19 +0200 Subject: [PATCH 22/26] Do not render the convex hull node unless the object is selected Contributes to #52 --- cura/ConvexHullNode.py | 3 +++ plugins/LayerView/LayerView.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/cura/ConvexHullNode.py b/cura/ConvexHullNode.py index a94ae60897..5be5820982 100644 --- a/cura/ConvexHullNode.py +++ b/cura/ConvexHullNode.py @@ -48,6 +48,9 @@ class ConvexHullNode(SceneNode): self.setMeshData(mesh) + def getWatchedNode(self): + return self._node + def render(self, renderer): if not self._material: self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag")) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 7f8c04986d..e32645d9ed 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -11,6 +11,9 @@ from . import LayerViewProxy from UM.Scene.Selection import Selection from UM.Math.Color import Color +from cura.ConvexHullNode import ConvexHullNode + + ## View used to display g-code paths. class LayerView(View): def __init__(self): @@ -45,6 +48,11 @@ class LayerView(View): self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128)) for node in DepthFirstIterator(scene.getRoot()): + # We do not want to render ConvexHullNode as it conflicts with the bottom layers. + # However, it is somewhat relevant when the node is selected, so do render it then. + if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()): + continue + if not node.render(renderer): if node.getMeshData() and node.isVisible(): if Selection.isSelected(node): From ad885063256f6461f8fe797a7ed47f2cefd05526 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Jun 2015 13:16:45 +0200 Subject: [PATCH 23/26] Use the new layer message properties to properly create layers Now we use the height as provided by the engine to render the layer at. Contributes to #52 --- plugins/CuraEngineBackend/LayerData.py | 74 ++++++++++++++++--- .../ProcessSlicedObjectListJob.py | 21 +++--- 2 files changed, 74 insertions(+), 21 deletions(-) diff --git a/plugins/CuraEngineBackend/LayerData.py b/plugins/CuraEngineBackend/LayerData.py index 546397e460..1c4c2a0b9c 100644 --- a/plugins/CuraEngineBackend/LayerData.py +++ b/plugins/CuraEngineBackend/LayerData.py @@ -2,7 +2,9 @@ # Cura is released under the terms of the AGPLv3 or higher. from UM.Mesh.MeshData import MeshData +from UM.Mesh.MeshBuilder import MeshBuilder from UM.Math.Color import Color +from UM.Math.Vector import Vector import numpy import math @@ -13,12 +15,19 @@ class LayerData(MeshData): self._layers = {} self._element_counts = {} - def addPolygon(self, layer, type, data): + def addLayer(self, layer): if layer not in self._layers: - self._layers[layer] = [] + self._layers[layer] = Layer(layer) - p = Polygon(self, type, data) - self._layers[layer].append(p) + def addPolygon(self, layer, type, data, line_width): + if layer not in self._layers: + self.addLayer(layer) + + p = Polygon(self, type, data, line_width) + self._layers[layer].polygons.append(p) + + def getLayer(self, layer): + return self._layers[layer] def getLayers(self): return self._layers @@ -26,14 +35,61 @@ class LayerData(MeshData): def getElementCounts(self): return self._element_counts + def setLayerHeight(self, layer, height): + if layer not in self._layers: + self.addLayer(layer) + + self._layers[layer].setHeight(height) + + def setLayerThickness(self, layer, thickness): + if layer not in self._layers: + self.addLayer(layer) + + self._layers[layer].setThickness(thickness) + def build(self): for layer, data in self._layers.items(): - if layer not in self._element_counts: - self._element_counts[layer] = [] + data.build() - for polygon in data: - polygon.build() - self._element_counts[layer].append(polygon.elementCount) + self._element_counts[layer] = data.elementCount + +class Layer(): + def __init__(self, id): + self._id = id + self._height = 0.0 + self._thickness = 0.0 + self._polygons = [] + self._element_count = 0 + + @property + def height(self): + return self._height + + @property + def thickness(self): + return self._thickness + + @property + def polygons(self): + return self._polygons + + @property + def elementCount(self): + return self._element_count + + def setHeight(self, height): + self._height = height + + def setThickness(self, thickness): + self._thickness = thickness + + def build(self): + for polygon in self._polygons: + if polygon._type == Polygon.InfillType or polygon._type == Polygon.SupportInfillType: + continue + + polygon.build() + self._element_count += polygon.elementCount class Polygon(): NoneType = 0 diff --git a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py b/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py index 804338e4dc..cef8ff754f 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py @@ -32,22 +32,24 @@ class ProcessSlicedObjectListJob(Job): settings = Application.getInstance().getActiveMachine() layerHeight = settings.getSettingValueByKey("layer_height") + mesh = MeshData() for object in self._message.objects: - try: + try: node = objectIdMap[object.id] except KeyError: continue - - mesh = MeshData() layerData = LayerData.LayerData() for layer in object.layers: + layerData.addLayer(layer.id) + layerData.setLayerHeight(layer.id, layer.height) + layerData.setLayerThickness(layer.id, layer.thickness) for polygon in layer.polygons: points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. points = numpy.asarray(points, dtype=numpy.float32) points /= 1000 - points = numpy.insert(points, 1, layer.id * layerHeight, axis = 1) + points = numpy.insert(points, 1, (layer.height / 1000), axis = 1) points[:,2] *= -1 @@ -55,16 +57,11 @@ class ProcessSlicedObjectListJob(Job): center = [settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2] points -= numpy.array(center) - #points = numpy.pad(points, ((0,0), (0,1)), "constant", constant_values=(0.0, 1.0)) - #inverse = node.getWorldTransformation().getInverse().getData() - #points = points.dot(inverse) - #points = points[:,0:3] layerData.addPolygon(layer.id, polygon.type, points) + # We are done processing all the layers we got from the engine, now create a mesh out of the data + layerData.build() + mesh.layerData = layerData - # We are done processing all the layers we got from the engine, now create a mesh out of the data - layerData.build() - mesh.layerData = layerData - new_node.setMeshData(mesh) new_node.setParent(self._scene.getRoot()) From 75fff176f4d3bd7c0a54962ff21a9a215646da21 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Jun 2015 13:17:52 +0200 Subject: [PATCH 24/26] Add support for line width and infill types to LayerData::Polygon Contributes to #52 --- plugins/CuraEngineBackend/LayerData.py | 46 ++++++++++++------- .../ProcessSlicedObjectListJob.py | 2 +- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/plugins/CuraEngineBackend/LayerData.py b/plugins/CuraEngineBackend/LayerData.py index 1c4c2a0b9c..15edc16e14 100644 --- a/plugins/CuraEngineBackend/LayerData.py +++ b/plugins/CuraEngineBackend/LayerData.py @@ -98,34 +98,26 @@ class Polygon(): SkinType = 3 SupportType = 4 SkirtType = 5 + InfillType = 6 + SupportInfillType = 7 - def __init__(self, mesh, type, data): + def __init__(self, mesh, type, data, line_width): super().__init__() self._mesh = mesh self._type = type self._data = data + self._line_width = line_width / 1000 def build(self): self._begin = self._mesh._vertex_count self._mesh.addVertices(self._data) self._end = self._begin + len(self._data) - 1 - color = None - if self._type == self.Inset0Type: - color = [1, 0, 0, 1] - elif self._type == self.InsetXType: - color = [0, 1, 0, 1] - elif self._type == self.SkinType: - color = [1, 1, 0, 1] - elif self._type == self.SupportType: - color = [0, 1, 1, 1] - elif self._type == self.SkirtType: - color = [0, 1, 1, 1] - else: - color = [1, 1, 1, 1] + color = self.getColor() + color[3] = 2.0 colors = [color for i in range(len(self._data))] - self._mesh.addColors(numpy.array(colors, dtype=numpy.float32)) + self._mesh.addColors(numpy.array(colors, dtype=numpy.float32) * 0.5) indices = [] for i in range(self._begin, self._end): @@ -136,6 +128,24 @@ class Polygon(): indices.append(self._begin) self._mesh.addIndices(numpy.array(indices, dtype=numpy.int32)) + def getColor(self): + if self._type == self.Inset0Type: + return [1.0, 0.0, 0.0, 1.0] + elif self._type == self.InsetXType: + return [0.0, 1.0, 0.0, 1.0] + elif self._type == self.SkinType: + return [1.0, 1.0, 0.0, 1.0] + elif self._type == self.SupportType: + return [0.0, 1.0, 1.0, 1.0] + elif self._type == self.SkirtType: + return [0.0, 1.0, 1.0, 1.0] + elif self._type == self.InfillType: + return [1.0, 1.0, 0.0, 1.0] + elif self._type == self.SupportInfillType: + return [0.0, 1.0, 1.0, 1.0] + else: + return [1.0, 1.0, 1.0, 1.0] + @property def type(self): return self._type @@ -146,4 +156,8 @@ class Polygon(): @property def elementCount(self): - return (self._end - self._begin) * 2 #The range of vertices multiplied by 2 since each vertex is used twice + return ((self._end - self._begin) + 1) * 2 #The range of vertices multiplied by 2 since each vertex is used twice + + @property + def lineWidth(self): + return self._line_width diff --git a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py b/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py index cef8ff754f..6113da78a0 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py @@ -57,8 +57,8 @@ class ProcessSlicedObjectListJob(Job): center = [settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2] points -= numpy.array(center) + layerData.addPolygon(layer.id, polygon.type, points, polygon.line_width) - layerData.addPolygon(layer.id, polygon.type, points) # We are done processing all the layers we got from the engine, now create a mesh out of the data layerData.build() mesh.layerData = layerData From 06b5e9d0ca4270e90263566534682d97b8e3e353 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Jun 2015 13:18:24 +0200 Subject: [PATCH 25/26] Add a createMesh function to LayerData::Layer that creates a mesh from a layer Contributes to #52 --- plugins/CuraEngineBackend/LayerData.py | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/plugins/CuraEngineBackend/LayerData.py b/plugins/CuraEngineBackend/LayerData.py index 15edc16e14..b129942c36 100644 --- a/plugins/CuraEngineBackend/LayerData.py +++ b/plugins/CuraEngineBackend/LayerData.py @@ -91,6 +91,57 @@ class Layer(): polygon.build() self._element_count += polygon.elementCount + def createMesh(self): + builder = MeshBuilder() + + for polygon in self._polygons: + poly_color = polygon.getColor() + poly_color = Color(poly_color[0], poly_color[1], poly_color[2], poly_color[3]) + + points = numpy.copy(polygon.data) + if polygon.type == Polygon.InfillType or polygon.type == Polygon.SkinType or polygon.type == Polygon.SupportInfillType: + points[:,1] -= 0.01 + + # Calculate normals for the entire polygon using numpy. + normals = numpy.copy(points) + normals[:,1] = 0.0 # We are only interested in 2D normals + + # Calculate the edges between points. + # The call to numpy.roll shifts the entire array by one so that + # we end up subtracting each next point from the current, wrapping + # around. This gives us the edges from the next point to the current + # point. + normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0) + # Calculate the length of each edge using standard Pythagoras + lengths = numpy.sqrt(normals[:,0] ** 2 + normals[:,2] ** 2) + # The normal of a 2D vector is equal to its x and y coordinates swapped + # and then x inverted. This code does that. + normals[:,[0, 2]] = normals[:,[2, 0]] + normals[:,0] *= -1 + + # Normalize the normals. + normals[:,0] /= lengths + normals[:,2] /= lengths + + # Scale all by the line width of the polygon so we can easily offset. + normals *= (polygon.lineWidth / 2) + + #TODO: Use numpy magic to perform the vertex creation to speed up things. + for i in range(len(points)): + start = points[i - 1] + end = points[i] + + normal = normals[i - 1] + + point1 = Vector(data = start - normal) + point2 = Vector(data = start + normal) + point3 = Vector(data = end + normal) + point4 = Vector(data = end - normal) + + builder.addQuad(point1, point2, point3, point4, color = poly_color) + + return builder.getData() + class Polygon(): NoneType = 0 Inset0Type = 1 From 995b76fad956bd0f747794076679b71e053f5243 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Jun 2015 13:19:45 +0200 Subject: [PATCH 26/26] Implement rendering the top 5 layers solid and with infill Fixes #52 --- plugins/LayerView/LayerView.py | 50 ++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index e32645d9ed..17cea9988c 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -7,12 +7,13 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Resources import Resources from UM.Event import Event, KeyEvent from UM.Signal import Signal -from . import LayerViewProxy from UM.Scene.Selection import Selection from UM.Math.Color import Color +from UM.Mesh.MeshData import MeshData from cura.ConvexHullNode import ConvexHullNode +from . import LayerViewProxy ## View used to display g-code paths. class LayerView(View): @@ -25,6 +26,9 @@ class LayerView(View): self._controller.getScene().sceneChanged.connect(self._onSceneChanged) self._max_layers = 10 self._current_layer_num = 10 + self._current_layer_mesh = None + + self._solid_layers = 5 def getCurrentLayer(self): return self._current_layer_num @@ -63,19 +67,39 @@ class LayerView(View): except AttributeError: continue - start = 0 - end = 0 + # Render all layers below a certain number as line mesh instead of vertices. + if self._current_layer_num - self._solid_layers > -1: + start = 0 + end = 0 + element_counts = layer_data.getElementCounts() + for layer, counts in element_counts.items(): + if layer + self._solid_layers > self._current_layer_num: + break + end += counts - element_counts = layer_data.getElementCounts() - for layer, counts in element_counts.items(): - end += sum(counts) - ## Hack to ensure the end is correct. Not quite sure what causes this - end += 2 * len(counts) + # This uses glDrawRangeElements internally to only draw a certain range of lines. + renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end) - if layer >= self._current_layer_num: - break + # We currently recreate the current "solid" layers every time a + if not self._current_layer_mesh: + self._current_layer_mesh = MeshData() + for i in range(self._solid_layers): + layer = self._current_layer_num - i + if layer < 0: + continue - renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end) + layer_mesh = layer_data.getLayer(layer).createMesh() + if not layer_mesh or layer_mesh.getVertices() is None: + continue + + self._current_layer_mesh.addVertices(layer_mesh.getVertices()) + + # Scale layer color by a brightness factor based on the current layer number + # This will result in a range of 0.5 - 1.0 to multiply colors by. + brightness = (2.0 - (i / self._solid_layers)) / 2.0 + self._current_layer_mesh.addColors(layer_mesh.getColors() * brightness) + + renderer.queueNode(node, mesh = self._current_layer_mesh, material = self._material) def setLayer(self, value): if self._current_layer_num != value: @@ -84,6 +108,8 @@ class LayerView(View): self._current_layer_num = 0 if self._current_layer_num > self._max_layers: self._current_layer_num = self._max_layers + + self._current_layer_mesh = None self.currentLayerNumChanged.emit() currentLayerNumChanged = Signal() @@ -104,7 +130,7 @@ class LayerView(View): except AttributeError: continue if new_max_layers < len(layer_data.getLayers()): - new_max_layers = len(layer_data.getLayers()) + new_max_layers = len(layer_data.getLayers()) - 1 if new_max_layers > 0 and new_max_layers != self._old_max_layers: self._max_layers = new_max_layers