本文是 CEP 扩展开发系列教程的第二篇,通过手把手实现一个 Hello World 级别的插件来初步掌握 CEP 插件的配置和开发。

CEP 扩展本身是跨系统(Windows,MacOS)平台的,但是不同宿主环境(Photoshop,AfterEffects 等)的 jsx 解释器(或者说 engine)的技术实现有些许差异。注入的 API 那更是完全不一样,毕竟不同宿主的文档模型和工具能力差异很大。比方说 PS 是 psd,AE 是 project,这两种文档模型完全不一样。

由于最近一段时间我都是在写 PS 插件,因此本文将会主要以 PS 为例子来讲解。

开发工具

在开始我们的 Hello World 之前我们先检查一下是否安装了以下开发 CEP 的必备工具:

  • 宿主应用:After Effects / Photoshop,创作这篇教程时我用的是 Photoshop 2022,版本号是 23.4.2,最近几个月已经不开发 AE 插件,主要在开发和维护 PS 扩展。因为电脑磁盘空间(251G)不够用,都没法保存 psd 了,暂时把 AE 都给卸了,有空清理下空间再装回来...
  • 代码编辑器:Visual Studio Code,理论上你用记事本编写代码也没关系,但是目前 ExtendScript 的 debugger 工具只有 VSCode 的 debugger 扩展还在维护。而且用 VSCode 你还可以安装一些 CEP 开发辅助的扩展,例如我开发的 Adobe Extension Development Tools 和 Scripting Listener
  • Debugger: ExtendScript Debugger 是 VSCode 上用于 debug ExtendScript 和 CEP 扩展的 debugger 插件,如果需要向官方反馈这个插件的问题请去:forums.adobeprerelease.com,在插件市场的评论区反馈是没用的
  • 操作系统:我本人用的是 MacOS Monterey12.5,CEP 扩展核心技术 chromium + nodejs + extendscript 都是跨平台的,所以本身是跨系统平台的。CEP 全拼是 Common Extensibility Platform,既然叫 Common(通用的意思) ,那么是跨平台也不然理解了。
  • 浏览器:Chrome,CEP 扩展本身是使用 Chromium 内核渲染的,你可以使用任何基于 Chromium 内核的浏览器来远程 debug CEP 的网页代码。我测试过 360 和 edge 也是可以的,其它浏览器例如 safari 和 firefox 我没试过,有需要的读者可以参考后面会讲的使用 chrome 来 debug CEP 扩展的方法自行摸索。

为什么我强烈建议使用英文界面而不是中文版

不知道学习编程开发后多久,对于和开发相关的工具,我开始有意识的尽量使用软件的原生语言。也就是说如果一个软件安装的时候默认是英文的我就用英文,不切换中文界面,也不用翻译包。换句话说,英文软件就用英文,中文软件就用中文,telegram 就用英文,钉钉就用中文。例如 VSCode 我是没用语言包,Chrome 我用的是中文版的,原因是用习惯了而且切到英文版后很多网站识别不出我是中文用户。

对于我个人来说,我更倾向于使用软件的原生语言,原因简单概括下:

  1. 我的英语水平够用,足够支撑我流畅阅读英文技术文档和软件界面的英文

  2. 我不信任第三方翻译/语言包,有很多第三方的翻译我觉得不太行,而且有可能更新也不及时,正常人都喜欢原汁原味的

  3. 有助于更快更准确的理解软件代码中使用的字段名,也方便抄代码和找到谷歌关键字

关于第三点,这里再展开讲讲。我们编写代码是英文的,而且使用 debugger 或者第三方扩展查看 PS 中各种数据时得到的也是英文的,因此如果你的软件界面是英文的,就能很快的对应起来。举个简单的例子,当我们想通过代码修改一个图层的是否可见的,在 PS 中设置一个图层是否可见只要点击左侧的眼睛图标就可以,当我们把光标移动到这个眼睛上,我们看看 hover 提示:

看到这其实我们基本上就能肯定 layer 上有一个 visibility 或者它的形容词 visible,通过 debugger 工具查看果不其然有个 visible 属性:

