mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 14:37:29 -06:00
Merge branch 'Ultimaker:main' into main
This commit is contained in:
commit
86576c6fbc
287 changed files with 72757 additions and 69638 deletions
|
@ -17,6 +17,7 @@ from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
|||
from UM.Scene.GroupDecorator import GroupDecorator
|
||||
from UM.Scene.SceneNode import SceneNode # For typing.
|
||||
from UM.Scene.SceneNodeSettings import SceneNodeSettings
|
||||
from UM.Util import parseBool
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Machines.ContainerTree import ContainerTree
|
||||
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
|
||||
|
@ -182,7 +183,7 @@ class ThreeMFReader(MeshReader):
|
|||
um_node.printOrder = int(setting_value)
|
||||
continue
|
||||
if key =="drop_to_buildplate":
|
||||
um_node.setSetting(SceneNodeSettings.AutoDropDown, eval(setting_value))
|
||||
um_node.setSetting(SceneNodeSettings.AutoDropDown, parseBool(setting_value))
|
||||
continue
|
||||
if key in known_setting_keys:
|
||||
setting_container.setProperty(key, "value", setting_value)
|
||||
|
|
|
@ -114,22 +114,24 @@ class ThreeMFWriter(MeshWriter):
|
|||
|
||||
mesh_data = um_node.getMeshData()
|
||||
|
||||
node_matrix = um_node.getLocalTransformation()
|
||||
node_matrix.preMultiply(transformation)
|
||||
|
||||
if center_mesh:
|
||||
node_matrix = Matrix()
|
||||
center_matrix = Matrix()
|
||||
# compensate for original center position, if object(s) is/are not around its zero position
|
||||
if mesh_data is not None:
|
||||
extents = mesh_data.getExtents()
|
||||
if extents is not None:
|
||||
# We use a different coordinate space while writing, so flip Z and Y
|
||||
center_vector = Vector(extents.center.x, extents.center.y, extents.center.z)
|
||||
node_matrix.setByTranslation(center_vector)
|
||||
node_matrix.multiply(um_node.getLocalTransformation())
|
||||
else:
|
||||
node_matrix = um_node.getLocalTransformation()
|
||||
center_vector = Vector(-extents.center.x, -extents.center.y, -extents.center.z)
|
||||
center_matrix.setByTranslation(center_vector)
|
||||
node_matrix.preMultiply(center_matrix)
|
||||
|
||||
matrix_string = ThreeMFWriter._convertMatrixToString(node_matrix.preMultiply(transformation))
|
||||
matrix_string = ThreeMFWriter._convertMatrixToString(node_matrix)
|
||||
|
||||
savitar_node.setTransformation(matrix_string)
|
||||
|
||||
if mesh_data is not None:
|
||||
savitar_node.getMeshData().setVerticesFromBytes(mesh_data.getVerticesAsByteArray())
|
||||
indices_array = mesh_data.getIndicesAsByteArray()
|
||||
|
|
|
@ -366,7 +366,12 @@ class StartSliceJob(Job):
|
|||
for extruder_stack in global_stack.extruderList:
|
||||
self._buildExtruderMessage(extruder_stack)
|
||||
|
||||
for plugin in CuraApplication.getInstance().getBackendPlugins():
|
||||
backend_plugins = CuraApplication.getInstance().getBackendPlugins()
|
||||
|
||||
# Sort backend plugins by name. Not a very good strategy, but at least it is repeatable. This will be improved later.
|
||||
backend_plugins = sorted(backend_plugins, key=lambda backend_plugin: backend_plugin.getId())
|
||||
|
||||
for plugin in backend_plugins:
|
||||
if not plugin.usePlugin():
|
||||
continue
|
||||
for slot in plugin.getSupportedSlots():
|
||||
|
@ -555,12 +560,16 @@ class StartSliceJob(Job):
|
|||
start_gcode = settings["machine_start_gcode"]
|
||||
# Remove all the comments from the start g-code
|
||||
start_gcode = re.sub(r";.+?(\n|$)", "\n", start_gcode)
|
||||
bed_temperature_settings = ["material_bed_temperature", "material_bed_temperature_layer_0"]
|
||||
pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(bed_temperature_settings) # match {setting} as well as {setting, extruder_nr}
|
||||
settings["material_bed_temp_prepend"] = re.search(pattern, start_gcode) == None
|
||||
print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature", "print_temperature"]
|
||||
pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
|
||||
settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) is None
|
||||
|
||||
if settings["material_bed_temp_prepend"]:
|
||||
bed_temperature_settings = ["material_bed_temperature", "material_bed_temperature_layer_0"]
|
||||
pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(bed_temperature_settings) # match {setting} as well as {setting, extruder_nr}
|
||||
settings["material_bed_temp_prepend"] = re.search(pattern, start_gcode) == None
|
||||
|
||||
if settings["material_print_temp_prepend"]:
|
||||
print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature", "print_temperature"]
|
||||
pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
|
||||
settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) is None
|
||||
|
||||
# Replace the setting tokens in start and end g-code.
|
||||
# Use values from the first used extruder by default so we get the expected temperatures
|
||||
|
|
|
@ -208,7 +208,7 @@ Item
|
|||
anchors.rightMargin: UM.Theme.getSize("thin_margin").height
|
||||
|
||||
enabled: UM.Backend.state == UM.Backend.Done
|
||||
currentIndex: UM.Backend.state == UM.Backend.Done ? dfFilenameTextfield.text.startsWith("MM")? 1 : 0 : 2
|
||||
currentIndex: UM.Backend.state == UM.Backend.Done ? (Cura.MachineManager.activeMachine.getOutputFileFormats.includes("application/x-makerbot") ? 1 : 0) : 2
|
||||
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2023 UltiMaker
|
||||
# Copyright (c) 2024 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from io import StringIO, BufferedIOBase
|
||||
import json
|
||||
|
@ -18,6 +18,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
|||
from UM.i18n import i18nCatalog
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||
from cura.Snapshot import Snapshot
|
||||
from cura.Utils.Threading import call_on_qt_thread
|
||||
from cura.CuraVersion import ConanInstalls
|
||||
|
@ -137,6 +138,30 @@ class MakerbotWriter(MeshWriter):
|
|||
for png_file in png_files:
|
||||
file, data = png_file["file"], png_file["data"]
|
||||
zip_stream.writestr(file, data)
|
||||
api = CuraApplication.getInstance().getCuraAPI()
|
||||
metadata_json = api.interface.settings.getSliceMetadata()
|
||||
|
||||
# All the mapping stuff we have to do:
|
||||
product_to_id_map = FormatMaps.getProductIdMap()
|
||||
printer_name_map = FormatMaps.getInversePrinterNameMap()
|
||||
extruder_type_map = FormatMaps.getInverseExtruderTypeMap()
|
||||
material_map = FormatMaps.getInverseMaterialMap()
|
||||
for key, value in metadata_json.items():
|
||||
if "all_settings" in value:
|
||||
if "machine_name" in value["all_settings"]:
|
||||
machine_name = value["all_settings"]["machine_name"]
|
||||
if machine_name in product_to_id_map:
|
||||
machine_name = product_to_id_map[machine_name][0]
|
||||
value["all_settings"]["machine_name"] = printer_name_map.get(machine_name, machine_name)
|
||||
if "machine_nozzle_id" in value["all_settings"]:
|
||||
extruder_type = value["all_settings"]["machine_nozzle_id"]
|
||||
value["all_settings"]["machine_nozzle_id"] = extruder_type_map.get(extruder_type, extruder_type)
|
||||
if "material_type" in value["all_settings"]:
|
||||
material_type = value["all_settings"]["material_type"]
|
||||
value["all_settings"]["material_type"] = material_map.get(material_type, material_type)
|
||||
|
||||
slice_metadata = json.dumps(metadata_json, separators=(", ", ": "), indent=4)
|
||||
zip_stream.writestr("slicemetadata.json", slice_metadata)
|
||||
except (IOError, OSError, BadZipFile) as ex:
|
||||
Logger.log("e", f"Could not write to (.makerbot) file because: '{ex}'.")
|
||||
self.setInformation(catalog.i18nc("@error", "MakerbotWriter could not save to the designated path."))
|
||||
|
@ -231,7 +256,7 @@ class MakerbotWriter(MeshWriter):
|
|||
"printMode": CuraApplication.getInstance().getIntentManager().currentIntentCategory,
|
||||
}
|
||||
|
||||
meta["miracle_config"] = {"gaggles": {str(node.getName()): {} for node in nodes}}
|
||||
meta["miracle_config"] = {"gaggles": {"instance0": {}}}
|
||||
|
||||
version_info = dict()
|
||||
cura_engine_info = ConanInstalls.get("curaengine", {"version": "unknown", "revision": "unknown"})
|
||||
|
|
|
@ -24,6 +24,7 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
|||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from cura.Utils.Threading import call_on_qt_thread
|
||||
from cura.API import CuraAPI
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
|
||||
|
@ -85,7 +86,8 @@ class UFPWriter(MeshWriter):
|
|||
try:
|
||||
archive.addContentType(extension="json", mime_type="application/json")
|
||||
setting_textio = StringIO()
|
||||
json.dump(self._getSliceMetadata(), setting_textio, separators=(", ", ": "), indent=4)
|
||||
api = CuraApplication.getInstance().getCuraAPI()
|
||||
json.dump(api.interface.settings.getSliceMetadata(), setting_textio, separators=(", ", ": "), indent=4)
|
||||
steam = archive.getStream(SLICE_METADATA_PATH)
|
||||
steam.write(setting_textio.getvalue().encode("UTF-8"))
|
||||
except EnvironmentError as e:
|
||||
|
@ -210,57 +212,3 @@ class UFPWriter(MeshWriter):
|
|||
return [{"name": item.getName()}
|
||||
for item in DepthFirstIterator(node)
|
||||
if item.getMeshData() is not None and not item.callDecoration("isNonPrintingMesh")]
|
||||
|
||||
def _getSliceMetadata(self) -> Dict[str, Dict[str, Dict[str, str]]]:
|
||||
"""Get all changed settings and all settings. For each extruder and the global stack"""
|
||||
print_information = CuraApplication.getInstance().getPrintInformation()
|
||||
machine_manager = CuraApplication.getInstance().getMachineManager()
|
||||
settings = {
|
||||
"material": {
|
||||
"length": print_information.materialLengths,
|
||||
"weight": print_information.materialWeights,
|
||||
"cost": print_information.materialCosts,
|
||||
},
|
||||
"global": {
|
||||
"changes": {},
|
||||
"all_settings": {},
|
||||
},
|
||||
"quality": asdict(machine_manager.activeQualityDisplayNameMap()),
|
||||
}
|
||||
|
||||
def _retrieveValue(container: InstanceContainer, setting_: str):
|
||||
value_ = container.getProperty(setting_, "value")
|
||||
for _ in range(0, 1024): # Prevent possibly endless loop by not using a limit.
|
||||
if not isinstance(value_, SettingFunction):
|
||||
return value_ # Success!
|
||||
value_ = value_(container)
|
||||
return 0 # Fallback value after breaking possibly endless loop.
|
||||
|
||||
global_stack = cast(GlobalStack, Application.getInstance().getGlobalContainerStack())
|
||||
|
||||
# Add global user or quality changes
|
||||
global_flattened_changes = InstanceContainer.createMergedInstanceContainer(global_stack.userChanges, global_stack.qualityChanges)
|
||||
for setting in global_flattened_changes.getAllKeys():
|
||||
settings["global"]["changes"][setting] = _retrieveValue(global_flattened_changes, setting)
|
||||
|
||||
# Get global all settings values without user or quality changes
|
||||
for setting in global_stack.getAllKeys():
|
||||
settings["global"]["all_settings"][setting] = _retrieveValue(global_stack, setting)
|
||||
|
||||
for i, extruder in enumerate(global_stack.extruderList):
|
||||
# Add extruder fields to settings dictionary
|
||||
settings[f"extruder_{i}"] = {
|
||||
"changes": {},
|
||||
"all_settings": {},
|
||||
}
|
||||
|
||||
# Add extruder user or quality changes
|
||||
extruder_flattened_changes = InstanceContainer.createMergedInstanceContainer(extruder.userChanges, extruder.qualityChanges)
|
||||
for setting in extruder_flattened_changes.getAllKeys():
|
||||
settings[f"extruder_{i}"]["changes"][setting] = _retrieveValue(extruder_flattened_changes, setting)
|
||||
|
||||
# Get extruder all settings values without user or quality changes
|
||||
for setting in extruder.getAllKeys():
|
||||
settings[f"extruder_{i}"]["all_settings"][setting] = _retrieveValue(extruder, setting)
|
||||
|
||||
return settings
|
||||
|
|
|
@ -17,6 +17,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
|
|||
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||
from cura.Machines.VariantType import VariantType
|
||||
|
||||
try:
|
||||
|
@ -249,7 +250,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
machine_variant_map[definition_id][variant_name] = variant_dict
|
||||
|
||||
# Map machine human-readable names to IDs
|
||||
product_id_map = self.getProductIdMap()
|
||||
product_id_map = FormatMaps.getProductIdMap()
|
||||
|
||||
for definition_id, container in machine_container_map.items():
|
||||
definition_id = container.getMetaDataEntry("definition")
|
||||
|
@ -647,7 +648,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
self._dirty = False
|
||||
|
||||
# Map machine human-readable names to IDs
|
||||
product_id_map = self.getProductIdMap()
|
||||
product_id_map = FormatMaps.getProductIdMap()
|
||||
|
||||
machines = data.iterfind("./um:settings/um:machine", self.__namespaces)
|
||||
for machine in machines:
|
||||
|
@ -923,7 +924,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
result_metadata.append(base_metadata)
|
||||
|
||||
# Map machine human-readable names to IDs
|
||||
product_id_map = cls.getProductIdMap()
|
||||
product_id_map = FormatMaps.getProductIdMap()
|
||||
|
||||
for machine in data.iterfind("./um:settings/um:machine", cls.__namespaces):
|
||||
machine_compatibility = common_compatibility
|
||||
|
@ -1083,10 +1084,9 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
# Skip material properties (eg diameter) or metadata (eg GUID)
|
||||
return
|
||||
|
||||
if instance.value is True:
|
||||
data = "yes"
|
||||
elif instance.value is False:
|
||||
data = "no"
|
||||
truth_map = { True: "yes", False: "no" }
|
||||
if tag_name != "cura:setting" and instance.value in truth_map:
|
||||
data = truth_map[instance.value]
|
||||
else:
|
||||
data = str(instance.value)
|
||||
|
||||
|
@ -1129,29 +1129,6 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
id_list = list(id_list)
|
||||
return id_list
|
||||
|
||||
__product_to_id_map: Optional[Dict[str, List[str]]] = None
|
||||
|
||||
@classmethod
|
||||
def getProductIdMap(cls) -> Dict[str, List[str]]:
|
||||
"""Gets a mapping from product names in the XML files to their definition IDs.
|
||||
|
||||
This loads the mapping from a file.
|
||||
"""
|
||||
if cls.__product_to_id_map is not None:
|
||||
return cls.__product_to_id_map
|
||||
|
||||
plugin_path = cast(str, PluginRegistry.getInstance().getPluginPath("XmlMaterialProfile"))
|
||||
product_to_id_file = os.path.join(plugin_path, "product_to_id.json")
|
||||
with open(product_to_id_file, encoding = "utf-8") as f:
|
||||
contents = ""
|
||||
for line in f:
|
||||
contents += line if "#" not in line else "".join([line.replace("#", str(n)) for n in range(1, 12)])
|
||||
cls.__product_to_id_map = json.loads(contents)
|
||||
cls.__product_to_id_map = {key: [value] for key, value in cls.__product_to_id_map.items()}
|
||||
#This also loads "Ultimaker S5" -> "ultimaker_s5" even though that is not strictly necessary with the default to change spaces into underscores.
|
||||
#However it is not always loaded with that default; this mapping is also used in serialize() without that default.
|
||||
return cls.__product_to_id_map
|
||||
|
||||
@staticmethod
|
||||
def _parseCompatibleValue(value: str):
|
||||
"""Parse the value of the "material compatible" property."""
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"Ultimaker #": "ultimaker#",
|
||||
"Ultimaker # Extended": "ultimaker#_extended",
|
||||
"Ultimaker # Extended+": "ultimaker#_extended_plus",
|
||||
"Ultimaker # Go": "ultimaker#_go",
|
||||
"Ultimaker #+": "ultimaker#_plus",
|
||||
"Ultimaker #+ Connect": "ultimaker#_plus_connect",
|
||||
"Ultimaker S#": "ultimaker_s#",
|
||||
"Ultimaker Factor #": "ultimaker_factor#",
|
||||
"Ultimaker Original": "ultimaker_original",
|
||||
"Ultimaker Original+": "ultimaker_original_plus",
|
||||
"Ultimaker Original Dual Extrusion": "ultimaker_original_dual",
|
||||
"IMADE3D JellyBOX": "imade3d_jellybox",
|
||||
"DUAL600": "strateo3d",
|
||||
"IDEX420": "strateo3d_IDEX420",
|
||||
"IDEX420 Duplicate": "strateo3d_IDEX420_duplicate",
|
||||
"IDEX420 Mirror": "strateo3d_IDEX420_mirror",
|
||||
"UltiMaker Method": "ultimaker_method",
|
||||
"UltiMaker Method X": "ultimaker_methodx",
|
||||
"UltiMaker Method XL": "ultimaker_methodxl",
|
||||
"UltiMaker Sketch": "ultimaker_sketch",
|
||||
"UltiMaker Sketch Large": "ultimaker_sketch_large"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue