搭建AE插件开发框架

        AE 全称 Adobe After Effects,是 adobe 公司推出的一款图形视频处理软件,其插件可以帮助我们更好地操作 AE。插件主要分为用户效果的和通用插件两种,入口函数也相应的分为 EffectMain() 和 EntryPointFunc() 两种,都是基于 c 或者 c++ 开发的。

        这里我们仅讨论通用插件 AGEP 开发情况,入口函数如 demo 中提供的 Easy_Cheese 项目:

A_Err EntryPointFunc(
	struct SPBasicSuite		*pica_basicP,		/* >> */
	A_long				 	major_versionL,		/* >> */		
	A_long					minor_versionL,		/* >> */		
	AEGP_PluginID			aegp_plugin_id,		/* >> */
	AEGP_GlobalRefcon		*global_refconP)	/* << */
{
	S_my_id = aegp_plugin_id;
	A_Err = A_Err_NONE, err2 = A_Err_NONE;
	
	sP = pica_basicP;
	
	AEGP_SuiteHandler suites(pica_basicP);
	
	err = suites.CommandSuite1()->AEGP_GetUniqueCommand(&S_Easy_Cheese_cmd);
	
	if (!err && S_Easy_Cheese_cmd) {
		ERR(suites.CommandSuite1()->AEGP_InsertMenuCommand(S_Easy_Cheese_cmd, "Easy Cheese", AEGP_Menu_KF_ASSIST, AEGP_MENU_INSERT_SORTED));
	} 
	ERR(suites.RegisterSuite5()->AEGP_RegisterCommandHook(	S_my_id, 
															AEGP_HP_BeforeAE, 
															AEGP_Command_ALL, 
															CommandHook, 
															0));
	
	ERR(suites.RegisterSuite5()->AEGP_RegisterUpdateMenuHook(S_my_id, UpdateMenuHook, 0));
	
	ERR(suites.RegisterSuite5()->AEGP_RegisterIdleHook(S_my_id, IdleHook, 0));
	
	if (err){ // not !err, err!
		ERR2(suites.UtilitySuite3()->AEGP_ReportInfo(S_my_id, "Easy_Cheese : Could not register command hook."));
	}
	return err;
}

        插件名称是通过方法 AEGP_InsertMenuCommand() 的第二个参数定义的,如果想改成自己的插件,可以定义为 "Test" 等。试着运行项目,会在如下目录生成对应包:

lucas@lucasdeMacBook-Pro Debug % pwd
/Users/lucas/Library/Developer/Xcode/DerivedData/Easy_Cheese-dymhdlixbjrvocgonjhlpbfqgqfk/Build/Products/Debug
lucas@lucasdeMacBook-Pro Debug % ll
total 0
drwxr-xr-x  3 lucas  staff  96 10  7 16:29 Easy_Cheese.plugin

        然后将其复制到 AE 插件安装目录下:

root@lucasdembp Plug-ins # pwd
/Applications/Adobe After Effects 2021/Plug-ins
root@lucasdembp Plug-ins # ll
total 0
drwxr-xr-x    3 root  admin    96  8 16 14:25 (AdobePSL)
drwxr-xr-x    2 root  admin    64  8 16 14:25 DataFormat
drwxr-xr-x    3 root  admin    96 10  7 16:29 Easy_Cheese.plugin
drwxr-xr-x  216 root  admin  6912  8 16 14:25 Effects
drwxr-xr-x    6 root  admin   192  8 16 14:25 Extensions
drwxr-xr-x   15 root  admin   480  8 16 14:25 Format
drwxr-xr-x   21 root  admin   672  8 16 14:25 Keyframe
drwxr-xr-x    8 root  admin   256  8 16 14:25 MAXON CINEWARE AE

        重启 AE 后,在 AE 界面并没有看到 Test 插件,此处只需调整方法 AEGP_InsertMenuCommand() 的第三个参数,将其调整为 AEGP_Menu_WINDOW 就能在 "窗口" 菜单项看到对应插件了。

 如果在入口函数中获取 layer 呢?

AEGP_LayerH layerPH;
ERR(suites.LayerSuite8()->AEGP_GetActiveLayer(&layerPH));

        重新打包后再次打开 AE 时就直接 crash 了,这是因为再打开 AE 时还没有选定 layer,直接获取会导致应用程序奔溃。再看入口函数注意到还有个 AEGP_RegisterCommandHook() 方法,其中第四个参数 CommandHook 是一个钩子函数,试着在这里面定义看看呢?可以添加日志打印看下:

AEGP_LayerH layerH = NULL;
ERR(suites.LayerSuite8()->AEGP_GetActiveLayer(&layerH));
ERR(suites.LayerSuite8()->AEGP_GetLayerID(layerH, &layer_indexL));
writeLog("lay id:" + std::to_string(layer_indexL));

        之后便在控制台中看到如下输出:

lay id:14

        以上便是插件的一个大概框架,具体如何应用参考 🔗官方sdk文档 即可。如果本地想起一个第三方应用控制插件呢?可以通过套接字进行交互,先在插件中定义个服务端进行截断:

int main(int argc, char* argv[])
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    char recv_buf[1024];
    struct sockaddr_in saddr, caddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(22222);
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sock, (struct sockaddr*)&saddr, sizeof(saddr));
    listen(sock, SOMAXCONN);
    socklen_t len = sizeof(caddr);
    while (true) {
        int clientsock = accept(sock, (struct sockaddr*)&caddr, &len);
        memset(recv_buf, 0, 1024);
		int recv_len = recv(clientsock, recv_buf, 1024, 0);
        ...
    }
    
    return 0;
}

        重新打包后可看到 22222 端口已处于监听状态:

lucas@lucasdeMacBook-Pro Desktop % lsof -i:22222
COMMAND    PID  USER   FD   TYPE      DEVICE      SIZE/OFF NODE NAME
After\x20 11767 lucas  319u  IPv4 0xdd6a6034d90b   0t0   TCP *:22222 (LISTEN)

        再定义个客户端:

int main()
{
    string st = "hello world test";
    char send_buf[200];
    strcpy(send_buf, st.c_str());
    
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(22222);
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    socklen_t len = sizeof(saddr);
    connect(sock, (const struct sockaddr *)&saddr, len);
    send(sock, send_buf, 200, 0);
}

        将客户端传到服务端的数据也打印输出看看:

hello world test
lay id:14

        至此就完成了第三方应用通过插件来控制AE的开发框架搭建了。

        以上,欢迎交流~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值