实际的项目开发你会发现很多场景这对于加速开发是非常帮助的,来一个更复杂的例子。例如我们最近的一个实际需求,检测一个矢量蒙版是否修改了密度,也就是不是默认的 100。产品给到我的示意图是这样的:

我看到这图的第一眼是很懵逼的,密度对应的英文单词是哪个?查了一下谷歌翻译:

那他丫的到底是 density 还是 thickness,又或者是 denseness 呢?直到我打开我英文版的 PS 的矢量蒙版的属性面板,一目了然:

这时英文版的优势就极大的体现出来了,使用我开发的 Adobe Extension Development Tools 打开图层的 Descriptor Info,直接搜索 density,毫无疑问 vectorMaskDensity 就是我们要找的属性。

这样代码写起来也很快:

javascript // 至于怎么拿到 layerDesc 这个后序教程讲 AM 的时候就知道了,暂时你就理解为图层的描述对象,和底层 c++ 图层的结构体对应 function isVectorDensityModified(layerDesc) { return layerDesc.vectorMaskDensity != null && layerDesc.vectorMaskDensity !== 255; }

Hello World

接下来我们动手写一个简单的 Hello World 级别的插件,功能很简单:插件面板有一个按钮,点击这个按钮在插件界面上显示出当前选中图层的名称。完整的项目代码我已经放到 github 上了:cep-hello-world。

项目结构

最终我们 Hello world 项目的目录结构是这样的:

. ├── .debug # CEP 扩展 debug 模式配置文件,只开开发时需要 ├── CSXS # 用于存放扩展的配置和资源文件(例如图标) │ └── manifest.xml # 扩展清单文件,用于配置扩展的名称,兼容性,图标,菜单等方方面面,类似 chrome 扩展和 pwa 应用的 manifest ├── JSX # 存放 extendscript 代码 │ └── index.jsx # jsx 代码入口 └── web # 前端代码 └── index.html # 扩展面板的 HTML

创建项目

插件必须要放在特定的文件夹才能被 PS 加载到。有三个位置都能存放 CEP 插件:

  • 软件安装文件夹
  • 系统级插件存放文件夹
  • 用户级插件存放文件夹

软件安装文件夹

软件安装文件夹/CEP/extensions

例如软件(或者说宿主)是 Photoshop,那么在 Mac 对应的路径默认就是:/Applications/Adobe Photoshop 2022,当然软件的安装路径你是可以修改的。这个文件夹不应该被用于存放第三方插件,是用来存放软件自带的 CEP 插件的,而且在 Mac 上修改这个文件夹是需要 Root 权限的。

系统级的插件存放文件夹

  • Win(x64): C:\Program Files (x86)\Common Files\Adobe\CEP\extensions, and C:\Program Files\Common Files\Adobe\CEP\extensions (since CEP 6.1)
  • macOS: /Library/Application Support/Adobe/CEP/extensions

既然是系统级的,那么将插件安装到这就是需要 root 权限。开发插件的时候肯定是不会放这的,放这都没权限修改代码。

这个文件夹适合存放生产环境的插件,某种程度上可以防止用户修改到插件内容,修改了插件内容一般会导致 PS 加载插件的时候报插件内容和签名不一致的问题

用户级别的插件存放文件夹

  • Win: C:\Users\<用户名>\AppData\Roaming\Adobe\CEP/extensions
  • macOS: ~/Library/Application Support/Adobe/CEP/extensions

这才是我们在开发插件时插件应该存放的目录,我们可以随意修改这个文件夹内的内容。

插件查找顺序

软件安装文件夹 > 系统级的插件存放文件夹 > 用户级别的插件存放文件夹。

所以我们第一步就是在用户级别的插件存放文件夹创建我们的插件文件夹

```bash

以 Mac 举例,Windows 就是 C:\Users\\AppData\Roaming\Adobe\CEP/extensions

cd '~/Library/Application Support/Adobe/CEP/extensions' mkdir cep-hello-world ```

添加插件配置文件

