mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 21:28:58 +08:00
Merge branch 'feature_material_inheritance' of github.com:Ultimaker/Cura
This commit is contained in:
commit
fbbbdb61e3
@ -19,6 +19,7 @@ from UM.i18n import i18nCatalog
|
|||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
class MachineManager(QObject):
|
class MachineManager(QObject):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
@ -502,7 +503,7 @@ class MachineManager(QObject):
|
|||||||
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
|
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
return
|
return
|
||||||
|
Logger.log("d", "Attempting to change the active material to %s", material_id)
|
||||||
old_variant = self._active_container_stack.findContainer({"type": "variant"})
|
old_variant = self._active_container_stack.findContainer({"type": "variant"})
|
||||||
old_material = self._active_container_stack.findContainer({"type": "material"})
|
old_material = self._active_container_stack.findContainer({"type": "material"})
|
||||||
old_quality = self._active_container_stack.findContainer({"type": "quality"})
|
old_quality = self._active_container_stack.findContainer({"type": "quality"})
|
||||||
@ -535,6 +536,7 @@ class MachineManager(QObject):
|
|||||||
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
|
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
return
|
return
|
||||||
|
Logger.log("d", "Attempting to change the active variant to %s", variant_id)
|
||||||
old_variant = self._active_container_stack.findContainer({"type": "variant"})
|
old_variant = self._active_container_stack.findContainer({"type": "variant"})
|
||||||
old_material = self._active_container_stack.findContainer({"type": "material"})
|
old_material = self._active_container_stack.findContainer({"type": "material"})
|
||||||
if old_variant:
|
if old_variant:
|
||||||
@ -554,6 +556,9 @@ class MachineManager(QObject):
|
|||||||
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = quality_id)
|
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = quality_id)
|
||||||
if not containers or not self._global_container_stack:
|
if not containers or not self._global_container_stack:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
Logger.log("d", "Attempting to change the active quality to %s", quality_id)
|
||||||
|
|
||||||
self.blurSettings.emit()
|
self.blurSettings.emit()
|
||||||
quality_container = None
|
quality_container = None
|
||||||
quality_changes_container = self._empty_quality_changes_container
|
quality_changes_container = self._empty_quality_changes_container
|
||||||
@ -829,7 +834,22 @@ class MachineManager(QObject):
|
|||||||
return containers[0]
|
return containers[0]
|
||||||
|
|
||||||
if "material" in search_criteria:
|
if "material" in search_criteria:
|
||||||
# If a quality for this specific material cannot be found, try finding qualities for a generic version of the material
|
# First check if we can solve our material not found problem by checking if we can find quality containers
|
||||||
|
# that are assigned to the parents of this material profile.
|
||||||
|
try:
|
||||||
|
inherited_files = material_container.getInheritedFiles()
|
||||||
|
if inherited_files:
|
||||||
|
for inherited_file in inherited_files:
|
||||||
|
# Extract the ID from the path we used to load the file.
|
||||||
|
search_criteria["material"] = os.path.basename(inherited_file).split(".")[0]
|
||||||
|
containers = container_registry.findInstanceContainers(**search_criteria)
|
||||||
|
if containers:
|
||||||
|
return containers[0]
|
||||||
|
except AttributeError: # Material_container does not support inheritance.
|
||||||
|
pass
|
||||||
|
|
||||||
|
# We still weren't able to find a quality for this specific material.
|
||||||
|
# Try to find qualities for a generic version of the material.
|
||||||
material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic" }
|
material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic" }
|
||||||
if definition.getMetaDataEntry("has_machine_quality"):
|
if definition.getMetaDataEntry("has_machine_quality"):
|
||||||
if material_container:
|
if material_container:
|
||||||
|
@ -7,8 +7,10 @@ import io
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from UM.Resources import Resources
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Util import parseBool
|
from UM.Util import parseBool
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
import UM.Dictionary
|
import UM.Dictionary
|
||||||
|
|
||||||
@ -18,6 +20,7 @@ import UM.Settings
|
|||||||
class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
||||||
def __init__(self, container_id, *args, **kwargs):
|
def __init__(self, container_id, *args, **kwargs):
|
||||||
super().__init__(container_id, *args, **kwargs)
|
super().__init__(container_id, *args, **kwargs)
|
||||||
|
self._inherited_files = []
|
||||||
|
|
||||||
## Overridden from InstanceContainer
|
## Overridden from InstanceContainer
|
||||||
def duplicate(self, new_id, new_name = None):
|
def duplicate(self, new_id, new_name = None):
|
||||||
@ -48,6 +51,9 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||||||
result.setMetaDataEntry("base_file", result.id)
|
result.setMetaDataEntry("base_file", result.id)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def getInheritedFiles(self):
|
||||||
|
return self._inherited_files
|
||||||
|
|
||||||
## Overridden from InstanceContainer
|
## Overridden from InstanceContainer
|
||||||
def setReadOnly(self, read_only):
|
def setReadOnly(self, read_only):
|
||||||
super().setReadOnly(read_only)
|
super().setReadOnly(read_only)
|
||||||
@ -246,6 +252,50 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||||||
|
|
||||||
return stream.getvalue()
|
return stream.getvalue()
|
||||||
|
|
||||||
|
# Recursively resolve loading inherited files
|
||||||
|
def _resolveInheritance(self, file_name):
|
||||||
|
xml = self._loadFile(file_name)
|
||||||
|
|
||||||
|
inherits = xml.find("./um:inherits", self.__namespaces)
|
||||||
|
if inherits is not None:
|
||||||
|
inherited = self._resolveInheritance(inherits.text)
|
||||||
|
xml = self._mergeXML(inherited, xml)
|
||||||
|
|
||||||
|
return xml
|
||||||
|
|
||||||
|
def _loadFile(self, file_name):
|
||||||
|
path = Resources.getPath(CuraApplication.getInstance().ResourceTypes.MaterialInstanceContainer, file_name + ".xml.fdm_material")
|
||||||
|
|
||||||
|
with open(path, encoding="utf-8") as f:
|
||||||
|
contents = f.read()
|
||||||
|
|
||||||
|
self._inherited_files.append(path)
|
||||||
|
return ET.fromstring(contents)
|
||||||
|
|
||||||
|
def _mergeXML(self, first, second):
|
||||||
|
result = copy.deepcopy(first)
|
||||||
|
self._combineElement(result, second)
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Recursively merges XML elements. Updates either the text or children if another element is found in first.
|
||||||
|
# If it does not exist, copies it from second.
|
||||||
|
def _combineElement(self, first, second):
|
||||||
|
# Create a mapping from tag name to element.
|
||||||
|
mapping = {el.tag: el for el in first}
|
||||||
|
for el in second:
|
||||||
|
if len(el): # Check if element has children.
|
||||||
|
try:
|
||||||
|
self._combineElement(mapping[el.tag], el) # Multiple elements, handle those.
|
||||||
|
except KeyError:
|
||||||
|
mapping[el.tag] = el
|
||||||
|
first.append(el)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
mapping[el.tag].text = el.text
|
||||||
|
except KeyError: # Not in the mapping, so simply add it
|
||||||
|
mapping[el.tag] = el
|
||||||
|
first.append(el)
|
||||||
|
|
||||||
## Overridden from InstanceContainer
|
## Overridden from InstanceContainer
|
||||||
def deserialize(self, serialized):
|
def deserialize(self, serialized):
|
||||||
data = ET.fromstring(serialized)
|
data = ET.fromstring(serialized)
|
||||||
@ -255,6 +305,11 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||||||
|
|
||||||
# TODO: Add material verfication
|
# TODO: Add material verfication
|
||||||
self.addMetaDataEntry("status", "unknown")
|
self.addMetaDataEntry("status", "unknown")
|
||||||
|
#for inherit in data.findall("./um:inherits", self.__namespaces):
|
||||||
|
inherits = data.find("./um:inherits", self.__namespaces)
|
||||||
|
if inherits is not None:
|
||||||
|
inherited = self._resolveInheritance(inherits.text)
|
||||||
|
data = self._mergeXML(inherited, data)
|
||||||
|
|
||||||
metadata = data.iterfind("./um:metadata/*", self.__namespaces)
|
metadata = data.iterfind("./um:metadata/*", self.__namespaces)
|
||||||
for entry in metadata:
|
for entry in metadata:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user