C2F4DT — Plugin/Extensions Developer Guide¶
This guide shows how to build drop-in extensions for C2F4DT without modifying main_window.py
.
Extensions live in the ./extensions/
folder and are loaded automatically at startup.
The Cloud2FEM plugin is included as an example, but the framework is designed for any plugin or extension.
TL;DR¶
- Create a folder under
extensions/your_plugin/
- Add a small
extension.json
manifest - Provide a Python module with a factory
create_extension()
that returns an object implementing: name: str
,version: str
activate(ctx: HostContext) -> None
deactivate() -> None
1) Folder layout¶
Example extension.json
:
package
: python module (filename without.py
)entry
: factory function returning the extension instancerequires_api
: host API version your plugin expects
2) Host API (what you get)¶
Extensions receive a HostContext
at activate()
:
(In the current codebase, HostContext
is defined in c2f4dt.plugins.manager
and re-used by plugins.)
- Use
ctx.add_tab(widget_title, widget, target="main")
to add whole tabs totabMain
. - Access existing content panels with:
scrollDISPLAY_CONTENT
,scrollSLICING_CONTENT
,scrollFEM_CONTENT
,scrollRESULTS_CONTENT
- Store persistent UI prefs in
ctx.window.view_opts
(a dict), e.g.,view_opts["slice_point_size"]
.
Stability: the host exposes APP_PLUGIN_API_VERSION
to gate incompatible plugins.
3) Minimal plugin template¶
Prefer embedding controls inside existing
scrollXXX_CONTENT
containers for a cohesive UX.
Usectx.add_tab(...)
if your feature needs a dedicated full tab.
4) UI targets & object names¶
Common insertion points (object names):
- Display:
scrollDISPLAY_CONTENT
- Slices:
scrollSLICING_CONTENT
- FEM:
scrollFEM_CONTENT
- Results:
scrollRESULTS_CONTENT
Adding toolbar actions is allowed (use ctx.window.menuBar()
or find toolbars by name), but keep toolbar minimal and consistent.
5) Reading & setting view options¶
Use ctx.window.view_opts
to store simple preferences:
Renderers (3D viewer, etc.) can read those values to affect visualization.
Example keys used by the Slices visualization extension:
slice_point_size
/slice_point_color
(all slices)slice_current_point_size
/slice_current_point_color
(current slice)
6) Integrating with existing logic (optional)¶
If you need to sync with host behavior, you can look up helpful widgets or actions:
cbSliceIndex
(QComboBox
): current slice indextoggle_current_slice_3D_view
/toggle_all_slices_3D_view
(QAction
)
Prefer host-agnostic logic; call internal helpers only when necessary and available.
7) Logging & messages¶
- Use
ctx.log("INFO", "message")
for plugin logs. - For user-facing messages, use the host’s message area:
8) Versioning & compatibility¶
- Set
requires_api
inextension.json
. - When the host bumps
APP_PLUGIN_API_VERSION
, incompatible plugins are skipped. - Keep your plugin’s
version
in sync with your changes.
9) Testing checklist¶
- No crashes if target containers are missing (fail gracefully).
- No global state required; clean up in
deactivate()
. - Works with/without a loaded point cloud.
- Honors dark theme where possible (avoid hard-coded colors).
- No blocking calls on the UI thread for long operations.
10) Packaging & distribution¶
- Ship your plugin folder (
your_plugin/
) as a zip; users unzip into./extensions/
. - Avoid heavy dependencies; if needed, handle absence gracefully.
- Keep names unique to avoid clashes.
11) Advanced tips¶
- Hot reload (dev): add a host command to call
plugin_manager.unload_all(); plugin_manager.load_all()
. - Shared services: use
ctx.registry
to publish/reuse services between plugins. - Targeted tabs: the host’s
add_tab
supportstarget="main"
and can be extended for additional tab stacks.