mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-11-23 02:41:01 -07:00
Merge branch 'master' into cura-2007
This commit is contained in:
commit
4ea9276682
46 changed files with 11348 additions and 383 deletions
|
|
@ -68,6 +68,7 @@ class ChangeLog(Extension, QObject,):
|
|||
line = line.replace("[","")
|
||||
line = line.replace("]","")
|
||||
open_version = Version(line)
|
||||
open_header = ""
|
||||
self._change_logs[open_version] = collections.OrderedDict()
|
||||
elif line.startswith("*"):
|
||||
open_header = line.replace("*","")
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ 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
|
||||
|
|
@ -33,7 +32,6 @@ import Arcus
|
|||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class CuraEngineBackend(Backend):
|
||||
## Starts the back-end plug-in.
|
||||
#
|
||||
|
|
@ -41,14 +39,30 @@ class CuraEngineBackend(Backend):
|
|||
# with the back-end in general.
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Find out where the engine is located, and how it is called.
|
||||
# This depends on how Cura is packaged and which OS we are running on.
|
||||
default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", "CuraEngine")
|
||||
if hasattr(sys, "frozen"):
|
||||
default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "CuraEngine")
|
||||
executable_name = "CuraEngine"
|
||||
if Platform.isWindows():
|
||||
default_engine_location += ".exe"
|
||||
executable_name += ".exe"
|
||||
default_engine_location = executable_name
|
||||
if os.path.exists(os.path.join(Application.getInstallPrefix(), "bin", executable_name)):
|
||||
default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", executable_name)
|
||||
if hasattr(sys, "frozen"):
|
||||
default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name)
|
||||
if Platform.isLinux() and not default_engine_location:
|
||||
if not os.getenv("PATH"):
|
||||
raise OSError("There is something wrong with your Linux installation.")
|
||||
for pathdir in os.getenv("PATH").split(os.pathsep):
|
||||
execpath = os.path.join(pathdir, executable_name)
|
||||
if os.path.exists(execpath):
|
||||
default_engine_location = execpath
|
||||
break
|
||||
|
||||
if not default_engine_location:
|
||||
raise EnvironmentError("Could not find CuraEngine")
|
||||
|
||||
Logger.log("i", "Found CuraEngine at: %s" %(default_engine_location))
|
||||
|
||||
default_engine_location = os.path.abspath(default_engine_location)
|
||||
Preferences.getInstance().addPreference("backend/location", default_engine_location)
|
||||
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ class StartSliceJob(Job):
|
|||
# global_inherits_stack property.
|
||||
def _buildGlobalInheritsStackMessage(self, stack):
|
||||
for key in stack.getAllKeys():
|
||||
extruder = int(stack.getProperty(key, "global_inherits_stack"))
|
||||
extruder = int(round(float(stack.getProperty(key, "global_inherits_stack"))))
|
||||
if extruder >= 0: #Set to a specific extruder.
|
||||
setting_extruder = self._slice_message.addRepeatedMessage("global_inherits_stack")
|
||||
setting_extruder.name = key
|
||||
|
|
|
|||
|
|
@ -13,7 +13,40 @@ import ".."
|
|||
Button {
|
||||
id: base;
|
||||
|
||||
style: UM.Theme.styles.sidebar_category;
|
||||
style: ButtonStyle {
|
||||
background: Item { }
|
||||
label: Row
|
||||
{
|
||||
spacing: UM.Theme.getSize("default_lining").width
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: label.height / 2
|
||||
width: height
|
||||
source: control.checked ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_right");
|
||||
color: control.hovered ? palette.highlight : palette.buttonText
|
||||
}
|
||||
UM.RecolorImage
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: label.height
|
||||
width: height
|
||||
source: control.iconSource
|
||||
color: control.hovered ? palette.highlight : palette.buttonText
|
||||
}
|
||||
Label
|
||||
{
|
||||
id: label
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: control.text
|
||||
color: control.hovered ? palette.highlight : palette.buttonText
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
}
|
||||
}
|
||||
|
||||
signal showTooltip(string text);
|
||||
signal hideTooltip();
|
||||
|
|
|
|||
|
|
@ -16,17 +16,17 @@ UM.TooltipArea
|
|||
width: childrenRect.width;
|
||||
height: childrenRect.height;
|
||||
|
||||
Button
|
||||
CheckBox
|
||||
{
|
||||
id: check
|
||||
|
||||
text: definition.label
|
||||
checked: addedSettingsModel.getVisible(model.key)
|
||||
|
||||
onClicked:
|
||||
{
|
||||
addedSettingsModel.setVisible(model.key, true);
|
||||
settingPickDialog.visible = false
|
||||
UM.ActiveTool.forceUpdate()
|
||||
addedSettingsModel.setVisible(model.key, checked);
|
||||
UM.ActiveTool.forceUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,12 +59,18 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand
|
|||
definition = self._stack.getSettingDefinition(item)
|
||||
if definition:
|
||||
new_instance = SettingInstance(definition, settings)
|
||||
if definition.global_inherits_stack:
|
||||
stack_nr = -1
|
||||
if definition.global_inherits_stack and self._stack.getProperty("machine_extruder_count", "value") > 1:
|
||||
#Obtain the value from the correct container stack. Only once, upon adding the setting.
|
||||
stack_nr = self._stack.getProperty(item, "global_inherits_stack") #Stack to get the setting from.
|
||||
if int(stack_nr) >= 0: #Only if it defines an extruder stack.
|
||||
extruder_stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0]
|
||||
new_instance.value = extruder_stack.getProperty(item, "value")
|
||||
stack_nr = str(int(round(float(self._stack.getProperty(item, "global_inherits_stack"))))) #Stack to get the setting from. Round it and remove the fractional part.
|
||||
if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty("extruder_nr", "value"): #Property not defined, but we have an extruder number.
|
||||
stack_nr = str(int(round(float(self._stack.getProperty("extruder_nr", "value")))))
|
||||
if stack_nr in ExtruderManager.getInstance().extruderIds: #We have either a global_inherits_stack or an extruder_nr.
|
||||
stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0]
|
||||
else:
|
||||
stack = UM.Application.getInstance().getGlobalContainerStack()
|
||||
new_instance.setProperty("value", stack.getProperty(item, "value"))
|
||||
new_instance.resetState() # Ensure that the state is not seen as a user state.
|
||||
settings.addInstance(new_instance)
|
||||
visibility_changed = True
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ Item {
|
|||
id: extruders_model
|
||||
onRowsInserted: extruderSelector.visible = extruders_model.rowCount() > 1
|
||||
onModelReset: extruderSelector.visible = extruders_model.rowCount() > 1
|
||||
onModelChanged: extruderSelector.color = extruders_model.getItem(extruderSelector.currentIndex).colour
|
||||
onModelChanged: extruderSelector.color = extruders_model.getItem(extruderSelector.currentIndex).color
|
||||
}
|
||||
property string color: extruders_model.getItem(extruderSelector.currentIndex).colour
|
||||
property string color: extruders_model.getItem(extruderSelector.currentIndex).color
|
||||
visible: extruders_model.rowCount() > 1
|
||||
textRole: "name"
|
||||
width: UM.Theme.getSize("setting_control").width
|
||||
|
|
@ -128,7 +128,11 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onActivated: UM.ActiveTool.setProperty("SelectedActiveExtruder", extruders_model.getItem(index).id);
|
||||
onActivated:
|
||||
{
|
||||
UM.ActiveTool.setProperty("SelectedActiveExtruder", extruders_model.getItem(index).id);
|
||||
extruderSelector.color = extruders_model.getItem(index).color;
|
||||
}
|
||||
onModelChanged: updateCurrentIndex();
|
||||
|
||||
function updateCurrentIndex()
|
||||
|
|
@ -138,7 +142,7 @@ Item {
|
|||
if(extruders_model.getItem(i).id == UM.ActiveTool.properties.getValue("SelectedActiveExtruder"))
|
||||
{
|
||||
extruderSelector.currentIndex = i;
|
||||
extruderSelector.color = extruders_model.getItem(i).colour;
|
||||
extruderSelector.color = extruders_model.getItem(i).color;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -147,106 +151,111 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Repeater
|
||||
Column
|
||||
{
|
||||
id: contents
|
||||
height: childrenRect.height;
|
||||
spacing: UM.Theme.getSize("default_lining").height
|
||||
|
||||
model: UM.SettingDefinitionsModel
|
||||
Repeater
|
||||
{
|
||||
id: addedSettingsModel;
|
||||
containerId: Cura.MachineManager.activeDefinitionId
|
||||
expanded: [ "*" ]
|
||||
id: contents
|
||||
height: childrenRect.height;
|
||||
|
||||
visibilityHandler: Cura.PerObjectSettingVisibilityHandler
|
||||
model: UM.SettingDefinitionsModel
|
||||
{
|
||||
selectedObjectId: UM.ActiveTool.properties.getValue("SelectedObjectId")
|
||||
}
|
||||
}
|
||||
id: addedSettingsModel;
|
||||
containerId: Cura.MachineManager.activeDefinitionId
|
||||
expanded: [ "*" ]
|
||||
|
||||
delegate: Row
|
||||
{
|
||||
Loader
|
||||
{
|
||||
id: settingLoader
|
||||
width: UM.Theme.getSize("setting").width;
|
||||
height: UM.Theme.getSize("section").height;
|
||||
|
||||
property var definition: model
|
||||
property var settingDefinitionsModel: addedSettingsModel
|
||||
property var propertyProvider: provider
|
||||
|
||||
//Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
|
||||
//In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
|
||||
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
|
||||
asynchronous: model.type != "enum" && model.type != "extruder"
|
||||
|
||||
onLoaded: {
|
||||
settingLoader.item.showRevertButton = false
|
||||
settingLoader.item.showInheritButton = false
|
||||
settingLoader.item.showLinkedSettingIcon = false
|
||||
settingLoader.item.doDepthIndentation = false
|
||||
settingLoader.item.doQualityUserSettingEmphasis = false
|
||||
}
|
||||
|
||||
sourceComponent:
|
||||
visibilityHandler: Cura.PerObjectSettingVisibilityHandler
|
||||
{
|
||||
switch(model.type)
|
||||
{
|
||||
case "int":
|
||||
return settingTextField
|
||||
case "float":
|
||||
return settingTextField
|
||||
case "enum":
|
||||
return settingComboBox
|
||||
case "extruder":
|
||||
return settingExtruder
|
||||
case "bool":
|
||||
return settingCheckBox
|
||||
case "str":
|
||||
return settingTextField
|
||||
case "category":
|
||||
return settingCategory
|
||||
default:
|
||||
return settingUnknown
|
||||
selectedObjectId: UM.ActiveTool.properties.getValue("SelectedObjectId")
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Row
|
||||
{
|
||||
Loader
|
||||
{
|
||||
id: settingLoader
|
||||
width: UM.Theme.getSize("setting").width
|
||||
height: UM.Theme.getSize("section").height
|
||||
|
||||
property var definition: model
|
||||
property var settingDefinitionsModel: addedSettingsModel
|
||||
property var propertyProvider: provider
|
||||
|
||||
//Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
|
||||
//In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
|
||||
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
|
||||
asynchronous: model.type != "enum" && model.type != "extruder"
|
||||
|
||||
onLoaded: {
|
||||
settingLoader.item.showRevertButton = false
|
||||
settingLoader.item.showInheritButton = false
|
||||
settingLoader.item.showLinkedSettingIcon = false
|
||||
settingLoader.item.doDepthIndentation = false
|
||||
settingLoader.item.doQualityUserSettingEmphasis = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
width: UM.Theme.getSize("setting").height;
|
||||
height: UM.Theme.getSize("setting").height;
|
||||
|
||||
onClicked: addedSettingsModel.setVisible(model.key, false);
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Item
|
||||
sourceComponent:
|
||||
{
|
||||
UM.RecolorImage
|
||||
switch(model.type)
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width/2
|
||||
height: parent.height/2
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
|
||||
source: UM.Theme.getIcon("cross1")
|
||||
case "int":
|
||||
return settingTextField
|
||||
case "float":
|
||||
return settingTextField
|
||||
case "enum":
|
||||
return settingComboBox
|
||||
case "extruder":
|
||||
return settingExtruder
|
||||
case "bool":
|
||||
return settingCheckBox
|
||||
case "str":
|
||||
return settingTextField
|
||||
case "category":
|
||||
return settingCategory
|
||||
default:
|
||||
return settingUnknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
id: provider
|
||||
|
||||
containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
|
||||
key: model.key
|
||||
watchedProperties: [ "value", "enabled", "validationState" ]
|
||||
storeIndex: 0
|
||||
removeUnusedValue: false
|
||||
Button
|
||||
{
|
||||
width: UM.Theme.getSize("setting").height / 2;
|
||||
height: UM.Theme.getSize("setting").height;
|
||||
|
||||
onClicked: addedSettingsModel.setVisible(model.key, false);
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Item
|
||||
{
|
||||
UM.RecolorImage
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width
|
||||
height: parent.height / 2
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
|
||||
source: UM.Theme.getIcon("minus")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
id: provider
|
||||
|
||||
containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
|
||||
key: model.key
|
||||
watchedProperties: [ "value", "enabled", "validationState" ]
|
||||
storeIndex: 0
|
||||
removeUnusedValue: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +266,7 @@ Item {
|
|||
height: UM.Theme.getSize("setting").height;
|
||||
visible: parseInt(UM.Preferences.getValue("cura/active_mode")) == 1
|
||||
|
||||
text: catalog.i18nc("@action:button", "Add Setting");
|
||||
text: catalog.i18nc("@action:button", "Select settings");
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
|
|
@ -297,16 +306,28 @@ Item {
|
|||
UM.Dialog {
|
||||
id: settingPickDialog
|
||||
|
||||
title: catalog.i18nc("@title:window", "Pick a Setting to Customize")
|
||||
title: catalog.i18nc("@title:window", "Select Settings to Customize for this object")
|
||||
width: screenScaleFactor * 360;
|
||||
|
||||
property string labelFilter: ""
|
||||
|
||||
onVisibilityChanged:
|
||||
{
|
||||
// force updating the model to sync it with addedSettingsModel
|
||||
if(visible)
|
||||
{
|
||||
listview.model.forceUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: filter;
|
||||
id: filter
|
||||
|
||||
anchors {
|
||||
top: parent.top;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: toggleShowAll.left
|
||||
rightMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
|
||||
placeholderText: catalog.i18nc("@label:textbox", "Filter...");
|
||||
|
|
@ -324,6 +345,23 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: toggleShowAll
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
text: catalog.i18nc("@label:checkbox", "Show all")
|
||||
checked: listview.model.showAll
|
||||
onClicked:
|
||||
{
|
||||
listview.model.showAll = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
id: scrollView
|
||||
|
|
@ -377,7 +415,7 @@ Item {
|
|||
|
||||
rightButtons: [
|
||||
Button {
|
||||
text: catalog.i18nc("@action:button", "Cancel");
|
||||
text: catalog.i18nc("@action:button", "Close");
|
||||
onClicked: {
|
||||
settingPickDialog.visible = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,8 @@ from UM.i18n import i18nCatalog
|
|||
from UM.Logger import Logger
|
||||
from UM.Platform import Platform
|
||||
from UM.Qt.Duration import DurationFormat
|
||||
from UM.Job import Job
|
||||
|
||||
import collections
|
||||
import json
|
||||
import os.path
|
||||
import copy
|
||||
import platform
|
||||
import math
|
||||
import urllib.request
|
||||
|
|
@ -24,6 +21,36 @@ import ssl
|
|||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
class SliceInfoJob(Job):
|
||||
data = None
|
||||
url = None
|
||||
|
||||
def __init__(self, url, data):
|
||||
super().__init__()
|
||||
self.url = url
|
||||
self.data = data
|
||||
|
||||
def run(self):
|
||||
if not self.url or not self.data:
|
||||
Logger.log("e", "URL or DATA for sending slice info was not set!")
|
||||
return
|
||||
|
||||
# Submit data
|
||||
kwoptions = {"data" : self.data,
|
||||
"timeout" : 5
|
||||
}
|
||||
|
||||
if Platform.isOSX():
|
||||
kwoptions["context"] = ssl._create_unverified_context()
|
||||
|
||||
try:
|
||||
f = urllib.request.urlopen(self.url, **kwoptions)
|
||||
Logger.log("i", "Sent anonymous slice info to %s", self.url)
|
||||
f.close()
|
||||
except urllib.error.HTTPError as http_exception:
|
||||
Logger.log("e", "An HTTP error occurred while trying to send slice information: %s" % http_exception)
|
||||
except Exception as e: # We don't want any exception to cause problems
|
||||
Logger.log("e", "An exception occurred while trying to send slice information: %s" % e)
|
||||
|
||||
## This Extension runs in the background and sends several bits of information to the Ultimaker servers.
|
||||
# The data is only sent when the user in question gave permission to do so. All data is anonymous and
|
||||
|
|
@ -112,19 +139,10 @@ class SliceInfo(Extension):
|
|||
submitted_data = urllib.parse.urlencode(submitted_data)
|
||||
binary_data = submitted_data.encode("utf-8")
|
||||
|
||||
# Submit data
|
||||
kwoptions = {"data" : binary_data,
|
||||
"timeout" : 1
|
||||
}
|
||||
if Platform.isOSX():
|
||||
kwoptions["context"] = ssl._create_unverified_context()
|
||||
try:
|
||||
f = urllib.request.urlopen(self.info_url, **kwoptions)
|
||||
Logger.log("i", "Sent anonymous slice info to %s", self.info_url)
|
||||
f.close()
|
||||
except Exception as e:
|
||||
Logger.logException("e", "An exception occurred while trying to send slice information")
|
||||
except:
|
||||
# Sending slice info non-blocking
|
||||
reportJob = SliceInfoJob(self.info_url, binary_data)
|
||||
reportJob.start()
|
||||
except Exception as e:
|
||||
# We really can't afford to have a mistake here, as this would break the sending of g-code to a device
|
||||
# (Either saving or directly to a printer). The functionality of the slice data is not *that* important.
|
||||
pass
|
||||
Logger.log("e", "Exception raised while sending slice info: %s" %(repr(e))) # But we should be notified about these problems of course.
|
||||
|
|
@ -8,6 +8,7 @@ from UM.Resources import Resources
|
|||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from UM.View.Renderer import Renderer
|
||||
from UM.Settings.Validator import ValidatorState
|
||||
|
||||
from UM.View.GL.OpenGL import OpenGL
|
||||
|
||||
|
|
@ -40,27 +41,32 @@ class SolidView(View):
|
|||
self._disabled_shader.setUniformValue("u_diffuseColor2", [0.68, 0.68, 0.68, 1.0])
|
||||
self._disabled_shader.setUniformValue("u_width", 50.0)
|
||||
|
||||
if Application.getInstance().getGlobalContainerStack():
|
||||
multi_extrusion = False
|
||||
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack:
|
||||
if Preferences.getInstance().getValue("view/show_overhang"):
|
||||
angle = Application.getInstance().getGlobalContainerStack().getProperty("support_angle", "value")
|
||||
if angle is not None:
|
||||
angle = global_container_stack.getProperty("support_angle", "value")
|
||||
if angle is not None and global_container_stack.getProperty("support_angle", "validationState") == ValidatorState.Valid:
|
||||
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle)))
|
||||
else:
|
||||
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang.
|
||||
else:
|
||||
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0)))
|
||||
|
||||
multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
|
||||
|
||||
for node in DepthFirstIterator(scene.getRoot()):
|
||||
if not node.render(renderer):
|
||||
if node.getMeshData() and node.isVisible():
|
||||
# TODO: Find a better way to handle this
|
||||
#if node.getBoundingBoxMesh():
|
||||
# renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines)
|
||||
|
||||
uniforms = {}
|
||||
if self._extruders_model.rowCount() == 0:
|
||||
material = Application.getInstance().getGlobalContainerStack().findContainer({ "type": "material" })
|
||||
material_color = material.getMetaDataEntry("color_code", default = self._extruders_model.defaultColours[0]) if material else self._extruders_model.defaultColours[0]
|
||||
if not multi_extrusion:
|
||||
if global_container_stack:
|
||||
material = global_container_stack.findContainer({ "type": "material" })
|
||||
material_color = material.getMetaDataEntry("color_code", default = self._extruders_model.defaultColors[0]) if material else self._extruders_model.defaultColors[0]
|
||||
else:
|
||||
material_color = self._extruders_model.defaultColors[0]
|
||||
else:
|
||||
# Get color to render this mesh in from ExtrudersModel
|
||||
extruder_index = 0
|
||||
|
|
@ -68,7 +74,7 @@ class SolidView(View):
|
|||
if extruder_id:
|
||||
extruder_index = max(0, self._extruders_model.find("id", extruder_id))
|
||||
|
||||
material_color = self._extruders_model.getItem(extruder_index)["colour"]
|
||||
material_color = self._extruders_model.getItem(extruder_index)["color"]
|
||||
try:
|
||||
# Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
|
||||
# an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
|
||||
|
|
|
|||
|
|
@ -32,16 +32,16 @@ UM.Dialog
|
|||
}
|
||||
|
||||
text: {
|
||||
if (manager.progress == 0)
|
||||
{
|
||||
//: Firmware update status label
|
||||
return catalog.i18nc("@label","Starting firmware update, this may take a while.")
|
||||
}
|
||||
else if (manager.progress > 99)
|
||||
if (manager.firmwareUpdateCompleteStatus)
|
||||
{
|
||||
//: Firmware update status label
|
||||
return catalog.i18nc("@label","Firmware update completed.")
|
||||
}
|
||||
else if (manager.progress == 0)
|
||||
{
|
||||
//: Firmware update status label
|
||||
return catalog.i18nc("@label","Starting firmware update, this may take a while.")
|
||||
}
|
||||
else
|
||||
{
|
||||
//: Firmware update status label
|
||||
|
|
@ -55,10 +55,10 @@ UM.Dialog
|
|||
ProgressBar
|
||||
{
|
||||
id: prog
|
||||
value: manager.progress
|
||||
value: manager.firmwareUpdateCompleteStatus ? 100 : manager.progress
|
||||
minimumValue: 0
|
||||
maximumValue: 100
|
||||
indeterminate: manager.progress < 100
|
||||
indeterminate: (manager.progress < 1) && (!manager.firmwareUpdateCompleteStatus)
|
||||
anchors
|
||||
{
|
||||
left: parent.left;
|
||||
|
|
@ -79,7 +79,7 @@ UM.Dialog
|
|||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button","Close");
|
||||
enabled: manager.progress >= 100;
|
||||
enabled: manager.firmwareUpdateCompleteStatus;
|
||||
onClicked: base.visible = false;
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
|
||||
class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||
|
||||
def __init__(self, serial_port):
|
||||
super().__init__(serial_port)
|
||||
self.setName(catalog.i18nc("@item:inmenu", "USB printing"))
|
||||
self.setShortDescription(catalog.i18nc("@action:button", "Print via USB"))
|
||||
self.setDescription(catalog.i18nc("@info:tooltip", "Print via USB"))
|
||||
self.setIconName("print")
|
||||
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
||||
|
||||
self._serial = None
|
||||
self._serial_port = serial_port
|
||||
|
|
@ -85,12 +87,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
self._updating_firmware = False
|
||||
|
||||
self._firmware_file_name = None
|
||||
self._firmware_update_finished = False
|
||||
|
||||
self._error_message = None
|
||||
|
||||
onError = pyqtSignal()
|
||||
|
||||
firmwareUpdateComplete = pyqtSignal()
|
||||
firmwareUpdateChange = pyqtSignal()
|
||||
|
||||
endstopStateChanged = pyqtSignal(str ,bool, arguments = ["key","state"])
|
||||
|
||||
|
|
@ -170,6 +174,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
## Private function (threaded) that actually uploads the firmware.
|
||||
def _updateFirmware(self):
|
||||
self.setProgress(0, 100)
|
||||
self._firmware_update_finished = False
|
||||
|
||||
if self._connection_state != ConnectionState.closed:
|
||||
self.close()
|
||||
|
|
@ -177,10 +182,10 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
if len(hex_file) == 0:
|
||||
Logger.log("e", "Unable to read provided hex file. Could not update firmware")
|
||||
return
|
||||
return
|
||||
|
||||
programmer = stk500v2.Stk500v2()
|
||||
programmer.progressCallback = self.setProgress
|
||||
programmer.progress_callback = self.setProgress
|
||||
|
||||
try:
|
||||
programmer.connect(self._serial_port)
|
||||
|
|
@ -192,7 +197,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
if not programmer.isConnected():
|
||||
Logger.log("e", "Unable to connect with serial. Could not update firmware")
|
||||
return
|
||||
return
|
||||
|
||||
self._updating_firmware = True
|
||||
|
||||
|
|
@ -206,8 +211,10 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
programmer.close()
|
||||
|
||||
self.setProgress(100, 100)
|
||||
self._firmware_update_finished = True
|
||||
|
||||
self.firmwareUpdateComplete.emit()
|
||||
self.firmwareUpdateChange.emit()
|
||||
|
||||
## Upload new firmware to machine
|
||||
# \param filename full path of firmware file to be uploaded
|
||||
|
|
@ -216,6 +223,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
self._firmware_file_name = file_name
|
||||
self._update_firmware_thread.start()
|
||||
|
||||
@property
|
||||
def firmwareUpdateFinished(self):
|
||||
return self._firmware_update_finished
|
||||
|
||||
def resetFirmwareUpdateFinished(self):
|
||||
self._firmware_update_finished = False
|
||||
self.firmwareUpdateChange.emit()
|
||||
|
||||
@pyqtSlot()
|
||||
def startPollEndstop(self):
|
||||
if not self._poll_endstop:
|
||||
|
|
@ -251,7 +266,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
# If the programmer connected, we know its an atmega based version.
|
||||
# Not all that useful, but it does give some debugging information.
|
||||
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)
|
||||
Logger.log("d","Attempting to connect to printer with serial %s on baud rate %s", self._serial_port, baud_rate)
|
||||
Logger.log("d", "Attempting to connect to printer with serial %s on baud rate %s", self._serial_port, baud_rate)
|
||||
if self._serial is None:
|
||||
try:
|
||||
self._serial = serial.Serial(str(self._serial_port), baud_rate, timeout = 3, writeTimeout = 10000)
|
||||
|
|
@ -260,7 +275,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
continue
|
||||
else:
|
||||
if not self.setBaudRate(baud_rate):
|
||||
continue # Could not set the baud rate, go to the next
|
||||
continue # Could not set the baud rate, go to the next
|
||||
|
||||
time.sleep(1.5) # Ensure that we are not talking to the bootloader. 1.5 seconds seems to be the magic number
|
||||
sucesfull_responses = 0
|
||||
|
|
@ -270,11 +285,13 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
while timeout_time > time.time():
|
||||
line = self._readline()
|
||||
if line is None:
|
||||
Logger.log("d", "No response from serial connection received.")
|
||||
# Something went wrong with reading, could be that close was called.
|
||||
self.setConnectionState(ConnectionState.closed)
|
||||
return
|
||||
|
||||
if b"T:" in line:
|
||||
Logger.log("d", "Correct response for auto-baudrate detection received.")
|
||||
self._serial.timeout = 0.5
|
||||
sucesfull_responses += 1
|
||||
if sucesfull_responses >= self._required_responses_auto_baud:
|
||||
|
|
@ -282,7 +299,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
self.setConnectionState(ConnectionState.connected)
|
||||
self._listen_thread.start() # Start listening
|
||||
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
|
||||
return
|
||||
return
|
||||
|
||||
self._sendCommand("M105") # Send M105 as long as we are listening, otherwise we end up in an undefined state
|
||||
|
||||
|
|
@ -310,7 +327,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
self._connect_thread = threading.Thread(target = self._connect)
|
||||
self._connect_thread.daemon = True
|
||||
|
||||
|
||||
self.setConnectionState(ConnectionState.closed)
|
||||
if self._serial is not None:
|
||||
try:
|
||||
|
|
@ -539,7 +556,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
ret = self._serial.readline()
|
||||
except Exception as e:
|
||||
Logger.log("e", "Unexpected error while reading serial port. %s" % e)
|
||||
self._setErrorState("Printer has been disconnected")
|
||||
self._setErrorState("Printer has been disconnected")
|
||||
self.close()
|
||||
return None
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -48,15 +48,24 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
|||
connectionStateChanged = pyqtSignal()
|
||||
|
||||
progressChanged = pyqtSignal()
|
||||
firmwareUpdateChange = pyqtSignal()
|
||||
|
||||
@pyqtProperty(float, notify = progressChanged)
|
||||
def progress(self):
|
||||
progress = 0
|
||||
for printer_name, device in self._usb_output_devices.items(): # TODO: @UnusedVariable "printer_name"
|
||||
progress += device.progress
|
||||
|
||||
return progress / len(self._usb_output_devices)
|
||||
|
||||
## Return True if all printers finished firmware update
|
||||
@pyqtProperty(float, notify = firmwareUpdateChange)
|
||||
def firmwareUpdateCompleteStatus(self):
|
||||
complete = True
|
||||
for printer_name, device in self._usb_output_devices.items(): # TODO: @UnusedVariable "printer_name"
|
||||
if not device.firmwareUpdateFinished:
|
||||
complete = False
|
||||
return complete
|
||||
|
||||
def start(self):
|
||||
self._check_updates = True
|
||||
self._update_thread.start()
|
||||
|
|
@ -93,13 +102,20 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
|||
Message(i18n_catalog.i18nc("@info","Cannot update firmware, there were no connected printers found.")).show()
|
||||
return
|
||||
|
||||
for printer_connection in self._usb_output_devices:
|
||||
self._usb_output_devices[printer_connection].resetFirmwareUpdateFinished()
|
||||
self.spawnFirmwareInterface("")
|
||||
for printer_connection in self._usb_output_devices:
|
||||
try:
|
||||
self._usb_output_devices[printer_connection].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
||||
except FileNotFoundError:
|
||||
# Should only happen in dev environments where the resources/firmware folder is absent.
|
||||
self._usb_output_devices[printer_connection].setProgress(100, 100)
|
||||
Logger.log("w", "No firmware found for printer %s", printer_connection)
|
||||
Message(i18n_catalog.i18nc("@info",
|
||||
"Could not find firmware required for the printer at %s.") % printer_connection).show()
|
||||
self._firmware_view.close()
|
||||
|
||||
continue
|
||||
|
||||
@pyqtSlot(str, result = bool)
|
||||
|
|
@ -200,6 +216,7 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
|||
device.connectionStateChanged.connect(self._onConnectionStateChanged)
|
||||
device.connect()
|
||||
device.progressChanged.connect(self.progressChanged)
|
||||
device.firmwareUpdateChange.connect(self.firmwareUpdateChange)
|
||||
self._usb_output_devices[serial_port] = device
|
||||
|
||||
## If one of the states of the connected devices change, we might need to add / remove them from the global list.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class Stk500v2(ispBase.IspBase):
|
|||
self.seq = 1
|
||||
self.last_addr = -1
|
||||
self.progress_callback = None
|
||||
|
||||
|
||||
def connect(self, port = "COM22", speed = 115200):
|
||||
if self.serial is not None:
|
||||
self.close()
|
||||
|
|
@ -69,7 +69,7 @@ class Stk500v2(ispBase.IspBase):
|
|||
self.serial = None
|
||||
return ret
|
||||
return None
|
||||
|
||||
|
||||
def isConnected(self):
|
||||
return self.serial is not None
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ class Stk500v2(ispBase.IspBase):
|
|||
def sendISP(self, data):
|
||||
recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])
|
||||
return recv[2:6]
|
||||
|
||||
|
||||
def writeFlash(self, flash_data):
|
||||
#Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
|
||||
page_size = self.chip["pageSize"] * 2
|
||||
|
|
@ -89,15 +89,15 @@ class Stk500v2(ispBase.IspBase):
|
|||
self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
|
||||
else:
|
||||
self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
|
||||
load_count = (len(flash_data) + page_size - 1) / page_size
|
||||
load_count = (len(flash_data) + page_size - 1) / page_size
|
||||
for i in range(0, int(load_count)):
|
||||
recv = self.sendMessage([0x13, page_size >> 8, page_size & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flash_data[(i * page_size):(i * page_size + page_size)])
|
||||
if self.progress_callback is not None:
|
||||
if self._has_checksum:
|
||||
self.progress_callback(i + 1, load_count)
|
||||
else:
|
||||
self.progress_callback(i + 1, load_count*2)
|
||||
|
||||
self.progress_callback(i + 1, load_count * 2)
|
||||
|
||||
def verifyFlash(self, flash_data):
|
||||
if self._has_checksum:
|
||||
self.sendMessage([0x06, 0x00, (len(flash_data) >> 17) & 0xFF, (len(flash_data) >> 9) & 0xFF, (len(flash_data) >> 1) & 0xFF])
|
||||
|
|
@ -121,7 +121,7 @@ class Stk500v2(ispBase.IspBase):
|
|||
for i in range(0, int(load_count)):
|
||||
recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]
|
||||
if self.progress_callback is not None:
|
||||
self.progress_callback(load_count + i + 1, load_count*2)
|
||||
self.progress_callback(load_count + i + 1, load_count * 2)
|
||||
for j in range(0, 0x100):
|
||||
if i * 0x100 + j < len(flash_data) and flash_data[i * 0x100 + j] != recv[j]:
|
||||
raise ispBase.IspError("Verify error at: 0x%x" % (i * 0x100 + j))
|
||||
|
|
@ -141,7 +141,7 @@ class Stk500v2(ispBase.IspBase):
|
|||
raise ispBase.IspError("Serial send timeout")
|
||||
self.seq = (self.seq + 1) & 0xFF
|
||||
return self.recvMessage()
|
||||
|
||||
|
||||
def recvMessage(self):
|
||||
state = "Start"
|
||||
checksum = 0
|
||||
|
|
|
|||
|
|
@ -73,13 +73,21 @@ class MachineInstance:
|
|||
config.set("general", "version", "2") # Hard-code version 2, since if this number changes the programmer MUST change this entire function.
|
||||
|
||||
import VersionUpgrade21to22 # Import here to prevent circular dependencies.
|
||||
has_machine_qualities = self._type_name in VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.machinesWithMachineQuality()
|
||||
type_name = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translatePrinter(self._type_name)
|
||||
active_profile = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateProfile(self._active_profile_name)
|
||||
active_material = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateProfile(self._active_material_name)
|
||||
variant = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateVariant(self._variant_name, type_name)
|
||||
variant_materials = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateVariantForMaterials(self._variant_name, type_name)
|
||||
active_profile = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateProfile(self._active_profile_name)
|
||||
if has_machine_qualities: #This machine now has machine-quality profiles.
|
||||
active_profile += "_" + active_material + "_" + variant
|
||||
active_material += "_" + variant_materials #That means that the profile was split into multiple.
|
||||
current_settings = "empty" #The profile didn't know the definition ID when it was upgraded, so it will have been invalid. Sorry, your current settings are lost now.
|
||||
else:
|
||||
current_settings = self._name + "_current_settings"
|
||||
|
||||
containers = [
|
||||
self._name + "_current_settings",
|
||||
current_settings,
|
||||
active_profile,
|
||||
active_material,
|
||||
variant,
|
||||
|
|
@ -97,4 +105,4 @@ class MachineInstance:
|
|||
|
||||
output = io.StringIO()
|
||||
config.write(output)
|
||||
return self._filename, output.getvalue()
|
||||
return [self._filename], [output.getvalue()]
|
||||
|
|
@ -77,4 +77,4 @@ class Preferences:
|
|||
#Output the result as a string.
|
||||
output = io.StringIO()
|
||||
self._config.write(output)
|
||||
return self._filename, output.getvalue()
|
||||
return [self._filename], [output.getvalue()]
|
||||
|
|
@ -91,7 +91,7 @@ class Profile:
|
|||
translated_machine = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translatePrinter(self._machine_type_id)
|
||||
config.set("general", "definition", translated_machine)
|
||||
else:
|
||||
config.set("general", "definition", "fdmprinter")
|
||||
config.set("general", "definition", "fdmprinter") #In this case, the machine definition is unknown, and it might now have machine-specific profiles, in which case this will fail.
|
||||
|
||||
config.add_section("metadata")
|
||||
if self._type:
|
||||
|
|
@ -105,8 +105,6 @@ class Profile:
|
|||
config.set("metadata", "variant", VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateVariant(self._machine_variant_name, self._machine_type_id))
|
||||
else:
|
||||
config.set("metadata", "variant", self._machine_variant_name)
|
||||
if self._material_name and self._type != "material":
|
||||
config.set("metadata", "material", self._material_name)
|
||||
|
||||
if self._settings:
|
||||
VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateSettings(self._settings)
|
||||
|
|
@ -128,6 +126,34 @@ class Profile:
|
|||
for item in disabled_settings_defaults[1:]:
|
||||
disabled_defaults_string += "," + str(item)
|
||||
|
||||
output = io.StringIO()
|
||||
config.write(output)
|
||||
return self._filename, output.getvalue()
|
||||
#Material metadata may cause the file to split, so do it last to minimise processing time (do more with the copy).
|
||||
filenames = []
|
||||
configs = []
|
||||
if self._material_name and self._type != "material":
|
||||
config.set("metadata", "material", self._material_name)
|
||||
filenames.append(self._filename)
|
||||
configs.append(config)
|
||||
elif self._type != "material" and self._machine_type_id in VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.machinesWithMachineQuality():
|
||||
#Split this profile into multiple profiles, one for each material.
|
||||
_new_materials = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.machinesWithMachineQuality()[self._machine_type_id]["materials"]
|
||||
_new_variants = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.machinesWithMachineQuality()[self._machine_type_id]["variants"]
|
||||
translated_machine = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translatePrinter(self._machine_type_id)
|
||||
for material_id in _new_materials:
|
||||
for variant_id in _new_variants:
|
||||
variant_id_new = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateVariant(variant_id, translated_machine)
|
||||
filenames.append("{profile}_{material}_{variant}".format(profile = self._filename, material = material_id, variant = variant_id_new))
|
||||
config_copy = configparser.ConfigParser(interpolation = None)
|
||||
config_copy.read_dict(config) #Copy the config to a new ConfigParser instance.
|
||||
variant_id_new_materials = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateVariantForMaterials(variant_id, translated_machine)
|
||||
config_copy.set("metadata", "material", "{material}_{variant}".format(material = material_id, variant = variant_id_new_materials))
|
||||
configs.append(config_copy)
|
||||
else:
|
||||
configs.append(config)
|
||||
filenames.append(self._filename)
|
||||
|
||||
outputs = []
|
||||
for config in configs:
|
||||
output = io.StringIO()
|
||||
config.write(output)
|
||||
outputs.append(output.getvalue())
|
||||
return filenames, outputs
|
||||
|
|
@ -9,6 +9,29 @@ from . import MachineInstance # To upgrade machine instances.
|
|||
from . import Preferences #To upgrade preferences.
|
||||
from . import Profile # To upgrade profiles.
|
||||
|
||||
## Which machines have material-specific profiles in the new version?
|
||||
#
|
||||
# These are the 2.1 machine identities with "has_machine_materials": true in
|
||||
# their definitions in Cura 2.2. So these are the machines for which profiles
|
||||
# need to split into multiple profiles, one for each material and variant.
|
||||
#
|
||||
# Each machine has the materials and variants listed in which it needs to
|
||||
# split, since those might be different per machine.
|
||||
#
|
||||
# This should contain the definition as they are stated in the profiles. The
|
||||
# inheritance structure cannot be found at this stage, since the definitions
|
||||
# may have changed in later versions than 2.2.
|
||||
_machines_with_machine_quality = {
|
||||
"ultimaker2plus": {
|
||||
"materials": { "generic_abs", "generic_cpe", "generic_pla", "generic_pva" },
|
||||
"variants": { "0.25 mm", "0.4 mm", "0.6 mm", "0.8 mm" }
|
||||
},
|
||||
"ultimaker2_extended_plus": {
|
||||
"materials": { "generic_abs", "generic_cpe", "generic_pla", "generic_pva" },
|
||||
"variants": { "0.25 mm", "0.4 mm", "0.6 mm", "0.8 mm" }
|
||||
}
|
||||
}
|
||||
|
||||
## How to translate printer names from the old version to the new.
|
||||
_printer_translations = {
|
||||
"ultimaker2plus": "ultimaker2_plus"
|
||||
|
|
@ -61,6 +84,24 @@ _variant_translations = {
|
|||
}
|
||||
}
|
||||
|
||||
## Cura 2.2's material profiles use a different naming scheme for variants.
|
||||
#
|
||||
# Getting pretty stressed out by this sort of thing...
|
||||
_variant_translations_materials = {
|
||||
"ultimaker2_plus": {
|
||||
"0.25 mm": "ultimaker2_plus_0.25_mm",
|
||||
"0.4 mm": "ultimaker2_plus_0.4_mm",
|
||||
"0.6 mm": "ultimaker2_plus_0.6_mm",
|
||||
"0.8 mm": "ultimaker2_plus_0.8_mm"
|
||||
},
|
||||
"ultimaker2_extended_plus": {
|
||||
"0.25 mm": "ultimaker2_plus_0.25_mm",
|
||||
"0.4 mm": "ultimaker2_plus_0.4_mm",
|
||||
"0.6 mm": "ultimaker2_plus_0.6_mm",
|
||||
"0.8 mm": "ultimaker2_plus_0.8_mm"
|
||||
}
|
||||
}
|
||||
|
||||
## Converts configuration from Cura 2.1's file formats to Cura 2.2's.
|
||||
#
|
||||
# It converts the machine instances and profiles.
|
||||
|
|
@ -77,6 +118,13 @@ class VersionUpgrade21to22(VersionUpgrade):
|
|||
parser.read_string(serialised)
|
||||
return int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
||||
|
||||
## Gets a set of the machines which now have per-material quality profiles.
|
||||
#
|
||||
# \return A set of machine identifiers.
|
||||
@staticmethod
|
||||
def machinesWithMachineQuality():
|
||||
return _machines_with_machine_quality
|
||||
|
||||
## Converts machine instances from format version 1 to version 2.
|
||||
#
|
||||
# \param serialised The serialised machine instance in version 1.
|
||||
|
|
@ -180,4 +228,18 @@ class VersionUpgrade21to22(VersionUpgrade):
|
|||
def translateVariant(variant, machine):
|
||||
if machine in _variant_translations and variant in _variant_translations[machine]:
|
||||
return _variant_translations[machine][variant]
|
||||
return variant
|
||||
|
||||
## Translates a variant name for the change from Cura 2.1 to 2.2 in
|
||||
# material profiles.
|
||||
#
|
||||
# \param variant The name of the variant in Cura 2.1.
|
||||
# \param machine The name of the machine this variant is part of in Cura
|
||||
# 2.2's naming.
|
||||
# \return The name of the corresponding variant for in material profiles
|
||||
# in Cura 2.2.
|
||||
@staticmethod
|
||||
def translateVariantForMaterials(variant, machine):
|
||||
if machine in _variant_translations_materials and variant in _variant_translations_materials[machine]:
|
||||
return _variant_translations_materials[machine][variant]
|
||||
return variant
|
||||
Loading…
Add table
Add a link
Reference in a new issue