一个包含 CSXS/manifest.xml 的文件夹就能称之为一个 CEP 插件。宿主扫描到存放插件的文件夹中的子文件中包含 CSXS/manifest.xml 便会将这个子文件夹识别为一个 CEP 插件。有过 chrome 扩展或者 pwa 应用的读者应该都见过个名为 manifest 的文件,同样的在 CEP 插件中也必须存在一个这样的配置文件。

在项目根目录下创建 CSXS 文件夹,并添加 manifest.xml 文件,文件内容:

xml <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- ExtensionBundleId 是插件 id --> <!-- Version 指的是 manifest.xml 的 schema 版本 --> <ExtensionManifest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ExtensionBundleId="org.ytj.helloWorld" ExtensionBundleVersion="1.0" Version="7.0"> <!-- 一个 CEP 插件可以注册多个面板,每一个面板都可以视为一个子插件 --> <ExtensionList> <!-- 注册一个面板,这个面板可以视为一个子插件,id 为 org.ytj.helloWorld.panel --> <Extension Id="org.ytj.helloWorld.panel" Version="0.0.1" /> </ExtensionList> <ExecutionEnvironment> <!-- 声明这个插件支持的宿主,也就是说是支持跑在 PS 还是 AE,还是其它 adobe 软件 --> <HostList> <!-- PHSP 和 PHXS 都是说 Photoshop --> <Host Name="PHSP" Version="16.0" /> <!-- 16.0 指的是兼容 ps 的 16.0 版本及其以上 --> <Host Name="PHXS" Version="16.0" /> </HostList> <!-- 插件支持的语言 --> <LocaleList> <Locale Code="All" /> </LocaleList> <RequiredRuntimeList> <!-- 声明支持的 CEP 版本为 CEP9 --> <RequiredRuntime Name="CSXS" Version="9.0" /> </RequiredRuntimeList> </ExecutionEnvironment> <DispatchInfoList> <!-- 面板的具体配置 --> <Extension Id="org.ytj.helloWorld.panel"> <DispatchInfo> <Resources> <!-- 面板的网页 HTML 首页路径,相对路径是相对于插件文件夹 --> <MainPath>./web/index.html</MainPath> <!-- 和这个面板相关联的 extendscript 线程加载的 extendscript 文件路径 --> <!-- 不同的面板它们的 jsx 环境是隔离的,这和宿主的实现有关,PS 是隔离的, AE 不是 --> <ScriptPath>./JSX/index.jsx</ScriptPath> <!-- 浏览器环境和 nodejs 环境的一些参数 --> <CEFCommandLine> <Parameter>--enable-speech-input</Parameter> <Parameter>--enable-media-stream</Parameter> <!-- 开启 nodejs 支持,可以在 node 环境直接写 nodejs 代码 --> <Parameter>--enable-nodejs</Parameter> </CEFCommandLine> </Resources> <Lifecycle> <!-- 设置打开插件显示面板界面,也可以设置为 false,打开后不会显示界面--> <AutoVisible>true</AutoVisible> </Lifecycle> <!-- 面板 UI 配置 --> <UI> <!-- 除了普通的面板类型还有 --> <!-- ModalDialog:模态框,不能嵌入 PS 界面,用户在关掉之前不能和 PS 交互 --> <!-- Modeless:和 ModalDialog 区别在于它不会阻止你和 PS 交互 --> <!-- Custom:配合 AutoVisible 实现无界面面板 --> <Type>Panel</Type> <!-- 插件名称,你在 PS 的菜单中看到的插件名称 --> <Menu>Hello World</Menu> <!-- 面板尺寸相关 --> <Geometry> <!-- 插件默认宽高 --> <Size> <Height>611</Height> <Width>280</Width> </Size> <!-- 插件最大宽高 --> <MaxSize> <Height>4000</Height> <Width>600</Width> </MaxSize> <!-- 插件最小宽高 --> <MinSize> <Height>611</Height> <Width>280</Width> </MinSize> </Geometry> </UI> </DispatchInfo> </Extension> </DispatchInfoList> </ExtensionManifest>

