diff --git a/cura/ConvexHullDecorator.py b/cura/ConvexHullDecorator.py
index 783d74e41b..5185579633 100644
--- a/cura/ConvexHullDecorator.py
+++ b/cura/ConvexHullDecorator.py
@@ -287,5 +287,5 @@ class ConvexHullDecorator(SceneNodeDecorator):
_affected_settings = [
"adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers",
- "raft_surface_thickness", "raft_airgap", "print_sequence",
+ "raft_surface_thickness", "raft_airgap", "raft_margin", "print_sequence",
"skirt_gap", "skirt_line_count", "skirt_brim_line_width", "skirt_distance"]
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index c51207862e..aa9478e491 100644
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.py
@@ -203,7 +203,7 @@ class CuraApplication(QtApplication):
"dialog_profile_path",
"dialog_material_path"]:
- Preferences.getInstance().addPreference("local_file/%s" % key, "~/")
+ Preferences.getInstance().addPreference("local_file/%s" % key, os.path.expanduser("~/"))
Preferences.getInstance().setDefault("local_file/last_used_type", "text/x-gcode")
@@ -346,6 +346,7 @@ class CuraApplication(QtApplication):
@pyqtSlot(str, result = QUrl)
def getDefaultPath(self, key):
default_path = Preferences.getInstance().getValue("local_file/%s" % key)
+ print(default_path)
return QUrl.fromLocalFile(default_path)
@pyqtSlot(str, str)
@@ -896,4 +897,4 @@ class CuraApplication(QtApplication):
self._additional_components[area_id] = []
self._additional_components[area_id].append(component)
- self.additionalComponentsChanged.emit(area_id)
\ No newline at end of file
+ self.additionalComponentsChanged.emit(area_id)
diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py
index 9184db109a..82be7c480f 100644
--- a/cura/Settings/ContainerManager.py
+++ b/cura/Settings/ContainerManager.py
@@ -244,6 +244,7 @@ class ContainerManager(QObject):
if not type_name or entry["type"] == type_name:
filters.append(filter_string)
+ filters.append("All Files (*)")
return filters
## Export a container to a file
@@ -280,6 +281,9 @@ class ContainerManager(QObject):
return { "status": "error", "message": "Container not found"}
container = containers[0]
+ if UM.Platform.isOSX() and "." in file_url:
+ file_url = file_url[:file_url.rfind(".")]
+
for suffix in mime_type.suffixes:
if file_url.endswith(suffix):
break
@@ -301,7 +305,7 @@ class ContainerManager(QObject):
with UM.SaveFile(file_url, "w") as f:
f.write(contents)
- return { "status": "success", "message": "Succesfully exported container"}
+ return { "status": "success", "message": "Succesfully exported container", "path": file_url}
## Imports a profile from a file
#
@@ -371,11 +375,20 @@ class ContainerManager(QObject):
"container": container_type
}
- suffix_list = "*." + mime_type.preferredSuffix
+ suffix = mime_type.preferredSuffix
+ if UM.Platform.isOSX() and "." in suffix:
+ # OSX's File dialog is stupid and does not allow selecting files with a . in its name
+ suffix = suffix[suffix.index(".") + 1:]
+
+ suffix_list = "*." + suffix
for suffix in mime_type.suffixes:
if suffix == mime_type.preferredSuffix:
continue
+ if UM.Platform.isOSX() and "." in suffix:
+ # OSX's File dialog is stupid and does not allow selecting files with a . in its name
+ suffix = suffix[suffix.index("."):]
+
suffix_list += ", *." + suffix
name_filter = "{0} ({1})".format(mime_type.comment, suffix_list)
diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py
index 24360ed992..f1e34a939a 100644
--- a/cura/Settings/SettingOverrideDecorator.py
+++ b/cura/Settings/SettingOverrideDecorator.py
@@ -75,6 +75,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
# \param extruder_stack_id The new extruder stack to print with.
def setActiveExtruder(self, extruder_stack_id):
self._extruder_stack = extruder_stack_id
+ self._updateNextStack()
self.activeExtruderChanged.emit()
def getStack(self):
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py
index 8028df5923..73054fb4dc 100644
--- a/plugins/CuraEngineBackend/CuraEngineBackend.py
+++ b/plugins/CuraEngineBackend/CuraEngineBackend.py
@@ -13,9 +13,11 @@ from UM.Resources import Resources
from UM.Settings.Validator import ValidatorState #To find if a setting is in an error state. We can't slice then.
from UM.Platform import Platform
+
import cura.Settings
from cura.OneAtATimeIterator import OneAtATimeIterator
+from cura.Settings.ExtruderManager import ExtruderManager
from . import ProcessSlicedLayersJob
from . import ProcessGCodeJob
from . import StartSliceJob
@@ -391,22 +393,35 @@ class CuraEngineBackend(Backend):
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
self._global_container_stack.containersChanged.disconnect(self._onChanged)
+ extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
+ if extruders:
+ for extruder in extruders:
+ extruder.propertyChanged.disconnect(self._onSettingChanged)
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
if self._global_container_stack:
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) #Note: Only starts slicing when the value changed.
self._global_container_stack.containersChanged.connect(self._onChanged)
+ extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
+ if extruders:
+ for extruder in extruders:
+ extruder.propertyChanged.connect(self._onSettingChanged)
self._onActiveExtruderChanged()
self._onChanged()
def _onActiveExtruderChanged(self):
+ if self._global_container_stack:
+ # Connect all extruders of the active machine. This might cause a few connects that have already happend,
+ # but that shouldn't cause issues as only new / unique connections are added.
+ extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
+ if extruders:
+ for extruder in extruders:
+ extruder.propertyChanged.connect(self._onSettingChanged)
if self._active_extruder_stack:
- self._active_extruder_stack.propertyChanged.disconnect(self._onSettingChanged)
self._active_extruder_stack.containersChanged.disconnect(self._onChanged)
self._active_extruder_stack = cura.Settings.ExtruderManager.getInstance().getActiveExtruderStack()
if self._active_extruder_stack:
- self._active_extruder_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
self._active_extruder_stack.containersChanged.connect(self._onChanged)
diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py
index ebc4495365..26cf71ec7e 100644
--- a/plugins/CuraEngineBackend/StartSliceJob.py
+++ b/plugins/CuraEngineBackend/StartSliceJob.py
@@ -211,7 +211,9 @@ class StartSliceJob(Job):
def _handlePerObjectSettings(self, node, message):
stack = node.callDecoration("getStack")
- if stack:
+ # Check if the node has a stack attached to it and the stack has any settings in the top container.
+ if stack and stack.getTop().getAllKeys():
+ # Because we want to use inheritance correctly, we send all settings as seen from the per object stack.
for key in stack.getAllKeys():
setting = message.addRepeatedMessage("settings")
setting.name = key
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 669d0bcef2..4017ab3a69 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -1511,14 +1511,44 @@
},
"speed_layer_0": {
"label": "Initial Layer Speed",
- "description": "The print speed for the initial layer. A lower value is advised to improve adhesion to the build plate.",
+ "description": "The speed for the initial layer. A lower value is advised to improve adhesion to the build plate.",
"unit": "mm/s",
"type": "float",
"default_value": 30,
"minimum_value": "0.1",
"maximum_value": "299792458000",
"maximum_value_warning": "300",
- "settable_per_mesh": true
+ "settable_per_mesh": true,
+ "children":
+ {
+ "speed_print_layer_0":
+ {
+ "label": "Initial Layer Print Speed",
+ "description": "The speed of printing for the initial layer. A lower value is advised to improve adhesion to the build plate.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 30,
+ "value": "speed_layer_0",
+ "minimum_value": "0.1",
+ "maximum_value": "299792458000",
+ "maximum_value_warning": "300",
+ "settable_per_mesh": true
+ },
+ "speed_travel_layer_0":
+ {
+ "label": "Initial Layer Travel Speed",
+ "description": "The speed of travel moves in the initial layer. A lower value is advised to prevent pulling previously printed parts away from the build plate.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 60,
+ "value": "speed_layer_0 * speed_travel / speed_print",
+ "minimum_value": "0.1",
+ "maximum_value": "299792458000",
+ "maximum_value_warning": "300",
+ "settable_per_mesh": true,
+ "settable_per_extruder": true
+ }
+ }
},
"skirt_brim_speed": {
"label": "Skirt/Brim Speed",
@@ -1546,8 +1576,8 @@
"settable_per_mesh": false,
"settable_per_extruder": false
},
-
-
+
+
"acceleration_enabled": {
"label": "Enable Acceleration Control",
"description": "Enables adjusting the print head acceleration. Increasing the accelerations can reduce printing time at the cost of print quality.",
@@ -1734,8 +1764,8 @@
"settable_per_mesh": false
},
-
-
+
+
"jerk_enabled": {
"label": "Enable Jerk Control",
"description": "Enables adjusting the jerk of print head when the velocity in the X or Y axis changes. Increasing the jerk can reduce printing time at the cost of print quality.",
diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml
index 9da5522762..f4a8df1dcf 100644
--- a/resources/qml/Preferences/MaterialsPage.qml
+++ b/resources/qml/Preferences/MaterialsPage.qml
@@ -255,7 +255,7 @@ UM.ManagementPage
else if(result.status == "success")
{
messageDialog.icon = StandardIcon.Information
- messageDialog.text = catalog.i18nc("@info:status", "Successfully exported material to %1").arg(fileUrl)
+ messageDialog.text = catalog.i18nc("@info:status", "Successfully exported material to %1").arg(result.path)
messageDialog.open()
}
CuraApplication.setDefaultPath("dialog_material_path", folder)