From d662770b225fa066815af644851644b87a8f198f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 23 Aug 2017 16:27:26 +0200 Subject: [PATCH] Fix setting new material for stacks CURA-4204 When a new material is created during project file loading, the material for each stack is set according to the parent material ID, but actually the child material should be used. This fix uses a hack to find the corresponding child material for a stack so when a user chooses to create a new material during project file loading, the material can be correctly set. --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 62 ++++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 8fdb120189..5747001a64 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -814,29 +814,26 @@ class ThreeMFWorkspaceReader(WorkspaceReader): each_extruder_stack.definitionChanges = each_changes_container if self._resolve_strategies["material"] == "new": + # the actual material instance container can have an ID such as + # __ + # which cannot be determined immediately, so here we use a HACK to find the right new material + # instance ID: + # - get the old material IDs for all material + # - find the old material with the longest common prefix in ID, that's the old material + # - update the name by replacing the old prefix with the new + # - find the new material container and set it to the stack + old_to_new_material_dict = {} for each_material in material_containers: - old_material = global_stack.material + # find the material's old name + for old_id, new_id in self._id_mapping.items(): + if each_material.getId() == new_id: + old_to_new_material_dict[old_id] = each_material + break - # check if the old material container has been renamed to this material container ID - # if the container hasn't been renamed, we do nothing. - new_id = self._id_mapping.get(old_material.getId()) - if new_id is None or new_id != each_material.getId(): - continue - - if old_material.getId() in self._id_mapping: - global_stack.material = each_material - - for each_extruder_stack in extruder_stacks: - old_material = each_extruder_stack.material - - # check if the old material container has been renamed to this material container ID - # if the container hasn't been renamed, we do nothing. - new_id = self._id_mapping.get(old_material.getId()) - if new_id is None or new_id != each_material.getId(): - continue - - if old_material.getId() in self._id_mapping: - each_extruder_stack.material = each_material + # replace old material in global and extruder stacks with new + self._replaceStackMaterialWithNew(global_stack, old_to_new_material_dict) + for each_extruder_stack in extruder_stacks: + self._replaceStackMaterialWithNew(each_extruder_stack, old_to_new_material_dict) if extruder_stacks: for stack in extruder_stacks: @@ -861,6 +858,29 @@ class ThreeMFWorkspaceReader(WorkspaceReader): nodes = [] return nodes + def _replaceStackMaterialWithNew(self, stack, old_new_material_dict): + old_material_id_in_stack = stack.material.getId() + best_matching_old_material_id = None + best_matching_old_meterial_prefix_length = -1 + for old_parent_material_id in old_new_material_dict: + if len(old_parent_material_id) < best_matching_old_meterial_prefix_length: + continue + if len(old_parent_material_id) <= len(old_material_id_in_stack): + if old_parent_material_id == old_material_id_in_stack[0:len(old_parent_material_id)]: + best_matching_old_meterial_prefix_length = len(old_parent_material_id) + best_matching_old_material_id = old_parent_material_id + + if best_matching_old_material_id is None: + return + + new_material_id = old_new_material_dict[best_matching_old_material_id].getId() + old_material_id_in_stack[len(best_matching_old_material_id):] + new_material_containers = self._container_registry.findInstanceContainers(id = new_material_id, type = "material") + if not new_material_containers: + Logger.log("e", "Cannot find new material container [%s]", new_material_id) + return + + stack.material = new_material_containers[0] + def _stripFileToId(self, file): mime_type = MimeTypeDatabase.getMimeTypeForFile(file) file = mime_type.stripExtension(file)