里面很多配置项的功能我都以注释的形式说明了。这里再提一下其中几个点:

  • manifest.xml 中所有的相对路径都是相对于插件的根路径
  • 一个 CEP 插件是可以包含多个面板,每一个面板都可以称之为一个子插件,这在 manifest.xml 和后面提到的 debug 配置里都能体现出来。这些面板可以是能嵌入 PS 界面的普通面板,也可以是是模态的,非模态的,还可以是无界面的面板。模态面板主要是阻止用户在使用插件时和 PS 交互,修改文档数据。无界面面板你可以作为后台服务来用,例如启动一个 nodejs 服务器提供图片压缩等耗时任务。每一个面板都是一个独立的进程,不同的进程相互是隔离的,不会因为一个面板崩溃影响到另一个面板。
  • CSXS 文件夹下我们一般还会存放其它插件用到的资源,例如 CSXS/logo 用来存放插件图标,当然这不是强制的,只不过我看社区的人很多都是这么干。学习一门技术同时也意味着需要去习惯这个社区的文化

顺便提醒一下,我们可以配置 VSCode 的 XML Schema 来获取 manifest.xml 文档提示,增加 .vscode/settings.json,在其中添加:

json { "xml.fileAssociations": [ { "pattern": "CSXS/manifest.xml", // 这里声明的是 7.0 版本,和 manifest.xml 中 ExtensionManifest 标签的 Version 属性对应 // raw.githubusercontent.com 这个域名似乎国内访较慢,你可以直接下载到本地,然后直接用本地文件路径 "systemId": "https://raw.githubusercontent.com/Adobe-CEP/CEP-Resources/master/CEP_7.x/ExtensionManifest_v_7_0.xsd" } ] }

浏览器代码

这部分内容我们来编写前端部分的代码,这部分代码是使用 chromium 内核渲染的,一个面板其实相当于一个浏览器标签页。

还记得前面 manifest.xml 我们有配置插件面板的 HTML 路径吗?其实就是 MainPath 标签的内容。

xml <Resources> <!-- 面板的网页 HTML 首页路径,相对路径是相对于插件文件夹 --> <MainPath>./web/index.html</MainPath> <!-- 和这个面板相关联的 extendscript 线程加载的 extendscript 文件路径 --> <!-- 不同的面板它们的 jsx 环境是隔离的,这和宿主的实现有关,PS 是隔离的, AE 不是 --> <ScriptPath>./jsx/index.jsx</ScriptPath> <!-- 浏览器环境和 nodejs 环境的一些参数 --> <CEFCommandLine> <Parameter>--enable-speech-input</Parameter> <Parameter>--enable-media-stream</Parameter> <!-- 开启 nodejs 支持,可以在 node 环境直接写 nodejs 代码 --> <Parameter>--enable-nodejs</Parameter> </CEFCommandLine> </Resources>

在插件根目录下新建文件夹 web,这个文件夹用来存在插件使用的前端代码,增加 index.html,添加如下内容:

```html

CEP Hello World rel="stylesheet" href="./style.css">

当前图层名称为:

刷新

【CEP 扩展开发二】Hello World相关推荐

  1. firefox扩展开发(二):用XUL创建窗口控件

    firefox扩展开发(二):用XUL创建窗口控件 2008-06-11 16:57 1.创建一个简单的窗口 <?xml version="1.0"?> <?xm ...

  2. 【CEP 扩展开发一】简介

    写作目的 Adobe 毫无疑问是设计软件行业的垄断级巨头,旗下的 PS,AE 等都是搞设计和自媒体的必装软件.有很多小公司的产品其实本质上是依赖这些设计软件生存的,例如开发 AE 特效插件的公司,例如 ...

  3. Adobe CEP 扩展开发教程 「 1 」

    本篇会从配置 CEP 的开发环境开始讲解如何从零开始构建一个 CEP 扩展,还有关于扩展调试的方法. 配置开发环境 常情况下宿主应用是不会运行未经签名扩展的,只有打包并签名才可以运行,这样我们就没法即 ...

  4. 【php7扩展开发二】全局变量

    使用C语言开发程序时经常会使用全局变量进行数据存储,这就涉及前面已经介绍过的一个问题:线程安全,PHP设计了TSRM(即:线程安全资源管理器)用于解决这个问题,内核中频繁使用到的EG.CG等都是根据是 ...

  5. PHP7扩展开发(二):配置项与全局数值

    起步 Zend引擎提供了另种管理设置值(INI)的途径.现在弄个简单的,我们经常看到php.ini里有诸如 display_errors = On 这样的全局设置.假设我们需要为我们扩展定义一个值: ...

  6. Thingworx自定义扩展开发(二)- Widget Demo Coding

    系列 Thingworx自定义扩展开发(一)- 开发环境搭建.Extension Demo Coding Thingworx自定义扩展开发(二)- Widget Demo Coding Thingwo ...

  7. 基于Chrome的扩展开发(二)

    Chrome启动时默认的效果如下图所示,有"most visited","Searches","Recent bookmarks",&quo ...

  8. vscode二次开发_vscode 扩展开发从入门到颈椎病康复

    笔者从业以来,各路插件开发无算,而 vscode 把插件开发体验做到了极致.其开发体验,如沐春风,如丝般顺滑,经常写完了还想删掉再写一遍! vscode 扩展的内置脚手架细心且精致,一键生成后即可运行 ...

  9. Mozilla 扩展开发环境设置

    一.构建开发环境 在动手开发之前,首先需要构建扩展开发所需的环境.Firefox 把用户的个人信息,包括设置. 已安装的扩展等,都保存在一个概要文件中,默认是使用名为 default 的概要文件.通过 ...

  10. php扩展调试,5分钟学会PHP扩展开发与断点调试

    很多PHPer都有尝试写PHP扩展的经历,但网上现有的扩展开发教程大都晦涩难懂,官方文档更是让人看的云里雾里.无形之中垒高了PHP扩展开发的门槛."每个PHPer都应该抽空看一些PHP扩展的 ...

最新文章

  1. 谷歌浏览器怎样通过检查验证图片路径问题
  2. C#委托(匿名函数)的各种变形写法
  3. streaming api_通过Spring Integration消费Twitter Streaming API
  4. c++11/14新特性学习
  5. linux下利用nohup后台运行jar文件包程序
  6. c++测试cpu_测评丨NXP系列 LS1028 LS1046等产品网络性能测试
  7. 保密检查usb痕迹清除_MD型卧式多级泵泵轴抱死故障原因分析和检查维修处理
  8. java源程序编译的结果_java源程序编译后
  9. win10计算机的用户名和密码在哪里查,Win10查看别人在自己电脑上输入过的账号密码...
  10. 蓝桥杯备考-python刷题之路-动态规划算法(DP算法)Part3【最终代码实现
  11. 暑假将至,人贩子猖狂
  12. python桌面程序臃肿_危险的转变:Python正在从简明转向臃肿,从实用转向媚俗
  13. 逻辑思维能力选择题30道
  14. matlab中函数功能汇总(一)——rectangle、bwlabel、regionprops
  15. 解决第三方网页在微信浏览器中点击图片会自动放大
  16. C语言:L1-059 敲笨钟 (20 分)
  17. 微信小程序获取用户信息相关问题
  18. 薄荷英语20181103
  19. [云原生专题-12]:容器 - Ubuntu/CentOS平台没有ifconfig/ping工具的解决办法
  20. MATLAB使用入门

热门文章

  1. Wireshark 设置中文
  2. 12306GT多线程、分流免费抢票工具使用
  3. aws(亚马逊云服务)ssh登录提示Error establishing SSH connection to your instance. Try again later.
  4. php发出声音,电容也会发出声音!电容啸叫是怎么产生的?如何解决?
  5. php上传头像的代码,关于微信小程序中上传头像的代码
  6. 用MATLAB制作音乐-小星星
  7. xenu工具如何扫描网站
  8. python打卡记录去重_Pandas 数据筛选,去重结合group by
  9. 腾讯汤道生:产业互联网时代,安全成为CEO的一把手工程
  10. 华为云服务之弹性云服务器ECS的深度使用和云端实践【华为云至简致远】