Merge branch 'feature_material_inheritance' of github.com:Ultimaker/Cura

This commit is contained in:
Jaime van Kessel 2016-08-30 16:05:10 +02:00
commit fbbbdb61e3
2 changed files with 77 additions and 2 deletions

View File

@ -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:

View File

@ -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: