前言
没想到过年一拖更,便是长达一个月,如今已经开工第二周了(:з」∠)
过年回家没有更新博客,倒是看了些许 Houdini 教程,记录在 HoudiniWiki 网站中了。
然而最近一周迷上了煲剧 - 庆余年,快前年的剧了,热播的时候就有所耳闻,一直压着没看。
最近回深圳上班之后,感觉不在状态,周末就想着看些爽剧休闲一下,结果打开了潘多拉的魔盒ε=(´ο`*)))唉
恰逢最近工作需要搭建流程框架,试图将影视的部分 publish 流程,迁移到现有的游戏工作流中。
这难免让我想起了以前老东家干的活,虽然那时候在实习,毕竟也是担任流程 TD 的岗位。
当时做的很多东西未能落地,实属我入行的遗憾,未接触过成熟的流程框架落地的感觉。
总算在这边可以尝试开源的 Pyblish 框架将流程落地了。
Pyblish 框架是 mottosson 大佬(由于 Github 的图片是秃头的,我们都尊称为秃子)结合开源社区制作的一款通用流程框架。
框架将前端后端分离,开源免费,适合大小 studio 结合不同平台来使用。
我个人收集的一些 studio 的案例
https://github.com/pyblish/pyblish-mindbender
https://github.com/BigRoy/pyblish-magenta
https://github.com/kredencstudio/pyblish-kredenc
https://github.com/bumpybox/pyblish-bumpybox
Pyblish 作用
Pyblish 是 Python + Publish 的合成词,以为结合 Python 的发布流程。
Pyblish 是前后端分离框架, pyblish-base 是底层内核的调度仓库。
由于前后端分离,因此 Pyblish 前端有 pyblish-lite 和 pyblish-qml 两种不同的实现方式
前端只是个界面,背后依靠的还是 pyblish-base 的调度,分为collect 收集
validate 校验
extract 提取
integrate 整合
四个环节。
这个四个环节官方去其英文首字母缩写为CVEI
流程
这四个环节就是 pyblish 集众多流程软件的经验总结抽象出来的核心。
四个环节的拆分可以让环节之间尽可能解耦,让框架更加灵活。
如果觉得我说的很抽象的话,可以看下面这个视频,这是秃子 Vimeo 账号下发布的 Pyblish 动画小短片。
这个是动画非常直观的表现了 Pyblish 框架的目的。
作为一个质检流程,避免错误的文件发布到下游,提前发现问题,降低沟通成本。
结合 Github 的 Qml 前端操作的截图,想必会更加具象。
pyblish 会将分成
CVEI
四个环节分部进行。
第一步是收集检查需要用到的信息,然后根据相关的信息生成对应 检查实例
第二步是根据生成的 检查实例 分类进行响应不同的检查项检查
第三步提取将文件导出关联的格式,比如 fbx abc 等等(影视流程要考虑更多,诸如 ass 高低模等等)
第四步整合则是对接到相关到任务管理软件,更新任务相关的数据。
Pyblish 的核心是
Validate
质检过程,通过大量的检查项确保发布的文件基本符合规格。
了解 Pyblish 的基础要素强烈推荐过一遍官方的 Learn文档
其中 Quick Start 章节有 Pyblish 的核心内容,
Pyblish 概念 & 使用
Pyblish 基础运用
Pyblish 内部有两种不同的 Plugin
ContextPlugin
和InstancePlugin
Collect 阶段使用ContextPlugin
随后生成InstancePlugin
来进行不同的调度。
1 | import pyblish |
上述代码基于官方教学整合而来。
注册 Plugin 之后通过调用 publish 方法可以不通过 UI 执行注册的发布。
所有的 Plugin 固定调用 process 方法
ContextPlugin 固定传入 Context 类
InstancePlugin 固定传入 Instance 类
Context 类可以通过
create_instance
方法创建实例,每个实例会根据 关联属性被相关的InstancePlugin
调度。 链接
Pyblish 调度执行
我们会创建很多不同检查项,但是不同的实例走的检查不尽相同,Pyblish 提供了相应的标签属性来合理调度检查项。
1 | import pyblish.api |
上面通过配置
families
参数可以让 分别走不同的InstancePlugin
类似的还有 hosts 属性和 targets 属性
order
属性来管理当前检查的顺序,下面是官方支持的范围
1 | -0.5 to 0.499.. = Collection |
action
属性可以给当前检查项添加右键菜单,触发额外的功能,比如获取错误的模型或者快速修复有问题的地方。
以上提到的就是 pyblish 的核心功能。
另外还有一些让 Pyblish 更加灵活的功能,比如 event 事件系统
可以在不同的状态下触发不同的事件。
也支持注册自定义事件,在检查项中触发
1 | import pyblish.util |
Pyblish-base 调度原理
常用数据结构
上面是 Context & Instance 类, process 传入的 context 和 instance 参数就是这两个类的相应实例
1 | class CollectInstances(pyblish.api.ContextPlugin): |
它们的基类 AbstractEntity 是个数组,所以可以进入 for 循环进行遍历。
publish
入口函数是 publish ,从上面的截图可以看到后续核心调用是
_convenience_iter
_convenience_iter
核心调度
logic.Iterator
返回的 Context 参数 和 Instance 参数
logic.Iterator
在
logic.Iterator
遍历器里面会先对 targets 属性进行过滤。
然后遍历一遍传入的 plugins 类,通过instances_by_plugin
的方法找出 plugin 和context.create_instance
生成实例的关系。
这里直接对传入的 context 当成 instances 变量进行 for 循环。
那为啥 context 是 instances 呢?
这就承接上面数据结构所提到的, context 的基类是个数组,执行context.create_instance
方法。
查看
create_instance
的调用可以看到如果传入 parent 就会将自身 append 到 parent 里面了。
所以 context 直接 for 循环就是其关联的 instances。
最后会通过
plugin.match
以及 instance 传入的family
和families
过滤出对应调用的 plugin 。
create_instance
的时候会将所有的后续参数 **kwargs update 到 data 中。
过滤 family 会用到 data 中的数据,因此 family 的调用可以写到create_instance
里面
1 | class ValidateMeshNonManifold(pyblish.api.Validator): |
plugin.process
通过上面的
logic.Iterator
可以返回 plugin 类和其关联的 instance 属性。
后续会到plugin.process
进行调用,注意这个 plugin 是小写是 模块 里面的函数调用。
process 为了兼容以前的 API 会分
__explicit_process
和__implicit_process
__explicit_process 会实例化传入的 plugin 类并且判断当前是 action 还是 plugin
从中分配好 process 使用的参数。
总结
虽然上述的调用有点绕,不过基本就是这个原理完成了 publish 的实例调度过程。
这么做可以根据当前文件里不同类型的数据拆分到不同 families 检查项下检查。
实现更细致的检查控制和调度。
pyblish-base 是无 GUI 下检查调度的功能。
pyblish-lite 带 GUI 检查的时候并不是直接用 pyblish-base 下的 publish 的。
为了同步响应 GUI , pyblish-lite 拆分了 publish 的过程,不过核心的调度还是用了 base 的 API。