撤销和重做!支持数据驱动的事务机制啦(使用OpenGL+QT开发三维CAD)
“ 事务机制是设计软件的基础和核心议题之一,基于此可以实现撤销和重做,对包括绘制、编辑、删除、复制、工作平面设置等操作进行撤销和重做,大大提高设计效率和设计容错性,提升用户体验。”
最近,我们在GLViewer中设计和实现了支持数据驱动的事务机制,并基于此开发了“撤销”和“重做”功能,一起看看吧~
原文:撤销和重做!支持数据驱动的事务机制啦(使用OpenGL+QT开发三维CAD)
01 设计理念
作者没有采用QT的UndoFrameWork,而是完整设计和实现了事务机制,并融入了“数据驱动更新”的理念,更灵活和可靠的处理各种复杂操作,进行数据库的更新,并“数据驱动”更新显示,完成操作--到处理--到数据--到显示的流水线的一系列动作。
重要理念:
-
数据库是唯一和可靠的数据源,所有数据更新和数据应用都要以数据库为基准和来源。其中显示也是数据应用的一种,要以数据库数据为依据进行显示。
-
数据驱动更新,由数据驱动进行相关的数据应用的更新,在数据库数据发生新增、删除、修改的时候,自动回调相关接口进行数据应用的更新,包括场景显示的更新。避免多源、繁杂的数据更新和应用依赖和交织。
-
事务机制记录完整的操作动作,并支持对当前撤销动作的重做。两点,(1)要能够记录从最开始到现在的所有操作动作,并支持撤销;(2)要支持当前撤销动作的重做。最大范围的提高设计的容错性。
哈市雪花肝出来的,如果对你有帮助可以让作者感知到哈!
02 服务的对象:GLView
我们在设计和实现一些机制、能力或功能的时候,是离不开用户的,离不开用户场景的,比如图层管理功能,要考虑设计师的使用场景和需求覆盖,包括但不限于新增/删除图层、修改图层颜色、线宽、线型、名称、控制图层的显隐、冻结对图层元素的编辑等。
同样事务机制的设计和实现离不开其“用户”,也就是GLView,GLView实际上做5类事情,这也是其功能表达和服务用户的价值所在,要服务好GLView,让其更好的做事情。
-
设计绘制,包括各种类型线、图片的绘制,支持用户进行设计;
-
显示,显示场景元素,包括线、组件、viewer元素等,直观的展现场景和设计;
-
撤销和重做,提高用户的设计容错性和工作效率;
-
文件和接口,支持打开和保存设计成果;
-
设置,支持图层设置、渲染设置等,更好的展现设计成果。
事务机制要服务好这5类事情的工作,如
-
设计和绘制,要支持设计成果和显示的同步更新,不能如出现设计成果显示了,但数据还未正确更新的情况,那操作半天成果未能正确保存就开了大玩笑。
-
支持撤销和重做,让用户更好的设计,发挥其灵动的设计思维。
-
文件保存时候要有唯一和可靠的数据源,不能从几个地方通过不同的筛选和过滤,甚至处理和分析来收集数据吧,需要唯一和可靠的数据源,文件保存或导出也是数据应用的范畴。
-
撤销了一些动作,再进行新的设计(绘制、编辑、复制、删除等),相当于已经确认并执行了此前的撤销,并基于此继续进行工作了,那么此前的“恢复”列表就要被清空。
-
其它不再赘述。
这也是需求分析、设计要素提取的过程,唯一和可靠的数据源、数据驱动应用更新(显示、自动保存等)、支持成效和重做......
03 流程逻辑图
分析需求,提取设计要素后就可以设计了,上述是事务机制参与的流程和逻辑图,也是设计事务机制时需要关心和实现的一些关键点。
当然还需要由详细设计,详细的进行动作存储、逆向、重做、回调函数、数据库数据修改、数据驱动更新等详细的设计,本文由于篇幅所限,不进行展开,如有兴趣可交流~
我们来看下`TransactionUtils`的部分public接口,
static void CommitCurveNotLine(const TNode& node);
static void CommitDrawImage(const TNode& node, const string& imageFile);
static void CommitCopy(const list<int>& originIds, const Vector3f& offset);
static void CommitDelete(const list<int>& ids);
static void CommitSetWorkPlane(const TNode& node);
static void Commit(const TNode& tNode, const OneTrans& oneTrans, bool isRedoCall = false);
//static void CommitBatch(const TNode& tNode, const OneTrans& oneTrans, bool isRedoCall = false);
static void BeginBatch();
static void PushNode(const TNode& tNode, const OneTrans& oneTrans);
static void EndBatch();
static const list<pair<TNode, OneTrans>>& GetTempBatchNode();
static void Revert();
static void Undo();
static void Redo();
static const TNode& Get(int id);
04 GLViewer中的实现和效果
在GLViewer中,我们设计和实现了完整的事务机制,并开放了撤销和重做功能,支持对多种类型线、图片绘制、复制、删除、工作平面设置等工作的撤销和重做,并以数据驱动显示的更新,实现了较为可靠和完整的工作流。
效果可参考视频:撤销和重做!支持数据驱动的事务机制啦(使用OpenGL+QT开发三维CAD)
https://www.bilibili.com/video/BV1S3gGzfEYG/
专注于图形学(渲染和几何算法)、数据处理、并行计算相关研究和研发,欢迎交流~
学习!《从零开发一款三维CAD软件(OpenGL/QT/C++)》课程上线啦
系列课程已上线,详细的视频讲解,打下扎实的图形学基础,欢迎大家观看和支持~
往期文章:
-
GLViewer:添加ViewCube
-
学习!《从零开发一款三维CAD软件(OpenGL/QT/C++)》课程上线啦
-
OpenGL模板缓冲:实现亮显外轮廓效果
-
2025 想从事工业软件开发要掌握哪些知识?
-
30.抗锯齿(anti aliasing):使用OpenGL+QT开发三维CAD
-
MSAA抗锯齿技术的不足和优化(PPAA)
-
相机:Camera原理讲解(使用OpenGL+QT开发三维CAD)
-
开发三维CAD:实现框选和反选功能
-
图形学:一分钟看懂网格剖分原理(耳切法)
-
视图立方体:ViewCube的绘制(使用OpenGL+QT开发三维CAD)
-
相机:以鼠标点为中心缩放(使用OpenGL+QT开发三维CAD)
-
添加旋转中心标识(使用OpenGL+QT开发三维CAD)
-
构件选中效果:通过自定义帧缓冲实现(使用OpenGL+QT开发三维CAD)
-
通过交互绘制图片(使用OpenGL+QT开发三维CAD)
-
撤销和重做!GLViewer支持事务机制啦
您的支持是作者更新的动力~ 互动起来吧~