diff --git a/docs/dev-notes/linked-file-features.md b/docs/dev-notes/linked-file-features.md index 7253e1783d..7d5b3f9572 100644 --- a/docs/dev-notes/linked-file-features.md +++ b/docs/dev-notes/linked-file-features.md @@ -165,6 +165,11 @@ Path changes update `link.name`/`filepath` and, with a host IFC, the reference `Location` + document name — which is why `ReloadLink` became a `tool.Ifc.Operator`. Script calls without arguments preserve all stored link values via `is_property_set`. +`bim.reload_all_links` (refresh button beside Link IFC in the panel header) reloads +every *loaded* link via argument-less `reload_link` calls — each link's stored +path/query/exclude replay and its cache rebuilds from disk. Unloaded links are left +alone. Deliberately expensive: one background cache rebuild per link. + ### Per-row lock toggle + auto-saved transforms Link editing moved from the panel header into each list row as a lock/unlock icon: diff --git a/src/bonsai/bonsai/bim/module/project/__init__.py b/src/bonsai/bonsai/bim/module/project/__init__.py index 36c0d085f5..f59b4b4d5b 100644 --- a/src/bonsai/bonsai/bim/module/project/__init__.py +++ b/src/bonsai/bonsai/bim/module/project/__init__.py @@ -66,6 +66,7 @@ classes = ( operator.QueryLinkedElement, operator.RefreshClippingPlanes, operator.RefreshLibrary, + operator.ReloadAllLinks, operator.ReloadLink, operator.RemoveProjectLibrary, operator.RevertProject, diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 41277a6487..e8d8d8e88f 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -1820,6 +1820,33 @@ class ReloadLink(bpy.types.Operator, tool.Ifc.Operator): ) or {"FINISHED"} +class ReloadAllLinks(bpy.types.Operator): + bl_idname = "bim.reload_all_links" + bl_label = "Reload All Links" + bl_options = {"REGISTER", "UNDO"} + bl_description = "Reload all loaded linked models from disk, rebuilding their caches" + + @classmethod + def poll(cls, context): + if not any(link.is_loaded for link in tool.Project.get_project_props().links): + cls.poll_message_set("No loaded links to reload.") + return False + return True + + def execute(self, context): + props = tool.Project.get_project_props() + reloaded = 0 + for i, link in enumerate(props.links): + if not link.is_loaded: + continue + # Called without filter properties, reload_link preserves each + # link's stored path, query and exclude. + bpy.ops.bim.reload_link(link_index=i) + reloaded += 1 + self.report({"INFO"}, f"Reloaded {reloaded} linked model(s).") + return {"FINISHED"} + + class SelectLinkFilepath(bpy.types.Operator): bl_idname = "bim.select_link_filepath" bl_label = "Select Link File Path" diff --git a/src/bonsai/bonsai/bim/module/project/ui.py b/src/bonsai/bonsai/bim/module/project/ui.py index 3c6473f251..c200bd18f2 100644 --- a/src/bonsai/bonsai/bim/module/project/ui.py +++ b/src/bonsai/bonsai/bim/module/project/ui.py @@ -492,6 +492,7 @@ class BIM_PT_links(Panel): row = self.layout.row(align=True) row.operator("bim.link_ifc") + row.operator("bim.reload_all_links", text="", icon="FILE_REFRESH") if self.props.links: if self.props.active_link: row = self.layout.row(align=True)