mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-11-02 20:52:20 -07:00
Merge branch 'master' into marketplace_redesign
This commit is contained in:
commit
a878cfae7a
1092 changed files with 109052 additions and 89476 deletions
|
|
@ -49,7 +49,9 @@ _ignored_machine_network_metadata = {
|
|||
"removal_warning",
|
||||
"group_name",
|
||||
"group_size",
|
||||
"connection_type"
|
||||
"connection_type",
|
||||
"capabilities",
|
||||
"octoprint_api_key",
|
||||
} # type: Set[str]
|
||||
|
||||
|
||||
|
|
@ -377,7 +379,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
# - the global stack DOESN'T exist but some/all of the extruder stacks exist
|
||||
# To simplify this, only check if the global stack exists or not
|
||||
global_stack_id = self._stripFileToId(global_stack_file)
|
||||
|
||||
serialized = archive.open(global_stack_file).read().decode("utf-8")
|
||||
|
||||
serialized = GlobalStack._updateSerialized(serialized, global_stack_file)
|
||||
machine_name = self._getMachineNameFromSerializedStack(serialized)
|
||||
self._machine_info.metadata_dict = self._getMetaDataDictFromSerializedStack(serialized)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
Logger.error("3MF Writer class is unavailable. Can't write workspace.")
|
||||
return False
|
||||
|
||||
global_stack = machine_manager.activeMachine
|
||||
if global_stack is None:
|
||||
self.setInformation(catalog.i18nc("@error", "There is no workspace yet to write. Please add a printer first."))
|
||||
Logger.error("Tried to write a 3MF workspace before there was a global stack.")
|
||||
return False
|
||||
|
||||
# Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it).
|
||||
mesh_writer.setStoreArchive(True)
|
||||
mesh_writer.write(stream, nodes, mode)
|
||||
|
|
@ -40,7 +46,6 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
if archive is None: # This happens if there was no mesh data to write.
|
||||
archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED)
|
||||
|
||||
global_stack = machine_manager.activeMachine
|
||||
|
||||
try:
|
||||
# Add global container stack data to the archive.
|
||||
|
|
@ -149,7 +154,8 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
"group_name",
|
||||
"group_size",
|
||||
"connection_type",
|
||||
"octoprint_api_key"
|
||||
"capabilities",
|
||||
"octoprint_api_key",
|
||||
}
|
||||
serialized_data = container.serialize(ignored_metadata_keys = ignore_keys)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ from UM.Application import Application
|
|||
from UM.Scene.SceneNode import SceneNode
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Utils.Threading import call_on_qt_thread
|
||||
from cura.Snapshot import Snapshot
|
||||
|
||||
from PyQt5.QtCore import QBuffer
|
||||
|
||||
import Savitar
|
||||
|
||||
|
|
@ -149,6 +153,22 @@ class ThreeMFWriter(MeshWriter):
|
|||
relations_element = ET.Element("Relationships", xmlns = self._namespaces["relationships"])
|
||||
model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel")
|
||||
|
||||
# Attempt to add a thumbnail
|
||||
snapshot = self._createSnapshot()
|
||||
if snapshot:
|
||||
thumbnail_buffer = QBuffer()
|
||||
thumbnail_buffer.open(QBuffer.ReadWrite)
|
||||
snapshot.save(thumbnail_buffer, "PNG")
|
||||
|
||||
thumbnail_file = zipfile.ZipInfo("Metadata/thumbnail.png")
|
||||
# Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get
|
||||
archive.writestr(thumbnail_file, thumbnail_buffer.data())
|
||||
|
||||
# Add PNG to content types file
|
||||
thumbnail_type = ET.SubElement(content_types, "Default", Extension = "png", ContentType = "image/png")
|
||||
# Add thumbnail relation to _rels/.rels file
|
||||
thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/Metadata/thumbnail.png", Id = "rel1", Type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail")
|
||||
|
||||
savitar_scene = Savitar.Scene()
|
||||
|
||||
metadata_to_store = CuraApplication.getInstance().getController().getScene().getMetaData()
|
||||
|
|
@ -212,3 +232,17 @@ class ThreeMFWriter(MeshWriter):
|
|||
self._archive = archive
|
||||
|
||||
return True
|
||||
|
||||
@call_on_qt_thread # must be called from the main thread because of OpenGL
|
||||
def _createSnapshot(self):
|
||||
Logger.log("d", "Creating thumbnail image...")
|
||||
if not CuraApplication.getInstance().isVisible:
|
||||
Logger.log("w", "Can't create snapshot when renderer not initialized.")
|
||||
return None
|
||||
try:
|
||||
snapshot = Snapshot.snapshot(width = 300, height = 300)
|
||||
except:
|
||||
Logger.logException("w", "Failed to create snapshot image")
|
||||
return None
|
||||
|
||||
return snapshot
|
||||
|
|
|
|||
|
|
@ -123,6 +123,9 @@ class StartSliceJob(Job):
|
|||
Job.yieldThread()
|
||||
|
||||
for changed_setting_key in changed_setting_keys:
|
||||
if not stack.getProperty(changed_setting_key, "enabled"):
|
||||
continue
|
||||
|
||||
validation_state = stack.getProperty(changed_setting_key, "validationState")
|
||||
|
||||
if validation_state is None:
|
||||
|
|
|
|||
|
|
@ -261,7 +261,10 @@ class DigitalFactoryController(QObject):
|
|||
"""
|
||||
Error function, called whenever the retrieval of the files in a library project fails.
|
||||
"""
|
||||
Logger.log("w", "Failed to retrieve the list of files in project '{}' from the Digital Library".format(self._project_model._projects[self._selected_project_idx]))
|
||||
try:
|
||||
Logger.warning(f"Failed to retrieve the list of files in project '{self._project_model._projects[self._selected_project_idx]}' from the Digital Library")
|
||||
except IndexError:
|
||||
Logger.warning(f"Failed to retrieve the list of files in a project from the Digital Library. And failed to get the project too.")
|
||||
self.setRetrievingFilesStatus(RetrievalStatus.Failed)
|
||||
|
||||
@pyqtSlot()
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ class FlavorParser:
|
|||
|
||||
# Only when extruding we can determine the latest known "layer height" which is the difference in height between extrusions
|
||||
# Also, 1.5 is a heuristic for any priming or whatsoever, we skip those.
|
||||
if z > self._previous_z and (z - self._previous_z < 1.5):
|
||||
if z > self._previous_z and (z - self._previous_z < 1.5) and (params.x is not None or params.y is not None):
|
||||
self._current_layer_thickness = z - self._previous_z # allow a tiny overlap
|
||||
self._previous_z = z
|
||||
elif self._previous_extrusion_value > e[self._extruder_number]:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
# Modified by Jaime van Kessel (Ultimaker), j.vankessel@ultimaker.com to make it work for 15.10 / 2.x
|
||||
# Modified by Ghostkeeper (Ultimaker), rubend@tutanota.com, to debug.
|
||||
# Modified by Wes Hanney, https://github.com/novamxd, Retract Length + Speed, Clean up
|
||||
# Modified by Alex Jaxon, https://github.com/legend069, Added option to modify Build Volume Temperature
|
||||
|
||||
|
||||
# history / changelog:
|
||||
# V3.0.1: TweakAtZ-state default 1 (i.e. the plugin works without any TweakAtZ comment)
|
||||
|
|
@ -33,13 +35,17 @@
|
|||
# V5.0: Bugfix for fall back after one layer and doubled G0 commands when using print speed tweak, Initial version for Cura 2.x
|
||||
# V5.0.1: Bugfix for calling unknown property 'bedTemp' of previous settings storage and unknown variable 'speed'
|
||||
# V5.1: API Changes included for use with Cura 2.2
|
||||
# V5.2.0: Wes Hanney. Added support for changing Retract Length and Speed. Removed layer spread option. Fixed issue of cumulative ChangeZ
|
||||
# V5.2.0: Wes Hanney. Added support for changing Retract Length and Speed. Removed layer spread option. Fixed issue of cumulative ChangeAtZ
|
||||
# mods so they can now properly be stacked on top of each other. Applied code refactoring to clean up various coding styles. Added comments.
|
||||
# Broke up functions for clarity. Split up class so it can be debugged outside of Cura.
|
||||
# V5.2.1: Wes Hanney. Added support for firmware based retractions. Fixed issue of properly restoring previous values in single layer option.
|
||||
# Added support for outputting changes to LCD (untested). Added type hints to most functions and variables. Added more comments. Created GCodeCommand
|
||||
# class for better detection of G1 vs G10 or G11 commands, and accessing arguments. Moved most GCode methods to GCodeCommand class. Improved wording
|
||||
# of Single Layer vs Keep Layer to better reflect what was happening.
|
||||
# V5.3.0 Alex Jaxon, Added option to modify Build Volume Temperature keeping current format
|
||||
#
|
||||
|
||||
|
||||
|
||||
# Uses -
|
||||
# M220 S<factor in percent> - set speed factor override percentage
|
||||
|
|
@ -56,9 +62,9 @@ from ..Script import Script
|
|||
import re
|
||||
|
||||
|
||||
# this was broken up into a separate class so the main ChangeZ script could be debugged outside of Cura
|
||||
# this was broken up into a separate class so the main ChangeAtZ script could be debugged outside of Cura
|
||||
class ChangeAtZ(Script):
|
||||
version = "5.2.1"
|
||||
version = "5.3.0"
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
|
|
@ -69,10 +75,10 @@ class ChangeAtZ(Script):
|
|||
"settings": {
|
||||
"caz_enabled": {
|
||||
"label": "Enabled",
|
||||
"description": "Allows adding multiple ChangeZ mods and disabling them as needed.",
|
||||
"description": "Allows adding multiple ChangeAtZ mods and disabling them as needed.",
|
||||
"type": "bool",
|
||||
"default_value": true
|
||||
},
|
||||
},
|
||||
"a_trigger": {
|
||||
"label": "Trigger",
|
||||
"description": "Trigger at height or at layer no.",
|
||||
|
|
@ -119,7 +125,7 @@ class ChangeAtZ(Script):
|
|||
"description": "Displays the current changes to the LCD",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
},
|
||||
},
|
||||
"e1_Change_speed": {
|
||||
"label": "Change Speed",
|
||||
"description": "Select if total speed (print and travel) has to be changed",
|
||||
|
|
@ -222,6 +228,23 @@ class ChangeAtZ(Script):
|
|||
"maximum_value_warning": "120",
|
||||
"enabled": "h1_Change_bedTemp"
|
||||
},
|
||||
"h1_Change_buildVolumeTemperature": {
|
||||
"label": "Change Build Volume Temperature",
|
||||
"description": "Select if Build Volume Temperature has to be changed",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
},
|
||||
"h2_buildVolumeTemperature": {
|
||||
"label": "Build Volume Temperature",
|
||||
"description": "New Build Volume Temperature",
|
||||
"unit": "C",
|
||||
"type": "float",
|
||||
"default_value": 20,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "10",
|
||||
"maximum_value_warning": "50",
|
||||
"enabled": "h1_Change_buildVolumeTemperature"
|
||||
},
|
||||
"i1_Change_extruderOne": {
|
||||
"label": "Change Extruder 1 Temp",
|
||||
"description": "Select if First Extruder Temperature has to be changed",
|
||||
|
|
@ -278,25 +301,25 @@ class ChangeAtZ(Script):
|
|||
"description": "Indicates you would like to modify retraction properties.",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
},
|
||||
},
|
||||
"caz_retractstyle": {
|
||||
"label": "Retract Style",
|
||||
"description": "Specify if you're using firmware retraction or linear move based retractions. Check your printer settings to see which you're using.",
|
||||
"type": "enum",
|
||||
"options": {
|
||||
"linear": "Linear Move",
|
||||
"linear": "Linear Move",
|
||||
"firmware": "Firmware"
|
||||
},
|
||||
"default_value": "linear",
|
||||
"enabled": "caz_change_retract"
|
||||
},
|
||||
},
|
||||
"caz_change_retractfeedrate": {
|
||||
"label": "Change Retract Feed Rate",
|
||||
"description": "Changes the retraction feed rate during print",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": "caz_change_retract"
|
||||
},
|
||||
},
|
||||
"caz_retractfeedrate": {
|
||||
"label": "Retract Feed Rate",
|
||||
"description": "New Retract Feed Rate (mm/s)",
|
||||
|
|
@ -325,7 +348,7 @@ class ChangeAtZ(Script):
|
|||
"minimum_value_warning": "0",
|
||||
"maximum_value_warning": "20",
|
||||
"enabled": "caz_change_retractlength"
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
|
|
@ -345,6 +368,7 @@ class ChangeAtZ(Script):
|
|||
self.setIntSettingIfEnabled(caz_instance, "g3_Change_flowrateOne", "flowrateOne", "g4_flowrateOne")
|
||||
self.setIntSettingIfEnabled(caz_instance, "g5_Change_flowrateTwo", "flowrateTwo", "g6_flowrateTwo")
|
||||
self.setFloatSettingIfEnabled(caz_instance, "h1_Change_bedTemp", "bedTemp", "h2_bedTemp")
|
||||
self.setFloatSettingIfEnabled(caz_instance, "h1_Change_buildVolumeTemperature", "buildVolumeTemperature", "h2_buildVolumeTemperature")
|
||||
self.setFloatSettingIfEnabled(caz_instance, "i1_Change_extruderOne", "extruderOne", "i2_extruderOne")
|
||||
self.setFloatSettingIfEnabled(caz_instance, "i3_Change_extruderTwo", "extruderTwo", "i4_extruderTwo")
|
||||
self.setIntSettingIfEnabled(caz_instance, "j1_Change_fanSpeed", "fanSpeed", "j2_fanSpeed")
|
||||
|
|
@ -776,6 +800,10 @@ class ChangeAtZProcessor:
|
|||
if "bedTemp" in values:
|
||||
codes.append("BedTemp: " + str(round(values["bedTemp"])))
|
||||
|
||||
# looking for wait for Build Volume Temperature
|
||||
if "buildVolumeTemperature" in values:
|
||||
codes.append("buildVolumeTemperature: " + str(round(values["buildVolumeTemperature"])))
|
||||
|
||||
# set our extruder one temp (if specified)
|
||||
if "extruderOne" in values:
|
||||
codes.append("Extruder 1 Temp: " + str(round(values["extruderOne"])))
|
||||
|
|
@ -858,6 +886,10 @@ class ChangeAtZProcessor:
|
|||
if "bedTemp" in values:
|
||||
codes.append("M140 S" + str(values["bedTemp"]))
|
||||
|
||||
# looking for wait for Build Volume Temperature
|
||||
if "buildVolumeTemperature" in values:
|
||||
codes.append("M141 S" + str(values["buildVolumeTemperature"]))
|
||||
|
||||
# set our extruder one temp (if specified)
|
||||
if "extruderOne" in values:
|
||||
codes.append("M104 S" + str(values["extruderOne"]) + " T0")
|
||||
|
|
@ -943,7 +975,7 @@ class ChangeAtZProcessor:
|
|||
# nothing to do
|
||||
return ""
|
||||
|
||||
# Returns the unmodified GCODE line from previous ChangeZ edits
|
||||
# Returns the unmodified GCODE line from previous ChangeAtZ edits
|
||||
@staticmethod
|
||||
def getOriginalLine(line: str) -> str:
|
||||
|
||||
|
|
@ -990,7 +1022,7 @@ class ChangeAtZProcessor:
|
|||
else:
|
||||
return self.currentZ >= self.targetZ
|
||||
|
||||
# Marks any current ChangeZ layer defaults in the layer for deletion
|
||||
# Marks any current ChangeAtZ layer defaults in the layer for deletion
|
||||
@staticmethod
|
||||
def markChangesForDeletion(layer: str):
|
||||
return re.sub(r";\[CAZD:", ";[CAZD:DELETE:", layer)
|
||||
|
|
@ -1288,7 +1320,7 @@ class ChangeAtZProcessor:
|
|||
# flag that we're inside our target layer
|
||||
self.insideTargetLayer = True
|
||||
|
||||
# Removes all the ChangeZ layer defaults from the given layer
|
||||
# Removes all the ChangeAtZ layer defaults from the given layer
|
||||
@staticmethod
|
||||
def removeMarkedChanges(layer: str) -> str:
|
||||
return re.sub(r";\[CAZD:DELETE:[\s\S]+?:CAZD\](\n|$)", "", layer)
|
||||
|
|
@ -1364,6 +1396,16 @@ class ChangeAtZProcessor:
|
|||
# move to the next command
|
||||
return
|
||||
|
||||
# handle Build Volume Temperature changes, really shouldn't want to wait for enclousure temp mid print though.
|
||||
if command.command == "M141" or command.command == "M191":
|
||||
|
||||
# get our bed temp if provided
|
||||
if "S" in command.arguments:
|
||||
self.lastValues["buildVolumeTemperature"] = command.getArgumentAsFloat("S")
|
||||
|
||||
# move to the next command
|
||||
return
|
||||
|
||||
# handle extruder temp changes
|
||||
if command.command == "M104" or command.command == "M109":
|
||||
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ class PauseAtHeight(Script):
|
|||
|
||||
# Optionally extrude material
|
||||
if extrude_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = 200) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = 200) + "; Extra extrude after the unpause\n"
|
||||
prepend_gcode += self.putValue("@info wait for cleaning nozzle from previous filament") + "\n"
|
||||
prepend_gcode += self.putValue("@pause remove the waste filament from parking area and press continue printing") + "\n"
|
||||
|
||||
|
|
@ -479,7 +479,15 @@ class PauseAtHeight(Script):
|
|||
else:
|
||||
Logger.log("w", "No previous feedrate found in gcode, feedrate for next layer(s) might be incorrect")
|
||||
|
||||
prepend_gcode += self.putValue(M = 82) + "\n"
|
||||
extrusion_mode_string = "absolute"
|
||||
extrusion_mode_numeric = 82
|
||||
|
||||
relative_extrusion = Application.getInstance().getGlobalContainerStack().getProperty("relative_extrusion", "value")
|
||||
if relative_extrusion:
|
||||
extrusion_mode_string = "relative"
|
||||
extrusion_mode_numeric = 83
|
||||
|
||||
prepend_gcode += self.putValue(M = extrusion_mode_numeric) + " ; switch back to " + extrusion_mode_string + " E values\n"
|
||||
|
||||
# reset extrude value to pre pause value
|
||||
prepend_gcode += self.putValue(G = 92, E = current_e) + "\n"
|
||||
|
|
@ -489,18 +497,17 @@ class PauseAtHeight(Script):
|
|||
# Set extruder resume temperature
|
||||
prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, 0))) + " ; resume temperature\n"
|
||||
|
||||
# Push the filament back,
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
if extrude_amount != 0: # Need to prime after the pause.
|
||||
# Push the filament back.
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
|
||||
# Optionally extrude material
|
||||
if extrude_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = extrude_speed * 60) + "\n"
|
||||
# Prime the material.
|
||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = extrude_speed * 60) + "; Extra extrude after the unpause\n"
|
||||
|
||||
# and retract again, the properly primes the nozzle
|
||||
# when changing filament.
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
# And retract again to make the movements back to the starting position.
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
|
||||
# Move the head back
|
||||
if park_enabled:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2020 Ultimaker B.V.
|
||||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Math.Color import Color
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ vertex41core =
|
|||
value = (abs_value - min_value) / (max_value - min_value);
|
||||
}
|
||||
float red = value;
|
||||
float green = 1-abs(1-4*value);
|
||||
float green = 1.0 - abs(1.0 - 4.0 * value);
|
||||
if (value > 0.375)
|
||||
{
|
||||
green = 0.5;
|
||||
}
|
||||
float blue = max(1-4*value, 0);
|
||||
float blue = max(1.0 - 4.0 * value, 0.0);
|
||||
return vec4(red, green, blue, 1.0);
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ vertex41core =
|
|||
{
|
||||
value = (abs_value - min_value) / (max_value - min_value);
|
||||
}
|
||||
float red = min(max(4*value-2, 0), 1);
|
||||
float red = min(max(4.0 * value - 2.0, 0.0), 1.0);
|
||||
float green = min(1.5*value, 0.75);
|
||||
if (value > 0.75)
|
||||
{
|
||||
|
|
@ -98,18 +98,18 @@ vertex41core =
|
|||
value = (abs_value - min_value) / (max_value - min_value);
|
||||
}
|
||||
float red = value;
|
||||
float green = 1 - abs(1 - 4 * value);
|
||||
float green = 1.0 - abs(1.0 - 4.0 * value);
|
||||
if(value > 0.375)
|
||||
{
|
||||
green = 0.5;
|
||||
}
|
||||
float blue = max(1 - 4 * value, 0);
|
||||
float blue = max(1.0 - 4.0 * value, 0.0);
|
||||
return vec4(red, green, blue, 1.0);
|
||||
}
|
||||
|
||||
float clamp(float v)
|
||||
{
|
||||
float t = v < 0 ? 0 : v;
|
||||
float t = v < 0.0 ? 0.0 : v;
|
||||
return t > 1.0 ? 1.0 : t;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Simulation View",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.1",
|
||||
"description": "Provides the Simulation view.",
|
||||
"description": "Provides the preview of sliced layerdata.",
|
||||
"api": 7,
|
||||
"i18n-catalog": "cura"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from PyQt5.QtWidgets import QApplication
|
|||
|
||||
from UM.Application import Application
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Operations.TranslateOperation import TranslateOperation
|
||||
from UM.Tool import Tool
|
||||
from UM.Event import Event, MouseEvent
|
||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||
|
|
@ -120,8 +121,8 @@ class SupportEraser(Tool):
|
|||
# First add node to the scene at the correct position/scale, before parenting, so the eraser mesh does not get scaled with the parent
|
||||
op.addOperation(AddSceneNodeOperation(node, self._controller.getScene().getRoot()))
|
||||
op.addOperation(SetParentOperation(node, parent))
|
||||
op.addOperation(TranslateOperation(node, position, set_position = True))
|
||||
op.push()
|
||||
node.setPosition(position, CuraSceneNode.TransformSpace.World)
|
||||
|
||||
CuraApplication.getInstance().getController().getScene().sceneChanged.emit(node)
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class CloudPackageChecker(QObject):
|
|||
self._application.getHttpRequestManager().get(url,
|
||||
callback = self._onUserPackagesRequestFinished,
|
||||
error_callback = self._onUserPackagesRequestFinished,
|
||||
timeout=10,
|
||||
timeout = 10,
|
||||
scope = self._scope)
|
||||
|
||||
def _onUserPackagesRequestFinished(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"] = None) -> None:
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"description": "Provides support for reading Ultimaker Format Packages.",
|
||||
"supported_sdk_versions": ["7.8.0"],
|
||||
"supported_sdk_versions": ["7.9.0"],
|
||||
"i18n-catalog": "cura"
|
||||
}
|
||||
|
|
@ -73,6 +73,8 @@ Item
|
|||
switch (printJob.state)
|
||||
{
|
||||
case "wait_cleanup":
|
||||
// This hack was removed previously. Then we found out that we don't get back 'aborted_wait_cleanup'
|
||||
// for the UM2+C it seems. Will communicate this to other teams, in the mean time, put this back.
|
||||
if (printJob.timeTotal > printJob.timeElapsed)
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
|
|
@ -88,6 +90,20 @@ Item
|
|||
return catalog.i18nc("@label:status", "Aborting...");
|
||||
case "aborted": // NOTE: Unused, see above
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
case "aborted_post_print":
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
case "aborted_wait_user_action":
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
case "aborted_wait_cleanup":
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
case "failed":
|
||||
return catalog.i18nc("@label:status", "Failed");
|
||||
case "failed_post_print":
|
||||
return catalog.i18nc("@label:status", "Failed");
|
||||
case "failed_wait_user_action":
|
||||
return catalog.i18nc("@label:status", "Failed");
|
||||
case "failed_wait_cleanup":
|
||||
return catalog.i18nc("@label:status", "Failed");
|
||||
case "pausing":
|
||||
return catalog.i18nc("@label:status", "Pausing...");
|
||||
case "paused":
|
||||
|
|
@ -97,7 +113,7 @@ Item
|
|||
case "queued":
|
||||
return catalog.i18nc("@label:status", "Action required");
|
||||
default:
|
||||
return catalog.i18nc("@label:status", "Finishes %1 at %2".arg(OutputDevice.getDateCompleted(printJob.timeRemaining)).arg(OutputDevice.getTimeCompleted(printJob.timeRemaining)));
|
||||
return catalog.i18nc("@label:status", "Finishes %1 at %2").arg(OutputDevice.getDateCompleted(printJob.timeRemaining)).arg(OutputDevice.getTimeCompleted(printJob.timeRemaining));
|
||||
}
|
||||
}
|
||||
width: contentWidth
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2020 Ultimaker B.V.
|
||||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import os
|
||||
|
|
@ -16,9 +16,10 @@ from UM.Util import parseBool
|
|||
from cura.API import Account
|
||||
from cura.API.Account import SyncState
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To update printer metadata with information received about cloud printers.
|
||||
from cura.Settings.CuraStackBuilder import CuraStackBuilder
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from cura.UltimakerCloud.UltimakerCloudConstants import META_UM_LINKED_TO_ACCOUNT
|
||||
from cura.UltimakerCloud.UltimakerCloudConstants import META_CAPABILITIES, META_UM_LINKED_TO_ACCOUNT
|
||||
from .CloudApiClient import CloudApiClient
|
||||
from .CloudOutputDevice import CloudOutputDevice
|
||||
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
||||
|
|
@ -127,8 +128,12 @@ class CloudOutputDeviceManager:
|
|||
# to the current account
|
||||
if not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")):
|
||||
self._um_cloud_printers[device_id].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True)
|
||||
if not self._um_cloud_printers[device_id].getMetaDataEntry(META_CAPABILITIES, None):
|
||||
self._um_cloud_printers[device_id].setMetaDataEntry(META_CAPABILITIES, ",".join(cluster_data.capabilities))
|
||||
self._onDevicesDiscovered(new_clusters)
|
||||
|
||||
self._updateOnlinePrinters(all_clusters)
|
||||
|
||||
# Hide the current removed_printers_message, if there is any
|
||||
if self._removed_printers_message:
|
||||
self._removed_printers_message.actionTriggered.disconnect(self._onRemovedPrintersMessageActionTriggered)
|
||||
|
|
@ -154,6 +159,8 @@ class CloudOutputDeviceManager:
|
|||
self._syncing = False
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SUCCESS)
|
||||
|
||||
Logger.debug("Synced cloud printers with account.")
|
||||
|
||||
def _onGetRemoteClusterFailed(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None:
|
||||
self._syncing = False
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR)
|
||||
|
|
@ -255,6 +262,16 @@ class CloudOutputDeviceManager:
|
|||
message_text = self.i18n_catalog.i18nc("info:status", "Printers added from Digital Factory:") + "<ul>" + device_names + "</ul>"
|
||||
message.setText(message_text)
|
||||
|
||||
def _updateOnlinePrinters(self, printer_responses: Dict[str, CloudClusterResponse]) -> None:
|
||||
"""
|
||||
Update the metadata of the printers to store whether they are online or not.
|
||||
:param printer_responses: The responses received from the API about the printer statuses.
|
||||
"""
|
||||
for container_stack in CuraContainerRegistry.getInstance().findContainerStacks(type = "machine"):
|
||||
cluster_id = container_stack.getMetaDataEntry("um_cloud_cluster_id", "")
|
||||
if cluster_id in printer_responses:
|
||||
container_stack.setMetaDataEntry("is_online", printer_responses[cluster_id].is_online)
|
||||
|
||||
def _updateOutdatedMachine(self, outdated_machine: GlobalStack, new_cloud_output_device: CloudOutputDevice) -> None:
|
||||
"""
|
||||
Update the cloud metadata of a pre-existing machine that is rediscovered (e.g. if the printer was removed and
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class CloudClusterResponse(BaseModel):
|
|||
self.friendly_name = friendly_name
|
||||
self.printer_type = printer_type
|
||||
self.printer_count = printer_count
|
||||
self.capabilities = capabilities
|
||||
self.capabilities = capabilities if capabilities is not None else []
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# Validates the model, raising an exception if the model is invalid.
|
||||
|
|
@ -45,3 +45,10 @@ class CloudClusterResponse(BaseModel):
|
|||
super().validate()
|
||||
if not self.cluster_id:
|
||||
raise ValueError("cluster_id is required on CloudCluster")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Convenience function for printing when debugging.
|
||||
:return: A human-readable representation of the data in this object.
|
||||
"""
|
||||
return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}})
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class ClusterPrintJobStatus(BaseModel):
|
|||
configuration_changes_required: List[
|
||||
Union[Dict[str, Any], ClusterPrintJobConfigurationChange]] = None,
|
||||
build_plate: Union[Dict[str, Any], ClusterBuildPlate] = None,
|
||||
compatible_machine_families: List[str] = None,
|
||||
compatible_machine_families: Optional[List[str]] = None,
|
||||
impediments_to_printing: List[Union[Dict[str, Any], ClusterPrintJobImpediment]] = None,
|
||||
preview_url: Optional[str] = None,
|
||||
**kwargs) -> None:
|
||||
|
|
@ -97,7 +97,7 @@ class ClusterPrintJobStatus(BaseModel):
|
|||
configuration_changes_required) \
|
||||
if configuration_changes_required else []
|
||||
self.build_plate = self.parseModel(ClusterBuildPlate, build_plate) if build_plate else None
|
||||
self.compatible_machine_families = compatible_machine_families if compatible_machine_families else []
|
||||
self.compatible_machine_families = compatible_machine_families if compatible_machine_families is not None else []
|
||||
self.impediments_to_printing = self.parseModels(ClusterPrintJobImpediment, impediments_to_printing) \
|
||||
if impediments_to_printing else []
|
||||
|
||||
|
|
@ -130,8 +130,10 @@ class ClusterPrintJobStatus(BaseModel):
|
|||
|
||||
model.updateConfiguration(self._createConfigurationModel())
|
||||
model.updateTimeTotal(self.time_total)
|
||||
model.updateTimeElapsed(self.time_elapsed)
|
||||
model.updateOwner(self.owner)
|
||||
if self.time_elapsed is not None:
|
||||
model.updateTimeElapsed(self.time_elapsed)
|
||||
if self.owner is not None:
|
||||
model.updateOwner(self.owner)
|
||||
model.updateState(self.status)
|
||||
model.setCompatibleMachineFamilies(self.compatible_machine_families)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import configparser
|
||||
import io
|
||||
import json
|
||||
import os.path
|
||||
from typing import List, Tuple
|
||||
|
||||
|
|
@ -49,6 +50,28 @@ class VersionUpgrade411to412(VersionUpgrade):
|
|||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "19"
|
||||
|
||||
# If the account scope in 4.11 is outdated, delete it so that the user is enforced to log in again and get the
|
||||
# correct permissions.
|
||||
new_scopes = {"account.user.read",
|
||||
"drive.backup.read",
|
||||
"drive.backup.write",
|
||||
"packages.download",
|
||||
"packages.rating.read",
|
||||
"packages.rating.write",
|
||||
"connect.cluster.read",
|
||||
"connect.cluster.write",
|
||||
"library.project.read",
|
||||
"library.project.write",
|
||||
"cura.printjob.read",
|
||||
"cura.printjob.write",
|
||||
"cura.mesh.read",
|
||||
"cura.mesh.write",
|
||||
"cura.material.write"}
|
||||
if "ultimaker_auth_data" in parser["general"]:
|
||||
ultimaker_auth_data = json.loads(parser["general"]["ultimaker_auth_data"])
|
||||
if new_scopes - set(ultimaker_auth_data["scope"].split(" ")):
|
||||
parser["general"]["ultimaker_auth_data"] = "{}"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser
|
||||
from typing import Tuple, List
|
||||
import io
|
||||
from UM.VersionUpgrade import VersionUpgrade
|
||||
|
||||
_removed_settings = {
|
||||
"travel_compensate_overlapping_walls_enabled",
|
||||
"travel_compensate_overlapping_walls_0_enabled",
|
||||
"travel_compensate_overlapping_walls_x_enabled",
|
||||
"fill_perimeter_gaps",
|
||||
"wall_min_flow",
|
||||
"wall_min_flow_retract",
|
||||
"speed_equalize_flow_enabled",
|
||||
"speed_equalize_flow_min"
|
||||
}
|
||||
|
||||
|
||||
class VersionUpgrade49to50(VersionUpgrade):
|
||||
def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades preferences to remove from the visibility list the settings that were removed in this version.
|
||||
It also changes the preferences to have the new version number.
|
||||
|
||||
This removes any settings that were removed in the new Cura version.
|
||||
:param serialized: The original contents of the preferences file.
|
||||
:param filename: The file name of the preferences file.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "18"
|
||||
|
||||
# Remove deleted settings from the visible settings list.
|
||||
if "general" in parser and "visible_settings" in parser["general"]:
|
||||
visible_settings = set(parser["general"]["visible_settings"].split(";"))
|
||||
for removed in _removed_settings:
|
||||
if removed in visible_settings:
|
||||
visible_settings.remove(removed)
|
||||
|
||||
# Replace Outer Before Inner Walls with equivalent.
|
||||
if "outer_inset_first" in visible_settings:
|
||||
visible_settings.remove("outer_inset_first")
|
||||
visible_settings.add("inset_direction")
|
||||
|
||||
parser["general"]["visible_settings"] = ";".join(visible_settings)
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades instance containers to remove the settings that were removed in this version.
|
||||
It also changes the instance containers to have the new version number.
|
||||
|
||||
This removes any settings that were removed in the new Cura version and updates settings that need to be updated
|
||||
with a new value.
|
||||
|
||||
:param serialized: The original contents of the instance container.
|
||||
:param filename: The original file name of the instance container.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes = ())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "18"
|
||||
|
||||
if "values" in parser:
|
||||
# Remove deleted settings from the instance containers.
|
||||
for removed in _removed_settings:
|
||||
if removed in parser["values"]:
|
||||
del parser["values"][removed]
|
||||
|
||||
# Replace Outer Before Inner Walls with equivalent setting.
|
||||
if "outer_inset_first" in parser["values"]:
|
||||
old_value = parser["values"]["outer_inset_first"]
|
||||
if old_value.startswith("="): # Was already a formula.
|
||||
old_value = old_value[1:]
|
||||
parser["values"]["inset_direction"] = f"='outside_in' if ({old_value}) else 'inside_out'" # Makes it work both with plain setting values and formulas.
|
||||
|
||||
# Disable Fuzzy Skin as it doesn't work with with the libArachne walls
|
||||
if "magic_fuzzy_skin_enabled" in parser["values"]:
|
||||
parser["values"]["magic_fuzzy_skin_enabled"] = "False"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades stacks to have the new version number.
|
||||
|
||||
:param serialized: The original contents of the stack.
|
||||
:param filename: The original file name of the stack.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
if "metadata" not in parser:
|
||||
parser["metadata"] = {}
|
||||
|
||||
parser["general"]["version"] = "5"
|
||||
parser["metadata"]["setting_version"] = "18"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
61
plugins/VersionUpgrade/VersionUpgrade49to50/__init__.py
Normal file
61
plugins/VersionUpgrade/VersionUpgrade49to50/__init__.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Copyright (c) 2020 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import Any, Dict, TYPE_CHECKING
|
||||
|
||||
from . import VersionUpgrade49to50
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from UM.Application import Application
|
||||
|
||||
upgrade = VersionUpgrade49to50.VersionUpgrade49to50()
|
||||
|
||||
def getMetaData() -> Dict[str, Any]:
|
||||
return { # Since there is no VersionUpgrade from 48 to 49 yet, upgrade the 48 profiles to 50.
|
||||
"version_upgrade": {
|
||||
# From To Upgrade function
|
||||
("preferences", 6000016): ("preferences", 6000018, upgrade.upgradePreferences),
|
||||
("machine_stack", 5000016): ("machine_stack", 5000018, upgrade.upgradeStack),
|
||||
("extruder_train", 5000016): ("extruder_train", 5000018, upgrade.upgradeStack),
|
||||
("machine_stack", 4000018): ("machine_stack", 5000018, upgrade.upgradeStack), # We made a mistake in the arachne beta 1
|
||||
("extruder_train", 4000018): ("extruder_train", 5000018, upgrade.upgradeStack), # We made a mistake in the arachne beta 1
|
||||
("definition_changes", 4000016): ("definition_changes", 4000018, upgrade.upgradeInstanceContainer),
|
||||
("quality_changes", 4000016): ("quality_changes", 4000018, upgrade.upgradeInstanceContainer),
|
||||
("quality", 4000016): ("quality", 4000018, upgrade.upgradeInstanceContainer),
|
||||
("user", 4000016): ("user", 4000018, 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/VersionUpgrade49to50/plugin.json
Normal file
8
plugins/VersionUpgrade/VersionUpgrade49to50/plugin.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Version Upgrade 4.9 to 5.0",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"description": "Upgrades configurations from Cura 4.9 to Cura 5.0.",
|
||||
"api": "7.4.0",
|
||||
"i18n-catalog": "cura"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue