上一篇文章介绍了CAX软件插件化架构的基本设计,今天接着聊聊我在这个框架上真正落地的那些硬核功能——不仅仅是插件能跑起来,更实现了完整的3D交互能力:模型导入、装配体展示、视角切换、鼠标拾取等。配合插件管理器,还完成了依赖库检查、菜单动态创建、信号槽通信和文档生命周期管理。这套体系目前已在项目中稳定运行。
一、插件管理器:加载、卸载与依赖检查
插件管理器(OcadPluginManager)是整个架构的心脏。它负责扫描指定目录,通过QPluginLoader加载符合接口规范的动态库。关键点有两个:
·依赖库检查:每个插件可能依赖特定版本的第三方库(如OpenCASCADE、Assimp等)。加载前,我会读取插件元数据中的依赖列表,检查环境中是否存在对应库文件及版本。若缺失,则拒绝加载并给出友好提示,避免运行时崩溃。
·动态卸载:unloadPlugin不仅调用插件的shutdown清理UI和内存,还会通过 QPluginLoader::unload()真正释放动态库。配合PluginRecord记录的路径和指针,实现热插拔。
二、插件内菜单创建与信号槽
每个插件在initialize(OcadRibbonWindow* mainWindow)中会自主创建自己的菜单页或工具栏按钮。例如,我的“3D导入插件”会添加“导入STEP/IGES”、“重置视角”等按钮。
关键技巧:信号槽连接完全在插件内部完成,主框架不感知具体按钮功能。插件持有主窗口指针,可以安全地将按钮点击信号连接到插件内部的私有槽函数。这样,即使插件被卸载,所有连接也会随着插件对象析构而自动断开,不会残留悬空回调。
三、文档管理:插件与主框架的协同
CAX软件离不开文档(Document)概念。我实现了一套轻量级的文档管理系统:
·主框架维护一个DocumentManager,负责创建、关闭、保存文档。
·插件可以请求创建新文档,或者获取当前活动文档的指针。
·当插件执行“导入模型”时,它会创建文档对象,并将加载的几何数据存入文档;视角切换、鼠标拾取等操作则通过文档对象访问当前模型数据。
这样,插件无需关心文档的存储路径或历史记录,只需通过接口与文档管理器交互,职责清晰,也便于未来支持多文档标签页。
四、3D插件功能实战:导入、装配体、视角、拾取
以我的“3D模型导入与交互插件”为例,具体实现了以下硬核能力:
模型导入:使用Assimp 、OCCT库读取几十种格式(STEP、IGES、STL、OBJ等),将面片或B-Rep数据转换为内部显示结构。支持异步加载,避免阻塞UI。
装配体展示:导入的装配体会保留层级结构(部件/子装配),插件自动为每个部件创建独立的变换节点,支持整体爆炸视图或单部件隐藏。通过树形控件管理装配树,点击节点高亮对应部件。
视角切换:通过自定义的视图控件,插件提供标准视角(前/后/左/右/俯/仰)以及“适应屏幕”功能。所有视角变换矩阵由插件计算并应用到相机,旋转/平移交互流畅。
鼠标拾取:鼠标点击时,插件向场景发射射线,检测相交的部件并高亮显示(改变轮廓线或半透明叠加)。拾取结果可通过信号发送给主框架的状态栏或其他插件,方便后续测量或属性查看。
五、整体效果与下一步计划
现在,软件启动时只加载核心框架,用户按需启用3D插件。首次加载时会检查OpenCASCADE/Assimp等依赖库,缺失则提示安装。插件加载后,菜单自动出现新页签,点击“导入模型”即可打开文件对话框,装配体展示流畅,鼠标拾取响应迅速。卸载插件时,所有菜单、文档和视图资源被完全清理。
下一步计划:增加插件间的通信总线,让“测量插件”能直接使用“导入插件”当前选中的几何元素;同时支持插件的延迟加载和按需加载,进一步优化启动速度。另外计划为插件增加脚本接口,允许用户用Python编写自定义处理流程。
这次从框架到3D功能的完整落地,让我深刻体会到:插件化不仅仅是代码解耦,更是一种让复杂系统保持敏捷的架构哲学。如果你也在开发CAX或CAD软件,不妨参考这条路径,少走弯路。欢迎留言交流,一起探讨工业软件的技术演进。

夜雨聆风