mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-24 23:23:57 -06:00
Merge branch 'master' of github.com:Ultimaker/Cura into sentry_crash_integration
This commit is contained in:
commit
4de28bed28
1251 changed files with 1842 additions and 1456 deletions
190
plugins/PostProcessingPlugin/scripts/ColorMix.py
Normal file
190
plugins/PostProcessingPlugin/scripts/ColorMix.py
Normal file
|
@ -0,0 +1,190 @@
|
|||
# ColorMix script - 2-1 extruder color mix and blending
|
||||
# This script is specific for the Geeetech A10M dual extruder but should work with other Marlin printers.
|
||||
# It runs with the PostProcessingPlugin which is released under the terms of the AGPLv3 or higher.
|
||||
# This script is licensed under the Creative Commons - Attribution - Share Alike (CC BY-SA) terms
|
||||
|
||||
#Authors of the 2-1 ColorMix plug-in / script:
|
||||
# Written by John Hryb - john.hryb.4@gmail.com
|
||||
|
||||
##history / change-log:
|
||||
##V1.0.0
|
||||
|
||||
## Uses -
|
||||
## M163 - Set Mix Factor
|
||||
## M164 - Save Mix - saves to T3 as a unique mix
|
||||
|
||||
import re #To perform the search and replace.
|
||||
from ..Script import Script
|
||||
|
||||
class ColorMix(Script):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name":"ColorMix 2-1",
|
||||
"key":"ColorMix 2-1",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"measurement_units":
|
||||
{
|
||||
"label": "Units of measurement",
|
||||
"description": "Input value as mm or layer number.",
|
||||
"type": "enum",
|
||||
"options": {"mm":"mm","layer":"Layer"},
|
||||
"default_value": "layer"
|
||||
},
|
||||
"start_height":
|
||||
{
|
||||
"label": "Start Height",
|
||||
"description": "Value to start at (mm or layer)",
|
||||
"type": "float",
|
||||
"default_value": 0,
|
||||
"minimum_value": "0"
|
||||
},
|
||||
"behavior":
|
||||
{
|
||||
"label": "Fixed or blend",
|
||||
"description": "Select Fixed (set new mixture) or Blend mode (dynamic mix)",
|
||||
"type": "enum",
|
||||
"options": {"fixed_value":"Fixed","blend_value":"Blend"},
|
||||
"default_value": "fixed_value"
|
||||
},
|
||||
"finish_height":
|
||||
{
|
||||
"label": "Finish Height",
|
||||
"description": "Value to stop at (mm or layer)",
|
||||
"type": "float",
|
||||
"default_value": 0,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "0.1",
|
||||
"enabled": "c_behavior == 'blend_value'"
|
||||
},
|
||||
"mix_start_ratio":
|
||||
{
|
||||
"label": "Start mix ratio",
|
||||
"description": "First extruder percentage 0-100",
|
||||
"type": "float",
|
||||
"default_value": 100,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "0",
|
||||
"maximum_value_warning": "100"
|
||||
},
|
||||
"mix_finish_ratio":
|
||||
{
|
||||
"label": "End mix ratio",
|
||||
"description": "First extruder percentage 0-100 to finish blend",
|
||||
"type": "float",
|
||||
"default_value": 0,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "0",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "c_behavior == 'blend_value'"
|
||||
},
|
||||
"notes":
|
||||
{
|
||||
"label": "Notes",
|
||||
"description": "A spot to put a note",
|
||||
"type": "str",
|
||||
"default_value": ""
|
||||
}
|
||||
}
|
||||
}"""
|
||||
def getValue(self, line, key, default = None): #replace default getvalue due to comment-reading feature
|
||||
if not key in line or (";" in line and line.find(key) > line.find(";") and
|
||||
not ";ChangeAtZ" in key and not ";LAYER:" in key):
|
||||
return default
|
||||
subPart = line[line.find(key) + len(key):] #allows for string lengths larger than 1
|
||||
if ";ChangeAtZ" in key:
|
||||
m = re.search("^[0-4]", subPart)
|
||||
elif ";LAYER:" in key:
|
||||
m = re.search("^[+-]?[0-9]*", subPart)
|
||||
else:
|
||||
#the minus at the beginning allows for negative values, e.g. for delta printers
|
||||
m = re.search("^[-]?[0-9]*\.?[0-9]*", subPart)
|
||||
if m == None:
|
||||
return default
|
||||
try:
|
||||
return float(m.group(0))
|
||||
except:
|
||||
return default
|
||||
|
||||
def execute(self, data):
|
||||
#get user variables
|
||||
firstHeight = 0.0
|
||||
secondHeight = 0.0
|
||||
firstMix = 0.0
|
||||
SecondMix = 0.0
|
||||
|
||||
firstHeight = self.getSettingValueByKey("start_height")
|
||||
secondHeight = self.getSettingValueByKey("finish_height")
|
||||
firstMix = self.getSettingValueByKey("mix_start_ratio")
|
||||
SecondMix = self.getSettingValueByKey("mix_finish_ratio")
|
||||
|
||||
#locals
|
||||
layer = 0
|
||||
|
||||
#get layer height
|
||||
layerHeight = .2
|
||||
for active_layer in data:
|
||||
lines = active_layer.split("\n")
|
||||
for line in lines:
|
||||
if ";Layer height: " in line:
|
||||
layerHeight = self.getValue(line, ";Layer height: ", layerHeight)
|
||||
break
|
||||
#get layers to use
|
||||
startLayer = 0
|
||||
endLayer = 0
|
||||
if self.getSettingValueByKey("measurement_units") == "mm":
|
||||
if firstHeight == 0:
|
||||
startLayer = 0
|
||||
else:
|
||||
startLayer = firstHeight / layerHeight
|
||||
if secondHeight == 0:
|
||||
endLayer = 0
|
||||
else:
|
||||
endLayer = secondHeight / layerHeight
|
||||
else: #layer height
|
||||
startLayer = firstHeight
|
||||
endLayer = secondHeight
|
||||
#see if one-shot
|
||||
if self.getSettingValueByKey("behavior") == "fixed_value":
|
||||
endLayer = startLayer
|
||||
firstExtruderIncrements = 0
|
||||
else: #blend
|
||||
firstExtruderIncrements = (SecondMix - firstMix) / (endLayer - startLayer)
|
||||
firstExtruderValue = 0
|
||||
index = 0
|
||||
#start scanning
|
||||
for active_layer in data:
|
||||
modified_gcode = ""
|
||||
lineIndex = 0;
|
||||
lines = active_layer.split("\n")
|
||||
for line in lines:
|
||||
#dont leave blanks
|
||||
if line != "":
|
||||
modified_gcode += line + "\n"
|
||||
# find current layer
|
||||
if ";LAYER:" in line:
|
||||
layer = self.getValue(line, ";LAYER:", layer)
|
||||
if (layer >= startLayer) and (layer <= endLayer): #find layers of interest
|
||||
if lines[lineIndex + 4] == "T2": #check if needing to delete old data
|
||||
del lines[(lineIndex + 1):(lineIndex + 5)]
|
||||
firstExtruderValue = int(((layer - startLayer) * firstExtruderIncrements) + firstMix)
|
||||
if firstExtruderValue == 100:
|
||||
modified_gcode += "M163 S0 P1\n"
|
||||
modified_gcode += "M163 S1 P0\n"
|
||||
elif firstExtruderValue == 0:
|
||||
modified_gcode += "M163 S0 P0\n"
|
||||
modified_gcode += "M163 S1 P1\n"
|
||||
else:
|
||||
modified_gcode += "M163 S0 P0.{:02d}\n".format(firstExtruderValue)
|
||||
modified_gcode += "M163 S1 P0.{:02d}\n".format(100 - firstExtruderValue)
|
||||
modified_gcode += "M164 S2\n"
|
||||
modified_gcode += "T2\n"
|
||||
lineIndex += 1 #for deleting index
|
||||
data[index] = modified_gcode
|
||||
index += 1
|
||||
return data
|
|
@ -1,7 +1,7 @@
|
|||
# Cura PostProcessingPlugin
|
||||
# Author: Mathias Lyngklip Kjeldgaard
|
||||
# Date: July 31, 2019
|
||||
# Modified: ---
|
||||
# Modified: November 26, 2019
|
||||
|
||||
# Description: This plugin displayes the remaining time on the LCD of the printer
|
||||
# using the estimated print-time generated by Cura.
|
||||
|
@ -23,7 +23,7 @@ class DisplayRemainingTimeOnLCD(Script):
|
|||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name":"Disaplay Remaining Time on LCD",
|
||||
"name":"Display Remaining Time on LCD",
|
||||
"key":"DisplayRemainingTimeOnLCD",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
|
@ -32,7 +32,7 @@ class DisplayRemainingTimeOnLCD(Script):
|
|||
"TurnOn":
|
||||
{
|
||||
"label": "Enable",
|
||||
"description": "When enabled, It will write Time Left: HHMMSS on the display",
|
||||
"description": "When enabled, It will write Time Left: HHMMSS on the display. This is updated every layer.",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ from UM.Logger import Logger
|
|||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Qt.Duration import DurationFormat
|
||||
|
||||
from cura import ApplicationMetadata
|
||||
|
||||
from .SliceInfoJob import SliceInfoJob
|
||||
|
||||
|
||||
|
@ -119,6 +121,7 @@ class SliceInfo(QObject, Extension):
|
|||
data["time_stamp"] = time.time()
|
||||
data["schema_version"] = 0
|
||||
data["cura_version"] = application.getVersion()
|
||||
data["cura_build_type"] = ApplicationMetadata.CuraBuildType
|
||||
|
||||
active_mode = Application.getInstance().getPreferences().getValue("cura/active_mode")
|
||||
if active_mode == 0:
|
||||
|
|
|
@ -125,11 +125,11 @@ class ZeroConfClient:
|
|||
if not info.address:
|
||||
info = zero_conf.get_service_info(service_type, name)
|
||||
|
||||
if info:
|
||||
if info and info.address:
|
||||
type_of_device = info.properties.get(b"type", None)
|
||||
if type_of_device:
|
||||
if type_of_device == b"printer":
|
||||
address = '.'.join(map(lambda n: str(n), info.address))
|
||||
address = '.'.join(map(str, info.address))
|
||||
self.addedNetworkCluster.emit(str(name), address, info.properties)
|
||||
else:
|
||||
Logger.log("w", "The type of the found device is '%s', not 'printer'." % type_of_device)
|
||||
|
|
|
@ -239,7 +239,7 @@ class VersionUpgrade41to42(VersionUpgrade):
|
|||
#
|
||||
# This renames the renamed settings in the containers.
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
|
|
|
@ -104,7 +104,7 @@ class VersionUpgrade42to43(VersionUpgrade):
|
|||
#
|
||||
# This renames the renamed settings in the containers.
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
|
|
|
@ -52,7 +52,7 @@ class VersionUpgrade43to44(VersionUpgrade):
|
|||
#
|
||||
# This renames the renamed settings in the containers.
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
import configparser
|
||||
from typing import Tuple, List
|
||||
import io
|
||||
from UM.VersionUpgrade import VersionUpgrade
|
||||
|
||||
# Merged preferences: machine_head_polygon and machine_head_with_fans_polygon -> machine_head_with_fans_polygon
|
||||
# When both are present, machine_head_polygon will be removed
|
||||
# When only one of the two is present, it's value will be used
|
||||
|
||||
|
||||
class VersionUpgrade44to45(VersionUpgrade):
|
||||
def getCfgVersion(self, serialised: str) -> int:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialised)
|
||||
format_version = int(parser.get("general", "version")) # Explicitly give an exception when this fails. That means that the file format is not recognised.
|
||||
setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
|
||||
return format_version * 1000000 + setting_version
|
||||
|
||||
## Upgrades Preferences to have the new version number.
|
||||
#
|
||||
# This renames the renamed settings in the list of visible settings.
|
||||
def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "11"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
## Upgrades instance containers to have the new version
|
||||
# number.
|
||||
#
|
||||
# This renames the renamed settings in the containers.
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "11"
|
||||
|
||||
if "values" in parser:
|
||||
# merge machine_head_with_fans_polygon (preferred) and machine_head_polygon
|
||||
if "machine_head_with_fans_polygon" in parser["values"]:
|
||||
if "machine_head_polygon" in parser["values"]:
|
||||
del parser["values"]["machine_head_polygon"]
|
||||
elif "machine_head_polygon" in parser["values"]:
|
||||
parser["values"]["machine_head_with_fans_polygon"] = parser["values"]["machine_head_polygon"]
|
||||
del parser["values"]["machine_head_polygon"]
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
## Upgrades stacks to have the new version number.
|
||||
def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
if "metadata" not in parser:
|
||||
parser["metadata"] = {}
|
||||
parser["metadata"]["setting_version"] = "11"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
61
plugins/VersionUpgrade/VersionUpgrade44to45/__init__.py
Normal file
61
plugins/VersionUpgrade/VersionUpgrade44to45/__init__.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Copyright (c) 2019 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import Any, Dict, TYPE_CHECKING
|
||||
|
||||
from . import VersionUpgrade44to45
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from UM.Application import Application
|
||||
|
||||
upgrade = VersionUpgrade44to45.VersionUpgrade44to45()
|
||||
|
||||
|
||||
def getMetaData() -> Dict[str, Any]:
|
||||
return {
|
||||
"version_upgrade": {
|
||||
# From To Upgrade function
|
||||
("preferences", 6000010): ("preferences", 6000011, upgrade.upgradePreferences),
|
||||
("machine_stack", 4000010): ("machine_stack", 4000011, upgrade.upgradeStack),
|
||||
("extruder_train", 4000010): ("extruder_train", 4000011, upgrade.upgradeStack),
|
||||
("definition_changes", 4000010): ("definition_changes", 4000011, upgrade.upgradeInstanceContainer),
|
||||
("quality_changes", 4000010): ("quality_changes", 4000011, upgrade.upgradeInstanceContainer),
|
||||
("quality", 4000010): ("quality", 4000011, upgrade.upgradeInstanceContainer),
|
||||
("user", 4000010): ("user", 4000011, upgrade.upgradeInstanceContainer),
|
||||
},
|
||||
"sources": {
|
||||
"preferences": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"."}
|
||||
},
|
||||
"machine_stack": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./machine_instances"}
|
||||
},
|
||||
"extruder_train": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./extruders"}
|
||||
},
|
||||
"definition_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./definition_changes"}
|
||||
},
|
||||
"quality_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality_changes"}
|
||||
},
|
||||
"quality": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality"}
|
||||
},
|
||||
"user": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./user"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def register(app: "Application") -> Dict[str, Any]:
|
||||
return {"version_upgrade": upgrade}
|
8
plugins/VersionUpgrade/VersionUpgrade44to45/plugin.json
Normal file
8
plugins/VersionUpgrade/VersionUpgrade44to45/plugin.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Version Upgrade 4.4 to 4.5",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"description": "Upgrades configurations from Cura 4.4 to Cura 4.5.",
|
||||
"api": "7.0",
|
||||
"i18n-catalog": "cura"
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import configparser
|
||||
|
||||
import VersionUpgrade44to45
|
||||
import pytest
|
||||
|
||||
before_update = """[general]
|
||||
version = 4
|
||||
name = Creality CR-10S_settings
|
||||
definition = creality_cr10s
|
||||
|
||||
[metadata]
|
||||
type = definition_changes
|
||||
setting_version = 11
|
||||
|
||||
[values]
|
||||
%s
|
||||
"""
|
||||
before_after_list = [
|
||||
("machine_head_with_fans_polygon = [[-99, 99], [-99, -44], [45, 99], [45, -44]]", "[[-99, 99], [-99, -44], [45, 99], [45, -44]]"),
|
||||
("", None),
|
||||
("machine_head_polygon = [[-98, 99], [-99, -44], [45, 99], [45, -44]]", "[[-98, 99], [-99, -44], [45, 99], [45, -44]]"),
|
||||
("machine_head_polygon = [[-87, 99], [-99, -44], [45, 99], [45, -44]]\nmachine_head_with_fans_polygon = [[-99, 99], [-99, -44], [45, 99], [45, -44]]", "[[-99, 99], [-99, -44], [45, 99], [45, -44]]"),
|
||||
]
|
||||
|
||||
|
||||
class TestVersionUpgrade44to45:
|
||||
|
||||
@pytest.mark.parametrize("after_string, after_value", before_after_list)
|
||||
def test_upgrade(self, after_string, after_value):
|
||||
upgrader = VersionUpgrade44to45.VersionUpgrade44to45()
|
||||
|
||||
|
||||
file_name, new_data = upgrader.upgradeInstanceContainer(before_update % after_string, "whatever")
|
||||
parser = configparser.ConfigParser(interpolation=None)
|
||||
parser.read_string(new_data[0])
|
||||
|
||||
if after_value is None:
|
||||
assert "machine_head_with_fans_polygon" not in parser["values"]
|
||||
else:
|
||||
assert parser["values"]["machine_head_with_fans_polygon"] == after_value
|
||||
|
||||
assert "machine_head_polygon" not in parser["values"]
|
|
@ -1104,6 +1104,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
"anti ooze retract speed": "material_anti_ooze_retraction_speed",
|
||||
"break preparation position": "material_break_preparation_retracted_position",
|
||||
"break preparation speed": "material_break_preparation_speed",
|
||||
"break preparation temperature": "material_break_preparation_temperature",
|
||||
"break position": "material_break_retracted_position",
|
||||
"break speed": "material_break_speed",
|
||||
"break temperature": "material_break_temperature"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue