cocos/example-projects

研发场景合并工具

jareguo opened this issue · 19 comments

暂时没有想法。。。明天再试

今天研究感觉难点在 Unity 用了一个 exe 的文件内容然后适配了多家流行的合作仓库工具,首先 gitkaren 是不行了,我用 sourceTree 在做实验。

不会吧,这个是通用的,什么工具都能用

现阶段第一步:
构建一个 gulp 的命令内容,通过命令行实现分支场景的合并。
传入参数设置为: BASE, REMOTE, LOCAL, MERGED 四个吧.
BASE: 基础文件,
REMOTE: 合并分支场景文件,
LOCAL: 需要合并的文件,
MERGED:解决冲突后文件。
conflict 冲突内容:

  1. 针对两个 fire (remote,local)文件获取后排序,逐行对比判断,不相同的内容直接覆盖,新生成的 fire 文件直接作为 output。
    测试方案设计:
  2. 获取文件(暂时可以使用设定好的文件进行对比)
    2.排序,检测冲突
    3.合并冲突,生成新文件
    4.输出(保存到自定义的文件夹下,暂时不需要提交)
  1. readfileSync-> create String -> match ([])-> sort use the id -> write to a new File

排序设计格式:
_id 总内容排序-> 主键
node: ——id—— 匹配对应节点 -> propertype

完成一个部分的内容排序之后,components 的排序放弃,因为考虑到同一节点的多个 component 内容无法正确的排序,所以这个部分采用局部循环查找对应部分进行内容对比。
nodes 的排序是为了方便对比,减少循环消耗,无法排序的部分就只能进行消耗。
(这里用 find 多消耗一下内存记录一下绑定的 components 到每个 nodes 上,可以考虑按照 --type-- 设计排序)
有了一个部分的排序之后获取剩下的两个排序。
进行对比,内容的覆盖。???? 他们怎么知道我们如何选择覆盖内容的?
完成之后设计输出文件样式。

流程设计:
获取了 sort 三个文件内容,首先命名是相同的,路径的选取在当前文件夹下创建新的文件夹 mergeSpace
将生成的文件导入,继续进入下一步。
merge.fire 文件名称与源文件相同,并且排序按照 id 获取原先的排序内容。

最后一步+结构调整:
1.经过重新的设计发现,传入的 base 应该是按照单个文件存在的,所以清除以前针对 array 的循环操作,改为针对单个文件操作。
2.针对设计在 package 添加了新的 proto , dependMergeTool 属性包含暂存文件路径以及调用工具。
3.目前对于 fire 文件以及非 fire 文件内容都进行了考虑,最后针对不同的数据输出路径进行调整。
4.进入 fire.merge 文件重新排序部分,也是最后一个部分了。排序规则,保持原有的节点树顺序,componets 内容针对对应节点顺序进行排序。

目前瓶颈在重新规划数据内容,把之前没有考虑到的 id 排序重新考虑进去。
我觉得目前考虑代码简化精简会给构建进度带来很大的困难,尤其是在知识储备不够丰富的前提下。
因此暂时不考虑代码精简内容,以完成功能实现为主。

第一阶段完结,撒花,现在开始进入‘测试’发布阶段

请把你的 json 格式贴上来,简单介绍一下

合并冲突解决工具文件处理流程:

  1. 传入 BASE,LOCAL,REMOTE 三个 fire 文件内容。
  2. 针对 fire 文件内的数据,每个类型的数据会生成对应的唯一标识,同时针对数据的结构进行调整。
  3. 生成调整过结构的 json 文件(BASE,LOCAL,REMOTE),调用第三方工具解决冲突。
    (调用第三方工具之前需要在 package.json 中新增一个设置如图:
    image
    添加你电脑中你常用的第三方冲突解决工具。)
  4. 解决冲突之后会保存一份 merge.json 文件到当前的文件目录下,同时还会有 MergeCache 的文件夹存储三个 json 文件。
  5. 工具最后会对 merge.json 文件进行重新排序处理。
  6. 生成新的 fire 文件,覆盖当前冲突文件。文件数据中节点顺序以及组件顺序会按照当前场景的节点树顺序重新排布。

