{
  "_provenance": "Everything about the 3MF editing measurement that the script cannot observe by unzipping files: the source code readings behind the Replace with STL and Reload from disk findings, and what each refusal said. Recorded by hand 2026-10-20 on Windows 11. scripts/measure-edit-3mf.py merges this into the published JSON.",
  "source_reading": [
    {
      "feature": "Replace with STL, Bambu Studio 02.08.02.61",
      "where": "https://github.com/bambulab/BambuStudio/blob/v02.08.02.61/src/slic3r/GUI/Plater.cpp#L11302",
      "finding": "Replaces one part of an object with the mesh from a file, and keeps from the old part: its settings (config.apply, line 11381), its type (part, modifier, negative part), its filament, its position, rotation and scale, and its unit conversion. The object, its other parts, its plate and its object settings are not touched. The new file must hold exactly one mesh; otherwise it stops with \"Unable to replace with more than one volume\" (line 11362).",
      "paint": "Painting (support, seam, fuzzy skin and colour) is copied as data, triangle number by triangle number (lines 11391 to 11394). On an edited mesh the triangle numbers belong to different faces, so the paint lands wherever those numbers now are. If any painted triangle number is beyond the new mesh's triangle count, the whole of that paint is discarded when it is loaded (TriangleSelector.cpp line 2085, which logs \"array bound:error\")."
    },
    {
      "feature": "Reload from disk, Bambu Studio 02.08.02.61",
      "where": "https://github.com/bambulab/BambuStudio/blob/v02.08.02.61/src/slic3r/GUI/Plater.cpp#L11487",
      "finding": "Keeps the part's settings, type, filament and transform like Replace with STL, but copies no painting at all, so the part comes back unpainted. It looks for the part's original source file, which a downloaded project does not have on your disk; when it is missing it asks for a file and then uses the Replace with STL code above."
    },
    {
      "feature": "Replace with STL, OrcaSlicer 2.4.2",
      "where": "https://github.com/OrcaSlicer/OrcaSlicer/blob/v2.4.2/src/slic3r/GUI/Plater.cpp#L8332",
      "finding": "Same as Bambu Studio for settings, type and transform. For painting it has a preference, \"Keep painted feature after mesh change\" (Preferences.cpp line 1990), described in the app as \"Highly experimental! Slow and may create artifact.\" When it is on, painting is remapped onto the new mesh by position (Plater.cpp line 8411). It is not in the app's default settings, so it is off until you tick it, and then the triangle number copy applies, under a source comment that says it \"Won't work well if mesh changed\"."
    }
  ],
  "paint_remap_example": {
    "how": "scripts/edit-3mf-bevel-example.py in Blender 5.2.2: the fixture's body box (40 x 20 x 10 mm, 12 triangles in the fixture's order) with a 1 mm, 2 segment bevel, exported as STL, read with trimesh. Triangles 2 and 3 carry the fixture's support paint.",
    "before": {
      "triangles": 12,
      "painted_triangles": [
        2,
        3
      ],
      "where": "the top face",
      "area_mm2_each": [
        400.0,
        400.0
      ]
    },
    "after": {
      "triangles": 108,
      "where": "two bevel facets at the bottom corner nearest (-20, -10, -5)",
      "area_mm2_each": [
        0.153,
        0.14
      ]
    }
  },
  "not_measured_here": [
    "The Replace with STL and Reload from disk results come from reading the source code at the versions named, not from operating the applications.",
    "Bambu Studio and OrcaSlicer were run through their command lines, which can refuse files the graphical apps open with a warning. Whether OrcaSlicer's graphical app opens this file was not tested.",
    "Colour painting: the fixture has support and seam painting only. Adding a second filament through Bambu Studio's command line crashed it. Colour paint is stored the same way, per triangle.",
    "Online 3MF editors (OwlCAD, Aspose and similar) and Fusion, SolidWorks and Tinkercad.",
    "Whether a reopened file slices to the same G-code as the original."
  ],
  "measured_on": "2026-10-20",
  "question": "What survives when a slicer project 3MF is opened in another program and saved again?",
  "fixture": "bambu-edit-test.3mf",
  "fixture_contents": {
    "files": [
      "3D/3dmodel.model",
      "3D/Objects/object_1.model",
      "3D/Objects/object_2.model",
      "3D/_rels/3dmodel.model.rels",
      "Metadata/cut_information.xml",
      "Metadata/filament_sequence.json",
      "Metadata/model_settings.config",
      "Metadata/pick_1.png",
      "Metadata/pick_2.png",
      "Metadata/plate_1.png",
      "Metadata/plate_1_small.png",
      "Metadata/plate_2.png",
      "Metadata/plate_2_small.png",
      "Metadata/plate_no_light_1.png",
      "Metadata/plate_no_light_2.png",
      "Metadata/project_settings.config",
      "Metadata/slice_info.config",
      "Metadata/top_1.png",
      "Metadata/top_2.png",
      "[Content_Types].xml",
      "_rels/.rels"
    ],
    "triangles": 48,
    "paint": {
      "paint_supports": 2,
      "paint_seam": 1,
      "paint_color": 0,
      "slic3rpe:custom_supports": 0,
      "slic3rpe:custom_seam": 0,
      "slic3rpe:mmu_segmentation": 0
    },
    "written_by": "BambuStudio-02.08.02.61",
    "build_items": 2,
    "object_types": [
      "model",
      "other"
    ],
    "body_scale": 1.0,
    "format": "bambu",
    "objects": [
      {
        "id": "4",
        "name": "body.stl",
        "settings": {},
        "parts": [
          {
            "subtype": "normal_part",
            "name": "body.stl",
            "settings": {}
          },
          {
            "subtype": "negative_part",
            "name": "negative.stl",
            "settings": {}
          },
          {
            "subtype": "modifier_part",
            "name": "modifier.stl",
            "settings": {
              "sparse_infill_density": "80%"
            }
          }
        ]
      },
      {
        "id": "6",
        "name": "plate2.stl",
        "settings": {
          "sparse_infill_density": "40%"
        },
        "parts": [
          {
            "subtype": "normal_part",
            "name": "plate2.stl",
            "settings": {}
          }
        ]
      }
    ],
    "plates": [
      [
        "4"
      ],
      [
        "6"
      ]
    ],
    "profiles": {
      "printer_settings_id": "Bambu Lab A1 0.4 nozzle",
      "print_settings_id": "0.20mm Standard @BBL A1",
      "filament_settings_id": [
        "Bambu PLA Basic @BBL A1"
      ],
      "sparse_infill_density": "15%"
    }
  },
  "fixture_expected": {
    "format_written": "bambu",
    "plates": 2,
    "objects_per_plate": [
      1,
      1
    ],
    "two_plates": true,
    "body_scale": 1.0,
    "modifier_kept": true,
    "negative_part_kept": true,
    "object_setting_kept": true,
    "modifier_setting_kept": true,
    "support_paint_triangles": 2,
    "seam_paint_triangles": 1,
    "printer_profile": "Bambu Lab A1 0.4 nozzle",
    "filament_profile": [
      "Bambu PLA Basic @BBL A1"
    ]
  },
  "rows": [
    {
      "editor": "bambu",
      "editor_name": "Bambu Studio 02.08.02.61 (command line)",
      "action": "resave",
      "exit_code": 0,
      "file_written": true,
      "output": "result.json: 0 Success.",
      "reopen_in_bambu": {
        "exit_code": 0,
        "output": "result.json: 0 Success.",
        "written": true
      },
      "format_written": "bambu",
      "plates": 2,
      "objects_per_plate": [
        1,
        1
      ],
      "two_plates": true,
      "body_scale": 1.0,
      "modifier_kept": true,
      "negative_part_kept": true,
      "object_setting_kept": true,
      "modifier_setting_kept": true,
      "support_paint_triangles": 2,
      "seam_paint_triangles": 1,
      "printer_profile": "Bambu Lab A1 0.4 nozzle",
      "filament_profile": [
        "Bambu PLA Basic @BBL A1"
      ],
      "detail": {
        "files": [
          "3D/3dmodel.model",
          "3D/Objects/object_1.model",
          "3D/Objects/object_2.model",
          "3D/_rels/3dmodel.model.rels",
          "Metadata/cut_information.xml",
          "Metadata/filament_sequence.json",
          "Metadata/model_settings.config",
          "Metadata/pick_1.png",
          "Metadata/pick_2.png",
          "Metadata/plate_1.png",
          "Metadata/plate_1_small.png",
          "Metadata/plate_2.png",
          "Metadata/plate_2_small.png",
          "Metadata/plate_no_light_1.png",
          "Metadata/plate_no_light_2.png",
          "Metadata/project_settings.config",
          "Metadata/slice_info.config",
          "Metadata/top_1.png",
          "Metadata/top_2.png",
          "[Content_Types].xml",
          "_rels/.rels"
        ],
        "triangles": 48,
        "paint": {
          "paint_supports": 2,
          "paint_seam": 1,
          "paint_color": 0,
          "slic3rpe:custom_supports": 0,
          "slic3rpe:custom_seam": 0,
          "slic3rpe:mmu_segmentation": 0
        },
        "written_by": "BambuStudio-02.08.02.61",
        "build_items": 2,
        "object_types": [
          "model",
          "other"
        ],
        "body_scale": 1.0,
        "format": "bambu",
        "objects": [
          {
            "id": "4",
            "name": "body.stl",
            "settings": {},
            "parts": [
              {
                "subtype": "normal_part",
                "name": "body.stl",
                "settings": {}
              },
              {
                "subtype": "negative_part",
                "name": "negative.stl",
                "settings": {}
              },
              {
                "subtype": "modifier_part",
                "name": "modifier.stl",
                "settings": {
                  "sparse_infill_density": "80%"
                }
              }
            ]
          },
          {
            "id": "6",
            "name": "plate2.stl",
            "settings": {
              "sparse_infill_density": "40%"
            },
            "parts": [
              {
                "subtype": "normal_part",
                "name": "plate2.stl",
                "settings": {}
              }
            ]
          }
        ],
        "plates": [
          [
            "4"
          ],
          [
            "6"
          ]
        ],
        "profiles": {
          "printer_settings_id": "Bambu Lab A1 0.4 nozzle",
          "print_settings_id": "0.20mm Standard @BBL A1",
          "filament_settings_id": [
            "Bambu PLA Basic @BBL A1"
          ],
          "sparse_infill_density": "15%"
        }
      },
      "refusal": null
    },
    {
      "editor": "bambu",
      "editor_name": "Bambu Studio 02.08.02.61 (command line)",
      "action": "scale110",
      "exit_code": 0,
      "file_written": true,
      "output": "result.json: 0 Success.",
      "reopen_in_bambu": {
        "exit_code": 0,
        "output": "result.json: 0 Success.",
        "written": true
      },
      "format_written": "bambu",
      "plates": 2,
      "objects_per_plate": [
        1,
        1
      ],
      "two_plates": true,
      "body_scale": 1.1,
      "modifier_kept": true,
      "negative_part_kept": true,
      "object_setting_kept": true,
      "modifier_setting_kept": true,
      "support_paint_triangles": 2,
      "seam_paint_triangles": 1,
      "printer_profile": "Bambu Lab A1 0.4 nozzle",
      "filament_profile": [
        "Bambu PLA Basic @BBL A1"
      ],
      "detail": {
        "files": [
          "3D/3dmodel.model",
          "3D/Objects/object_1.model",
          "3D/Objects/object_2.model",
          "3D/_rels/3dmodel.model.rels",
          "Metadata/cut_information.xml",
          "Metadata/filament_sequence.json",
          "Metadata/model_settings.config",
          "Metadata/pick_1.png",
          "Metadata/pick_2.png",
          "Metadata/plate_1.png",
          "Metadata/plate_1_small.png",
          "Metadata/plate_2.png",
          "Metadata/plate_2_small.png",
          "Metadata/plate_no_light_1.png",
          "Metadata/plate_no_light_2.png",
          "Metadata/project_settings.config",
          "Metadata/slice_info.config",
          "Metadata/top_1.png",
          "Metadata/top_2.png",
          "[Content_Types].xml",
          "_rels/.rels"
        ],
        "triangles": 48,
        "paint": {
          "paint_supports": 2,
          "paint_seam": 1,
          "paint_color": 0,
          "slic3rpe:custom_supports": 0,
          "slic3rpe:custom_seam": 0,
          "slic3rpe:mmu_segmentation": 0
        },
        "written_by": "BambuStudio-02.08.02.61",
        "build_items": 2,
        "object_types": [
          "model",
          "other"
        ],
        "body_scale": 1.1,
        "format": "bambu",
        "objects": [
          {
            "id": "4",
            "name": "body.stl",
            "settings": {},
            "parts": [
              {
                "subtype": "normal_part",
                "name": "body.stl",
                "settings": {}
              },
              {
                "subtype": "negative_part",
                "name": "negative.stl",
                "settings": {}
              },
              {
                "subtype": "modifier_part",
                "name": "modifier.stl",
                "settings": {
                  "sparse_infill_density": "80%"
                }
              }
            ]
          },
          {
            "id": "6",
            "name": "plate2.stl",
            "settings": {
              "sparse_infill_density": "40%"
            },
            "parts": [
              {
                "subtype": "normal_part",
                "name": "plate2.stl",
                "settings": {}
              }
            ]
          }
        ],
        "plates": [
          [
            "4"
          ],
          [
            "6"
          ]
        ],
        "profiles": {
          "printer_settings_id": "Bambu Lab A1 0.4 nozzle",
          "print_settings_id": "0.20mm Standard @BBL A1",
          "filament_settings_id": [
            "Bambu PLA Basic @BBL A1"
          ],
          "sparse_infill_density": "15%"
        }
      },
      "refusal": null
    },
    {
      "editor": "orca",
      "editor_name": "OrcaSlicer 2.4.2 (command line, defaults)",
      "action": "resave",
      "exit_code": 4294967272,
      "file_written": false,
      "output": "Slic3r::CLI::run found error, exit",
      "reopen_in_bambu": null,
      "refusal": "Wrote no file. Its log: \"Version Check: File Version 2.8.2.61 not supported by current cli version 2.4.2\". The command line compares its own version number with the version of Bambu Studio that saved the file (OrcaSlicer.cpp at v2.4.2, the allow_newer_file check)."
    },
    {
      "editor": "orca",
      "editor_name": "OrcaSlicer 2.4.2 (command line, defaults)",
      "action": "scale110",
      "exit_code": 4294967272,
      "file_written": false,
      "output": "Slic3r::CLI::run found error, exit",
      "reopen_in_bambu": null,
      "refusal": "Wrote no file. Its log: \"Version Check: File Version 2.8.2.61 not supported by current cli version 2.4.2\". The command line compares its own version number with the version of Bambu Studio that saved the file (OrcaSlicer.cpp at v2.4.2, the allow_newer_file check)."
    },
    {
      "editor": "orca-allow",
      "editor_name": "OrcaSlicer 2.4.2 (command line, --allow-newer-file)",
      "action": "resave",
      "exit_code": 4294967278,
      "file_written": false,
      "output": "Slic3r::CLI::run found error, exit\nParam values in 3mf/config error: \nraft_first_layer_expansion: -1 not in range [0.000000,340282346638528859811704183484516925440.000000]\ntree_support_wall_count: -1 not in range [0.000000,2.000000]",
      "reopen_in_bambu": null,
      "refusal": "Wrote no file. With the version check switched off it rejected two settings Bambu Studio wrote: \"raft_first_layer_expansion: -1 not in range\" and \"tree_support_wall_count: -1 not in range [0.000000,2.000000]\"."
    },
    {
      "editor": "orca-allow",
      "editor_name": "OrcaSlicer 2.4.2 (command line, --allow-newer-file)",
      "action": "scale110",
      "exit_code": 4294967278,
      "file_written": false,
      "output": "Slic3r::CLI::run found error, exit\nParam values in 3mf/config error: \nraft_first_layer_expansion: -1 not in range [0.000000,340282346638528859811704183484516925440.000000]\ntree_support_wall_count: -1 not in range [0.000000,2.000000]",
      "reopen_in_bambu": null,
      "refusal": "Wrote no file. With the version check switched off it rejected two settings Bambu Studio wrote: \"raft_first_layer_expansion: -1 not in range\" and \"tree_support_wall_count: -1 not in range [0.000000,2.000000]\"."
    },
    {
      "editor": "prusa",
      "editor_name": "PrusaSlicer 2.9.6 (command line)",
      "action": "resave",
      "exit_code": 1,
      "file_written": false,
      "output": "D:\\SEO_Workflows\\3d-tools-site\\data\\fixtures\\3mf\\bambu-edit-test.3mf: Error (Invalid 3MF format) while parsing '3D/3dmodel.model' at line 24",
      "reopen_in_bambu": null,
      "refusal": "Wrote no file: \"Error (Invalid 3MF format) while parsing '3D/3dmodel.model' at line 24\". Line 24 is the second component pointing into 3D/Objects/object_1.model: the negative part (object 2, type=\"other\", offset 2 mm in Z, matching the negative part's matrix in model_settings.config). This is how Bambu Studio stores a part's modifiers and negative parts."
    },
    {
      "editor": "prusa",
      "editor_name": "PrusaSlicer 2.9.6 (command line)",
      "action": "scale110",
      "exit_code": 1,
      "file_written": false,
      "output": "D:\\SEO_Workflows\\3d-tools-site\\data\\fixtures\\3mf\\bambu-edit-test.3mf: Error (Invalid 3MF format) while parsing '3D/3dmodel.model' at line 24",
      "reopen_in_bambu": null,
      "refusal": "Wrote no file: \"Error (Invalid 3MF format) while parsing '3D/3dmodel.model' at line 24\". Line 24 is the second component pointing into 3D/Objects/object_1.model: the negative part (object 2, type=\"other\", offset 2 mm in Z, matching the negative part's matrix in model_settings.config). This is how Bambu Studio stores a part's modifiers and negative parts."
    },
    {
      "editor": "blender",
      "editor_name": "Blender 5.2.2 with the 3MF Import/Export extension 2.7.7",
      "action": "resave",
      "exit_code": 0,
      "file_written": true,
      "output": "IMPORT {'FINISHED'} 4 ['body.stl.001', 'negative.stl', 'modifier.stl', '3MF Object']\nEXPORT {'FINISHED'}",
      "reopen_in_bambu": {
        "exit_code": 3221225477,
        "output": "",
        "written": false
      },
      "format_written": "bambu",
      "plates": 1,
      "objects_per_plate": [
        2
      ],
      "two_plates": false,
      "body_scale": 1.0,
      "modifier_kept": true,
      "negative_part_kept": true,
      "object_setting_kept": true,
      "modifier_setting_kept": true,
      "support_paint_triangles": 0,
      "seam_paint_triangles": 0,
      "printer_profile": "Bambu Lab A1 0.4 nozzle",
      "filament_profile": [
        "Bambu PLA Basic @BBL A1",
        "Bambu PLA Basic @BBL A1",
        "Bambu PLA Basic @BBL A1"
      ],
      "detail": {
        "files": [
          "3D/3dmodel.model",
          "3D/Objects/3MF_Object_4.model",
          "3D/Objects/body.stl.001_1.model",
          "3D/Objects/modifier.stl_2.model",
          "3D/Objects/negative.stl_3.model",
          "3D/_rels/3dmodel.model.rels",
          "Metadata/model_settings.config",
          "Metadata/project_settings.config",
          "[Content_Types].xml",
          "_rels/.rels"
        ],
        "triangles": 48,
        "paint": {
          "paint_supports": 0,
          "paint_seam": 0,
          "paint_color": 24,
          "slic3rpe:custom_supports": 0,
          "slic3rpe:custom_seam": 0,
          "slic3rpe:mmu_segmentation": 0
        },
        "written_by": "BambuStudio-2.3.0",
        "build_items": 2,
        "object_types": [
          "model"
        ],
        "body_scale": 1.0,
        "format": "bambu",
        "objects": [
          {
            "id": "9",
            "name": "body.stl",
            "settings": {},
            "parts": [
              {
                "subtype": "normal_part",
                "name": "body.stl.001",
                "settings": {}
              },
              {
                "subtype": "modifier_part",
                "name": "modifier.stl",
                "settings": {
                  "sparse_infill_density": "80%"
                }
              },
              {
                "subtype": "negative_part",
                "name": "negative.stl",
                "settings": {}
              }
            ]
          },
          {
            "id": "8",
            "name": "3MF Object",
            "settings": {
              "sparse_infill_density": "40%"
            },
            "parts": [
              {
                "subtype": "normal_part",
                "name": "3MF Object",
                "settings": {}
              }
            ]
          }
        ],
        "plates": [
          [
            "9",
            "8"
          ]
        ],
        "profiles": {
          "printer_settings_id": "Bambu Lab A1 0.4 nozzle",
          "print_settings_id": "0.20mm Standard @BBL A1",
          "filament_settings_id": [
            "Bambu PLA Basic @BBL A1",
            "Bambu PLA Basic @BBL A1",
            "Bambu PLA Basic @BBL A1"
          ],
          "sparse_infill_density": "15%"
        }
      },
      "refusal": null
    },
    {
      "editor": "blender",
      "editor_name": "Blender 5.2.2 with the 3MF Import/Export extension 2.7.7",
      "action": "scale110",
      "exit_code": 0,
      "file_written": true,
      "output": "IMPORT {'FINISHED'} 4 ['body.stl.001', 'negative.stl', 'modifier.stl', '3MF Object']\nEXPORT {'FINISHED'}",
      "reopen_in_bambu": {
        "exit_code": 3221225477,
        "output": "",
        "written": false
      },
      "format_written": "bambu",
      "plates": 1,
      "objects_per_plate": [
        2
      ],
      "two_plates": false,
      "body_scale": 1.1,
      "modifier_kept": true,
      "negative_part_kept": true,
      "object_setting_kept": true,
      "modifier_setting_kept": true,
      "support_paint_triangles": 0,
      "seam_paint_triangles": 0,
      "printer_profile": "Bambu Lab A1 0.4 nozzle",
      "filament_profile": [
        "Bambu PLA Basic @BBL A1",
        "Bambu PLA Basic @BBL A1",
        "Bambu PLA Basic @BBL A1"
      ],
      "detail": {
        "files": [
          "3D/3dmodel.model",
          "3D/Objects/3MF_Object_4.model",
          "3D/Objects/body.stl.001_1.model",
          "3D/Objects/modifier.stl_2.model",
          "3D/Objects/negative.stl_3.model",
          "3D/_rels/3dmodel.model.rels",
          "Metadata/model_settings.config",
          "Metadata/project_settings.config",
          "[Content_Types].xml",
          "_rels/.rels"
        ],
        "triangles": 48,
        "paint": {
          "paint_supports": 0,
          "paint_seam": 0,
          "paint_color": 24,
          "slic3rpe:custom_supports": 0,
          "slic3rpe:custom_seam": 0,
          "slic3rpe:mmu_segmentation": 0
        },
        "written_by": "BambuStudio-2.3.0",
        "build_items": 2,
        "object_types": [
          "model"
        ],
        "body_scale": 1.1,
        "format": "bambu",
        "objects": [
          {
            "id": "9",
            "name": "body.stl",
            "settings": {},
            "parts": [
              {
                "subtype": "normal_part",
                "name": "body.stl.001",
                "settings": {}
              },
              {
                "subtype": "modifier_part",
                "name": "modifier.stl",
                "settings": {
                  "sparse_infill_density": "80%"
                }
              },
              {
                "subtype": "negative_part",
                "name": "negative.stl",
                "settings": {}
              }
            ]
          },
          {
            "id": "8",
            "name": "3MF Object",
            "settings": {
              "sparse_infill_density": "40%"
            },
            "parts": [
              {
                "subtype": "normal_part",
                "name": "3MF Object",
                "settings": {}
              }
            ]
          }
        ],
        "plates": [
          [
            "9",
            "8"
          ]
        ],
        "profiles": {
          "printer_settings_id": "Bambu Lab A1 0.4 nozzle",
          "print_settings_id": "0.20mm Standard @BBL A1",
          "filament_settings_id": [
            "Bambu PLA Basic @BBL A1",
            "Bambu PLA Basic @BBL A1",
            "Bambu PLA Basic @BBL A1"
          ],
          "sparse_infill_density": "15%"
        }
      },
      "refusal": null
    }
  ]
}