mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-24 13:39:05 +08:00
Merge branch 'main' into bump-to-5.9.0-alpha.1
This commit is contained in:
commit
5b9b26f28e
@ -1,7 +1,13 @@
|
|||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from dataclasses import asdict
|
||||||
|
|
||||||
|
from typing import cast, Dict, TYPE_CHECKING
|
||||||
|
|
||||||
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
|
from UM.Settings.SettingFunction import SettingFunction
|
||||||
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
@ -47,3 +53,57 @@ class Settings:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self.application.getSidebarCustomMenuItems()
|
return self.application.getSidebarCustomMenuItems()
|
||||||
|
|
||||||
|
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 = self.application.getPrintInformation()
|
||||||
|
machine_manager = self.application.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, self.application.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
|
||||||
|
106
cura/PrinterOutput/FormatMaps.py
Normal file
106
cura/PrinterOutput/FormatMaps.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# Copyright (c) 2024 UltiMaker
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
from UM.Resources import Resources
|
||||||
|
|
||||||
|
import json
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
class FormatMaps:
|
||||||
|
|
||||||
|
# A map from the printer-type in their native file-formats to the internal name we use.
|
||||||
|
PRINTER_TYPE_NAME = {
|
||||||
|
"fire_e": "ultimaker_method",
|
||||||
|
"lava_f": "ultimaker_methodx",
|
||||||
|
"magma_10": "ultimaker_methodxl",
|
||||||
|
"sketch": "ultimaker_sketch"
|
||||||
|
}
|
||||||
|
|
||||||
|
# A map from the extruder-name in their native file-formats to the internal name we use.
|
||||||
|
EXTRUDER_NAME_MAP = {
|
||||||
|
"mk14_hot": "1XA",
|
||||||
|
"mk14_hot_s": "2XA",
|
||||||
|
"mk14_c": "1C",
|
||||||
|
"mk14": "1A",
|
||||||
|
"mk14_s": "2A",
|
||||||
|
"mk14_e": "LABS"
|
||||||
|
}
|
||||||
|
|
||||||
|
# A map from the material-name in their native file-formats to some info, including the internal name we use.
|
||||||
|
MATERIAL_MAP = {
|
||||||
|
"abs": {"name": "ABS", "guid": "2780b345-577b-4a24-a2c5-12e6aad3e690"},
|
||||||
|
"abs-cf10": {"name": "ABS-CF", "guid": "495a0ce5-9daf-4a16-b7b2-06856d82394d"},
|
||||||
|
"abs-wss1": {"name": "ABS-R", "guid": "88c8919c-6a09-471a-b7b6-e801263d862d"},
|
||||||
|
"asa": {"name": "ASA", "guid": "f79bc612-21eb-482e-ad6c-87d75bdde066"},
|
||||||
|
"nylon12-cf": {"name": "Nylon 12 CF", "guid": "3c6f2877-71cc-4760-84e6-4b89ab243e3b"},
|
||||||
|
"nylon": {"name": "Nylon", "guid": "283d439a-3490-4481-920c-c51d8cdecf9c"},
|
||||||
|
"pc": {"name": "PC", "guid": "62414577-94d1-490d-b1e4-7ef3ec40db02"},
|
||||||
|
"petg": {"name": "PETG", "guid": "69386c85-5b6c-421a-bec5-aeb1fb33f060"},
|
||||||
|
"pla": {"name": "PLA", "guid": "abb9c58e-1f56-48d1-bd8f-055fde3a5b56"},
|
||||||
|
"pva": {"name": "PVA", "guid": "add51ef2-86eb-4c39-afd5-5586564f0715"},
|
||||||
|
"wss1": {"name": "RapidRinse", "guid": "a140ef8f-4f26-4e73-abe0-cfc29d6d1024"},
|
||||||
|
"sr30": {"name": "SR-30", "guid": "77873465-83a9-4283-bc44-4e542b8eb3eb"},
|
||||||
|
"bvoh": {"name": "BVOH", "guid": "923e604c-8432-4b09-96aa-9bbbd42207f4"},
|
||||||
|
"cpe": {"name": "CPE", "guid": "da1872c1-b991-4795-80ad-bdac0f131726"},
|
||||||
|
"hips": {"name": "HIPS", "guid": "a468d86a-220c-47eb-99a5-bbb47e514eb0"},
|
||||||
|
"tpu": {"name": "TPU 95A", "guid": "19baa6a9-94ff-478b-b4a1-8157b74358d2"},
|
||||||
|
"im-pla": {"name": "Tough", "guid": "de031137-a8ca-4a72-bd1b-17bb964033ad"}
|
||||||
|
}
|
||||||
|
|
||||||
|
__inverse_printer_name: Optional[Dict[str, str]] = None
|
||||||
|
__inverse_extruder_type: Optional[Dict[str, str]] = None
|
||||||
|
__inverse_material_map: Optional[Dict[str, str]] = None
|
||||||
|
__product_to_id_map: Optional[Dict[str, List[str]]] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getInversePrinterNameMap(cls) -> Dict[str, str]:
|
||||||
|
"""Returns the inverse of the printer name map, that is, from the internal name to the name used in output."""
|
||||||
|
if cls.__inverse_printer_name is not None:
|
||||||
|
return cls.__inverse_printer_name
|
||||||
|
cls.__inverse_printer_name = {}
|
||||||
|
for key, value in cls.PRINTER_TYPE_NAME.items():
|
||||||
|
cls.__inverse_printer_name[value] = key
|
||||||
|
return cls.__inverse_printer_name
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getInverseExtruderTypeMap(cls) -> Dict[str, str]:
|
||||||
|
"""Returns the inverse of the extruder type map, that is, from the internal name to the name used in output."""
|
||||||
|
if cls.__inverse_extruder_type is not None:
|
||||||
|
return cls.__inverse_extruder_type
|
||||||
|
cls.__inverse_extruder_type = {}
|
||||||
|
for key, value in cls.EXTRUDER_NAME_MAP.items():
|
||||||
|
cls.__inverse_extruder_type[value] = key
|
||||||
|
return cls.__inverse_extruder_type
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getInverseMaterialMap(cls) -> Dict[str, str]:
|
||||||
|
"""Returns the inverse of the material map, that is, from the internal name to the name used in output.
|
||||||
|
|
||||||
|
Note that this drops the extra info saved in the non-inverse material map, use that if you need it.
|
||||||
|
"""
|
||||||
|
if cls.__inverse_material_map is not None:
|
||||||
|
return cls.__inverse_material_map
|
||||||
|
cls.__inverse_material_map = {}
|
||||||
|
for key, value in cls.MATERIAL_MAP.items():
|
||||||
|
cls.__inverse_material_map[value["name"]] = key
|
||||||
|
return cls.__inverse_material_map
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getProductIdMap(cls) -> Dict[str, List[str]]:
|
||||||
|
"""Gets a mapping from product names (for example, 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
|
||||||
|
|
||||||
|
product_to_id_file = Resources.getPath(Resources.Texts, "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
|
@ -1,9 +1,10 @@
|
|||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2024 UltiMaker
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtProperty, QObject, pyqtSignal
|
from PyQt6.QtCore import pyqtProperty, QObject, pyqtSignal
|
||||||
|
|
||||||
|
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||||
from .MaterialOutputModel import MaterialOutputModel
|
from .MaterialOutputModel import MaterialOutputModel
|
||||||
|
|
||||||
|
|
||||||
@ -45,16 +46,8 @@ class ExtruderConfigurationModel(QObject):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def applyNameMappingHotend(hotendId) -> str:
|
def applyNameMappingHotend(hotendId) -> str:
|
||||||
_EXTRUDER_NAME_MAP = {
|
if hotendId in FormatMaps.EXTRUDER_NAME_MAP:
|
||||||
"mk14_hot":"1XA",
|
return FormatMaps.EXTRUDER_NAME_MAP[hotendId]
|
||||||
"mk14_hot_s":"2XA",
|
|
||||||
"mk14_c":"1C",
|
|
||||||
"mk14":"1A",
|
|
||||||
"mk14_s":"2A",
|
|
||||||
"mk14_e": "LABS"
|
|
||||||
}
|
|
||||||
if hotendId in _EXTRUDER_NAME_MAP:
|
|
||||||
return _EXTRUDER_NAME_MAP[hotendId]
|
|
||||||
return hotendId
|
return hotendId
|
||||||
|
|
||||||
@pyqtProperty(str, fset = setHotendID, notify = extruderConfigurationChanged)
|
@pyqtProperty(str, fset = setHotendID, notify = extruderConfigurationChanged)
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2024 UltiMaker
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtProperty, QObject
|
from PyQt6.QtCore import pyqtProperty, QObject
|
||||||
|
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||||
|
|
||||||
|
|
||||||
class MaterialOutputModel(QObject):
|
class MaterialOutputModel(QObject):
|
||||||
@ -23,30 +24,9 @@ class MaterialOutputModel(QObject):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getMaterialFromDefinition(guid, type, brand, name):
|
def getMaterialFromDefinition(guid, type, brand, name):
|
||||||
|
if guid is None and brand != "empty" and type in FormatMaps.MATERIAL_MAP:
|
||||||
_MATERIAL_MAP = { "abs" :{"name" :"ABS" ,"guid": "2780b345-577b-4a24-a2c5-12e6aad3e690"},
|
name = FormatMaps.MATERIAL_MAP[type]["name"]
|
||||||
"abs-cf10" :{"name": "ABS-CF" ,"guid": "495a0ce5-9daf-4a16-b7b2-06856d82394d"},
|
guid = FormatMaps.MATERIAL_MAP[type]["guid"]
|
||||||
"abs-wss1" :{"name" :"ABS-R" ,"guid": "88c8919c-6a09-471a-b7b6-e801263d862d"},
|
|
||||||
"asa" :{"name" :"ASA" ,"guid": "f79bc612-21eb-482e-ad6c-87d75bdde066"},
|
|
||||||
"nylon12-cf":{"name": "Nylon 12 CF" ,"guid": "3c6f2877-71cc-4760-84e6-4b89ab243e3b"},
|
|
||||||
"nylon" :{"name" :"Nylon" ,"guid": "283d439a-3490-4481-920c-c51d8cdecf9c"},
|
|
||||||
"pc" :{"name" :"PC" ,"guid": "62414577-94d1-490d-b1e4-7ef3ec40db02"},
|
|
||||||
"petg" :{"name" :"PETG" ,"guid": "69386c85-5b6c-421a-bec5-aeb1fb33f060"},
|
|
||||||
"pla" :{"name" :"PLA" ,"guid": "abb9c58e-1f56-48d1-bd8f-055fde3a5b56"},
|
|
||||||
"pva" :{"name" :"PVA" ,"guid": "add51ef2-86eb-4c39-afd5-5586564f0715"},
|
|
||||||
"wss1" :{"name" :"RapidRinse" ,"guid": "a140ef8f-4f26-4e73-abe0-cfc29d6d1024"},
|
|
||||||
"sr30" :{"name" :"SR-30" ,"guid": "77873465-83a9-4283-bc44-4e542b8eb3eb"},
|
|
||||||
"bvoh" :{"name" :"BVOH" ,"guid": "923e604c-8432-4b09-96aa-9bbbd42207f4"},
|
|
||||||
"cpe" :{"name" :"CPE" ,"guid": "da1872c1-b991-4795-80ad-bdac0f131726"},
|
|
||||||
"hips" :{"name" :"HIPS" ,"guid": "a468d86a-220c-47eb-99a5-bbb47e514eb0"},
|
|
||||||
"tpu" :{"name" :"TPU 95A" ,"guid": "19baa6a9-94ff-478b-b4a1-8157b74358d2"},
|
|
||||||
"im-pla" :{"name": "Tough" ,"guid": "de031137-a8ca-4a72-bd1b-17bb964033ad"}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if guid is None and brand != "empty" and type in _MATERIAL_MAP:
|
|
||||||
name = _MATERIAL_MAP[type]["name"]
|
|
||||||
guid = _MATERIAL_MAP[type]["guid"]
|
|
||||||
return name, guid
|
return name, guid
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2021 Ultimaker B.V.
|
# Copyright (c) 2024 UltiMaker
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from UM.FileHandler.FileHandler import FileHandler #For typing.
|
from UM.FileHandler.FileHandler import FileHandler #For typing.
|
||||||
@ -6,6 +6,7 @@ from UM.Logger import Logger
|
|||||||
from UM.Scene.SceneNode import SceneNode #For typing.
|
from UM.Scene.SceneNode import SceneNode #For typing.
|
||||||
from cura.API import Account
|
from cura.API import Account
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||||
|
|
||||||
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
|
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
|
||||||
|
|
||||||
@ -419,14 +420,8 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def applyPrinterTypeMapping(printer_type):
|
def applyPrinterTypeMapping(printer_type):
|
||||||
_PRINTER_TYPE_NAME = {
|
if printer_type in FormatMaps.PRINTER_TYPE_NAME:
|
||||||
"fire_e": "ultimaker_method",
|
return FormatMaps.PRINTER_TYPE_NAME[printer_type]
|
||||||
"lava_f": "ultimaker_methodx",
|
|
||||||
"magma_10": "ultimaker_methodxl",
|
|
||||||
"sketch": "ultimaker_sketch"
|
|
||||||
}
|
|
||||||
if printer_type in _PRINTER_TYPE_NAME:
|
|
||||||
return _PRINTER_TYPE_NAME[printer_type]
|
|
||||||
return printer_type
|
return printer_type
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2023 UltiMaker
|
# Copyright (c) 2024 UltiMaker
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from io import StringIO, BufferedIOBase
|
from io import StringIO, BufferedIOBase
|
||||||
import json
|
import json
|
||||||
@ -18,6 +18,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
|||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||||
from cura.Snapshot import Snapshot
|
from cura.Snapshot import Snapshot
|
||||||
from cura.Utils.Threading import call_on_qt_thread
|
from cura.Utils.Threading import call_on_qt_thread
|
||||||
from cura.CuraVersion import ConanInstalls
|
from cura.CuraVersion import ConanInstalls
|
||||||
@ -137,6 +138,30 @@ class MakerbotWriter(MeshWriter):
|
|||||||
for png_file in png_files:
|
for png_file in png_files:
|
||||||
file, data = png_file["file"], png_file["data"]
|
file, data = png_file["file"], png_file["data"]
|
||||||
zip_stream.writestr(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:
|
except (IOError, OSError, BadZipFile) as ex:
|
||||||
Logger.log("e", f"Could not write to (.makerbot) file because: '{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."))
|
self.setInformation(catalog.i18nc("@error", "MakerbotWriter could not save to the designated path."))
|
||||||
|
@ -24,6 +24,7 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
|||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.Settings.GlobalStack import GlobalStack
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
from cura.Utils.Threading import call_on_qt_thread
|
from cura.Utils.Threading import call_on_qt_thread
|
||||||
|
from cura.API import CuraAPI
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
@ -85,7 +86,8 @@ class UFPWriter(MeshWriter):
|
|||||||
try:
|
try:
|
||||||
archive.addContentType(extension="json", mime_type="application/json")
|
archive.addContentType(extension="json", mime_type="application/json")
|
||||||
setting_textio = StringIO()
|
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 = archive.getStream(SLICE_METADATA_PATH)
|
||||||
steam.write(setting_textio.getvalue().encode("UTF-8"))
|
steam.write(setting_textio.getvalue().encode("UTF-8"))
|
||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
@ -210,57 +212,3 @@ class UFPWriter(MeshWriter):
|
|||||||
return [{"name": item.getName()}
|
return [{"name": item.getName()}
|
||||||
for item in DepthFirstIterator(node)
|
for item in DepthFirstIterator(node)
|
||||||
if item.getMeshData() is not None and not item.callDecoration("isNonPrintingMesh")]
|
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 UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.PrinterOutput.FormatMaps import FormatMaps
|
||||||
from cura.Machines.VariantType import VariantType
|
from cura.Machines.VariantType import VariantType
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -249,7 +250,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
machine_variant_map[definition_id][variant_name] = variant_dict
|
machine_variant_map[definition_id][variant_name] = variant_dict
|
||||||
|
|
||||||
# Map machine human-readable names to IDs
|
# 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():
|
for definition_id, container in machine_container_map.items():
|
||||||
definition_id = container.getMetaDataEntry("definition")
|
definition_id = container.getMetaDataEntry("definition")
|
||||||
@ -647,7 +648,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
self._dirty = False
|
self._dirty = False
|
||||||
|
|
||||||
# Map machine human-readable names to IDs
|
# 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)
|
machines = data.iterfind("./um:settings/um:machine", self.__namespaces)
|
||||||
for machine in machines:
|
for machine in machines:
|
||||||
@ -923,7 +924,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
result_metadata.append(base_metadata)
|
result_metadata.append(base_metadata)
|
||||||
|
|
||||||
# Map machine human-readable names to IDs
|
# 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):
|
for machine in data.iterfind("./um:settings/um:machine", cls.__namespaces):
|
||||||
machine_compatibility = common_compatibility
|
machine_compatibility = common_compatibility
|
||||||
@ -1128,29 +1129,6 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
id_list = list(id_list)
|
id_list = list(id_list)
|
||||||
return 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
|
@staticmethod
|
||||||
def _parseCompatibleValue(value: str):
|
def _parseCompatibleValue(value: str):
|
||||||
"""Parse the value of the "material compatible" property."""
|
"""Parse the value of the "material compatible" property."""
|
||||||
|
@ -28,6 +28,18 @@
|
|||||||
"icon": "Printer",
|
"icon": "Printer",
|
||||||
"children":
|
"children":
|
||||||
{
|
{
|
||||||
|
"build_volume_fan_nr":
|
||||||
|
{
|
||||||
|
"label": "Build volume fan number",
|
||||||
|
"description": "The number of the fan that cools the build volume. If this is set to 0, it's means that there is no build volume fan",
|
||||||
|
"default_value": 0,
|
||||||
|
"minimum_value": "0",
|
||||||
|
"maximum_value": "999999",
|
||||||
|
"type": "int",
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false
|
||||||
|
},
|
||||||
"machine_name":
|
"machine_name":
|
||||||
{
|
{
|
||||||
"label": "Machine Type",
|
"label": "Machine Type",
|
||||||
@ -4467,6 +4479,37 @@
|
|||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
},
|
},
|
||||||
|
"build_fan_full_at_height":
|
||||||
|
{
|
||||||
|
"label": "Build Fan Speed at Height",
|
||||||
|
"description": "The height at which the fans spin on regular fan speed. At the layers below the fan speed gradually increases from Initial Fan Speed to Regular Fan Speed.",
|
||||||
|
"unit": "mm",
|
||||||
|
"type": "float",
|
||||||
|
"default_value": 0,
|
||||||
|
"minimum_value": "0",
|
||||||
|
"enabled": "build_volume_fan_nr != 0",
|
||||||
|
"maximum_value_warning": "10.0",
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false,
|
||||||
|
"children":
|
||||||
|
{
|
||||||
|
"build_fan_full_layer":
|
||||||
|
{
|
||||||
|
"label": "Build Fan Speed at Layer",
|
||||||
|
"description": "The layer at which the build fans spin on full fan speed. This value is calculated and rounded to a whole number.",
|
||||||
|
"type": "int",
|
||||||
|
"default_value": 0,
|
||||||
|
"minimum_value": "0",
|
||||||
|
"enabled": "build_volume_fan_nr != 0",
|
||||||
|
"maximum_value_warning": "10 / resolveOrValue('layer_height')",
|
||||||
|
"value": "max(1, int(math.floor((build_fan_full_at_height - resolveOrValue('layer_height_0')) / resolveOrValue('layer_height')) + 2))",
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"cool_fan_speed":
|
"cool_fan_speed":
|
||||||
{
|
{
|
||||||
"label": "Fan Speed",
|
"label": "Fan Speed",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user