生成的 json 文件数据结构:

image
当前生成 json 文件的对比格式是如上图。

mark:是一个由代码生成的数据唯一标识。合并工具会根据这个唯一标识对数据内容进行索引位置确认。生成标识的结构针对不同的数据类型会有细微的变化。
content:为 fire 文件内的原数据内容,但是为了更好的合并 cc.Node 类型去除了 components, prefab 两个数据的索引信息。
_prefabInfos:当前节点的 prefab 信息。
_components:是当前节点的绑定组件内容 。image
上图为 components 的存储数据结构,Components 去除了 node 关于 cc.Node 的索引信息, prefabInfo 则去除了 root 关于 cc.Node 的索引信息。
_clickEvent:是根据特殊的组件如: cc.Button 绑定的 clickEvent 记录。通过 components 的 clickEvent [] 获取相关记录之后关联到当前组件的绑定节点上。

image
clickEvent 数据内容如上图。

target: 为绑定节点索引信息。
component:为绑定节点上相应组件。
handler:组件内自定义的函数内容。
customEventData:自定义收发事件信息。

根据 fire 文件获取的 clickEvent->content 数据内容不足以支持 Components 在文件数据排序之后仍然获取正确的 clickEvent,因此在这里通过一个 clickEvent 数组对这种数据进行了关联记录。

可能存在无法解决的问题:

比较特殊的冲突问题是针对 _id 数据的比较,目前没有特别好的办法调整。举例而言,当一个版本场景下增添了一个节点数据,在另一个版本下并没有通过合并的方式修改场景,而是通过手动增添一个同样的节点数据在场景中,这会导致相同的节点数据信息但是拥有不同的 _id 数据,因为新生成的节点都会有相应的唯一 _id 生成。
冲突对比过程中,以上结构尽量减少了索引信息的存在。

当前工具经过实验测试了两个场景:
1.9.3 的 webp-test。
2.0 的 TestList (调整过,场景内添加了所有的功能组件)。
image

最后结果是:场景稳定打开,绑定内容都在。

  1. 合并 example-case v1.9-release 到 master 分支。
  2. 实际上使用 sourceTree 合并我认为应该先发布 npm 的包,确保内容是可以被调用的再进行场景合并测试。
  3. 场景合并只针对有冲突的场景文件进行调整。
    目前 npm 被人干了。。。所以我们只能暂时放弃 publish 新的 package,直接借助 sourceTree 生成的三个对比文件进行场景合并。
    git push 的效率也极低。。。我调整了 global config 好像也没什么作用。所以目前针对场景先进行研究吧。

image
mark 设置成为 JSON 的形式之后再 locationID mark 转换 id 的过程中会出现 JSON 无法解析的情况,因为本身。
image

这样只能通过先转换为一般数据在通过添加 ‘’ 包裹使对象成为字符串,在经过转换获得能够转换的 JSON 脚本。

举例:
image

image
这个部分匹配字符串十分糟糕。。。
image
因为在输出文件的时候要以字符串的形式,所以原本就是 json 格式的字符串进行了二次封装成为 string
导致最上图的糟糕的比较。不好看啊

目前测试了几个场景基本上都通过了,调试完成之后融合生成的场景可以正常的打开并且功能正常。
但是因为不是发布工具的原因吧,sourceTree 会重新扫描生成的 fire 文件,并对文件进行重新的编辑。
接下来的工作我想尝试着将工具与 sourceTree 进行合并。即发布当前版本工具并在 sourceTree 设置内进行调试。

在制作 pipe 内容的过程中,思考到关于排序的问题。 现在第一阶段排序,即针对三个对比文件的排序规则是按照 id 表示排序,实际上算是按照 type: cc.Type 这样的方式进行排序。主要是根据 Node 属性,但是转换 merge 文件的时候我会进行一次节点树的排序,我认为可以将节点树的这个排序方案直接提前,将三个对比文件也按照节点树的顺序进行排列。因为这样生成出来的数据是有依据的(根据 _children _parent 什么的)。

总体上是开发完毕了。。。
由于目前 NPM 无法发布新的 package 所以暂时无法连接 SourceTree 直接使用。
所以暂时需要等待。