ENH: Smart import naming rules — auto-assign filament & part type from body name tags#10451
Open
jomixlaf wants to merge 18 commits intobambulab:masterfrom
Open
ENH: Smart import naming rules — auto-assign filament & part type from body name tags#10451jomixlaf wants to merge 18 commits intobambulab:masterfrom
jomixlaf wants to merge 18 commits intobambulab:masterfrom
Conversation
Parse [tag] tokens from body/volume names on import and automatically assign filament and part type. Supports STEP and 3MF. Default tags: [f1]-[f16] for filament, [part], [neg], [mod], [blk], [enf] for part type. Tags are case-insensitive and combinable. Example: body named "logo[f2][mod]" imports as filament 2, Modifier type.
…ansfer map OCCT's XCAF layer only preserves names from PRODUCT entities, so bodies that live directly inside a root Fusion 360 component (stored as MANIFOLD_SOLID_BREP in STEP) were always imported as "SOLID" regardless of their actual name. After the XCAF transfer, iterate all STEP entities via the transfer process to build a TShape-pointer → MANIFOLD_SOLID_BREP-name map. getNamedSolids now consults this map when naming solid shapes, so tags like [f3] embedded in a body name are correctly preserved and subsequently applied by the smart-import naming rules.
…nents
When a Fusion 360 file has a body directly inside the root component, OCCT's
XCAF layer creates a virtual label for that geometry with a shape-type default
name ("SOLID") rather than the component/product name. The previous approach
tried to recover the MANIFOLD_SOLID_BREP entity name (the body name), but that
gives the wrong result — users should tag the *component* name, not the body
name, consistent with how sub-components already work.
Fix: treat OCCT shape-type default strings (SOLID, COMPOUND, SHELL, etc.) as
missing names and fall back to the parent component name (prefix). Bodies that
live directly in an assembly component now inherit the component name so tags
like [f3] or [neg] placed on the component are correctly applied on import.
When reloading a STEP file from disk, the old volume's config and type were restored after loading, but naming rules were never re-applied. This meant that body name tag changes (e.g. renaming a component from [f1] to [f3]) or newly added bodies had no effect until the file was re-imported via drag-and-drop. Apply naming rules to the new volume after the old config is restored, so tags always reflect the current state of the file on disk. Both reload code paths (ENABLE_RELOAD_FROM_DISK_REWORK and legacy) are covered.
Two issues with reload from disk for STEP files: 1. New bodies added to the STEP file were never imported — the reload loop only iterated over existing volumes looking for matches, so anything new in the file was silently dropped. 2. Component name changes didn't trigger naming rule re-evaluation because the old config/type were restored after loading without re-running rules. Fix: track which new_model volumes were matched during the update loop, then add all unmatched volumes as new volumes to the target object. Naming rules are applied to both updated and newly added volumes so filament/type tags are always current with what's in the file on disk.
…odies When a STEP file is updated with new bodies, existing volumes can shift to different indices in the newly-loaded model. The previous source-index match only checked input_file, so adding a body could silently match the wrong volume and copy its type/config onto a different volume (e.g. giving the wrong part a NEGATIVE_VOLUME type). Now the candidate must also have the same name as the old volume before the source-index match is accepted.
After reloading volumes from disk, the sidebar object list was not updated, leaving stale volume names, types, and filament columns from before the reload. Now add_volumes_to_object_in_list() is called for every modified object after the reload loop completes, so the sidebar immediately reflects new component names, updated tags, and newly-added volumes.
Previously, renaming a component (e.g. polo[f2] → polo[f5]) caused reload to fail with an error because source-index+name and name-search both required the old name. Now matching uses three passes: Pass 1: source index + exact name match (unchanged bodies) Pass 2: name search (body moved to different index, name kept) Pass 3: source index only (body renamed in place) Already-claimed new_model slots are skipped at every pass to prevent two old volumes from mapping to the same new geometry. Source indices on the resulting volume are updated to the new model positions so the next reload also finds the correct slot.
Three related fixes: 1. Deleted bodies: when a body no longer exists in the reloaded STEP file (deleted from Fusion), it now gets silently removed from the model instead of showing an error and leaving a stale volume behind. 2. sort_volumes moved out of per-volume loop: calling sort_volumes after each swap/delete was reordering the volumes array and making later vol_idx values point to the wrong volumes, causing duplicates and missed updates. sort_volumes is now called once after the loop for all modified objects. 3. Deleted-volume cleanup: volumes marked as deleted are removed in reverse index order after the loop so earlier indices stay valid.
When a body is added to a Fusion 360 STEP file and the model is reloaded, the new body appeared at the center of the plate instead of its correct position. Root cause: center_around_origin() shifts all volumes by -bb_center. On initial import the bb_center is computed from the original set of bodies; on reload new_model has an extra body that shifts the bounding-box center. Matched volumes are repositioned via old_volume->get_transformation(), so they land correctly. New (unmatched) volumes were copied directly from new_model, which uses the new shifted center — wrong coordinate frame. Fix: capture coord_shift = old_offset - new_model_offset from the first matched volume. This equals new_bb_center - initial_bb_center. Apply the shift to every newly added volume so it lands in the same coordinate frame as the existing volumes.
Logs new_model structure (objects, volumes, offsets) before and after center_around_origin, coord_shift capture, per-matched-volume final offsets, and per-new-body pre/post shift values. Useful for diagnosing position issues across reload sequences.
Pass 2 (name-based fallback) was gated by has_name, which only fires when old_volume->name equals the reloaded file's filename — false for multi-body STEP files where each body has its own name. The result: Pass 2 never ran, and when Fusion reordered bodies in the new STEP, Pass 1 missed and Pass 3 fell through, matching by source.volume_idx alone and routing the wrong body's transform. Run Pass 2 whenever the volume has a name; the outer has_source || has_name gate already restricts processing to volumes from the file being reloaded.
Previously, set_transformation(old_volume->get_transformation()) preserved the matched volume's old position regardless of whether the body moved in CAD. This broke when users repositioned bodies between exports — matched bodies stayed at stale offsets while only their meshes updated. Use the new STEP position translated by coord_shift instead. For the first matched volume (which defines coord_shift), this yields its old offset exactly, keeping the object's plate anchor stable. For all other volumes, it tracks their new STEP positions in the existing scene's coordinate frame.
OCCT's TCollection_AsciiString(extString) without a replacement character preserves raw bytes >= 0x80, which then fail BambuStudio's isUtf8 check (a lone continuation byte like 0xA0 is invalid UTF-8). The body falls back to the parent component name, losing both the user's body name and any [tag] inside it. This bites users who paste a non-breaking space in Fusion (the typical source of STEP \X\A0 escapes) — for example renaming a body to 'cylinder [f4]' with a stray NBSP would import as 'test_step' with no filament tag. Pass ' ' as the replacement so non-ASCII becomes a regular space, keeping the name readable, the [tag] discoverable, and the isUtf8 check happy.
The previous attempt of passing a replacement char to TCollection_AsciiString did not engage as expected (OCCT's behavior with that constructor preserved raw high bytes). A lone byte like 0xE9 (é) or 0xA0 (NBSP) then failed StepPreProcessor::isUtf8 and the body fell back to the parent component name, losing both the name and any [tag] inside it. Walk the OCCT extended (UTF-16) string codepoint by codepoint and emit a benign space for anything outside printable ASCII. Pure ASCII output always passes isUtf8, so the user's tags are preserved no matter what character they paste into a body name in Fusion.
apply_import_name_tags only updated filament/type when a recognized tag was found. Removing a [mod] or [neg] tag in Fusion left the volume stuck on its previous type after reload; same story for removing a [fN] tag. The user's mental model is that bracket-tags are the source of truth and absent ones mean default. Gate naming-rule application on the volume's name containing at least one [<anything>] sequence. If yes, apply complete tags defaulting filament=1 and type=MODEL_PART for missing/unrecognized tags. If no brackets at all, leave the volume's filament/type alone so manual adjustments the user made in BambuStudio survive reload.
Strip the .stl/.STL extension from the imported object and volume name in load_stl() so filename tags like "MyPart [f3] [neg].stl" display as "MyPart [f3] [neg]". The existing apply_naming_rules_to_objects pipeline in Plater::priv::load_model_objects then picks up the bracket tags and assigns filament + part type, matching STEP body-name behavior.
This was referenced Apr 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a small naming-rules system that parses tags inside body/object names at import time (and on reload) to auto-assign filament and part type. Tagging a body in your CAD as
wheel[f3][mod]is enough to land it in BambuStudio with filament 3 and type Modifier — no clicking through the type submenu, no remembering which body needs which filament after every reload.Works for STEP, 3MF, OBJ, and STL — every multi-body format BambuStudio supports.
This builds on top of PR #10380 (reload-from-disk fixes). The reload path here calls into the naming-rules helpers added by this PR, so #10380 should land first.
Tag syntax
body_name[tag1][tag2]…— tags are case-insensitive, order-independent, combinable.[f1]…[f16][part][neg][mod][blk][enf]Examples:
gear[f2]→ Part on filament 2cavity[neg]→ Negative Partsupport_zone[enf][f5]→ Support Enforcer on filament 5Why brackets? They survive every CAD export I tested, are ASCII-safe, path-safe, readable, and don't collide with normal naming.
Behavior
Files added
src/libslic3r/ImportNamingRules.hpp/.cpp— rule definitions, tag parser, andapply_naming_rules_to_volume/apply_naming_rules_to_objectshelpers.Files touched
src/slic3r/GUI/Plater.cpp— callsapply_naming_rules_to_objectsafter import; callsapply_naming_rules_to_volumeon matched + new volumes during reload.Test plan
[f1]…[f16]tags → filament column populated correctly[neg]/[mod]/[blk]/[enf]→ volume type set[f3][mod]→ both applied[mod]→ no tag → back to Part)[...]left alone — manual filament adjustments survive reload