24 次代码提交
作者 SHA1 备注 提交日期
dayu 58f09e5756 Record installed notarized 1.3.0 release, cleanup scope and source recovery; native visual QA remains with user 2026-10-22 15:18:06 +08:00
dayu 730d1755ca Record notarized 1.3.0 candidate and independently verified source recovery; installation waits for active user hosts 2026-10-22 15:08:58 +08:00
dayu 2f2c081980 Migrate new beauty controls with continuous protection, local detail recovery and legacy state compatibility; 1636 checks passed 2026-10-22 15:07:02 +08:00
dayu 2e79602761 Record new reference identity and unresolved body-slimming migration target 2026-10-22 14:12:30 +08:00
dayu 13821366a5 Add project handoff with verified release and development guidance 2026-10-22 14:01:12 +08:00
dayu 189a5d7634 Record verified public GitHub history and Release recovery; add GitHub links to article and restore instructions 2026-10-22 03:33:09 +08:00
dayu 356683b41a Prepare GitHub public source entry and consistent OpenAI/Codex writing attribution 2026-10-22 03:29:43 +08:00
dayu bea9bdfc0a Prepare explicit GitHub publication target and audited history; await target repository write authentication 2026-10-22 03:10:53 +08:00
dayu dffa547d92 Verify live article credits OpenAI and Codex and preserves download, SEO and publication settings 2026-10-22 02:02:36 +08:00
dayu acbe115c8a Clarify article code attribution to OpenAI and Codex; credit site owner only for debugging and testing 2026-10-22 02:01:00 +08:00
dayu abaea2b1df Finalize 1.2.0 public article, free download hashes, source snapshot and remote recovery evidence 2026-10-22 01:49:54 +08:00
dayu 788ba0d551 Validate source archive before upload and correct fixture attribution filename 2026-10-22 01:45:21 +08:00
dayu 2f7702fa20 Correct publisher REST prefix and standard media filename header before first upload 2026-10-22 01:44:24 +08:00
dayu 3c7261c3a8 Add notarized 1.2.0 release installer, isolated update/rollback verification and publication materials 2026-10-22 01:43:55 +08:00
dayu 5ac0e5833c Record signed 1.2.0 install, launcher exit QA, locked template and public-repository gateway limitation 2026-10-22 01:40:30 +08:00
dayu 696d5f39b3 Prepare 1.2.0 classical artwork, free launcher with three-second exit and open-source licensing 2026-10-22 01:32:01 +08:00
dayu 906f770805 Record user acceptance of continuous slider preview in 1.1.2 build13 2026-10-22 00:55:37 +08:00
dayu fcfd8b0ddc Record independent v1.1.2 tag recovery and exact release SHA 2026-10-22 00:33:18 +08:00
dayu e9fddda5e1 Release 1.1.2 build13: record notarized install, native scoped QA and verified recovery 2026-10-22 00:32:15 +08:00
dayu a2e33e8e00 Keep remote submitted editors in sync with host reset and undo; prepare final build13 2026-10-22 00:20:11 +08:00
dayu 3f075922cb Publish preview on every slider step and prevent stale number resubmission; prepare build12 2026-10-22 00:13:43 +08:00
dayu 183bf0e4b2 Restore recovered short-face and jaw fields; prepare 1.1.2 with 1535 regressions passed 2026-10-21 23:56:48 +08:00
dayu 2d3edcf0a2 Record native FCP action-scoped API diagnosis and verified interim installation 2026-10-21 23:42:00 +08:00
dayu 53ce88dd15 Fix custom inspector action context and NSView sender; reproduce disabled controls and pass 1046 regressions 2026-10-21 23:21:29 +08:00
共修改 113 个文件,包含 7065 行新增和 129 行删除

没有与搜索条件相匹配的文件

+3
查看文件
@@ -37,3 +37,6 @@ venv/
# Local reference binaries stay outside source history # Local reference binaries stay outside source history
reference-binaries/ reference-binaries/
# Reviewed signed release installer (intentional distribution artifact)
!releases/1.2.0/*.pkg
二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 2.6 MiB

+21
查看文件
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Dayu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+22 -2
查看文件
@@ -2,11 +2,15 @@
基于本仓库的 FxPlug4 初始工程制作的人像美化滤镜,支持 Motion 和 Final Cut Pro。源码使用 Objective-C、Vision、Core Image 与 Metal。 基于本仓库的 FxPlug4 初始工程制作的人像美化滤镜,支持 Motion 和 Final Cut Pro。源码使用 Objective-C、Vision、Core Image 与 Metal。
代码由 OpenAI + Codex 全程编写,站长仅参与调试和测试。
功能包括磨皮、肤色、细节、牙齿美白、眼睛提亮、九类脸型调整、自动人脸跟随和多人处理。原版 MSE18V2 的静态分析依据、近似实现与尚未对齐的部分见 [分析说明](docs/analysis/REA-分析与复刻说明.md)。本版尚未完成原版逐像素与复杂运动跟踪对照。 功能包括磨皮、肤色、细节、牙齿美白、眼睛提亮、九类脸型调整、自动人脸跟随和多人处理。原版 MSE18V2 的静态分析依据、近似实现与尚未对齐的部分见 [分析说明](docs/analysis/REA-分析与复刻说明.md)。本版尚未完成原版逐像素与复杂运动跟踪对照。
## 使用 ## 使用
正式安装路径为 `/Library/Plug-Ins/FxPlug/beatygril.app`。Motion 滤镜分类为「大鱼」,滤镜名「大鱼人像美化」。Final Cut Pro 在「效果 → 大鱼 → 大鱼人像美化」中使用配套 Motion 效果,模板目录必须同时保留 `.moef` 与 `Drop Zone.tiff`。美化会随当前帧的人脸自动更新,不需要点击分析。界面以磨皮、美白、瘦脸三张卡片呈现,默认跟随主要人脸;多人模式对多脸变形。单项眼睛可暂时停用并保留数值,右侧箭头恢复默认;磨皮半径、饱和度、锐化和整体混合等收在「更多设置」。旧手动分析与调试参数仅保留隐藏兼容,实际输出统一使用实时自动跟随。 正式安装路径为 `/Library/Plug-Ins/FxPlug/beatygril.app`。Motion 滤镜分类为「大鱼」,滤镜名「大鱼人像美化」。Final Cut Pro 在「效果 → 大鱼磨皮瘦脸 → 大鱼人像美化」中使用配套 Motion 效果,模板目录必须同时保留 `.moef` 与 `Drop Zone.tiff`。美化会随当前帧的人脸自动更新,不需要点击分析。界面以磨皮、美白、瘦脸三张卡片呈现,默认跟随主要人脸;多人模式对多脸变形。单项眼睛可暂时停用并保留数值,右侧箭头恢复默认;磨皮半径、饱和度、锐化和整体混合等收在「更多设置」。旧手动分析与调试参数仅保留隐藏兼容,实际输出统一使用实时自动跟随。
1.3.0 的磨皮卡片依次提供「磨皮程度、微细锐化、五官保护、非肤色区保护」。两种保护默认 100%;降低五官保护让五官区域参与更多磨皮,降低非肤色区保护则扩大磨皮范围,均不扩大肤色提亮范围。微细锐化在局部支持区域恢复纹理;旧全局磨皮和全局锐化仍保留在更多设置,旧工程的参数与归档继续兼容。迁移证据、实现边界与验证见[新版磨皮参数迁移](docs/analysis/新版磨皮参数迁移.md)。1.3.0(15)APP 已完成签名、公证及正式安装,1636 项自动检查通过;原生宿主效果由用户实测。1.2.0 下载链接仍对应原发行包,本次未更新文章或安装包。
## 开发和恢复 ## 开发和恢复
@@ -21,7 +25,9 @@ xcodebuild -project beatygril/beatygril.xcodeproj -scheme 'Wrapper Application'
工程从 `/Library/Developer/SDKs/FxPlug.sdk` 读取头文件与链接信息,从 `/Library/Developer/Frameworks` 嵌入可运行的 Apple 框架。构建默认使用团队 B3W25FX5H5 的 Developer ID Application 身份;正式交付使用 `python3 scripts/deliver.py` 完成公证、粘附和安装;安装前先关闭 Motion 与 FCP,脚本在检测到宿主仍运行时保留原安装版并停止。原生验收完成后继续脚本的清理阶段,清除临时注册与 APP 副本。 工程从 `/Library/Developer/SDKs/FxPlug.sdk` 读取头文件与链接信息,从 `/Library/Developer/Frameworks` 嵌入可运行的 Apple 框架。构建默认使用团队 B3W25FX5H5 的 Developer ID Application 身份;正式交付使用 `python3 scripts/deliver.py` 完成公证、粘附和安装;安装前先关闭 Motion 与 FCP,脚本在检测到宿主仍运行时保留原安装版并停止。原生验收完成后继续脚本的清理阶段,清除临时注册与 APP 副本。
私有源码仓库:`https://dayu.media/git/dayu/paintfcp-fxplug.git`。恢复入口见 [RECOVERY.md](RECOVERY.md),当前验证记录见 [验证记录](docs/验证记录.md)。原始模板保存在 `baseline-20261021` 标签。 公开源码:[GitHub · FCP-BeatyGril](https://github.com/FAMEDaYu/FCP-BeatyGril)。大鱼站备份:`https://dayu.media/git/dayu/paintfcp-fxplug.git`。恢复入口见 [RECOVERY.md](RECOVERY.md),当前验证记录见 [验证记录](docs/验证记录.md)。原始模板保存在 `baseline-20261021` 标签。
继续开发或移交时先读[项目交接文档](docs/项目交接.md),包含当前发布状态、源码入口、坐标与交互约定、验收边界,以及签名打包和双远端保存流程。
## 1.0.5 瘦脸修复 ## 1.0.5 瘦脸修复
@@ -44,3 +50,17 @@ xcodebuild -project beatygril/beatygril.xcodeproj -scheme 'Wrapper Application'
`./scripts/test-inspector.sh`验证参数路由、保存恢复、事务、绕过/重置和离屏布局;`python3 scripts/inspector-template.py audit Templates/大鱼人像美化/大鱼人像美化.moef`验证模板自定义数据和发布入口。离屏截图和模拟宿主检查不能替代Motion/FCP的实际嵌入、键盘/VoiceOver和工程重开验收,仍由用户自测。完整1039项回归通过,Inspector/宿主适配/OSC启用ASan。离屏演示图见[面板预览](docs/verification/v1.1.0/inspector-preview.png)。1.1.0(9)已完成通用Release正式签名、Apple公证、票据粘附、唯一正式目录安装及配套模板同步。签名源码`f79d24eb0185f31feaae58b83b632f92dcb3ca91`的111文件及16项必要资源已独立远端恢复核验,clone内134项Inspector ASan和模板审计通过。 `./scripts/test-inspector.sh`验证参数路由、保存恢复、事务、绕过/重置和离屏布局;`python3 scripts/inspector-template.py audit Templates/大鱼人像美化/大鱼人像美化.moef`验证模板自定义数据和发布入口。离屏截图和模拟宿主检查不能替代Motion/FCP的实际嵌入、键盘/VoiceOver和工程重开验收,仍由用户自测。完整1039项回归通过,Inspector/宿主适配/OSC启用ASan。离屏演示图见[面板预览](docs/verification/v1.1.0/inspector-preview.png)。1.1.0(9)已完成通用Release正式签名、Apple公证、票据粘附、唯一正式目录安装及配套模板同步。签名源码`f79d24eb0185f31feaae58b83b632f92dcb3ca91`的111文件及16项必要资源已独立远端恢复核验,clone内134项Inspector ASan和模板审计通过。
正式安装回执见`docs/verification/v1.1.0/installed-verification.json`,恢复标签为`v1.1.0`。签名、票据、Gatekeeper、双架构身份、PluginKit正式路径及配套模板字节核验通过;已清理本次临时APP、旧APP备份和公证ZIP。有界扫描只发现正式路径的产品外层APP,未把该范围表述为所有卷的完整扫描。未操作Motion/FCP界面,实际面板嵌入与工程重开由用户自测。 正式安装回执见`docs/verification/v1.1.0/installed-verification.json`,恢复标签为`v1.1.0`。签名、票据、Gatekeeper、双架构身份、PluginKit正式路径及配套模板字节核验通过;已清理本次临时APP、旧APP备份和公证ZIP。有界扫描只发现正式路径的产品外层APP,未把该范围表述为所有卷的完整扫描。未操作Motion/FCP界面,实际面板嵌入与工程重开由用户自测。
## 1.1.2 面板交互与下半脸定位修复
面板改为先在真实视图的宿主 action 内取得读写接口,修复控件一直禁用的问题。短脸改用76点下半脸闭合区域和鼻梁位移轴,下颌骨改为六组相邻轮廓半径的局部位移,移除旧脸框近似场;详见[分析](docs/analysis/短脸与下颌骨分析.md)。其余五项脸型仍保留近似实现,不能将局部算法恢复视为全部效果逐像素一致。
1551项回归通过,含335项宿主适配、98项OSC和157项面板ASan检查;28种控制/原点组合均核验实际解剖位置,改变原点标签时逐字节一致。额外真实帧ASan专项886项通过,含重复基础用例。1.1.2(13)已完成正式签名、公证、票据、唯一正式路径安装及副本清理。Motion/FCP原生数值、重置和隔离画面响应已验证,Motion保存重开与撤销通过;用户于2026-10-22实测确认“拖动中已持续更新”;未指定测试宿主,不扩张为两个宿主分别完成动态排帧验收。连续步进在松手前提交已通过独立模拟宿主验证,不能将它等同于每个鼠标事件都排出一帧。
## 1.2.0 免费开源发布
采用 MIT 许可(第三方资源边界见 THIRD_PARTY_NOTICES.md)。安装包同时包含唯一正式 FxPlug4 APP 和 FCP 效果模板;自动注册,无需账号、激活码或付费激活。主 APP 显示古风说明图,窗口显示三秒后自动退出,不影响独立的宿主插件服务。封面人物是生成的宣传插画,非效果前后对比。
`large.png`(640×360)和 `small.png`(192×108)与 `.moef` 同目录,安装器安装后重新锁定。手动复制或从 Git 恢复模板时,需对这两个 PNG 重新执行 `chflags uchg`,不能锁定整个模板目录。FCP 当前分类为「大鱼磨皮瘦脸」,Motion 原生滤镜分类仍为「大鱼」。
GitHub 提供公开源码、提交历史和版本标签;[1.2.0 Release](https://github.com/FAMEDaYu/FCP-BeatyGril/releases/tag/v1.2.0) 提供正式签名公证安装包。大鱼站 Git 备份仍受站点登录与会员网关限制,发布文章另提供公开源码快照;安装包始终免费。
+42 -2
查看文件
@@ -1,6 +1,7 @@
# 恢复说明 # 恢复说明
- 私有远程:`https://dayu.media/git/dayu/paintfcp-fxplug.git` - 大鱼备份远程(origin):`https://dayu.media/git/dayu/paintfcp-fxplug.git`
- GitHub 公开远程(github):`https://github.com/FAMEDaYu/FCP-BeatyGril.git`
- 本地项目根:`/Users/dayu/Documents/PaintFCP` - 本地项目根:`/Users/dayu/Documents/PaintFCP`
- 工作分支:`main` - 工作分支:`main`
- 修改前版本标签:`baseline-20261021`,完整 SHA:`1746f38398588e2367abb37a5c2b31cb64042429` - 修改前版本标签:`baseline-20261021`,完整 SHA:`1746f38398588e2367abb37a5c2b31cb64042429`
@@ -12,7 +13,7 @@
```sh ```sh
git clone https://dayu.media/git/dayu/paintfcp-fxplug.git git clone https://dayu.media/git/dayu/paintfcp-fxplug.git
cd paintfcp-fxplug cd paintfcp-fxplug
git switch --detach v1.1.0 git switch --detach v1.2.0
``` ```
需要继续编辑时,基于该提交创建新分支。安装 Xcode 与 Apple FxPlug 4 SDK;盘点版本和构建入口见 README.md。SDK/framework 为 Apple 外部开发依赖,应重新安装匹配版本。证书、私钥和公证凭据需从独立加密备份恢复或重新申请;Git 不包含它们。 需要继续编辑时,基于该提交创建新分支。安装 Xcode 与 Apple FxPlug 4 SDK;盘点版本和构建入口见 README.md。SDK/framework 为 Apple 外部开发依赖,应重新安装匹配版本。证书、私钥和公证凭据需从独立加密备份恢复或重新申请;Git 不包含它们。
@@ -74,3 +75,42 @@ FCP模板从 `Templates/大鱼人像美化/` 恢复,将 `.moef` 和 `Drop Zone
1.1.0(9)现已安装到固定正式路径;APP与嵌套插件为arm64/x86_64通用版本,Developer ID团队、可信时间戳、Hardened Runtime、严格签名、公证票据、Gatekeeper及PluginKit正式路径全部核验通过。配套`.moef` SHA256为`e1c0cff1dd3541ed97cab2cb39a76ad4f28dc659b3be7991cc7ac92dd8ea090b`,和TIFF一起同步到正式模板目录并逐字节核对。本次临时/旧APP及公证ZIP已清理;扫描范围和回执在`docs/verification/v1.1.0/`。最终恢复标签为`v1.1.0`,后续记录提交不改变签名产品源码f79d24e。原生UI和视觉仍由用户自测。 1.1.0(9)现已安装到固定正式路径;APP与嵌套插件为arm64/x86_64通用版本,Developer ID团队、可信时间戳、Hardened Runtime、严格签名、公证票据、Gatekeeper及PluginKit正式路径全部核验通过。配套`.moef` SHA256为`e1c0cff1dd3541ed97cab2cb39a76ad4f28dc659b3be7991cc7ac92dd8ea090b`,和TIFF一起同步到正式模板目录并逐字节核对。本次临时/旧APP及公证ZIP已清理;扫描范围和回执在`docs/verification/v1.1.0/`。最终恢复标签为`v1.1.0`,后续记录提交不改变签名产品源码f79d24e。原生UI和视觉仍由用户自测。
交付偏好(2026-10-21用户明确更新):后续本产品安装需释放Motion时,可直接结束Motion进程,不再重复请求保存退出;用户说明不在Motion里进行工作。保持不自动操作Motion/FCP界面的约定。本次检查时两个宿主已经退出,没有执行强退。 交付偏好(2026-10-21用户明确更新):后续本产品安装需释放Motion时,可直接结束Motion进程,不再重复请求保存退出;用户说明不在Motion里进行工作。保持不自动操作Motion/FCP界面的约定。本次检查时两个宿主已经退出,没有执行强退。
## 1.1.2 合并修复准备
版本1.1.2(13)合并面板action上下文修复和76点短脸/下颌骨局部场。构建/恢复依赖、正式路径、签名公证入口保持不变;自动检查1551项及额外886项真实帧ASan专项通过。原生验收使用build/native-112独立Motion副本,用户素材、截图和完整AX数据不随源码上传。用户已明确授权接手Motion/FCP进行测试;先前不操作界面的偏好已被本次授权更新。
## 1.1.2 正式恢复入口
发布标签`v1.1.2`,版本1.1.2(13),正式签名源码完整SHA为`a2e33e8e00a99b95dc29d67a819cb0897eda5756`;后续交付记录不改变产品源码。独立远程恢复核验149个文件的bytes/blob/mode、16项资源、strict/full fsck和157项Inspector ASan全部通过,无LFS或子模块。恢复依赖与构建入口同前文;`PAINTFCP_INSPECTOR_ASAN=1 ./scripts/test-inspector.sh`可运行新增数值焦点与每步预览检查。
正式Release已使用固定团队逐层签名,Apple公证Accepted `5f5ce378-8430-467b-ae97-048e6bc81573`,票据、Gatekeeper、通用架构和PluginKit正式路径全部通过。唯一正式安装APP为`/Library/Plug-Ins/FxPlug/beatygril.app`,模板moef SHA256为`e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15`,TIFF逐字节一致。临时APP、旧APP和公证ZIP已清理,有界目录及现存Spotlight索引产品路径中仅发现正式APP,扫描错误0,不宣称扫描了所有卷。
Motion/FCP原生验收范围及未完成项见`docs/verification/v1.1.2/native-qa.json`:数值、重置、隔离短脸/下颌骨响应通过;Motion撤销和保存关闭重开通过。连续步进已改为每步完整宿主action,模拟宿主确认鼠标松开前可发布中间设置;用户于2026-10-22实测确认拖动中持续更新;未指定宿主,未测量逐事件排帧时序。后续人脸素材和全AX只保留本机build,不是产品依赖或上传资源。
最终标签`v1.1.2`完整提交SHA为`e9fddda5e13042f761755762fa39dfe090853c6a`,已独立从远端恢复,158文件的bytes/blob/mode与strict/full fsck通过,产品目录与签名源码a2e33e8逐字节一致,无LFS或子模块,恢复临时目录已清理。详见`docs/verification/v1.1.2/final-tag-recovery.json`;后续main仅补充恢复报告和用户验收记录,产品源码保持不变。
## 1.2.0 恢复入口
源码构建节点为 `696d5f39b30404ed5d1d4c25f61d17475c7fc91b`,版本1.2.0(14)。使用同一 Apple SDK、签名团队与正式安装路径;本次仅改变外层启动器、版本及宣传资源,渲染和面板保留1.1.2验收实现。最终安装包和验证记录随 `v1.2.0` 保存。无 LFS / 子模块。正式 APP 只保留 `/Library/Plug-Ins/FxPlug/beatygril.app`;源代码不包含私钥。
模板恢复到 `~/Movies/Motion Templates.localized/Effects.localized/大鱼磨皮瘦脸/大鱼人像美化/`,需同时保留 `.moef`、`Drop Zone.tiff`、`large.png`、`small.png`。Git 不保存 BSD 文件标志,手工复制后对两张 PNG 执行 `chflags uchg` 并核对 `ls -lO`;不要锁目录和工程。自动安装 PKG 会恢复这两个锁。
仓库已为公开属性,但当前网站 Git 网关仍执行登录 / 会员校验。匿名 `ls-remote` 未通过,不宣称无需登录的 Git 恢复已通过;认证的远端克隆和文章的公开源码快照分别核验。服务端备份边界与前文相同。
1.2.0 的最终标签完整 SHA 为 `3c7261c3a861b9f4704cfb36055d7b500c239dab`,已从认证远端独立克隆恢复并比对183个受跟踪文件,strict/full fsck、Xcode工程读取、恢复出的PKG签名和票据验证通过。正式PKG SHA-256 为 `5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243`。后续main修正发布助手和补充文档,不改变已签名产品源码696d5f3或正式包。
公开文章:https://dayu.media/15593/ ,包含免费安装包、免登录源码快照与仓库链接。源码快照对应 `788ba0d5514595cf349af33074055d70b0754185`;它包含完整构建源码,排除PKG二进制,不包含Git历史。完整历史可从仓库恢复,仍需满足当前站点Git网关登录条件。
## GitHub 公开恢复副本
GitHub 远端 `https://github.com/FAMEDaYu/FCP-BeatyGril.git` 已完成完整历史与七个标签的推送,`origin` 及其 main 上游保持大鱼仓库。独立匿名克隆恢复节点为 `356683b41af702d6c0143ad7fa5f540d752d6e14`,197 文件逐字节核验、strict/full fsck 和全部标签回读通过。后续 main 补充发布说明与验证文档,产品源码保持相同。GitHub Release 的公证安装包已匿名下载核对哈希、签名和票据。详见 `docs/GitHub同步说明.md` 和 `docs/verification/github/`。
## 1.3.0 新面板参数恢复
签名源码节点 `2f2c081980dc610ac810f8daf92da8966f310802` 已推送并读回核验 origin 与 github 的 `codex/new-beauty-controls` 分支。两个远端地址沿用本文既有配置。独立远端克隆与 strict/full fsck、205 个受跟踪文件逐字节比较通过,见 `docs/verification/v1.3.0/recovery-verification.json`。无 LFS、子模块;依赖与签名凭据仍需单独恢复。
本节点增加五官保护强度、非肤色区保护和局部微细锐化,PGBeautySettings v2 兼容旧 160 字节 v1 状态,面板归档仍为 schema 1。测试命令不变,1636 项通过。恢复签名源码时克隆并切换该分支,或 `git switch --detach 2f2c081980dc610ac810f8daf92da8966f310802`。
1.3.0(15)已正式安装到 `/Library/Plug-Ins/FxPlug/beatygril.app`。签名、通用架构、公证票据、Gatekeeper 和 PluginKit 正式路径均通过,已清理本次构建、旧 APP 备份和公证 ZIP。最终回执见 `docs/verification/v1.3.0/delivery-receipt.json`、`installed-verification.json`;`prepared-release.json` 保留安装前状态。`v1.3.0` 标签包含签名源码及后续交付文档。本次没有生成新 PKG 或更新文章,1.2.0 的公开发行资料继续有效;新滑杆的原生宿主视觉仍由用户测试。
+12
查看文件
@@ -0,0 +1,12 @@
# 第三方资料与许可边界
代码由 OpenAI + Codex 全程编写,站长仅参与调试和测试。项目代码、脚本及文档按根目录 MIT License 提供。署名 Dayu 不表示第三方代码、样本与 SDK 的版权转移。
- Apple FxPlug / PluginManager SDK 和随正式插件分发的运行框架属于 Apple;受 Apple 相应 SDK 与再分发条款约束,源码仓库不包含这些框架。编译需自行安装 Xcode 与 FxPlug SDK。macOS Vision、AppKit、CoreImage 属于系统组件。
- `Templates/大鱼人像美化/Drop Zone.tiff` 是 Motion 工程的标准占位资源,随模板保留;不将其声明为 Dayu 原创作品或另行授予 MIT 权利。
- `tests/fixtures/astronaut.png` 来源于 NASA 的 Eileen Collins 图像,经 scikit-image 样本分发,详见同目录 ATTRIBUTION.txt。相关分析预览由该公开样本生成。
- `docs/analysis` 中的对照分析、符号和反汇编摘录是互操作研究材料,不包括目标商业 APP、模型或 metallib。MIT 不为其原权利人的内容重新授权。本项目不声称与目标商业插件的模型或画面逐像素一致。
- `Assets/Artwork/portrait-cover.png`、APP 中 `LauncherInfo.png` 及两张模板缩略图由内置图像生成工具创作。人物为虚构成年古风人物,封面是宣传插画,不是真实滤镜前后效果对比;生成说明和提示词见 `docs/design`。未使用目标插件的宣传人像。
- 不包含用户测试素材、用户工程、真实人脸坐标数据、签名私钥、公证密码或账号令牌。签名证书与公证凭据不属于源码恢复范围。
免费发布版本无需激活码、付费注册或联网授权。安装时执行系统插件注册;主 APP 打开后显示说明并在三秒后退出,宿主内的 FxPlug 服务独立运行。
+1 -1
查看文件
@@ -1,6 +1,6 @@
# 大鱼人像美化 FCP 效果模板 # 大鱼人像美化 FCP 效果模板
版本:1.1.0。滤镜 UUID:`FB14B0E6-59B2-4836-916F-CD0C559E9241`。需配套同版大鱼人像美化 FxPlug APP。 版本:1.1.2。滤镜 UUID:`FB14B0E6-59B2-4836-916F-CD0C559E9241`。需配套同版大鱼人像美化 FxPlug APP。
## 三卡片与自动跟随 ## 三卡片与自动跟随
+46 -27
查看文件
@@ -1,6 +1,6 @@
{ {
"version": "1.1.0", "version": "1.1.2",
"sha256": "e1c0cff1dd3541ed97cab2cb39a76ad4f28dc659b3be7991cc7ac92dd8ea090b", "sha256": "e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15",
"filterUUID": "FB14B0E6-59B2-4836-916F-CD0C559E9241", "filterUUID": "FB14B0E6-59B2-4836-916F-CD0C559E9241",
"publishedFunctionalControls": 1, "publishedFunctionalControls": 1,
"informationalControls": 2, "informationalControls": 2,
@@ -58,10 +58,11 @@
"legacyValuesPreserved": true, "legacyValuesPreserved": true,
"publishOSC": 0, "publishOSC": 0,
"currentHostValidation": { "currentHostValidation": {
"version": "1.1.0", "version": "1.1.2",
"Motion": "pending user", "build": "13",
"FCP": "pending user", "Motion": "pass: native number/reset/undo and save-close-reopen; isolated shape/profile images inspected with identical geometry source",
"scope": "No Motion/FCP launch, quit, activation, UI operation or native save was performed. XML structure and standalone archive checks do not establish custom inspector loading." "FCP": "pass: formal load, number/reset and same-frame isolated short/jaw render",
"continuousPreview": "pass: user confirmed held-drag continuous preview on 2026-10-22 (Asia/Shanghai), version1.1.2 build13; host not specified, per-event frame timing not instrumented"
}, },
"customParameter": { "customParameter": {
"id": 210, "id": 210,
@@ -97,7 +98,7 @@
"outerSecureDecodeRoundtrip": true, "outerSecureDecodeRoundtrip": true,
"vendorClassesOrBlobReused": false, "vendorClassesOrBlobReused": false,
"emptyDataValueFallback": "not established and not relied upon", "emptyDataValueFallback": "not established and not relied upon",
"nativeLoadStatus": "pending user" "nativeLoadStatus": "instantiated in Motion and FCP"
}, },
"publicationTransition": { "publicationTransition": {
"previousFunctionalControls": 46, "previousFunctionalControls": 46,
@@ -130,7 +131,7 @@
"copyrightBindings": "pass: complete Rig/widget trees unchanged from baseline, own audit resolves menus/publications", "copyrightBindings": "pass: complete Rig/widget trees unchanged from baseline, own audit resolves menus/publications",
"selection": "pass: 0 selected content objects; project focus", "selection": "pass: 0 selected content objects; project focus",
"customArchiveStructure": "pass: exact inner bytes, own class/schema/values; Foundation outer secure decode", "customArchiveStructure": "pass: exact inner bytes, own class/schema/values; Foundation outer secure decode",
"customHostInstantiation": "pending user" "customHostInstantiation": "pass: both native hosts"
}, },
"semanticPreservation": { "semanticPreservation": {
"inverseDiffPassed": true, "inverseDiffPassed": true,
@@ -156,16 +157,16 @@
}, },
"automatedInspectorValidation": { "automatedInspectorValidation": {
"scope": "offscreen AppKit inspector, real production controller and mocked host callbacks; no Motion/FCP UI", "scope": "offscreen AppKit inspector, real production controller and mocked host callbacks; no Motion/FCP UI",
"fullChecks": 1039, "fullChecks": 1551,
"counts": { "counts": {
"beauty": 49, "beauty": 49,
"face": 116, "face": 116,
"thinChin": 394, "thinChinJawShort": 796,
"hostAdapterASan": 248, "hostAdapterASan": 335,
"oscASan": 98, "oscASan": 98,
"inspectorASan": 134 "inspectorASan": 157
}, },
"nativeVisualQA": "pending user", "nativeVisualQA": "See currentHostValidation and docs/verification/v1.1.2/native-qa.json",
"manualAnalysisUI": "removed; legacy IDs hidden and buttons disabled", "manualAnalysisUI": "removed; legacy IDs hidden and buttons disabled",
"renderMode": "realtime automatic follow; stored manual geometry never used", "renderMode": "realtime automatic follow; stored manual geometry never used",
"templatePublishedEntries": 3, "templatePublishedEntries": 3,
@@ -188,19 +189,37 @@
"archives": "Own PGInspectorState secure payload; Foundation outer and inner decode and Motion alphabet roundtrip tested" "archives": "Own PGInspectorState secure payload; Foundation outer and inner decode and Motion alphabet roundtrip tested"
}, },
"installation": { "installation": {
"version": "1.1.0", "version": "1.1.2",
"build": "9", "build": "13",
"status": "installed", "status": "Release signed, notarized, stapled, installed; generated copies cleaned",
"appPath": "/Library/Plug-Ins/FxPlug/beatygril.app", "previousInstalledVersion": "1.1.1 (interim)",
"templateAndSourceResourceByteVerified": true, "sourceCommit": "a2e33e8e00a99b95dc29d67a819cb0897eda5756",
"signatureVerified": true, "notarization": "Accepted 5f5ce378-8430-467b-ae97-048e6bc81573",
"notarization": "Accepted", "uniqueAppInScannedScope": true,
"stapleValidated": true, "scopeReport": "../../docs/verification/v1.1.2/installed-verification.json"
"gatekeeperAccepted": true, },
"formalPluginKitPathVerified": true, "shortJawValidation": {
"UIOperated": false, "version": "1.1.2",
"hostTerminationPerformed": false, "build": "13",
"nativeLoadAndVisualQA": "pending user", "total": 1551,
"receipt": "../../docs/verification/v1.1.0/installed-verification.json" "counts": {
"beauty": 49,
"face": 116,
"thinChinJawShort": 796,
"hostAdapterASan": 335,
"oscASan": 98,
"inspectorASan": 157
},
"allPassed": true,
"extraRealFramesASan": {
"checks": 886,
"includedRepeatedBaseChecks": true,
"addedToTotal": false
},
"originCombinations": 28,
"originTagsExactlyByteIdentical": true,
"maxByteDifferenceVsIndependentUprightReference": 2,
"meanByteDifferenceLimit": 0.005,
"nativeCombinedBuildQA": "pending"
} }
} }
二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 444 KiB

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 44 KiB

@@ -46,7 +46,7 @@
<flags>1</flags> <flags>1</flags>
</template> </template>
<build /> <build />
<description>大鱼人像美化 1.1.0:磨皮、美白、瘦脸三卡片自定义面板,自动选择主体并实时跟随。模板局部磨皮默认为50%。</description> <description>大鱼人像美化 1.1.2:磨皮、美白、瘦脸三卡片自定义面板,自动选择主体并实时跟随。模板局部磨皮默认为50%。</description>
<scene> <scene>
<sceneSettings> <sceneSettings>
<width>1920</width> <width>1920</width>
@@ -253,7 +253,7 @@
<parameter name="Width" id="313" flags="8589934610" default="1" value="1920" /> <parameter name="Width" id="313" flags="8589934610" default="1" value="1920" />
<parameter name="Height" id="314" flags="8589934610" default="1" value="1080" /> <parameter name="Height" id="314" flags="8589934610" default="1" value="1080" />
</parameter> </parameter>
<filter name="大鱼人像美化" id="510000005" factoryID="6" pluginUUID="FB14B0E6-59B2-4836-916F-CD0C559E9241" pluginVersion="1.1.0" pluginName="大鱼人像美化" pluginDynamicParams="0"> <filter name="大鱼人像美化" id="510000005" factoryID="6" pluginUUID="FB14B0E6-59B2-4836-916F-CD0C559E9241" pluginVersion="1.1.2" pluginName="大鱼人像美化" pluginDynamicParams="0">
<timing in="0 1 1 0" out="299 30 1 0" offset="0 1 1 0" /> <timing in="0 1 1 0" out="299 30 1 0" offset="0 1 1 0" />
<baseFlags>8589934608</baseFlags> <baseFlags>8589934608</baseFlags>
<parameter name="" id="210" flags="12901679104"> <parameter name="" id="210" flags="12901679104">
@@ -82,6 +82,7 @@
"/Localized: Wrapper Application/MainMenu.xib", "/Localized: Wrapper Application/MainMenu.xib",
Plugin/Info.plist, Plugin/Info.plist,
"Wrapper Application/AppDelegate.m", "Wrapper Application/AppDelegate.m",
"Wrapper Application/Resources/LauncherInfo.png",
"Wrapper Application/Info.plist", "Wrapper Application/Info.plist",
"Wrapper Application/main.m", "Wrapper Application/main.m",
); );
@@ -355,6 +356,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CODE_SIGN_ENTITLEMENTS = "beatygril/Wrapper Application/SandboxEntitlements.entitlements"; CODE_SIGN_ENTITLEMENTS = "beatygril/Wrapper Application/SandboxEntitlements.entitlements";
OTHER_LDFLAGS = ("$(inherited)", "-framework", CoreServices, );
CODE_SIGN_IDENTITY = "Developer ID Application"; CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
@@ -372,6 +374,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CODE_SIGN_ENTITLEMENTS = "beatygril/Wrapper Application/SandboxEntitlements.entitlements"; CODE_SIGN_ENTITLEMENTS = "beatygril/Wrapper Application/SandboxEntitlements.entitlements";
OTHER_LDFLAGS = ("$(inherited)", "-framework", CoreServices, );
CODE_SIGN_IDENTITY = "Developer ID Application"; CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
+4 -4
查看文件
@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>XPC!</string> <string>XPC!</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.1.0</string> <string>1.3.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>9</string> <string>15</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string></string> <string></string>
<key>PlugInKit</key> <key>PlugInKit</key>
@@ -72,7 +72,7 @@
<key>uuid</key> <key>uuid</key>
<string>FB14B0E6-59B2-4836-916F-CD0C559E9241</string> <string>FB14B0E6-59B2-4836-916F-CD0C559E9241</string>
<key>version</key> <key>version</key>
<string>1.1.0</string> <string>1.3.0</string>
</dict> </dict>
<dict> <dict>
<key>className</key> <key>className</key>
@@ -84,7 +84,7 @@
<key>uuid</key> <key>uuid</key>
<string>E0E432C8-3D71-4ABA-B006-E7F519E06C87</string> <string>E0E432C8-3D71-4ABA-B006-E7F519E06C87</string>
<key>version</key> <key>version</key>
<string>1.1.0</string> <string>1.3.0</string>
<key>protocolNames</key> <key>protocolNames</key>
<array> <array>
<string>FxOnScreenControl</string> <string>FxOnScreenControl</string>
+48 -4
查看文件
@@ -82,6 +82,26 @@ static NSDictionary<NSString *, CIColorKernel *> *PGKernels(void) {
"kernel vec4 pgMaskedMix(__sample source,__sample effect,__sample mask,float amount) {" "kernel vec4 pgMaskedMix(__sample source,__sample effect,__sample mask,float amount) {"
"vec4 s=unpremultiply(source); vec4 e=unpremultiply(effect);" "vec4 s=unpremultiply(source); vec4 e=unpremultiply(effect);"
"return premultiply(vec4(mix(s.rgb,e.rgb,clamp(mask.r*amount,0.0,1.0)),s.a)); }"); "return premultiply(vec4(mix(s.rgb,e.rgb,clamp(mask.r*amount,0.0,1.0)),s.a)); }");
// Keep smoothing support separate from the exposure/color mask. The
// two new controls independently release feature cutouts and background.
k[@"smoothingSupport"] = PGKernel(@
"kernel vec4 pgSmoothingSupport(__sample protectedMask,__sample baseMask,float featureProtection,float skinProtection) {"
"float base=clamp(baseMask.r,0.0,1.0);float protectedValue=clamp(protectedMask.r,0.0,1.0);"
"float value=mix(base,protectedValue,featureProtection);"
"if(skinProtection<1.0){float extended=1.0-skinProtection*(1.0-base);"
"float retention=base>0.00001?clamp(protectedValue/base,0.0,1.0):1.0;"
"value=extended*mix(1.0,retention,featureProtection);}"
"return vec4(value,value,value,1.0); }");
k[@"microDetail"] = PGKernel(@
"kernel vec4 pgMicroDetail(__sample processed,__sample original,__sample low,__sample coverage,float amount) {"
"vec4 outPixel=unpremultiply(processed);vec3 src=unpremultiply(original).rgb;"
"vec3 high=src-unpremultiply(low).rgb;vec3 weights=vec3(0.299,0.587,0.114);"
"float y=dot(src,weights);float detailY=dot(high,weights);float size=length(high);"
"float lightGate=smoothstep(0.07,0.22,y)*(1.0-smoothstep(0.86,0.99,y));"
"float textureGate=smoothstep(0.0015,0.010,size)*(1.0-smoothstep(0.16,0.36,size));"
"float gain=amount*clamp(coverage.r,0.0,1.0)*lightGate*textureGate*1.18;"
"vec3 detail=vec3(detailY*0.92)+(high-vec3(detailY))*0.28;"
"return premultiply(vec4(clamp(outPixel.rgb+detail*gain,0.0,1.0),outPixel.a)); }");
k[@"colorCoverage"] = PGKernel(@ k[@"colorCoverage"] = PGKernel(@
"kernel vec4 pgColorCoverage(__sample coverage,__sample image,float invert) {" "kernel vec4 pgColorCoverage(__sample coverage,__sample image,float invert) {"
"vec3 c=unpremultiply(image).rgb; float y=dot(c,vec3(0.299,0.587,0.114));" "vec3 c=unpremultiply(image).rgb; float y=dot(c,vec3(0.299,0.587,0.114));"
@@ -157,7 +177,7 @@ static NSDictionary<NSString *, CIColorKernel *> *PGKernels(void) {
float mix = PGClamp(s.mix, 0, 1); float mix = PGClamp(s.mix, 0, 1);
if (mix == 0 && !s.showMask) return image; if (mix == 0 && !s.showMask) return image;
NSDictionary *k = PGKernels(); NSDictionary *k = PGKernels();
if (k.count != 11) { if (k.count != 13) {
if (error) *error = [NSError errorWithDomain:@"PGBeautyRenderer" code:2 if (error) *error = [NSError errorWithDomain:@"PGBeautyRenderer" code:2
userInfo:@{NSLocalizedDescriptionKey:@"The beauty image kernels could not be compiled."}]; userInfo:@{NSLocalizedDescriptionKey:@"The beauty image kernels could not be compiled."}];
return nil; return nil;
@@ -173,7 +193,10 @@ static NSDictionary<NSString *, CIColorKernel *> *PGKernels(void) {
float sharpness = PGClamp(s.sharpness,0,2); float sharpness = PGClamp(s.sharpness,0,2);
float teeth = PGClamp(s.teethWhitening,0,1); float teeth = PGClamp(s.teethWhitening,0,1);
float eyes = PGClamp(s.eyeBrightening,0,1); float eyes = PGClamp(s.eyeBrightening,0,1);
BOOL needsSkin = local*amount>0 || brightness>0 || hue!=0 || saturation!=0 || even>0 || float protection = s.featureProtection ? PGClamp(s.featureProtectionAmount,0,1) : 0;
float skinProtection = PGClamp(s.nonSkinProtection,0,1);
float micro = PGClamp(s.microDetail,0,1)*amount;
BOOL needsSkin = local*amount>0 || micro>0 || brightness>0 || hue!=0 || saturation!=0 || even>0 ||
(s.skinTonePreset>0 && s.skinTonePreset<=6) || (s.showMask && s.debugChannel==0); (s.skinTonePreset>0 && s.skinTonePreset<=6) || (s.showMask && s.debugChannel==0);
CIImage *black = [[CIImage imageWithColor:[CIColor colorWithRed:0 green:0 blue:0 alpha:1]] imageByCroppingToRect:extent]; CIImage *black = [[CIImage imageWithColor:[CIColor colorWithRed:0 green:0 blue:0 alpha:1]] imageByCroppingToRect:extent];
CIImage *teethInput = teethMask ? [teethMask imageByCroppingToRect:extent] : black; CIImage *teethInput = teethMask ? [teethMask imageByCroppingToRect:extent] : black;
@@ -200,12 +223,29 @@ static NSDictionary<NSString *, CIColorKernel *> *PGKernels(void) {
float invert = s.debugChannel==1 || s.debugChannel==2 ? (s.invertMask ? 1 : 0) : 0; float invert = s.debugChannel==1 || s.debugChannel==2 ? (s.invertMask ? 1 : 0) : 0;
return PGApply(k[@"debug"],extent,@[image,preview,@(invert)]); return PGApply(k[@"debug"],extent,@[image,preview,@(invert)]);
} }
CIImage *smoothingMask=mask;
if((local*amount>0 || micro>0) && (protection<1 || skinProtection<1)) {
CIImage *baseRaw=colorMask ? [colorMask imageByCroppingToRect:extent] : raw;
float soft=PGClamp(s.maskSoftness,0,1);
CIImage *baseMask=PGApply(k[@"mask"],extent,@[baseRaw,PGBlur(baseRaw,0.35+soft*radius*0.35,extent),
image,PGBlur(image,1.5,extent),eyeInput,teethInput,
@(PGClamp(s.maskThreshold,0,255)/255.f),@(soft),@(PGClamp(s.maskEdgeProtect,0,1)),@0,@(s.invertMask?1:0)]);
smoothingMask=PGApply(k[@"smoothingSupport"],extent,@[mask,baseMask,@(protection),@(skinProtection)]);
}
// Detail protection may contain small eye, brow, nose and lip cutouts. // Detail protection may contain small eye, brow, nose and lip cutouts.
// Exposure and color must not reuse those holes or sharpen a face ellipse // Exposure and color must not reuse those holes or sharpen a face ellipse
// with the detail threshold; that creates visible rings and islands. // with the detail threshold; that creates visible rings and islands.
CIImage *toneMask=mask; CIImage *toneMask=mask;
BOOL changesColor=brightness>0 || hue!=0 || saturation!=0 || even>0 || BOOL changesColor=brightness>0 || hue!=0 || saturation!=0 || even>0 ||
(s.skinTonePreset>0 && s.skinTonePreset<=6); (s.skinTonePreset>0 && s.skinTonePreset<=6);
if(!colorMask && changesColor && s.featureProtection) {
// Standalone callers may not supply the separate uncut coverage.
// At least keep our eye/teeth cutouts out of their color adjustment.
float soft=PGClamp(s.maskSoftness,0,1);
toneMask=PGApply(k[@"mask"],extent,@[raw,PGBlur(raw,0.35+soft*radius*0.35,extent),
image,PGBlur(image,1.5,extent),eyeInput,teethInput,
@(PGClamp(s.maskThreshold,0,255)/255.f),@(soft),@(PGClamp(s.maskEdgeProtect,0,1)),@0,@(s.invertMask?1:0)]);
}
if(colorMask && changesColor) { if(colorMask && changesColor) {
CGFloat feather=MAX(3,MIN(extent.size.width,extent.size.height)*0.03); CGFloat feather=MAX(3,MIN(extent.size.width,extent.size.height)*0.03);
CIImage *support=[colorMask imageByCroppingToRect:extent]; CIImage *support=[colorMask imageByCroppingToRect:extent];
@@ -219,8 +259,12 @@ static NSDictionary<NSString *, CIColorKernel *> *PGKernels(void) {
CGFloat broad = fmin(16,(2.55+0.45*local)*fine+1.1+1.3*local); CGFloat broad = fmin(16,(2.55+0.45*local)*fine+1.1+1.3*local);
float compression = 0.12+2.4*powf(local,2.15)+1.25*local; float compression = 0.12+2.4*powf(local,2.15)+1.25*local;
CIImage *detail = PGApply(k[@"detail"],extent,@[result,PGBlur(result,fine,extent), CIImage *detail = PGApply(k[@"detail"],extent,@[result,PGBlur(result,fine,extent),
PGBlur(result,broad,extent),@(compression),@(s.featureProtection ? 1 : 0)]); PGBlur(result,broad,extent),@(compression),@(protection)]);
result = PGApply(k[@"maskedMix"],extent,@[result,detail,mask,@(amount)]); result = PGApply(k[@"maskedMix"],extent,@[result,detail,smoothingMask,@(amount)]);
}
if(micro>0) {
CGFloat fine=fmin(7.4,2.275+3.15*pow(local,0.72)+0.95*local);
result=PGApply(k[@"microDetail"],extent,@[result,image,PGBlur(image,fine,extent),smoothingMask,@(micro)]);
} }
CIImage *color = result; CIImage *color = result;
if (brightness>0) { if (brightness>0) {
+11 -1
查看文件
@@ -1,5 +1,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
#include <math.h>
// Persisted FxPlug render state. Append fields and bump version for migrations. // Persisted FxPlug render state. Append fields and bump version for migrations.
typedef struct { typedef struct {
@@ -12,11 +14,17 @@ typedef struct {
float faceJumpGuardRange, selectionX, selectionY; float faceJumpGuardRange, selectionX, selectionY;
uint32_t featureProtection, skinTonePreset, showMask, invertMask, debugChannel; uint32_t featureProtection, skinTonePreset, showMask, invertMask, debugChannel;
uint32_t showFaceBoxes, showTrackBox, singleFace, fastMultiFace, trackingEnabled, targetIndex; uint32_t showFaceBoxes, showTrackBox, singleFace, fastMultiFace, trackingEnabled, targetIndex;
// v2 keeps the entire 160-byte v1 prefix, including legacy bool/strength IDs.
float featureProtectionAmount, nonSkinProtection, microDetail;
} PGBeautySettings; } PGBeautySettings;
enum { PGBeautySettingsV1Size = 160, PGBeautySettingsVersion = 2 };
_Static_assert(offsetof(PGBeautySettings,featureProtectionAmount)==PGBeautySettingsV1Size,
"The v1 render-state prefix must remain stable");
static inline PGBeautySettings PGBeautyDefaults(void) { static inline PGBeautySettings PGBeautyDefaults(void) {
PGBeautySettings s = {0}; PGBeautySettings s = {0};
s.version = 1; s.version = PGBeautySettingsVersion;
s.amount = 1.0f; s.amount = 1.0f;
s.radius = 8.0f; s.radius = 8.0f;
s.mix = 1.0f; s.mix = 1.0f;
@@ -24,6 +32,8 @@ static inline PGBeautySettings PGBeautyDefaults(void) {
s.maskSoftness = 0.6f; s.maskSoftness = 0.6f;
s.maskEdgeProtect = 0.4f; s.maskEdgeProtect = 0.4f;
s.featureProtection = 1; s.featureProtection = 1;
s.featureProtectionAmount = 1;
s.nonSkinProtection = 1;
s.faceJumpGuardRange = 1.8f; s.faceJumpGuardRange = 1.8f;
s.selectionX = s.selectionY = 0.5f; s.selectionX = s.selectionY = 0.5f;
return s; return s;
+62 -14
查看文件
@@ -14,6 +14,8 @@ static const uint8_t PGThinPins[17][2] = {
{69,49},{65,49},{68,52},{66,52},{67,47} {69,49},{65,49},{68,52},{66,52},{67,47}
}; };
static const uint8_t PGChinPins[3][2] = {{68,38},{67,37},{66,36}}; static const uint8_t PGChinPins[3][2] = {{68,38},{67,37},{66,36}};
// Origin and radius neighbour; all six directions point toward landmark 29.
static const uint8_t PGJawPins[6][2] = {{72,71},{62,63},{71,70},{63,64},{70,71},{64,63}};
@interface PGFaceFrame () @interface PGFaceFrame ()
@property (nonatomic, copy, readwrite) NSArray<VNFaceObservation *> *faces; @property (nonatomic, copy, readwrite) NSArray<VNFaceObservation *> *faces;
@@ -125,7 +127,8 @@ static NSDictionary *PGSanitizedGeometry(id value) {
result[name] = points; result[name] = points;
} }
// Old archives and partially detected faces remain usable by the other // Old archives and partially detected faces remain usable by the other
// controls. Missing or malformed full topology disables local thin/chin pins. // controls. Missing or malformed full topology disables the recovered local
// thin/chin/jaw/short fields without discarding otherwise usable old records.
NSArray *points76 = PGSanitizedPoints76(value[@"points76"]); NSArray *points76 = PGSanitizedPoints76(value[@"points76"]);
if (points76) result[@"points76"] = points76; if (points76) result[@"points76"] = points76;
return [result copy]; return [result copy];
@@ -344,10 +347,11 @@ static NSDictionary *PGStableGeometry(NSDictionary *current, NSDictionary *previ
_lock = [[NSLock alloc] init]; _lock = [[NSLock alloc] init];
_realtime = [PGRealtimeFaceTracker new]; _realtime = [PGRealtimeFaceTracker new];
_targets = [NSMutableArray arrayWithObjects:[NSMutableDictionary dictionary], [NSMutableDictionary dictionary], [NSMutableDictionary dictionary], nil]; _targets = [NSMutableArray arrayWithObjects:[NSMutableDictionary dictionary], [NSMutableDictionary dictionary], [NSMutableDictionary dictionary], nil];
// Local thinning and chin use the recovered 17/3-pin coordinate math. // Thin/chin/jaw/short reconstruct the recovered local coordinate math.
// The other seven controls retain this project's analytic approximation. // The other five controls retain this project's analytic approximation.
// Chin follows those analytic body controls and precedes the eye warp; // Recovered jaw -> chin -> short order follows the reference. The other
// this combined order is not a reconstruction of the full reference chain. // analytic body controls still precede jaw, so the full combined chain
// (narrow/V/cheek/small-head/eyes) is not claimed reference-equivalent.
// Each pin changes the sampling coordinate, with only one image resample. // Each pin changes the sampling coordinate, with only one image resample.
NSMutableString *source = [NSMutableString stringWithString: NSMutableString *source = [NSMutableString stringWithString:
@"vec2 pgThinPin(vec2 q, vec4 control, float ratio) {" @"vec2 pgThinPin(vec2 q, vec4 control, float ratio) {"
@@ -355,9 +359,24 @@ static NSDictionary *PGStableGeometry(NSDictionary *current, NSDictionary *previ
" if(radius<=0.0001) return q;" " if(radius<=0.0001) return q;"
" float weight=clamp(1.0-length(q-control.xy)/radius,0.0,1.0);" " float weight=clamp(1.0-length(q-control.xy)/radius,0.0,1.0);"
" return clamp(q-direction*ratio*weight,vec2(0.0),vec2(1.0)); }" " return clamp(q-direction*ratio*weight,vec2(0.0),vec2(1.0)); }"
" kernel vec2 pgFaceWarp(vec2 c, vec2 size, vec2 le, vec2 re, vec2 er, float thinRatio, float bigEye, float shortFace, float narrow, float chinRatio, float vFace, float jaw, float cheek, float smallHead, float headRange, vec2 imageOrigin, vec2 imageSize"]; " vec2 pgJawPin(vec2 q, vec4 edge, vec2 anchor, float ratio) {"
" float radius=length(edge.xy-edge.zw); if(radius<=0.0001) return q;"
" float weight=clamp(1.0-length(q-edge.xy)/radius,0.0,1.0);"
" return clamp(q-(anchor-edge.xy)*ratio*weight,vec2(0.0),vec2(1.0)); }"
" vec2 pgShortEdge(vec2 q, vec2 a, vec2 b) {"
" vec2 d=b-a; float squared=dot(d,d);"
" float t=0.0; if(squared>0.000001) t=clamp(dot(q-a,d)/squared,0.0,1.0);"
" float distance=length(q-(a+t*d)); float crossing=0.0;"
" if((a.y>q.y && b.y<=q.y) || (b.y>q.y && a.y<=q.y)) {"
" float dy=b.y-a.y; if(abs(dy)<=0.000001) dy=dy<0.0?-0.000001:0.000001;"
" if(q.x<a.x+(b.x-a.x)*(q.y-a.y)/dy) crossing=1.0; }"
" return vec2(distance,crossing); }"
" kernel vec2 pgFaceWarp(vec2 c, vec2 size, vec2 le, vec2 re, vec2 er, float thinRatio, float bigEye, float shortRatio, float narrow, float chinRatio, float vFace, float jawRatio, float cheek, float smallHead, float headRange, vec2 imageOrigin, vec2 imageSize"];
for (NSUInteger i=0; i<17; i++) [source appendFormat:@", vec4 pin%lu",(unsigned long)i]; for (NSUInteger i=0; i<17; i++) [source appendFormat:@", vec4 pin%lu",(unsigned long)i];
for (NSUInteger i=0; i<3; i++) [source appendFormat:@", vec4 chinPin%lu",(unsigned long)i]; for (NSUInteger i=0; i<3; i++) [source appendFormat:@", vec4 chinPin%lu",(unsigned long)i];
[source appendString:@", vec2 jawAnchor, vec2 shortAxis"];
for (NSUInteger i=0; i<6; i++) [source appendFormat:@", vec4 jawPin%lu",(unsigned long)i];
for (NSUInteger i=0; i<11; i++) [source appendFormat:@", vec2 shortPoint%lu",(unsigned long)i];
[source appendString:@") { vec2 p=destCoord();" [source appendString:@") { vec2 p=destCoord();"
" if(thinRatio>0.000001) { vec2 q=(p-imageOrigin)/imageSize; q.y=1.0-q.y;"]; " if(thinRatio>0.000001) { vec2 q=(p-imageOrigin)/imageSize; q.y=1.0-q.y;"];
for (NSUInteger i=0; i<17; i++) [source appendFormat:@" q=pgThinPin(q,pin%lu,thinRatio);",(unsigned long)i]; for (NSUInteger i=0; i<17; i++) [source appendFormat:@" q=pgThinPin(q,pin%lu,thinRatio);",(unsigned long)i];
@@ -370,11 +389,21 @@ static NSDictionary *PGStableGeometry(NSDictionary *current, NSDictionary *previ
" float ch=(n.y-0.02)/0.19; float cheekBand = exp(-ch*ch)*body;" " float ch=(n.y-0.02)/0.19; float cheekBand = exp(-ch*ch)*body;"
" float head = 1.0-smoothstep(0.38,0.75+0.32*headRange,length(n*vec2(0.9,0.65)));" " float head = 1.0-smoothstep(0.38,0.75+0.32*headRange,length(n*vec2(0.9,0.65)));"
" p += (p-c)*smallHead*0.18*head;" " p += (p-c)*smallHead*0.18*head;"
" p.x += size.x*n.x*(narrow*0.30*body + vFace*0.24*jawBand + jaw*0.20*jawBand + cheek*0.18*cheekBand)*sides;" " p.x += size.x*n.x*(narrow*0.30*body + vFace*0.24*jawBand + cheek*0.18*cheekBand)*sides;"
" p.y += size.y*(-shortFace*0.16*lower - vFace*0.025*lower);" " p.y += size.y*(-vFace*0.025*lower);"
" if(abs(jawRatio)>0.000001) { vec2 q=(p-imageOrigin)/imageSize; q.y=1.0-q.y;"];
for (NSUInteger i=0; i<6; i++) [source appendFormat:@" q=pgJawPin(q,jawPin%lu,jawAnchor,jawRatio);",(unsigned long)i];
[source appendString:@" q.y=1.0-q.y; p=imageOrigin+q*imageSize; }"
" if(abs(chinRatio)>0.000001) { vec2 q=(p-imageOrigin)/imageSize; q.y=1.0-q.y;"]; " if(abs(chinRatio)>0.000001) { vec2 q=(p-imageOrigin)/imageSize; q.y=1.0-q.y;"];
for (NSUInteger i=0; i<3; i++) [source appendFormat:@" q=pgThinPin(q,chinPin%lu,chinRatio);",(unsigned long)i]; for (NSUInteger i=0; i<3; i++) [source appendFormat:@" q=pgThinPin(q,chinPin%lu,chinRatio);",(unsigned long)i];
[source appendString:@" q.y=1.0-q.y; p=imageOrigin+q*imageSize; }" [source appendString:@" q.y=1.0-q.y; p=imageOrigin+q*imageSize; }"
" if(abs(shortRatio)>0.000001 && length(shortAxis)>0.0001) {"
" vec2 q=(p-imageOrigin)/imageSize; q.y=1.0-q.y;"
" float nearest=10.0; float crossings=0.0;"];
for (NSUInteger i=0; i<11; i++) [source appendFormat:@" { vec2 edge=pgShortEdge(q,shortPoint%lu,shortPoint%lu); nearest=min(nearest,edge.x); crossings+=edge.y; }",(unsigned long)i,(unsigned long)((i+1)%11)];
[source appendString:@" float weight=mod(crossings,2.0)>0.5?1.0:clamp(1.0-nearest/length(shortAxis),0.0,1.0);"
" q=clamp(q-shortAxis*shortRatio*weight,vec2(0.0),vec2(1.0));"
" q.y=1.0-q.y; p=imageOrigin+q*imageSize; }"
" vec2 dl = (p-le)/er; float wl = 1.0-smoothstep(0.0,1.0,length(dl));" " vec2 dl = (p-le)/er; float wl = 1.0-smoothstep(0.0,1.0,length(dl));"
" p -= (p-le)*bigEye*0.33*wl*wl;" " p -= (p-le)*bigEye*0.33*wl*wl;"
" vec2 dr = (p-re)/er; float wr = 1.0-smoothstep(0.0,1.0,length(dr));" " vec2 dr = (p-re)/er; float wr = 1.0-smoothstep(0.0,1.0,length(dr));"
@@ -498,7 +527,7 @@ static NSDictionary *PGStableGeometry(NSDictionary *current, NSDictionary *previ
for (NSDictionary *face in geometry) { for (NSDictionary *face in geometry) {
CGRect box = PGArrayRect(face[@"box"]), pixels = PGToPixels(box, extent); CGRect box = PGArrayRect(face[@"box"]), pixels = PGToPixels(box, extent);
NSArray *points76 = PGSanitizedPoints76(face[@"points76"]); NSArray *points76 = PGSanitizedPoints76(face[@"points76"]);
float thinRatio = 0, chinRatio = 0; float thinRatio = 0, chinRatio = 0, jawRatio = 0, shortRatio = 0;
if (points76) { if (points76) {
double width = hypot(([points76[75][0] doubleValue]-[points76[59][0] doubleValue])*extent.size.width, double width = hypot(([points76[75][0] doubleValue]-[points76[59][0] doubleValue])*extent.size.width,
([points76[75][1] doubleValue]-[points76[59][1] doubleValue])*extent.size.height); ([points76[75][1] doubleValue]-[points76[59][1] doubleValue])*extent.size.height);
@@ -510,19 +539,21 @@ static NSDictionary *PGStableGeometry(NSDictionary *current, NSDictionary *previ
thinRatio = PGClamp(s.faceThin,0,1)*.025*gain; thinRatio = PGClamp(s.faceThin,0,1)*.025*gain;
float chin = PGClamp(s.faceChin,-1,1); float chin = PGClamp(s.faceChin,-1,1);
chinRatio = chin*(chin>0 ? .04 : .02)*gain; chinRatio = chin*(chin>0 ? .04 : .02)*gain;
jawRatio = PGClamp(s.faceJaw,0,1)*.05*gain;
shortRatio = PGClamp(s.faceShort,-1,1)*.25*gain;
} }
BOOL otherControls = s.faceBigEye || s.faceShort || s.faceNarrow || s.faceV || s.faceJaw || s.faceCheekbone || s.faceSmallHead; BOOL otherControls = s.faceBigEye || s.faceNarrow || s.faceV || s.faceCheekbone || s.faceSmallHead;
// No full topology means no guessed bbox thin/chin deformation. Legacy // No full topology means no guessed bbox thin/chin/jaw/short deformation. Legacy
// archives using only those controls remain exact image/mask pass-through. // archives using only those controls remain exact image/mask pass-through.
if (thinRatio <= .000001 && fabsf(chinRatio) <= .000001 && !otherControls) continue; if (thinRatio <= .000001 && fabsf(chinRatio) <= .000001 && fabsf(jawRatio) <= .000001 && fabsf(shortRatio) <= .000001 && !otherControls) continue;
CGRect le = PGRegionBounds(face, @"leftEye", PGInFace(box, 0.16, 0.53, 0.25, 0.15)); CGRect le = PGRegionBounds(face, @"leftEye", PGInFace(box, 0.16, 0.53, 0.25, 0.15));
CGRect re = PGRegionBounds(face, @"rightEye", PGInFace(box, 0.59, 0.53, 0.25, 0.15)); CGRect re = PGRegionBounds(face, @"rightEye", PGInFace(box, 0.59, 0.53, 0.25, 0.15));
CGPoint left = PGCenter(PGToPixels(le, extent)), right = PGCenter(PGToPixels(re, extent)); CGPoint left = PGCenter(PGToPixels(le, extent)), right = PGCenter(PGToPixels(re, extent));
NSMutableArray *arguments = [@[PGVector(PGCenter(pixels)), [CIVector vectorWithX:pixels.size.width Y:pixels.size.height], NSMutableArray *arguments = [@[PGVector(PGCenter(pixels)), [CIVector vectorWithX:pixels.size.width Y:pixels.size.height],
PGVector(left), PGVector(right), [CIVector vectorWithX:MAX(2, pixels.size.width * 0.24) Y:MAX(2, pixels.size.height * 0.17)], PGVector(left), PGVector(right), [CIVector vectorWithX:MAX(2, pixels.size.width * 0.24) Y:MAX(2, pixels.size.height * 0.17)],
@(thinRatio), @(PGClamp(s.faceBigEye, 0, 1)), @(PGClamp(s.faceShort, -1, 1)), @(thinRatio), @(PGClamp(s.faceBigEye, 0, 1)), @(shortRatio),
@(PGClamp(s.faceNarrow, -1, 1)), @(chinRatio), @(PGClamp(s.faceV, 0, 1)), @(PGClamp(s.faceNarrow, -1, 1)), @(chinRatio), @(PGClamp(s.faceV, 0, 1)),
@(PGClamp(s.faceJaw, 0, 1)), @(PGClamp(s.faceCheekbone, 0, 1)), @(PGClamp(s.faceSmallHead, 0, 1)), @(PGClamp(s.faceSmallHeadRange, 0, 1)), @(jawRatio), @(PGClamp(s.faceCheekbone, 0, 1)), @(PGClamp(s.faceSmallHead, 0, 1)), @(PGClamp(s.faceSmallHeadRange, 0, 1)),
[CIVector vectorWithX:extent.origin.x Y:extent.origin.y], [CIVector vectorWithX:extent.size.width Y:extent.size.height]] mutableCopy]; [CIVector vectorWithX:extent.origin.x Y:extent.origin.y], [CIVector vectorWithX:extent.size.width Y:extent.size.height]] mutableCopy];
for (NSUInteger i=0; i<17; i++) { for (NSUInteger i=0; i<17; i++) {
double ox=0,oy=0,ax=0,ay=0; double ox=0,oy=0,ax=0,ay=0;
@@ -542,6 +573,23 @@ static NSDictionary *PGStableGeometry(NSDictionary *current, NSDictionary *previ
} }
[arguments addObject:[CIVector vectorWithX:ox Y:oy Z:ax W:ay]]; [arguments addObject:[CIVector vectorWithX:ox Y:oy Z:ax W:ay]];
} }
CGPoint anchor=CGPointZero,axis=CGPointZero;
if(points76){
anchor=CGPointMake([points76[29][0]doubleValue],1-[points76[29][1]doubleValue]);
axis=CGPointMake([points76[46][0]doubleValue]-[points76[48][0]doubleValue],
[points76[48][1]doubleValue]-[points76[46][1]doubleValue]);
}
[arguments addObject:PGVector(anchor)];[arguments addObject:PGVector(axis)];
for(NSUInteger i=0;i<6;i++){
double ox=0,oy=0,nx=0,ny=0;
if(points76){NSArray *origin=points76[PGJawPins[i][0]],*neighbour=points76[PGJawPins[i][1]];
ox=[origin[0]doubleValue];oy=1-[origin[1]doubleValue];nx=[neighbour[0]doubleValue];ny=1-[neighbour[1]doubleValue];}
[arguments addObject:[CIVector vectorWithX:ox Y:oy Z:nx W:ny]];
}
for(NSUInteger i=62;i<=72;i++){
CGPoint point=CGPointZero;if(points76)point=CGPointMake([points76[i][0]doubleValue],1-[points76[i][1]doubleValue]);
[arguments addObject:PGVector(point)];
}
CIImage *input = [result imageByClampingToExtent]; CIImage *input = [result imageByClampingToExtent];
result = [_warp applyWithExtent:extent roiCallback:^CGRect(int index, CGRect rect) { (void)index; (void)rect; return extent; } inputImage:input arguments:arguments]; result = [_warp applyWithExtent:extent roiCallback:^CGRect(int index, CGRect rect) { (void)index; (void)rect; return extent; } inputImage:input arguments:arguments];
if (!result) return nil; if (!result) return nil;
@@ -30,6 +30,8 @@ FOUNDATION_EXPORT PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings
@property (nonatomic, strong, readonly) PGInspectorState *state; @property (nonatomic, strong, readonly) PGInspectorState *state;
@property (nonatomic, readonly) BOOL available; @property (nonatomic, readonly) BOOL available;
@property (nonatomic, copy, readonly) NSString *statusMessage; @property (nonatomic, copy, readonly) NSString *statusMessage;
/// The actual custom inspector view identifies the action to the native host.
@property (nonatomic, weak, nullable) NSView *actionSender;
- (instancetype)initWithAPIManager:(id<PROAPIAccessing>)manager; - (instancetype)initWithAPIManager:(id<PROAPIAccessing>)manager;
- (void)refresh; - (void)refresh;
- (void)documentDidChange; - (void)documentDidChange;
+59 -13
查看文件
@@ -1,6 +1,7 @@
#import "PGInspectorState.h" #import "PGInspectorState.h"
#import <math.h> #import <math.h>
#import <stddef.h> #import <stddef.h>
#import <os/log.h>
NSArray<NSDictionary *> *PGInspectorControls(void) { NSArray<NSDictionary *> *PGInspectorControls(void) {
static NSArray *controls; static dispatch_once_t once; static NSArray *controls; static dispatch_once_t once;
@@ -10,9 +11,10 @@ NSArray<NSDictionary *> *PGInspectorControls(void) {
#define ITEM(ID,NAME,FIELD,SECTION,KIND,FORMAT,MIN,MAX,BYPASS,STORAGE) \ #define ITEM(ID,NAME,FIELD,SECTION,KIND,FORMAT,MIN,MAX,BYPASS,STORAGE) \
[items addObject:@{@"id":@(ID),@"name":@NAME,@"section":@SECTION,@"kind":@KIND,@"format":@FORMAT,@"min":@(MIN),@"max":@(MAX),@"default":@(defaults.FIELD),@"bypass":@(BYPASS),@"offset":@(offsetof(PGBeautySettings,FIELD)),@"storage":@STORAGE}] [items addObject:@{@"id":@(ID),@"name":@NAME,@"section":@SECTION,@"kind":@KIND,@"format":@FORMAT,@"min":@(MIN),@"max":@(MAX),@"default":@(defaults.FIELD),@"bypass":@(BYPASS),@"offset":@(offsetof(PGBeautySettings,FIELD)),@"storage":@STORAGE}]
ITEM(PGSmoothingEnabled,"磨皮",featureProtection,"smooth","master","integer",0,1,NO,"master"); ITEM(PGSmoothingEnabled,"磨皮",featureProtection,"smooth","master","integer",0,1,NO,"master");
ITEM(PGMidtone,"局部磨皮",midtoneDetail,"smooth","slider","percent",0,1,YES,"float"); ITEM(PGMidtone,"磨皮程度",midtoneDetail,"smooth","slider","percent",0,1,YES,"float");
ITEM(PGHighPass,"全局磨皮",highPassDetail,"smooth","slider","percent",0,1,YES,"float"); ITEM(PGMicroDetail,"微细锐化",microDetail,"smooth","slider","percent",0,1,YES,"float");
ITEM(PGFeatureProtect,"五官保护",featureProtection,"smooth","toggle","integer",0,1,NO,"uint"); ITEM(PGFeatureProtectionAmount,"五官保护",featureProtectionAmount,"smooth","slider","percent",0,1,YES,"float");
ITEM(PGNonSkinProtection,"非肤色区保护",nonSkinProtection,"smooth","slider","percent",0,1,YES,"float");
ITEM(PGColorEnabled,"美白",featureProtection,"color","master","integer",0,1,NO,"master"); ITEM(PGColorEnabled,"美白",featureProtection,"color","master","integer",0,1,NO,"master");
ITEM(PGTonePreset,"肤色",skinTonePreset,"color","preset","integer",0,6,NO,"uint"); ITEM(PGTonePreset,"肤色",skinTonePreset,"color","preset","integer",0,6,NO,"uint");
NSMutableDictionary *preset=[items.lastObject mutableCopy]; NSMutableDictionary *preset=[items.lastObject mutableCopy];
@@ -21,9 +23,10 @@ NSArray<NSDictionary *> *PGInspectorControls(void) {
ITEM(PGTeeth,"白牙",teethWhitening,"color","slider","percent",0,1,YES,"float"); ITEM(PGTeeth,"白牙",teethWhitening,"color","slider","percent",0,1,YES,"float");
ITEM(PGHue,"皮肤色相",skinHue,"color","slider","degrees",-30,30,YES,"float"); ITEM(PGHue,"皮肤色相",skinHue,"color","slider","degrees",-30,30,YES,"float");
ITEM(PGShapeEnabled,"瘦脸",featureProtection,"shape","master","integer",0,1,NO,"master"); ITEM(PGShapeEnabled,"瘦脸",featureProtection,"shape","master","integer",0,1,NO,"master");
ITEM(PGTrackBoxes,"人脸框预览",showTrackBox,"shape","toggle","integer",0,1,NO,"uint"); ITEM(PGTrackBoxes,"检测框预览",showTrackBox,"shape","toggle","integer",0,1,NO,"uint");
ITEM(PGFastMulti,"多人模式",fastMultiFace,"shape","toggle","integer",0,1,NO,"uint"); ITEM(PGFastMulti,"多人模式",fastMultiFace,"shape","toggle","integer",0,1,NO,"uint");
ITEM(PGJumpGuard,"防跳脸范围",faceJumpGuardRange,"shape","slider","percent",1,4,NO,"float"); NSMutableDictionary *multi=[items.lastObject mutableCopy];
multi[@"tooltip"]=@"多人模式易抖动,请谨慎使用";items[items.count-1]=multi;
ITEM(PGThin,"瘦脸",faceThin,"shape","slider","signed",0,1,YES,"float"); ITEM(PGThin,"瘦脸",faceThin,"shape","slider","signed",0,1,YES,"float");
ITEM(PGBigEye,"大眼",faceBigEye,"shape","slider","signed",0,1,YES,"float"); ITEM(PGBigEye,"大眼",faceBigEye,"shape","slider","signed",0,1,YES,"float");
ITEM(PGShort,"短脸",faceShort,"shape","slider","signed",-1,1,YES,"float"); ITEM(PGShort,"短脸",faceShort,"shape","slider","signed",-1,1,YES,"float");
@@ -35,11 +38,13 @@ NSArray<NSDictionary *> *PGInspectorControls(void) {
ITEM(PGSmallHead,"小头",faceSmallHead,"shape","slider","signed",0,1,YES,"float"); ITEM(PGSmallHead,"小头",faceSmallHead,"shape","slider","signed",0,1,YES,"float");
ITEM(PGSmallHeadRange,"小头范围",faceSmallHeadRange,"shape","slider","percent",0,1,NO,"float"); ITEM(PGSmallHeadRange,"小头范围",faceSmallHeadRange,"shape","slider","percent",0,1,NO,"float");
ITEM(PGAmount,"磨皮强度",amount,"more","slider","percent",0,1,YES,"float"); ITEM(PGAmount,"磨皮强度",amount,"more","slider","percent",0,1,YES,"float");
ITEM(PGHighPass,"全局磨皮",highPassDetail,"more","slider","percent",0,1,YES,"float");
ITEM(PGRadius,"磨皮半径",radius,"more","slider","radius",1,30,NO,"float"); ITEM(PGRadius,"磨皮半径",radius,"more","slider","radius",1,30,NO,"float");
ITEM(PGSaturation,"肤色饱和度",skinSaturation,"more","slider","percent",-100,100,YES,"float"); ITEM(PGSaturation,"肤色饱和度",skinSaturation,"more","slider","percent",-100,100,YES,"float");
ITEM(PGEvenTone,"均匀肤色",skinEvenTone,"more","slider","percent",0,1,YES,"float"); ITEM(PGEvenTone,"均匀肤色",skinEvenTone,"more","slider","percent",0,1,YES,"float");
ITEM(PGEyeBright,"眼睛提亮",eyeBrightening,"more","slider","percent",0,1,YES,"float"); ITEM(PGEyeBright,"眼睛提亮",eyeBrightening,"more","slider","percent",0,1,YES,"float");
ITEM(PGSharpness,"锐化",sharpness,"more","slider","percent",0,1,YES,"float"); ITEM(PGSharpness,"锐化",sharpness,"more","slider","percent",0,1,YES,"float");
ITEM(PGJumpGuard,"防跳脸范围",faceJumpGuardRange,"more","slider","percent",1,4,NO,"float");
ITEM(PGMix,"整体混合",mix,"more","slider","percent",0,1,NO,"float"); ITEM(PGMix,"整体混合",mix,"more","slider","percent",0,1,NO,"float");
#undef ITEM #undef ITEM
controls=[items copy]; controls=[items copy];
@@ -61,7 +66,12 @@ static double PGControlValue(id raw,NSDictionary *d) {
+ (instancetype)stateWithValues:(NSDictionary *)values disabledParameters:(NSSet *)disabled hasEdits:(BOOL)edited { + (instancetype)stateWithValues:(NSDictionary *)values disabledParameters:(NSSet *)disabled hasEdits:(BOOL)edited {
PGInspectorState *state=[self new]; NSMutableDictionary *safe=[NSMutableDictionary new];NSMutableSet *bypassed=[NSMutableSet new]; PGInspectorState *state=[self new]; NSMutableDictionary *safe=[NSMutableDictionary new];NSMutableSet *bypassed=[NSMutableSet new];
for(NSDictionary *d in PGInspectorControls()) { for(NSDictionary *d in PGInspectorControls()) {
NSNumber *key=d[@"id"];safe[key]=@(PGControlValue(values[key],d)); NSNumber *key=d[@"id"];id raw=values[key];
// Schema 1 documents stored five-feature protection as the legacy bool.
// New numeric values win when present; old archives gain its exact 0/1.
if(key.unsignedIntValue==PGFeatureProtectionAmount && !raw && [values[@(PGFeatureProtect)] isKindOfClass:NSNumber.class])
raw=@([values[@(PGFeatureProtect)] boolValue]?1:0);
safe[key]=@(PGControlValue(raw,d));
if([d[@"bypass"] boolValue] && [disabled containsObject:key]) [bypassed addObject:key]; if([d[@"bypass"] boolValue] && [disabled containsObject:key]) [bypassed addObject:key];
} }
state->_values=[safe copy];state->_disabledParameters=[bypassed copy];state->_hasEdits=edited;return state; state->_values=[safe copy];state->_disabledParameters=[bypassed copy];state->_hasEdits=edited;return state;
@@ -114,7 +124,8 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
if([storage isEqual:@"float"]) *(float *)((uint8_t *)&s+offset)=value; if([storage isEqual:@"float"]) *(float *)((uint8_t *)&s+offset)=value;
else *(uint32_t *)((uint8_t *)&s+offset)=(uint32_t)value; else *(uint32_t *)((uint8_t *)&s+offset)=(uint32_t)value;
} }
if(![state valueForParameter:PGSmoothingEnabled])s.amount=s.midtoneDetail=s.highPassDetail=0; s.featureProtection=s.featureProtectionAmount>0;
if(![state valueForParameter:PGSmoothingEnabled])s.amount=s.midtoneDetail=s.highPassDetail=s.microDetail=0;
if(![state valueForParameter:PGColorEnabled]) {s.skinBrightness=s.skinHue=s.skinSaturation=s.skinEvenTone=s.teethWhitening=s.eyeBrightening=0;s.skinTonePreset=0;} if(![state valueForParameter:PGColorEnabled]) {s.skinBrightness=s.skinHue=s.skinSaturation=s.skinEvenTone=s.teethWhitening=s.eyeBrightening=0;s.skinTonePreset=0;}
if(![state valueForParameter:PGShapeEnabled]) {s.faceThin=s.faceBigEye=s.faceShort=s.faceNarrow=s.faceChin=s.faceV=s.faceJaw=s.faceCheekbone=s.faceSmallHead=0;s.showTrackBox=0;} if(![state valueForParameter:PGShapeEnabled]) {s.faceThin=s.faceBigEye=s.faceShort=s.faceNarrow=s.faceChin=s.faceV=s.faceJaw=s.faceCheekbone=s.faceSmallHead=0;s.showTrackBox=0;}
return s; return s;
@@ -129,6 +140,9 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
@property (nonatomic) BOOL interacting; @property (nonatomic) BOOL interacting;
@property (nonatomic) NSTimeInterval pendingUntil; @property (nonatomic) NSTimeInterval pendingUntil;
@property (nonatomic) CMTime pendingTime; @property (nonatomic) CMTime pendingTime;
@property (nonatomic, strong) id activeSender;
@property (nonatomic) BOOL reportedConnection;
@property (nonatomic) BOOL reportedMissingAction;
@end @end
@implementation PGInspectorController @implementation PGInspectorController
- (instancetype)initWithAPIManager:(id<PROAPIAccessing>)manager { - (instancetype)initWithAPIManager:(id<PROAPIAccessing>)manager {
@@ -138,13 +152,34 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
- (BOOL)start { - (BOOL)start {
if(_interacting)return YES; if(_interacting)return YES;
_action=[_manager apiForProtocol:@protocol(FxCustomParameterActionAPI_v4)]; _action=[_manager apiForProtocol:@protocol(FxCustomParameterActionAPI_v4)];
if(!_action){
_available=NO;_statusMessage=@"等待宿主连接";
if(!_reportedMissingAction){os_log(OS_LOG_DEFAULT,"PGInspector action API unavailable manager=%{public}d viewSender=%{public}d onMain=%{public}d",_manager!=nil,_actionSender!=nil,NSThread.isMainThread);_reportedMissingAction=YES;}
return NO;
}
// A native host can expose parameter APIs only after the custom view's
// action has established its document context. Never gate startAction on
// those APIs being available before entering the action.
BOOL readBefore=NO,writeBefore=NO;
if(!_reportedConnection){
readBefore=[_manager apiForProtocol:@protocol(FxParameterRetrievalAPI_v6)]!=nil;
writeBefore=[_manager apiForProtocol:@protocol(FxParameterSettingAPI_v5)]!=nil;
}
_activeSender=_actionSender ?: self;
[_action startAction:_activeSender];_interacting=YES;
@try {
id retrieval=[_manager apiForProtocol:@protocol(FxParameterRetrievalAPI_v6)]; id retrieval=[_manager apiForProtocol:@protocol(FxParameterRetrievalAPI_v6)];
id setting=[_manager apiForProtocol:@protocol(FxParameterSettingAPI_v5)]; id setting=[_manager apiForProtocol:@protocol(FxParameterSettingAPI_v5)];
_available=_action && retrieval && setting; _available=retrieval && setting;
if(!_available){_statusMessage=@"等待宿主连接";return NO;} if(!_reportedConnection){
[_action startAction:self];_interacting=YES;return YES; os_log(OS_LOG_DEFAULT,"PGInspector connection readBefore=%{public}d writeBefore=%{public}d readInAction=%{public}d writeInAction=%{public}d viewSender=%{public}d onMain=%{public}d",readBefore,writeBefore,retrieval!=nil,setting!=nil,[_activeSender isKindOfClass:NSView.class],NSThread.isMainThread);
_reportedConnection=YES;
}
if(!_available){_statusMessage=@"等待宿主连接";[self finish];return NO;}
} @catch(NSException *exception) {[self finish];@throw exception;}
return YES;
} }
- (void)finish {if(_interacting){_interacting=NO;[_action endAction:self];_action=nil;}} - (void)finish {if(_interacting){_interacting=NO;[_action endAction:_activeSender];_action=nil;_activeSender=nil;}}
- (void)readAtTime:(CMTime)time { - (void)readAtTime:(CMTime)time {
if(_pendingUntil && CMTimeCompare(time,_pendingTime)!=0)_pendingUntil=0; if(_pendingUntil && CMTimeCompare(time,_pendingTime)!=0)_pendingUntil=0;
id<FxParameterRetrievalAPI_v6> api=[_manager apiForProtocol:@protocol(FxParameterRetrievalAPI_v6)]; id<FxParameterRetrievalAPI_v6> api=[_manager apiForProtocol:@protocol(FxParameterRetrievalAPI_v6)];
@@ -164,6 +199,12 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
else [api getFloatValue:&value fromParameter:key atTime:time]; else [api getFloatValue:&value fromParameter:key atTime:time];
values[@(key)]=@(value); values[@(key)]=@(value);
} }
// The old bool can still disable protection. A true value must preserve a
// numeric setting already read above; its registered default is one for
// old documents that have no independently stored numeric parameter.
BOOL legacyFeatureProtection=YES;
if([api getBoolValue:&legacyFeatureProtection fromParameter:PGFeatureProtect atTime:time] && !legacyFeatureProtection)
values[@(PGFeatureProtectionAmount)]=@0;
BOOL legacyDetail=YES;[api getBoolValue:&legacyDetail fromParameter:PGDetailEnabled atTime:time]; BOOL legacyDetail=YES;[api getBoolValue:&legacyDetail fromParameter:PGDetailEnabled atTime:time];
NSMutableSet *disabled=legacyDetail?[NSMutableSet set]:[NSMutableSet setWithObjects:@(PGHighPass),@(PGSharpness),nil]; NSMutableSet *disabled=legacyDetail?[NSMutableSet set]:[NSMutableSet setWithObjects:@(PGHighPass),@(PGSharpness),nil];
// Earlier versions put high-pass smoothing under a different group. Keep // Earlier versions put high-pass smoothing under a different group. Keep
@@ -171,7 +212,7 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
// off, rather than turning a still-active global effect off on first edit. // off, rather than turning a still-active global effect off on first edit.
if(![values[@(PGSmoothingEnabled)] boolValue] && legacyDetail && [values[@(PGHighPass)] doubleValue]>0) { if(![values[@(PGSmoothingEnabled)] boolValue] && legacyDetail && [values[@(PGHighPass)] doubleValue]>0) {
values[@(PGSmoothingEnabled)]=@YES; values[@(PGSmoothingEnabled)]=@YES;
[disabled addObject:@(PGMidtone)];[disabled addObject:@(PGAmount)]; [disabled addObject:@(PGMidtone)];[disabled addObject:@(PGAmount)];[disabled addObject:@(PGMicroDetail)];
} }
_state=[PGInspectorState stateWithValues:values disabledParameters:disabled hasEdits:NO]; _state=[PGInspectorState stateWithValues:values disabledParameters:disabled hasEdits:NO];
} }
@@ -207,6 +248,11 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
else if([d[@"kind"] isEqual:@"toggle"] || [d[@"kind"] isEqual:@"master"]) [api setBoolValue:value!=0 toParameter:key atTime:time]; else if([d[@"kind"] isEqual:@"toggle"] || [d[@"kind"] isEqual:@"master"]) [api setBoolValue:value!=0 toParameter:key atTime:time];
else [api setFloatValue:value toParameter:key atTime:time]; else [api setFloatValue:value toParameter:key atTime:time];
} }
BOOL featureProtection=[next isParameterEnabled:PGFeatureProtectionAmount] && [next valueForParameter:PGFeatureProtectionAmount]>0;
id<FxParameterRetrievalAPI_v6> reader=[_manager apiForProtocol:@protocol(FxParameterRetrievalAPI_v6)];
BOOL previousProtection=!featureProtection;
if(![reader getBoolValue:&previousProtection fromParameter:PGFeatureProtect atTime:time] || previousProtection!=featureProtection)
[api setBoolValue:featureProtection toParameter:PGFeatureProtect atTime:time];
_state=next;_pendingUntil=NSDate.timeIntervalSinceReferenceDate+.35;_pendingTime=time;_statusMessage=@"";return YES; _state=next;_pendingUntil=NSDate.timeIntervalSinceReferenceDate+.35;_pendingTime=time;_statusMessage=@"";return YES;
} }
- (BOOL)setValue:(double)value forParameter:(UInt32)identifier { - (BOOL)setValue:(double)value forParameter:(UInt32)identifier {
@@ -241,5 +287,5 @@ PGBeautySettings PGSettingsWithInspectorState(PGBeautySettings s,PGInspectorStat
ok=[self commit:[PGInspectorState stateWithValues:values disabledParameters:disabled hasEdits:YES]]; ok=[self commit:[PGInspectorState stateWithValues:values disabledParameters:disabled hasEdits:YES]];
} @finally {if(owned)[self finish];}return ok; } @finally {if(owned)[self finish];}return ok;
} }
- (void)dealloc {if(_interacting)[_action endAction:self];} - (void)dealloc {if(_interacting)[_action endAction:_activeSender];}
@end @end
+31 -10
查看文件
@@ -155,6 +155,7 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
@property (nonatomic, strong) NSColor *accent; @property (nonatomic, strong) NSColor *accent;
@property (nonatomic, strong) NSTextField *label; @property (nonatomic, strong) NSTextField *label;
@property (nonatomic, strong) NSTextField *valueField; @property (nonatomic, strong) NSTextField *valueField;
@property (nonatomic) BOOL numberHasUnsubmittedEdit;
@property (nonatomic, strong) NSTextField *hint; @property (nonatomic, strong) NSTextField *hint;
@property (nonatomic, strong) PGInspectorSlider *slider; @property (nonatomic, strong) PGInspectorSlider *slider;
@property (nonatomic, strong) PGInspectorGlyphButton *eye; @property (nonatomic, strong) PGInspectorGlyphButton *eye;
@@ -201,6 +202,8 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
} }
} }
NSString *key=[descriptor[@"id"]stringValue]; NSString *key=[descriptor[@"id"]stringValue];
NSString *tooltip=descriptor[@"tooltip"];
if(tooltip.length){self.toolTip=tooltip;_label.toolTip=tooltip;_toggle.toolTip=tooltip;_slider.toolTip=tooltip;_valueField.toolTip=tooltip;}
_slider.identifier=[@"pg.value."stringByAppendingString:key];_valueField.identifier=[@"pg.number."stringByAppendingString:key]; _slider.identifier=[@"pg.value."stringByAppendingString:key];_valueField.identifier=[@"pg.number."stringByAppendingString:key];
_toggle.identifier=[@"pg.toggle."stringByAppendingString:key];_eye.identifier=[@"pg.enable."stringByAppendingString:key];_reset.identifier=[@"pg.reset."stringByAppendingString:key]; _toggle.identifier=[@"pg.toggle."stringByAppendingString:key];_eye.identifier=[@"pg.enable."stringByAppendingString:key];_reset.identifier=[@"pg.reset."stringByAppendingString:key];
}return self; }return self;
@@ -232,7 +235,7 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
_label.alphaValue=master&&enabled?1:.5;_eye.state=enabled?NSControlStateValueOn:NSControlStateValueOff;_eye.enabled=available&&master; _label.alphaValue=master&&enabled?1:.5;_eye.state=enabled?NSControlStateValueOn:NSControlStateValueOff;_eye.enabled=available&&master;
_reset.enabled=available;_reset.state=fabs(value-[_descriptor[@"default"]doubleValue])>.000001?NSControlStateValueOn:NSControlStateValueOff; _reset.enabled=available;_reset.state=fabs(value-[_descriptor[@"default"]doubleValue])>.000001?NSControlStateValueOn:NSControlStateValueOff;
_slider.enabled=available&&master&&enabled;_slider.doubleValue=value; _slider.enabled=available&&master&&enabled;_slider.doubleValue=value;
_valueField.enabled=available&&master&&enabled;if(!_valueField.currentEditor)_valueField.stringValue=PGFormattedValue(_descriptor,value); _valueField.enabled=available&&master&&enabled;if(!_valueField.currentEditor || !_numberHasUnsubmittedEdit)_valueField.stringValue=PGFormattedValue(_descriptor,value);
_toggle.enabled=available&&master&&enabled;_toggle.state=value>.5?NSControlStateValueOn:NSControlStateValueOff; _toggle.enabled=available&&master&&enabled;_toggle.state=value>.5?NSControlStateValueOn:NSControlStateValueOff;
UInt32 identifierForHint=[_descriptor[@"id"]unsignedIntValue]; UInt32 identifierForHint=[_descriptor[@"id"]unsignedIntValue];
_hint.stringValue=identifierForHint==PGFastMulti?(value>.5?@"多人":@"单人"):identifierForHint==PGTrackBoxes?(value>.5?@"预览中":@"隐藏"):(value>.5?@"开启":@"关闭"); _hint.stringValue=identifierForHint==PGFastMulti?(value>.5?@"多人":@"单人"):identifierForHint==PGTrackBoxes?(value>.5?@"预览中":@"隐藏"):(value>.5?@"开启":@"关闭");
@@ -244,7 +247,11 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
- (void)toggleEnabled:(id)sender { (void)sender;[_inspector.controller toggleEnabledForParameter:[_descriptor[@"id"]unsignedIntValue]];[_inspector reloadControls]; } - (void)toggleEnabled:(id)sender { (void)sender;[_inspector.controller toggleEnabledForParameter:[_descriptor[@"id"]unsignedIntValue]];[_inspector reloadControls]; }
- (void)resetValue:(id)sender { (void)sender;[_inspector.controller resetParameter:[_descriptor[@"id"]unsignedIntValue]];[_inspector reloadControls]; } - (void)resetValue:(id)sender { (void)sender;[_inspector.controller resetParameter:[_descriptor[@"id"]unsignedIntValue]];[_inspector reloadControls]; }
- (void)numberCommitted:(id)sender { - (void)numberCommitted:(id)sender {
(void)sender;NSString *text=[_valueField.stringValue stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]; // The explicit Return action and the subsequent end-editing notification
// describe the same submission. Clear the dirty flag before host callbacks
// so focus loss cannot write stale text over a reset or a host undo.
_numberHasUnsubmittedEdit=NO;
NSString *text=[_valueField.stringValue stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
if([text hasSuffix:@"%"]||[text hasSuffix:@"°"])text=[text substringToIndex:text.length-1]; if([text hasSuffix:@"%"]||[text hasSuffix:@"°"])text=[text substringToIndex:text.length-1];
NSNumber *number=nil; NSNumber *number=nil;
for(NSLocale *locale in @[NSLocale.currentLocale,[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]){ for(NSLocale *locale in @[NSLocale.currentLocale,[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]){
@@ -259,18 +266,29 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
[_inspector writeValue:value parameter:[_descriptor[@"id"]unsignedIntValue]]; [_inspector writeValue:value parameter:[_descriptor[@"id"]unsignedIntValue]];
}else NSBeep(); }else NSBeep();
_valueField.stringValue=PGFormattedValue(_descriptor,[_inspector.controller.state valueForParameter:[_descriptor[@"id"]unsignedIntValue]]); _valueField.stringValue=PGFormattedValue(_descriptor,[_inspector.controller.state valueForParameter:[_descriptor[@"id"]unsignedIntValue]]);
if(sender==_valueField) {
[_valueField.window makeFirstResponder:nil];
// A remote inspector can retain its field editor after the host has
// consumed Return. End the already-submitted edit at the control too.
[_valueField abortEditing];
}
}
- (void)controlTextDidChange:(NSNotification *)notification { (void)notification;_numberHasUnsubmittedEdit=YES; }
- (void)controlTextDidEndEditing:(NSNotification *)notification {
(void)notification;
if(_numberHasUnsubmittedEdit)[self numberCommitted:nil];
[_inspector refreshFromHost];
} }
- (void)controlTextDidEndEditing:(NSNotification *)notification { (void)notification;[self numberCommitted:_valueField]; }
@end @end
@implementation PGInspectorCard @implementation PGInspectorCard
- (BOOL)isFlipped { return YES; } - (BOOL)isFlipped { return YES; }
- (CGFloat)heightForWidth:(CGFloat)width { - (CGFloat)heightForWidth:(CGFloat)width {
if(!_expanded)return 44;CGFloat height=49;for(PGInspectorRow *row in _rows){height+=[row heightForWidth:MAX(0,width-24)];if([row.descriptor[@"id"]unsignedIntValue]==PGJumpGuard)height+=8;}return height+7; if(!_expanded)return 44;CGFloat height=49;for(PGInspectorRow *row in _rows){height+=[row heightForWidth:MAX(0,width-24)];if([row.descriptor[@"id"]unsignedIntValue]==PGFastMulti)height+=8;}return height+7;
} }
- (void)layout { - (void)layout {
[super layout];CGFloat w=NSWidth(self.bounds);_titleLabel.frame=NSMakeRect(25,13,MAX(70,w-80),22);_master.frame=NSMakeRect(w-39,10,25,25); [super layout];CGFloat w=NSWidth(self.bounds);_titleLabel.frame=NSMakeRect(25,13,MAX(70,w-80),22);_master.frame=NSMakeRect(w-39,10,25,25);
CGFloat y=49;for(PGInspectorRow *row in _rows){row.hidden=!_expanded;if(!_expanded)continue;CGFloat h=[row heightForWidth:w-24];row.frame=NSMakeRect(12,y,w-24,h);y+=h;if([row.descriptor[@"id"]unsignedIntValue]==PGJumpGuard)y+=8;} CGFloat y=49;for(PGInspectorRow *row in _rows){row.hidden=!_expanded;if(!_expanded)continue;CGFloat h=[row heightForWidth:w-24];row.frame=NSMakeRect(12,y,w-24,h);y+=h;if([row.descriptor[@"id"]unsignedIntValue]==PGFastMulti)y+=8;}
} }
- (void)drawRect:(NSRect)dirtyRect { - (void)drawRect:(NSRect)dirtyRect {
(void)dirtyRect;NSBezierPath *shape=[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(self.bounds,.5,.5) xRadius:13 yRadius:13]; (void)dirtyRect;NSBezierPath *shape=[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(self.bounds,.5,.5) xRadius:13 yRadius:13];
@@ -278,7 +296,7 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
[[_accent colorWithAlphaComponent:.22]setStroke];shape.lineWidth=.8;[shape stroke]; [[_accent colorWithAlphaComponent:.22]setStroke];shape.lineWidth=.8;[shape stroke];
NSRect pill=NSMakeRect(12,10,MAX(53,[_heading length]*13+20),25);[[_accent colorWithAlphaComponent:.10]setFill];NSBezierPath *p=[NSBezierPath bezierPathWithRoundedRect:pill xRadius:8 yRadius:8];[p fill];[[_accent colorWithAlphaComponent:.32]setStroke];p.lineWidth=.7;[p stroke]; NSRect pill=NSMakeRect(12,10,MAX(53,[_heading length]*13+20),25);[[_accent colorWithAlphaComponent:.10]setFill];NSBezierPath *p=[NSBezierPath bezierPathWithRoundedRect:pill xRadius:8 yRadius:8];[p fill];[[_accent colorWithAlphaComponent:.32]setStroke];p.lineWidth=.7;[p stroke];
if(_expanded){[[PGUIMuted() colorWithAlphaComponent:.20]setStroke];NSBezierPath *line=[NSBezierPath bezierPath];[line moveToPoint:NSMakePoint(12,43)];[line lineToPoint:NSMakePoint(NSWidth(self.bounds)-12,43)];line.lineWidth=.5;[line stroke]; if(_expanded){[[PGUIMuted() colorWithAlphaComponent:.20]setStroke];NSBezierPath *line=[NSBezierPath bezierPath];[line moveToPoint:NSMakePoint(12,43)];[line lineToPoint:NSMakePoint(NSWidth(self.bounds)-12,43)];line.lineWidth=.5;[line stroke];
for(PGInspectorRow *row in _rows)if([row.descriptor[@"id"]unsignedIntValue]==PGJumpGuard){CGFloat y=NSMaxY(row.frame)+4;[line removeAllPoints];[line moveToPoint:NSMakePoint(12,y)];[line lineToPoint:NSMakePoint(NSWidth(self.bounds)-12,y)];[line stroke];} for(PGInspectorRow *row in _rows)if([row.descriptor[@"id"]unsignedIntValue]==PGFastMulti){CGFloat y=NSMaxY(row.frame)+4;[line removeAllPoints];[line moveToPoint:NSMakePoint(12,y)];[line lineToPoint:NSMakePoint(NSWidth(self.bounds)-12,y)];[line stroke];}
} }
} }
@end @end
@@ -293,7 +311,7 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
- (instancetype)initWithAPIManager:(id<PROAPIAccessing>)manager { return [self initWithController:[[PGInspectorController alloc]initWithAPIManager:manager]]; } - (instancetype)initWithAPIManager:(id<PROAPIAccessing>)manager { return [self initWithController:[[PGInspectorController alloc]initWithAPIManager:manager]]; }
- (instancetype)initWithController:(PGInspectorController *)controller { - (instancetype)initWithController:(PGInspectorController *)controller {
if((self=[super initWithFrame:NSMakeRect(0,0,320,100)])){ if((self=[super initWithFrame:NSMakeRect(0,0,320,100)])){
_controller=controller;self.appearance=[NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; _controller=controller;_controller.actionSender=self;self.appearance=[NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
NSArray *sections=@[@"smooth",@"color",@"shape",@"more"],*headings=@[@"磨皮",@"美白",@"瘦脸",@"更多设置"]; NSArray *sections=@[@"smooth",@"color",@"shape",@"more"],*headings=@[@"磨皮",@"美白",@"瘦脸",@"更多设置"];
NSArray *colors=@[PGUIColor(.28,.83,.96,1),PGUIColor(.34,.89,.84,1),PGUIColor(.59,.69,.98,1),PGUIColor(.54,.64,.76,1)]; NSArray *colors=@[PGUIColor(.28,.83,.96,1),PGUIColor(.34,.89,.84,1),PGUIColor(.59,.69,.98,1),PGUIColor(.54,.64,.76,1)];
NSMutableArray *cards=[NSMutableArray new]; NSMutableArray *cards=[NSMutableArray new];
@@ -332,12 +350,15 @@ static PGInspectorGlyphButton *PGUIButton(NSString *glyph, NSColor *accent, id t
} }
_status.stringValue=_controller.statusMessage.length?_controller.statusMessage:@"自动跟随 · 无需手动分析";_status.toolTip=_status.stringValue; _status.stringValue=_controller.statusMessage.length?_controller.statusMessage:@"自动跟随 · 无需手动分析";_status.toolTip=_status.stringValue;
} }
- (BOOL)hasActiveTextEditor { for(PGInspectorCard *card in _cards)for(PGInspectorRow *row in card.rows)if(row.valueField.currentEditor)return YES;return NO; } - (BOOL)hasActiveTextEditor { for(PGInspectorCard *card in _cards)for(PGInspectorRow *row in card.rows)if(row.valueField.currentEditor && row.numberHasUnsubmittedEdit)return YES;return NO; }
- (void)refreshFromHost { if(_interactionDepth || [self hasActiveTextEditor])return;[_controller refresh];[self reloadControls]; } - (void)refreshFromHost { if(_interactionDepth || [self hasActiveTextEditor])return;[_controller refresh];[self reloadControls]; }
- (void)hostParameterChanged { if(_interactionDepth || [self hasActiveTextEditor])return;[_controller documentDidChange];[self reloadControls]; } - (void)hostParameterChanged { if(_interactionDepth || [self hasActiveTextEditor])return;[_controller documentDidChange];[self reloadControls]; }
- (void)writeValue:(double)value parameter:(UInt32)identifier { [_controller setValue:value forParameter:identifier];[self reloadControls]; } - (void)writeValue:(double)value parameter:(UInt32)identifier { [_controller setValue:value forParameter:identifier];[self reloadControls]; }
- (void)beginControlInteraction { if(_interactionDepth++==0)[_controller beginInteraction]; } // Keep refreshes out of the tracking loop, but let writeValue own a complete
- (void)endControlInteraction { if(!_interactionDepth)return;if(--_interactionDepth==0){[_controller endInteraction];[self refreshFromHost];} } // FxPlug action for each continuous step. Holding the action until mouse-up
// prevents hosts that publish at endAction from previewing intermediate values.
- (void)beginControlInteraction { _interactionDepth++; }
- (void)endControlInteraction { if(!_interactionDepth)return;if(--_interactionDepth==0)[self refreshFromHost]; }
- (void)masterChanged:(NSButton *)sender { [_controller setValue:sender.state==NSControlStateValueOn?1:0 forParameter:(UInt32)sender.tag];[self reloadControls]; } - (void)masterChanged:(NSButton *)sender { [_controller setValue:sender.state==NSControlStateValueOn?1:0 forParameter:(UInt32)sender.tag];[self reloadControls]; }
- (void)moreChanged:(NSButton *)sender { _more.expanded=sender.state==NSControlStateValueOn;sender.accessibilityLabel=_more.expanded?@"收起更多设置":@"展开更多设置";[_more setNeedsDisplay:YES];[self setFrameSize:self.frame.size]; } - (void)moreChanged:(NSButton *)sender { _more.expanded=sender.state==NSControlStateValueOn;sender.accessibilityLabel=_more.expanded?@"收起更多设置":@"展开更多设置";[_more setNeedsDisplay:YES];[self setFrameSize:self.frame.size]; }
- (void)viewDidMoveToWindow { - (void)viewDidMoveToWindow {
@@ -14,5 +14,6 @@ enum {
PGTrackData1=60, PGTrackData2=61, PGTrackData3=62, PGTrackData1=60, PGTrackData2=61, PGTrackData3=62,
PGSmoothingEnabled=70, PGColorEnabled=71, PGShapeEnabled=72, PGSmoothingEnabled=70, PGColorEnabled=71, PGShapeEnabled=72,
PGDetailEnabled=73, PGHelp=74, PGDetailEnabled=73, PGHelp=74,
PGFeatureProtectionAmount=75, PGNonSkinProtection=76, PGMicroDetail=77,
PGInspectorPanel=210 PGInspectorPanel=210
}; };
+15 -4
查看文件
@@ -30,6 +30,9 @@ static const PGSlider PGSliders[] = {
PGS(PGEyeBright,"眼睛提亮",eyeBrightening,0,1,.01,YES), PGS(PGEyeBright,"眼睛提亮",eyeBrightening,0,1,.01,YES),
PGS(PGHighPass,"高频细节平滑",highPassDetail,0,1,.01,YES), PGS(PGHighPass,"高频细节平滑",highPassDetail,0,1,.01,YES),
PGS(PGSharpness,"锐化",sharpness,0,1,.01,YES), PGS(PGSharpness,"锐化",sharpness,0,1,.01,YES),
PGS(PGFeatureProtectionAmount,"五官保护强度",featureProtectionAmount,0,1,.01,YES),
PGS(PGNonSkinProtection,"非肤色区保护",nonSkinProtection,0,1,.01,YES),
PGS(PGMicroDetail,"微细锐化",microDetail,0,1,.01,YES),
PGS(PGThin,"瘦脸",faceThin,0,1,.01,YES), PGS(PGThin,"瘦脸",faceThin,0,1,.01,YES),
PGS(PGBigEye,"大眼",faceBigEye,0,1,.01,YES), PGS(PGBigEye,"大眼",faceBigEye,0,1,.01,YES),
PGS(PGShort,"短脸",faceShort,-1,1,.01,NO), PGS(PGShort,"短脸",faceShort,-1,1,.01,NO),
@@ -141,6 +144,7 @@ static CIImage *PGImageFromTile(FxImageTile *tile) {
void (^end)(void)=^{ok=[api endParameterSubGroup]&&ok;}; void (^end)(void)=^{ok=[api endParameterSubGroup]&&ok;};
group(@"磨皮",100); toggle(@"启用磨皮",PGSmoothingEnabled,YES); group(@"磨皮",100); toggle(@"启用磨皮",PGSmoothingEnabled,YES);
slider(PGAmount); slider(PGMidtone); slider(PGRadius); toggle(@"保护五官",PGFeatureProtect,YES); end(); slider(PGAmount); slider(PGMidtone); slider(PGRadius); toggle(@"保护五官",PGFeatureProtect,YES); end();
group(@"磨皮保护与细节",106); slider(PGFeatureProtectionAmount); slider(PGNonSkinProtection); slider(PGMicroDetail); end();
group(@"肤色",101); toggle(@"启用肤色",PGColorEnabled,YES); group(@"肤色",101); toggle(@"启用肤色",PGColorEnabled,YES);
ok=[api addPopupMenuWithName:@"肤色风格" parameterID:PGTonePreset defaultValue:0 menuEntries:@[@"原色",@"自然白",@"冷白",@"暖白",@"红润白",@"小麦",@"古铜"] parameterFlags:kFxParameterFlag_HIDDEN]&&ok; ok=[api addPopupMenuWithName:@"肤色风格" parameterID:PGTonePreset defaultValue:0 menuEntries:@[@"原色",@"自然白",@"冷白",@"暖白",@"红润白",@"小麦",@"古铜"] parameterFlags:kFxParameterFlag_HIDDEN]&&ok;
slider(PGBrightness); slider(PGHue); slider(PGSaturation); slider(PGEvenTone); slider(PGTeeth); slider(PGEyeBright); end(); slider(PGBrightness); slider(PGHue); slider(PGSaturation); slider(PGEvenTone); slider(PGTeeth); slider(PGEyeBright); end();
@@ -207,7 +211,7 @@ static CIImage *PGImageFromTile(FxImageTile *tile) {
double x=.5,y=.5; [api getXValue:&x YValue:&y fromParameter:PGSelection atTime:time]; double x=.5,y=.5; [api getXValue:&x YValue:&y fromParameter:PGSelection atTime:time];
s.selectionX=isfinite(x)?fmin(1,fmax(0,x)):.5; s.selectionY=isfinite(y)?fmin(1,fmax(0,y)):.5; s.selectionX=isfinite(x)?fmin(1,fmax(0,x)):.5; s.selectionY=isfinite(y)?fmin(1,fmax(0,y)):.5;
BOOL enabled=YES; BOOL enabled=YES;
[api getBoolValue:&enabled fromParameter:PGSmoothingEnabled atTime:time]; if(!enabled) s.amount=s.midtoneDetail=0; [api getBoolValue:&enabled fromParameter:PGSmoothingEnabled atTime:time]; if(!enabled) s.amount=s.midtoneDetail=s.microDetail=0;
enabled=YES; [api getBoolValue:&enabled fromParameter:PGColorEnabled atTime:time]; enabled=YES; [api getBoolValue:&enabled fromParameter:PGColorEnabled atTime:time];
if(!enabled) {s.skinBrightness=s.skinHue=s.skinSaturation=s.skinEvenTone=s.teethWhitening=s.eyeBrightening=0;s.skinTonePreset=0;} if(!enabled) {s.skinBrightness=s.skinHue=s.skinSaturation=s.skinEvenTone=s.teethWhitening=s.eyeBrightening=0;s.skinTonePreset=0;}
enabled=YES; [api getBoolValue:&enabled fromParameter:PGDetailEnabled atTime:time]; if(!enabled) s.highPassDetail=s.sharpness=0; enabled=YES; [api getBoolValue:&enabled fromParameter:PGDetailEnabled atTime:time]; if(!enabled) s.highPassDetail=s.sharpness=0;
@@ -263,9 +267,16 @@ static CIImage *PGImageFromTile(FxImageTile *tile) {
- (BOOL)renderDestinationImage:(FxImageTile *)destination sourceImages:(NSArray<FxImageTile *> *)sources pluginState:(NSData *)state atTime:(CMTime)time error:(NSError **)error { - (BOOL)renderDestinationImage:(FxImageTile *)destination sourceImages:(NSArray<FxImageTile *> *)sources pluginState:(NSData *)state atTime:(CMTime)time error:(NSError **)error {
if(sources.count==0||!sources.firstObject.ioSurface||!destination.ioSurface||![state isKindOfClass:NSData.class]||state.length==0||state.length>320*1024*1024) return PGFail(error,@"宿主传入的画面或状态无效。"); if(sources.count==0||!sources.firstObject.ioSurface||!destination.ioSurface||![state isKindOfClass:NSData.class]||state.length==0||state.length>320*1024*1024) return PGFail(error,@"宿主传入的画面或状态无效。");
NSDictionary *plist=[NSPropertyListSerialization propertyListWithData:state options:NSPropertyListImmutable format:nil error:error]; NSDictionary *plist=[NSPropertyListSerialization propertyListWithData:state options:NSPropertyListImmutable format:nil error:error];
if(![plist isKindOfClass:NSDictionary.class]||![plist[@"settings"] isKindOfClass:NSData.class]||[plist[@"settings"] length]!=sizeof(PGBeautySettings)) return PGFail(error,@"渲染状态版本无效。"); if(![plist isKindOfClass:NSDictionary.class]||![plist[@"settings"] isKindOfClass:NSData.class]) return PGFail(error,@"渲染状态版本无效。");
PGBeautySettings s;[plist[@"settings"] getBytes:&s length:sizeof(s)]; NSData *encoded=plist[@"settings"]; uint32_t version=0;
if(s.version!=1) return PGFail(error,@"此版本不支持保存的渲染状态。"); if(encoded.length<sizeof(version)) return PGFail(error,@"渲染状态版本无效。");
[encoded getBytes:&version length:sizeof(version)];
PGBeautySettings s=PGBeautyDefaults();
if(version==1 && encoded.length==PGBeautySettingsV1Size) {
[encoded getBytes:&s length:PGBeautySettingsV1Size];s.version=PGBeautySettingsVersion;
} else if(version==PGBeautySettingsVersion && encoded.length==sizeof(s)) {
[encoded getBytes:&s length:sizeof(s)];
} else return PGFail(error,@"此版本不支持保存的渲染状态。");
s.trackingEnabled=0;s.singleFace=0; s.trackingEnabled=0;s.singleFace=0;
CIImage *input=PGImageFromTile(sources.firstObject); if(!input) return PGFail(error,@"无法读取 IOSurface。"); CIImage *input=PGImageFromTile(sources.firstObject); if(!input) return PGFail(error,@"无法读取 IOSurface。");
@synchronized(self) { @synchronized(self) {
@@ -1,34 +1,45 @@
#import "AppDelegate.h" #import "AppDelegate.h"
#import <CoreServices/CoreServices.h>
@interface AppDelegate () @interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window; @property (weak) IBOutlet NSWindow *window;
@property (strong) NSTimer *exitTimer;
@end @end
@implementation AppDelegate @implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)notification { - (void)applicationDidFinishLaunching:(NSNotification *)notification {
self.window.title=@"大鱼人像美化"; self.window.title = @"大鱼人像美化 · 免费开源";
[self.window setContentSize:NSMakeSize(600,360)]; [self.window setContentSize:NSMakeSize(800, 450)];
NSView *content=[NSView new];self.window.contentView=content; self.window.styleMask &= ~NSWindowStyleMaskResizable;
NSStackView *stack=[NSStackView new];stack.orientation=NSUserInterfaceLayoutOrientationVertical; self.window.backgroundColor = [NSColor colorWithRed:0.94 green:0.92 blue:0.85 alpha:1];
stack.alignment=NSLayoutAttributeLeading;stack.spacing=16;stack.translatesAutoresizingMaskIntoConstraints=NO; NSImageView *card = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, 800, 450)];
[content addSubview:stack]; card.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[NSLayoutConstraint activateConstraints:@[[stack.leadingAnchor constraintEqualToAnchor:content.leadingAnchor constant:32],[stack.trailingAnchor constraintEqualToAnchor:content.trailingAnchor constant:-32],[stack.topAnchor constraintEqualToAnchor:content.topAnchor constant:30]]]; card.imageScaling = NSImageScaleProportionallyUpOrDown;
NSTextField *title=[NSTextField labelWithString:@"大鱼人像美化"]; NSURL *artwork = [NSBundle.mainBundle URLForResource:@"LauncherInfo" withExtension:@"png"];
title.font=[NSFont systemFontOfSize:28 weight:NSFontWeightSemibold];[stack addArrangedSubview:title]; card.image = [[NSImage alloc] initWithContentsOfURL:artwork];
NSTextField *subtitle=[NSTextField labelWithString:@"beatygril · FxPlug 4"]; card.accessibilityLabel = @"大鱼人像美化,免费开源,自动注册,无需激活码。主程序启动三秒后自动退出;Final Cut Pro 和 Motion 中的滤镜继续独立运行。";
subtitle.textColor=NSColor.secondaryLabelColor;[stack addArrangedSubview:subtitle]; self.window.contentView = card;
NSTextField *description=[NSTextField wrappingLabelWithString:@"在 Motion 的滤镜资源库中选择「大鱼 → 大鱼人像美化」。Final Cut Pro 的效果浏览器中也可使用配套效果。\n\n美化会随画面人脸自动更新,无需先点分析。脸型默认跟随主要人脸,多人模式可处理多张脸。启用「只处理选中人脸」后,可点击画面更换目标。向前/向后分析为可选功能,结果可随工程保存。"]; if (!card.image) {
description.font=[NSFont systemFontOfSize:13];[stack addArrangedSubview:description]; NSTextField *fallback = [NSTextField wrappingLabelWithString:card.accessibilityLabel];
NSStackView *buttons=[NSStackView new];buttons.orientation=NSUserInterfaceLayoutOrientationHorizontal;buttons.spacing=12; fallback.frame = NSMakeRect(48, 160, 704, 130);
[buttons addArrangedSubview:[NSButton buttonWithTitle:@"打开 Motion" target:self action:@selector(openMotion:)]]; fallback.font = [NSFont systemFontOfSize:24 weight:NSFontWeightSemibold];
[buttons addArrangedSubview:[NSButton buttonWithTitle:@"打开 Final Cut Pro" target:self action:@selector(openFinalCut:)]]; [card addSubview:fallback];
[stack addArrangedSubview:buttons]; }
NSTextField *note=[NSTextField wrappingLabelWithString:@"建议先调高中频磨皮,再按需调节肤色与脸型。肤色风格为本插件独立调色预设。"];
note.textColor=NSColor.secondaryLabelColor;note.font=[NSFont systemFontOfSize:11];[stack addArrangedSubview:note];
[self.window center]; [self.window center];
[self.window makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
// Only this launcher exits. The FxPlug service has its own process/lifetime.
self.exitTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 repeats:NO block:^(NSTimer *timer) {
[NSApp terminate:nil];
}];
// Re-register our own bundle. There is no paid activation or account step.
NSURL *bundleURL = NSBundle.mainBundle.bundleURL;
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
OSStatus status = LSRegisterURL((__bridge CFURLRef)bundleURL, true);
if (status != noErr) NSLog(@"LaunchServices registration status: %d", (int)status);
});
} }
- (void)openMotion:(id)sender {[self openApplication:@"com.apple.motionapp"];} - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
- (void)openFinalCut:(id)sender {[self openApplication:@"com.apple.FinalCut"];} return YES;
- (void)openApplication:(NSString *)identifier {
NSURL *url=[NSWorkspace.sharedWorkspace URLForApplicationWithBundleIdentifier:identifier];
if(url) [NSWorkspace.sharedWorkspace openApplicationAtURL:url configuration:NSWorkspaceOpenConfiguration.configuration completionHandler:nil];
} }
@end @end
@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.1.0</string> <string>1.3.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>9</string> <string>15</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string> <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 2.9 MiB

+23
查看文件
@@ -0,0 +1,23 @@
# GitHub 同步与恢复
公开源码:https://github.com/FAMEDaYu/FCP-BeatyGril
正式安装包:https://github.com/FAMEDaYu/FCP-BeatyGril/releases/tag/v1.2.0
本地 `github` 远端指向上述 GitHub 仓库,`origin` 继续指向大鱼仓库,`main` 仍跟随 `origin/main`。当前项目的完整提交历史、main 和七个版本标签已推送,两端引用与本地一致;未改写历史或覆盖标签。后续更新需要分别推送到 origin 和 github,不会自动定时同步。
## 已验证的 GitHub 恢复节点
匿名恢复提交:`356683b41af702d6c0143ad7fa5f540d752d6e14`。在关闭凭据助手和交互登录的独立临时目录中成功克隆 GitHub,197 个受跟踪文件逐字节一致、七个标签引用一致,strict/full fsck 通过。正式 PKG 的源码内副本与 GitHub Release 匿名下载副本 SHA-256 相同,下载副本的 Installer 签名与公证票据通过。后续 main 提交补充文章和验证记录,产品源码与该恢复节点一致。
安装包:`Dayu-Portrait-1.2.0.pkg`,5,011,005 bytes,SHA-256 `5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243`。Release 标签 `v1.2.0` 仍指向 `3c7261c3a861b9f4704cfb36055d7b500c239dab`,没有重新编译或改动正式安装包。
```sh
git clone https://github.com/FAMEDaYu/FCP-BeatyGril.git
cd FCP-BeatyGril
git switch --detach 356683b41af702d6c0143ad7fa5f540d752d6e14
```
本项目没有 LFS 或子模块。编译仍需自行安装 Xcode 和 Apple FxPlug SDK;签名私钥与公证凭据不在 Git 内。GitHub 公共克隆无需登录;大鱼备份仍受站点登录和会员网关限制。两边都只承诺已经提交、推送并核验的节点。
源代码编写署名:代码由 OpenAI + Codex 全程编写,站长仅参与调试和测试。
+1
查看文件
@@ -0,0 +1 @@
{"artifacts":[{"architecture":"arm64","digest":{"sha256":"f01e8c0b7e2676b2961950b0e48efdd2589af218e4b36de7d39f5d1c76852bfb"},"format":"mach-o"}],"captures":[],"environments":[],"providers":[{"id":"ghidra","name":"Ghidra","version":"12.1.4"}],"records":[{"analysis_profile":{"digest":"20565088524a2d0359b9b96f46ac48e679d774c7b0092c56abc06de8fdbec11c","parameters":{"analyzer_preset":"ghidra-default","annotation_policy":"atomic-function-entry-metadata-v1","architecture":"arm64","available_architectures":["arm64"],"compiler_spec_id":"auto-default","decompiler_jump_loads":true,"function_body_evidence":"complete-inclusive-ranges-v1","function_boundary_observations":"ghidra-terminal-call-limitations-v1","function_references":"complete-body-and-entry-reference-manager-v2","import_mode":"ephemeral-source-immutable","instruction_flow_evidence":"decoded-return-pcode-v1","jump_table_evidence":"typed-case-default-blocks-v1","language_id":"auto-from-header","load_image_observations":"source-mappings-entry-context-v2","loader":"auto-from-header","location_resolution":"explicit-address-exact-entry-symbol-first-v3","no_return_repair":"returning-imports-decoded-return-v2","process_launch":"inspected-jvm-launch-support-v1","string_inventory_evidence":"defined-data-coverage-v1","target_format":"mach-o","target_kind":"executable"},"provider":{"id":"ghidra","name":"Ghidra","version":"12.1.4"}},"authority":"shipped-artifact","confidence":"observed","environment":null,"evidence_id":"ev_8bc31392c07788d2482546121297c3f177d527282275ef21fd3e5edef9921544","evidence_links":[],"limitations":["The session serves operations only after Ghidra reports default auto-analysis complete; incomplete analysis does not expose partial results.","The imported Program and temporary project are ephemeral and deleted on close. Annotation operations edit session database metadata; original executable bytes are never written.","Cancelling an active Ghidra request terminates its ephemeral database and discards session annotations. The selected target remains open; the next provider query imports the original artifact again.","Default-space addresses use lowercase 0x-prefixed hexadecimal; other address spaces use <percent-encoded-space>:0x<hex>.","Assembly is Ghidra Listing text and does not claim textual equivalence with Hopper output.","macOS sessions require a matching executable Ghidra native decompiler; REA checks for it but does not build native components or change Gatekeeper quarantine state."],"locations":[],"normalized_result":"0x1000279f4: stp d9, d8, [sp, #-0x30]!\n0x1000279f8: stp x20, x19, [sp, #0x10]\n0x1000279fc: stp x29, x30, [sp, #0x20]\n0x100027a00: add x29, sp, #0x20\n0x100027a04: fmov d8, d0\n0x100027a08: str xzr, [x8, #0x20]\n0x100027a0c: movi v0.2D, #0x0\n0x100027a10: stp q0, q0, [x8]\n0x100027a14: cbz x0, 0x100027bac\n0x100027a18: mov x20, x0\n0x100027a1c: mov x19, x8\n0x100027a20: bl 0x10001a8c0\n0x100027a24: cbz w0, 0x100027bac\n0x100027a28: fmov d1, 0x3ff0000000000000\n0x100027a2c: fcmp d8, d1\n0x100027a30: fcsel d2, d1, d8, gt\n0x100027a34: fcmp d8, #0.0\n0x100027a38: movi d0, #0x0\n0x100027a3c: fcsel d2, d0, d2, mi\n0x100027a40: fcvt s2, d2\n0x100027a44: ldr d3, [x20, #0x80]\n0x100027a48: fcmp d3, d1\n0x100027a4c: fcsel d4, d1, d3, gt\n0x100027a50: fmov d5, -0x4010000000000000\n0x100027a54: fcmp d3, d5\n0x100027a58: fcsel d4, d5, d4, mi\n0x100027a5c: fcmp d4, #0.0\n0x100027a60: cset w8, gt\n0x100027a64: fcvt d3, s2\n0x100027a68: ldp d5, d2, [x20, #0x60]\n0x100027a6c: fcmp d2, d1\n0x100027a70: fcsel d6, d1, d2, gt\n0x100027a74: adrp x9, 0x10005f000\n0x100027a78: ldr d7, [x9, #0xb80]\n0x100027a7c: fmul d6, d6, d7\n0x100027a80: fcmp d2, #0.0\n0x100027a84: fcsel d2, d0, d6, mi\n0x100027a88: fmul d2, d2, d3\n0x100027a8c: fcvt s2, d2\n0x100027a90: add x9, x20, #0x78\n0x100027a94: ldur q6, [x20, #0x88]\n0x100027a98: ld1 v5, x9, \n0x100027a9c: adrp x9, 0x10005f000\n0x100027aa0: ldr q7, [x9, #0x980]\n0x100027aa4: fcmgt v7.2D, v7.2D, v5.2D\n0x100027aa8: fcmlt v16.2D, v6.2D\n0x100027aac: fmov v17.2D, #0x3ff0000000000000\n0x100027ab0: fcmgt v18.2D, v5.2D, v17.2D\n0x100027ab4: bit v5.16B, v17.16B, v18.16B\n0x100027ab8: fcmgt v18.2D, v6.2D, v17.2D\n0x100027abc: bit v6.16B, v17.16B, v18.16B\n0x100027ac0: adrp x9, 0x10005f000\n0x100027ac4: ldr q18, [x9, #0x990]\n0x100027ac8: fmul v5.2D, v5.2D, v18.2D\n0x100027acc: adrp x9, 0x10005f000\n0x100027ad0: ldr q18, [x9, #0x9a0]\n0x100027ad4: fmul v6.2D, v6.2D, v18.2D\n0x100027ad8: adrp x9, 0x10005f000\n0x100027adc: ldr q18, [x9, #0x9b0]\n0x100027ae0: bit v5.16B, v18.16B, v7.16B\n0x100027ae4: bic v6.16B, v6.16B, v16.16B\n0x100027ae8: fmul v6.2D, v6.2D, v3.D[0x0]\n0x100027aec: fmul v5.2D, v5.2D, v3.D[0x0]\n0x100027af0: fcvtn v5.2S, v5.2D\n0x100027af4: fcvtn2 v5.4S, v6.2D\n0x100027af8: ldr d6, [x20, #0x98]\n0x100027afc: fcmp d6, d1\n0x100027b00: fcsel d7, d1, d6, gt\n0x100027b04: adrp x9, 0x10005f000\n0x100027b08: ldr d16, [x9, #0xe68]\n0x100027b0c: fmul d7, d7, d16\n0x100027b10: fcmp d6, #0.0\n0x100027b14:Line truncated
+371
查看文件
@@ -0,0 +1,371 @@
Source AIR SHA256: f97705b88f5491057df2117aef457ffca84e11020574cd57742b0670db4484d8
Line numbers refer to the complete original metal-objdump text. Static IR; original shader not executed.
583: define internal fastcc <2 x float> @_ZL25mssFaceShapePinCoordinateDv2_fPU11MTLconstantK16MSSFaceThinPointi18MSSFaceShapeParamsS_(<2 x float> %0, %struct.MSSFaceThinPoint addrspace(2)* nocapture readonly %1, i32 %2, float %3, float %4, float %5, float %6, float %7, float %8, float %9, float %10, float %11, float %12, <2 x float> %13) unnamed_addr #2 {
584: %15 = alloca [17 x <3 x i32>], align 16
585: %16 = alloca [16 x <2 x i32>], align 8
586: %17 = alloca [4 x <2 x i32>], align 8
587: %18 = alloca [6 x <3 x i32>], align 16
588: %19 = alloca [6 x <2 x i32>], align 8
589: %20 = alloca [3 x <2 x i32>], align 8
590: %21 = alloca [11 x i32], align 4
591: %22 = alloca [11 x <2 x float>], align 8
592: %23 = add nsw i32 %2, 75
593: %24 = sext i32 %23 to i64
594: %25 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %24, i32 0
595: %26 = load <2 x float>, <2 x float> addrspace(2)* %25, align 8, !tbaa !62
596: %27 = add nsw i32 %2, 59
597: %28 = sext i32 %27 to i64
598: %29 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %28, i32 0
599: %30 = load <2 x float>, <2 x float> addrspace(2)* %29, align 8, !tbaa !62
600: %31 = add nsw i32 %2, 67
601: %32 = sext i32 %31 to i64
602: %33 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %32, i32 0
603: %34 = load <2 x float>, <2 x float> addrspace(2)* %33, align 8, !tbaa !62
604: %35 = add nsw i32 %2, 74
605: %36 = sext i32 %35 to i64
606: %37 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %36, i32 0
607: %38 = load <2 x float>, <2 x float> addrspace(2)* %37, align 8, !tbaa !62
608: %39 = add nsw i32 %2, 60
609: %40 = sext i32 %39 to i64
610: %41 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %40, i32 0
611: %42 = load <2 x float>, <2 x float> addrspace(2)* %41, align 8, !tbaa !62
612: %43 = fadd fast <2 x float> %42, %38
613: %44 = fmul fast <2 x float> %43, <float 5.000000e-01, float 5.000000e-01>
614: %45 = fsub fast <2 x float> %26, %30
615: %46 = fmul fast <2 x float> %45, %13
616: %47 = tail call fast float @air.dot.v2f32(<2 x float> %46, <2 x float> %46) #3
617: %48 = tail call fast float @air.fast_sqrt.f32(float %47) #3
618: %49 = fsub fast <2 x float> %34, %44
619: %50 = fmul fast <2 x float> %49, %13
620: %51 = tail call fast float @air.dot.v2f32(<2 x float> %50, <2 x float> %50) #3
621: %52 = tail call fast float @air.fast_sqrt.f32(float %51) #3
622: %53 = fmul fast float %52, 2.000000e+00
623: %54 = tail call fast float @air.fast_fmax.f32(float %48, float %53) #3
624: %55 = tail call fast float @air.fast_fmax.f32(float %54, float 1.000000e+00) #3
625: %56 = fdiv fast float 2.800000e+02, %55
626: %57 = tail call fast float @air.fast_clamp.f32(float %56, float 1.000000e+00, float 2.250000e+00) #3
627: %58 = fmul fast float %57, %3
628: %59 = fmul fast float %57, %4
629: %60 = fmul fast float %57, %5
630: %61 = fmul fast float %57, %6
631: %62 = fmul fast float %57, %7
632: %63 = fmul fast float %57, %8
633: %64 = fmul fast float %57, %9
634: %65 = tail call fast float @air.fast_fabs.f32(float %58) #3
635: %66 = fcmp fast ogt float %65, 0x3EB0C6F7A0000000
899: 251: ; preds = %212, %200
900: %252 = phi <2 x float> [ %248, %212 ], [ %201, %200 ]
901: %253 = tail call fast float @air.fast_fabs.f32(float %61) #3
902: %254 = fcmp fast ogt float %253, 0x3EB0C6F7A0000000
903: br i1 %254, label %255, label %309
904:
905: 255: ; preds = %251
906: %256 = bitcast [6 x <3 x i32>]* %18 to i8*
907: call void @llvm.lifetime.start.p0i8(i64 96, i8* nonnull %256) #8
908: %257 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 0
909: store <3 x i32> <i32 72, i32 71, i32 29>, <3 x i32>* %257, align 16
910: %258 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 1
911: store <3 x i32> <i32 62, i32 63, i32 29>, <3 x i32>* %258, align 16
912: %259 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 2
913: store <3 x i32> <i32 71, i32 70, i32 29>, <3 x i32>* %259, align 16
914: %260 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 3
915: store <3 x i32> <i32 63, i32 64, i32 29>, <3 x i32>* %260, align 16
916: %261 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 4
917: store <3 x i32> <i32 70, i32 71, i32 29>, <3 x i32>* %261, align 16
918: %262 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 5
919: store <3 x i32> <i32 64, i32 63, i32 29>, <3 x i32>* %262, align 16
920: %263 = insertelement <2 x float> undef, float %61, i64 0
921: %264 = shufflevector <2 x float> %263, <2 x float> undef, <2 x i32> zeroinitializer
922: br label %266
923:
924: 265: ; preds = %305
925: call void @llvm.lifetime.end.p0i8(i64 96, i8* nonnull %256) #8
926: br label %309
927:
928: 266: ; preds = %305, %255
929: %267 = phi <2 x float> [ %252, %255 ], [ %306, %305 ]
930: %268 = phi i32 [ 0, %255 ], [ %307, %305 ]
931: %269 = zext i32 %268 to i64
932: %270 = getelementptr inbounds [6 x <3 x i32>], [6 x <3 x i32>]* %18, i64 0, i64 %269
933: %271 = load <3 x i32>, <3 x i32>* %270, align 16
934: %272 = extractelement <3 x i32> %271, i64 0
935: %273 = add nsw i32 %272, %2
936: %274 = sext i32 %273 to i64
937: %275 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %274, i32 0
938: %276 = load <2 x float>, <2 x float> addrspace(2)* %275, align 8, !tbaa !62
939: %277 = extractelement <3 x i32> %271, i64 1
940: %278 = add nsw i32 %277, %2
941: %279 = sext i32 %278 to i64
942: %280 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %279, i32 0
943: %281 = load <2 x float>, <2 x float> addrspace(2)* %280, align 8, !tbaa !62
944: %282 = fsub fast <2 x float> %276, %281
945: %283 = tail call fast float @air.dot.v2f32(<2 x float> %282, <2 x float> %282) #3
946: %284 = tail call fast float @air.fast_sqrt.f32(float %283) #3
947: %285 = fcmp fast ugt float %284, 0x3F1A36E2E0000000
948: br i1 %285, label %286, label %305
949:
950: 286: ; preds = %266
951: %287 = extractelement <3 x i32> %271, i64 2
952: %288 = add nsw i32 %287, %2
953: %289 = sext i32 %288 to i64
954: %290 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %289, i32 0
955: %291 = load <2 x float>, <2 x float> addrspace(2)* %290, align 8, !tbaa !62
956: %292 = fsub fast <2 x float> %291, %276
957: %293 = fsub fast <2 x float> %267, %276
958: %294 = tail call fast float @air.dot.v2f32(<2 x float> %293, <2 x float> %293) #3
959: %295 = tail call fast float @air.fast_sqrt.f32(float %294) #3
960: %296 = fdiv fast float %295, %284
961: %297 = fsub fast float 1.000000e+00, %296
962: %298 = tail call fast float @air.fast_clamp.f32(float %297, float 0.000000e+00, float 1.000000e+00) #3
963: %299 = insertelement <2 x float> undef, float %298, i64 0
964: %300 = shufflevector <2 x float> %299, <2 x float> undef, <2 x i32> zeroinitializer
965: %301 = fmul fast <2 x float> %292, %264
966: %302 = fmul fast <2 x float> %301, %300
967: %303 = fsub fast <2 x float> %267, %302
968: %304 = tail call fast <2 x float> @air.fast_clamp.v2f32(<2 x float> %303, <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00>) #3
969: br label %305
970:
971: 305: ; preds = %286, %266
972: %306 = phi <2 x float> [ %304, %286 ], [ %267, %266 ]
973: %307 = add nuw nsw i32 %268, 1
974: %308 = icmp eq i32 %307, 6
975: br i1 %308, label %265, label %266, !llvm.loop !67
976:
977: 309: ; preds = %265, %251
978: %310 = phi <2 x float> [ %306, %265 ], [ %252, %251 ]
979: %311 = tail call fast float @air.fast_fabs.f32(float %62) #3
980: %312 = fcmp fast ogt float %311, 0x3EB0C6F7A0000000
981: br i1 %312, label %313, label %372
982:
983: 313: ; preds = %309
984: %314 = bitcast [6 x <2 x i32>]* %19 to i8*
985: call void @llvm.lifetime.start.p0i8(i64 48, i8* nonnull %314) #8
986: %315 = getelementptr inbounds [6 x <2 x i32>], [6 x <2 x i32>]* %19, i64 0, i64 0
1127: 422: ; preds = %383, %372
1128: %423 = phi <2 x float> [ %419, %383 ], [ %373, %372 ]
1129: %424 = tail call fast float @air.fast_fabs.f32(float %64) #3
1130: %425 = fcmp fast ogt float %424, 0x3EB0C6F7A0000000
1131: br i1 %425, label %426, label %585
1132:
1133: 426: ; preds = %422
1134: %427 = bitcast [11 x i32]* %21 to i8*
1135: call void @llvm.lifetime.start.p0i8(i64 44, i8* nonnull %427) #8
1136: %428 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 0
1137: store i32 62, i32* %428, align 4
1138: %429 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 1
1139: store i32 63, i32* %429, align 4
1140: %430 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 2
1141: store i32 64, i32* %430, align 4
1142: %431 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 3
1143: store i32 65, i32* %431, align 4
1144: %432 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 4
1145: store i32 66, i32* %432, align 4
1146: %433 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 5
1147: store i32 67, i32* %433, align 4
1148: %434 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 6
1149: store i32 68, i32* %434, align 4
1150: %435 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 7
1151: store i32 69, i32* %435, align 4
1152: %436 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 8
1153: store i32 70, i32* %436, align 4
1154: %437 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 9
1155: store i32 71, i32* %437, align 4
1156: %438 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 10
1157: store i32 72, i32* %438, align 4
1158: %439 = add nsw i32 %2, 46
1159: %440 = sext i32 %439 to i64
1160: %441 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %440, i32 0
1161: %442 = load <2 x float>, <2 x float> addrspace(2)* %441, align 8, !tbaa !62
1162: %443 = add nsw i32 %2, 48
1163: %444 = sext i32 %443 to i64
1164: %445 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %444, i32 0
1165: %446 = load <2 x float>, <2 x float> addrspace(2)* %445, align 8, !tbaa !62
1166: %447 = bitcast [11 x <2 x float>]* %22 to i8*
1167: call void @llvm.lifetime.start.p0i8(i64 88, i8* nonnull %447) #8
1168: br label %492
1169:
1170: 448: ; preds = %492
1171: %449 = fsub fast <2 x float> %442, %446
1172: %450 = extractelement <2 x float> %423, i64 1
1173: %451 = extractelement <2 x float> %423, i64 0
1174: %452 = getelementptr inbounds [11 x <2 x float>], [11 x <2 x float>]* %22, i64 0, i64 10
1175: %453 = load <2 x float>, <2 x float>* %452, align 8, !tbaa !62
1176: br label %454
1177:
1178: 454: ; preds = %484, %448
1179: %455 = phi <2 x float> [ %453, %448 ], [ %460, %484 ]
1180: %456 = phi i8 [ 0, %448 ], [ %485, %484 ]
1181: %457 = phi i32 [ 0, %448 ], [ %486, %484 ]
1182: %458 = zext i32 %457 to i64
1183: %459 = getelementptr inbounds [11 x <2 x float>], [11 x <2 x float>]* %22, i64 0, i64 %458
1184: %460 = load <2 x float>, <2 x float>* %459, align 8, !tbaa !62
1185: %461 = extractelement <2 x float> %455, i64 1
1186: %462 = extractelement <2 x float> %460, i64 1
1187: %463 = fcmp fast ule float %462, %450
1188: %464 = fcmp fast ogt float %461, %450
1189: %465 = xor i1 %463, %464
1190: br i1 %465, label %484, label %466
1191:
1192: 466: ; preds = %454
1193: %467 = fsub fast float %461, %462
1194: %468 = tail call fast float @air.fast_fabs.f32(float %467) #3
1195: %469 = fcmp fast ugt float %468, 0x3EB0C6F7A0000000
1196: %470 = fcmp fast olt float %467, 0.000000e+00
1197: %471 = select fast i1 %470, float 0xBEB0C6F7A0000000, float 0x3EB0C6F7A0000000
1198: %472 = select i1 %469, float %467, float %471
1199: %473 = extractelement <2 x float> %455, i64 0
1200: %474 = extractelement <2 x float> %460, i64 0
1201: %475 = fsub fast float %473, %474
1202: %476 = fsub fast float %450, %462
1203: %477 = fmul fast float %475, %476
1204: %478 = fdiv fast float %477, %472
1205: %479 = fadd fast float %478, %474
1206: %480 = fcmp fast olt float %451, %479
1207: br i1 %480, label %481, label %484
1208:
1209: 481: ; preds = %466
1210: %482 = and i8 %456, 1
1211: %483 = xor i8 %482, 1
1212: br label %484
1213:
1214: 484: ; preds = %481, %466, %454
1215: %485 = phi i8 [ %483, %481 ], [ %456, %466 ], [ %456, %454 ]
1216: %486 = add nuw nsw i32 %457, 1
1217: %487 = icmp eq i32 %486, 11
1218: br i1 %487, label %488, label %454, !llvm.loop !70
1219:
1220: 488: ; preds = %484
1221: %489 = getelementptr inbounds [11 x <2 x float>], [11 x <2 x float>]* %22, i64 0, i64 0
1222: %490 = and i8 %485, 1
1223: %491 = load <2 x float>, <2 x float>* %489, align 8, !tbaa !62
1224: br label %506
1225:
1226: 492: ; preds = %492, %426
1227: %493 = phi i32 [ 0, %426 ], [ %502, %492 ]
1228: %494 = zext i32 %493 to i64
1229: %495 = getelementptr inbounds [11 x i32], [11 x i32]* %21, i64 0, i64 %494
1230: %496 = load i32, i32* %495, align 4, !tbaa !53
1231: %497 = add nsw i32 %496, %2
1232: %498 = sext i32 %497 to i64
1233: %499 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %498, i32 0
1234: %500 = load <2 x float>, <2 x float> addrspace(2)* %499, align 8, !tbaa !62
1235: %501 = getelementptr inbounds [11 x <2 x float>], [11 x <2 x float>]* %22, i64 0, i64 %494
1236: store <2 x float> %500, <2 x float>* %501, align 8, !tbaa !62
1237: %502 = add nuw nsw i32 %493, 1
1238: %503 = icmp eq i32 %502, 11
1239: br i1 %503, label %448, label %492, !llvm.loop !71
1240:
1241: 504: ; preds = %531
1242: %505 = icmp eq i8 %490, 0
1243: br i1 %505, label %559, label %540
1244:
1245: 506: ; preds = %531, %488
1246: %507 = phi i32 [ 0, %488 ], [ %513, %531 ]
1247: %508 = phi <2 x float> [ %491, %488 ], [ %538, %531 ]
1248: %509 = phi float [ 1.000000e+01, %488 ], [ %537, %531 ]
1249: %510 = zext i32 %507 to i64
1250: %511 = getelementptr inbounds [11 x <2 x float>], [11 x <2 x float>]* %22, i64 0, i64 %510
1251: %512 = load <2 x float>, <2 x float>* %511, align 8, !tbaa !62
1252: %513 = add nuw nsw i32 %507, 1
1253: %514 = trunc i32 %513 to i8
1254: %515 = urem i8 %514, 11
1255: %516 = zext i8 %515 to i64
1256: %517 = getelementptr inbounds [11 x <2 x float>], [11 x <2 x float>]* %22, i64 0, i64 %516
1257: %518 = load <2 x float>, <2 x float>* %517, align 8, !tbaa !62
1258: %519 = fsub fast <2 x float> %518, %512
1259: %520 = tail call fast float @air.dot.v2f32(<2 x float> %519, <2 x float> %519) #3
1260: %521 = fcmp fast ugt float %520, 0x3EB0C6F7A0000000
1261: br i1 %521, label %522, label %531
1262:
1263: 522: ; preds = %506
1264: %523 = fsub fast <2 x float> %423, %512
1265: %524 = tail call fast float @air.dot.v2f32(<2 x float> %523, <2 x float> %519) #3
1266: %525 = fdiv fast float %524, %520
1267: %526 = tail call fast float @air.fast_clamp.f32(float %525, float 0.000000e+00, float 1.000000e+00) #3
1268: %527 = insertelement <2 x float> undef, float %526, i64 0
1269: %528 = shufflevector <2 x float> %527, <2 x float> undef, <2 x i32> zeroinitializer
1270: %529 = fmul fast <2 x float> %528, %519
1271: %530 = fadd fast <2 x float> %529, %512
1272: br label %531
1273:
1274: 531: ; preds = %522, %506
1275: %532 = phi <2 x float> [ %530, %522 ], [ %512, %506 ]
1276: %533 = fsub fast <2 x float> %423, %532
1277: %534 = tail call fast float @air.dot.v2f32(<2 x float> %533, <2 x float> %533) #3
1278: %535 = tail call fast float @air.fast_sqrt.f32(float %534) #3
1279: %536 = fcmp fast olt float %535, %509
1280: %537 = select i1 %536, float %535, float %509
1281: %538 = select i1 %536, <2 x float> %532, <2 x float> %508
1282: %539 = icmp eq i32 %513, 11
1283: br i1 %539, label %504, label %506, !llvm.loop !72
1284:
1285: 540: ; preds = %504
1286: %541 = fsub fast <2 x float> <float -0.000000e+00, float -0.000000e+00>, %449
1287: %542 = tail call fast float @air.dot.v2f32(<2 x float> %541, <2 x float> %541) #3
1288: %543 = tail call fast float @air.fast_sqrt.f32(float %542) #3
1289: %544 = fcmp fast ugt float %543, 0x3F1A36E2E0000000
1290: br i1 %544, label %545, label %583
1291:
1292: 545: ; preds = %540
1293: %546 = tail call fast float @air.dot.v2f32(<2 x float> zeroinitializer, <2 x float> zeroinitializer) #3
1294: %547 = tail call fast float @air.fast_sqrt.f32(float %546) #3
1295: %548 = fdiv fast float %547, %543
1296: %549 = fsub fast float 1.000000e+00, %548
1297: %550 = tail call fast float @air.fast_clamp.f32(float %549, float 0.000000e+00, float 1.000000e+00) #3
1298: %551 = insertelement <2 x float> undef, float %550, i64 0
1299: %552 = shufflevector <2 x float> %551, <2 x float> undef, <2 x i32> zeroinitializer
1300: %553 = insertelement <2 x float> undef, float %64, i64 0
1301: %554 = shufflevector <2 x float> %553, <2 x float> undef, <2 x i32> zeroinitializer
1302: %555 = fmul fast <2 x float> %449, %554
1303: %556 = fmul fast <2 x float> %555, %552
1304: %557 = fsub fast <2 x float> %423, %556
1305: %558 = tail call fast <2 x float> @air.fast_clamp.v2f32(<2 x float> %557, <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00>) #3
1306: br label %583
1307:
1308: 559: ; preds = %504
1309: %560 = tail call fast float @air.dot.v2f32(<2 x float> %449, <2 x float> %449) #3
1310: %561 = tail call fast float @air.fast_sqrt.f32(float %560) #3
1311: %562 = fcmp fast olt float %537, %561
1312: br i1 %562, label %563, label %583
1313:
1314: 563: ; preds = %559
1315: %564 = fsub fast <2 x float> <float -0.000000e+00, float -0.000000e+00>, %449
1316: %565 = tail call fast float @air.dot.v2f32(<2 x float> %564, <2 x float> %564) #3
1317: %566 = tail call fast float @air.fast_sqrt.f32(float %565) #3
1318: %567 = fcmp fast ugt float %566, 0x3F1A36E2E0000000
1319: br i1 %567, label %568, label %583
1320:
1321: 568: ; preds = %563
1322: %569 = fsub fast <2 x float> %423, %538
1323: %570 = tail call fast float @air.dot.v2f32(<2 x float> %569, <2 x float> %569) #3
1324: %571 = tail call fast float @air.fast_sqrt.f32(float %570) #3
1325: %572 = fdiv fast float %571, %566
1326: %573 = fsub fast float 1.000000e+00, %572
1327: %574 = tail call fast float @air.fast_clamp.f32(float %573, float 0.000000e+00, float 1.000000e+00) #3
1328: %575 = insertelement <2 x float> undef, float %574, i64 0
1329: %576 = shufflevector <2 x float> %575, <2 x float> undef, <2 x i32> zeroinitializer
1330: %577 = insertelement <2 x float> undef, float %64, i64 0
1331: %578 = shufflevector <2 x float> %577, <2 x float> undef, <2 x i32> zeroinitializer
1332: %579 = fmul fast <2 x float> %449, %578
1333: %580 = fmul fast <2 x float> %579, %576
1334: %581 = fsub fast <2 x float> %423, %580
1335: %582 = tail call fast <2 x float> @air.fast_clamp.v2f32(<2 x float> %581, <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00>) #3
1336: br label %583
1337:
1338: 583: ; preds = %568, %563, %559, %545, %540
1339: %584 = phi <2 x float> [ %423, %559 ], [ %558, %545 ], [ %423, %540 ], [ %582, %568 ], [ %423, %563 ]
1340: call void @llvm.lifetime.end.p0i8(i64 88, i8* nonnull %447) #8
1341: call void @llvm.lifetime.end.p0i8(i64 44, i8* nonnull %427) #8
1342: br label %585
1343:
1344: 585: ; preds = %583, %422
1345: %586 = phi <2 x float> [ %584, %583 ], [ %423, %422 ]
1346: %587 = tail call fast float @air.fast_fabs.f32(float %10) #3
1347: %588 = fcmp fast ogt float %587, 0x3EB0C6F7A0000000
1348: br i1 %588, label %589, label %613
4634: !27 = !{i32 8, !"air.buffer", !"air.location_index", i32 7, i32 1, !"air.read", !"air.struct_type_info", !28, !"air.arg_type_size", i32 40, !"air.arg_type_align_size", i32 4, !"air.arg_type_name", !"MSSFaceShapeParams", !"air.arg_name", !"faceShapeParams"}
4635: !28 = !{i32 0, i32 4, i32 0, !"float", !"shoulian", i32 4, i32 4, i32 0, !"float", !"zhailian", i32 8, i32 4, i32 0, !"float", !"vlian", i32 12, i32 4, i32 0, !"float", !"xiaegu", i32 16, i32 4, i32 0, !"float", !"quangu", i32 20, i32 4, i32 0, !"float", !"xiaba", i32 24, i32 4, i32 0, !"float", !"duanlian", i32 28, i32 4, i32 0, !"float", !"xiaotou", i32 32, i32 4, i32 0, !"float", !"xiaotoufanwei", i32 36, i32 4, i32 0, !"float", !"dayan"}
+178
查看文件
@@ -0,0 +1,178 @@
{
"authority": "Static shipped-artifact analysis; original shader not executed. Public Vision76 region mapping reused from slim-pose-report.json.",
"target_arm64_sha256": "f01e8c0b7e2676b2961950b0e48efdd2589af218e4b36de7d39f5d1c76852bfb",
"air_sha256": "f97705b88f5491057df2117aef457ffca84e11020574cd57742b0670db4484d8",
"evidence_ids": {
"cpu_constants": "ev_d1b8a49fc62e384710bac234967c3e8cbf7c5127081c9b2c6f6a0bbd80b80967",
"cpu_assembly": "ev_8bc31392c07788d2482546121297c3f177d527282275ef21fd3e5edef9921544"
},
"common": {
"uv": "full-image normalized, y down; production stores y up and must convert points and q together",
"gain": "clamp(280/max(length((P75-P59)*pixelSize),2*length((P67-(P74+P60)/2)*pixelSize),1),1,2.25)",
"original_order": [
"thin17",
"narrow16",
"vFace4",
"jaw6",
"cheek6",
"chin3",
"shortPolygon",
"smallHead",
"bigEye"
],
"enable_threshold": "abs(effectiveRatio)>1e-6",
"per_pin_or_field_result": "clamp(q-newOffset,0,1)"
},
"jaw": {
"struct_field": "xiaegu offset12 / helper parameter6",
"ui_range": [
0,
1
],
"cpu_scale": 0.05,
"constant_address": "0x10005f9a8",
"pins_origin_radiusNeighbour_directionAnchor": [
[
72,
71,
29
],
[
62,
63,
29
],
[
71,
70,
29
],
[
63,
64,
29
],
[
70,
71,
29
],
[
64,
63,
29
]
],
"radius": "length(Porigin-Pneighbour) in UV; skip radius<=.0001",
"direction": "P29-Porigin",
"weight": "clamp(1-length(q-Porigin)/radius,0,1)",
"step": "q=clamp(q-direction*clamp(jaw,0,1)*.05*gain*weight,0,1)",
"execution": "6 sequential q updates; each radius uses the second triplet index, unlike thin/chin which use the direction anchor distance",
"air_lines": [
899,
986
]
},
"short": {
"struct_field": "duanlian offset24 / helper parameter9",
"ui_range": [
-1,
1
],
"cpu_scale": 0.25,
"constant_address": "0x10005f9e0",
"cpu_clamp_min_address": "0x10005f9d0 = -1",
"cpu_scaled_min_address": "0x10005f9f0 = -.25",
"polygon_indices": [
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72
],
"polygon_closure": "P72->P62",
"axis": "P46-P48 (nose crest region)",
"radius": "length(axis) in UV; skip radius<=.0001",
"inside": "even-odd point-in-polygon; weight1",
"outside": "d=minimum distance to11 closed segments; weight=clamp(1-d/radius,0,1), only when d<radius",
"step": "q=clamp(q-axis*clamp(short,-1,1)*.25*gain*weight,0,1)",
"nearest_segment_threshold": "squared edge length>1e-6 then project t=clamp(dot(q-A,B-A)/dot(B-A,B-A),0,1); else choose A",
"ray_crossing_denominator": "dy if abs(dy)>1e-6 else signed1e-6",
"air_lines": [
1127,
1340
]
},
"implementation": {
"source": "beatygril/beatygril/Plugin/PGFaceProcessor.m",
"order": [
"thin17",
"existing analytic narrow/V/cheek/small-head body",
"jaw6",
"chin3",
"shortPolygon",
"existing analytic bigEye"
],
"control_coefficients": {
"jaw": 0.05,
"short": 0.25
},
"strength": "Original CPU clamps a common shape strength. Product fixes that multiplier at1 and maps it to no user parameter: PGAmount/s.amount is smoothing strength only and is not used by thin/chin/jaw/short. All4 share the same pixel-size gain. Each shape uses its own control; PGMix is applied independently to the total output later by the host adapter. No new common shape-strength UI is introduced.",
"sampling": "All sequential coordinates are evaluated within one CIWarpKernel per face; image and all4 masks share the same method.",
"missing_or_invalid76": "Preserve legacy face/archive and other5 analytic controls; skip thin/chin/jaw/short exactly.",
"unchanged": "Existing thin17/chin3 index order, constants and formulas remain unchanged.",
"source_sha256": "e4122ca95f7ba41bc925b4cc4bf2bf88a72044ea41880cd66acd9c8278a7daf4"
},
"limits": [
"No original target app/shader executed; these are static CPU/AIR observations.",
"The complete vendor chain is not reconstructed: narrow/V/cheek/small-head/eye algorithms and their ordering remain project approximations. Isolated jaw/short plus recovered thin/chin ordering is tested.",
"No new explicit yaw, pitch, roll or landmark-quality attenuation is inferred. Profile behavior follows detected 2D landmarks, as in the recovered branches.",
"Physical PNG checks bypass the host IOSurface adapter. Original vendor pixel equivalence and Motion/FCP1.1.2 runtime acceptance remain unverified.",
"Independent public Vision CGImage and CIImage detections differ slightly. Tests allow .025 normalized location difference; eye/temple displacement tests measure the actual GPU inverse field."
],
"verification": {
"core": {
"exit_code": 0,
"beauty_checks": 49,
"face_checks": 116,
"slim_checks": 796,
"total": 961
},
"real_frames_asan": {
"exit_code": 0,
"checks": 886,
"frames": [
"public NASA astronaut",
"local user upright/rolled0s",
"local user profile4s"
],
"diagnostics": []
},
"max_uv_oracle_error": 1.09828022e-05,
"physical_checks": "Public Vision76 lower-contour response, pupil/upper-contour positions beyond support unchanged; separate CGImage Vision point locations cross-check the CIImage production path.",
"local_logs": [
"build/analysis-jaw-short/core-tests.txt",
"build/analysis-jaw-short/real-frames-asan.txt"
],
"app_built": false,
"host_operated": false
},
"pre_fix_difference": {
"source": "PGFaceProcessor.m; PGBeautyRenderer only does appearance",
"jaw": "axis-aligned bbox jawBand, .20 multiplier, no radiusNeighbour or lip anchor",
"short": "axis-aligned bbox lower field, .16 multiplier, no lower-contour polygon or nose axis",
"bounds": "Difference in algorithm is established. It does not by itself prove why a specific installed screenshot looks like temple movement; coordinate/isolated-control localization must be checked in actual image output.",
"processor_sha256": "fe4f2a6fc28799cc9b81832baaa2d6739320bde9def175ecc8a4494d004d6b28"
},
"air_excerpts": {
"path": "docs/analysis/short-jaw-air.txt",
"sha256": "f4ade84fdb2303515dab7b4d7eca8a9c2241039b9e6428cd51ceffc32b3f6b9b",
"formatNote": "Trailing whitespace removed from numbered excerpt; original AIR source SHA remains unchanged."
}
}
+37
查看文件
@@ -0,0 +1,37 @@
# 2.4.0 面板参数迁移
2026-10-22(Asia/Shanghai)。用户通过截图纠正原需求:迁移新版面板参数,并非新增身体瘦身。此前[瘦身目标核对](瘦身迁移目标核对.md)保留为历史调查;本次继续工作使用 `codex/new-beauty-controls`,不再等待其他目标包。
## 参考与证据
目标:`/Users/dayu/Downloads/MSE18V2.app`,2.4.0 / 20260724150000;插件通用二进制 SHA-256:`577303e0de72e07feb576c882e82382b3f056b023a7e987d990ffb37f6b16109`;arm64 切片:`afc71d0d21fd3c1ca95ca745ddafcd729e36ad95f17d8638009f2e45d9b7e8df`。分析使用 Ghidra 12.1.4 与只读 Mach-O 元数据/反汇编,原文件未改。
| 参考面板 | 目标字段/转换 | 本项目入口 |
| --- | --- | --- |
| 磨皮程度 | ID12 → midtoneDetail,直接 0–100% | 保留 PGMidtone 12,调整名称 |
| 微细锐化 | ID4 → sharpness,局部细节恢复 | 新 PGMicroDetail 77;原全局锐化 4 留在更多设置 |
| 五官保护 | ID30 → featureProtectionRelease = 1 − UI;旧 bool 随 release 接近 1 而关闭 | 新 PGFeatureProtectionAmount 75,直接保护量;旧 bool 30 保留类型与读取 |
| 非肤色区保护 | ID17 → highPassDetail = 1 − UI;新主路径用于肤色蒙版扩展 | 新 PGNonSkinProtection 76;原独立全局磨皮 17 留在更多设置 |
| 白牙、检测框预览、多人及脸型 | 截图中的这些项已经存在 | 保留;检测框名称调整、多人模式增加提示 |
两个新保护量默认为 100%,微细锐化默认为 0%。内部使用直接保护量,不直接复用参考包的反向 release 数值。
`setFloatValue:parameterID:minValue:maxValue:`(`0x1000116d8`)分别反转 17/30 的输入;Evidence:`ev_1fb7d2361dabf814edd6f22d217265b63efa9af24739741772ad5f579e0c67e3`。`valuesForControlPanelValue:` 返回相应原始字段;Evidence:`ev_20da8abf4eb5101b0902627255c643a783b7a15337aa4a757820ab71616f33e7`。显示格式 `strength` 是直接乘 100,只有 `protectionInverse` 格式自身反转;17/30 在绘制与交互同步时提前反转,不能把所有 strength 控制都解释为反向。格式函数汇编 Evidence:`ev_8e2a143f81d173c7643ecee2f1dac4a02145edbf82f113c8a48271428baf747c`。
目标原生处理入口 `applySkinSmoothingToImage:…`(`0x1000358d8`)把 params+0x50 用于非肤色参与,把 params+0x48 用于五官保护释放。Evidence:`ev_34eb4fe26dbaed9fc37d664d9363db903339c1447b6cd7fdb1980dcd61e99572`。可读 CI 内核字符串建立两个关键关系:肤色蒙版向白色线性扩展;保护蒙版与未保护蒙版按 release 线性混合。细节恢复使用原画与低频图的差,并受局部蒙版和亮度/纹理门控。字符串证据:`ev_d02bfe8046953e9287bd46c5403e6585354a5aa6df782a775d6a6fd0d96f1d62`。这里只记录公式和含义,不提交目标模型、metallib 或资源。
## 实施与兼容
本项目继续使用自研 Vision 几何蒙版与 Core Image 管线。新的平滑支持蒙版通过现有未保护/已保护覆盖率恢复五官衰减比例,再对非肤色区域扩展;两个控制独立于曝光/肤色蒙版。默认 100%/100% 直接沿用原覆盖路径。微细锐化在局部支持区域恢复亮度细节与少量色彩细节,可在磨皮量为零时独立使用。
原目标的语义蒙版、特征形状、纹理处理和复杂组合尚未全链对齐,因此本次是参数含义、连续控制和对应局部处理的迁移,不表示整个新版已逐像素复刻。旧版全局磨皮/全局锐化仍可通过更多设置使用,不与新保护项偷换含义;历史工程保留原强度。
PGBeautySettings v2 尾部增加三个 float,保留 v1 的 160 字节前缀。解码只接受 v1+160 字节或 v2+新完整长度;旧状态补中性默认值。PGInspectorState 仍使用 schema 1 数值字典,旧 bool 30 迁移到缺失的 75,新数值存在时优先采用新值。面板提交先保存权威对象 210,成功后再镜像旧 bool;每次拖动步进仍使用独立宿主 action。
模板继续发布原 210 对象与两项署名。新隐藏参数由插件注册和缺省值补齐,原 `.moef` 字节未改,无须覆盖用户模板。固定 Bundle ID、滤镜 UUID、安装路径及宣传资源不变。
## 验证
最终通过 1636 项:Beauty 57、Face 116、几何 796、宿主适配 ASan 341、OSC ASan 98、Inspector ASan 228(其中 1 项为可选离屏 PNG 输出)。新增检查包含保护量 0/50/100 的像素响应、非肤色保护只改变局部磨皮支持、微细锐化区域、颜色覆盖隔离、v1 状态迁移与错误长度拒绝、新滑杆归档/插值/输入/重置/旁路/主开关、松手前中间状态发布。离屏 AppKit 面板在多种宽度检查;原生宿主视觉验收需另记实际结果。
完整 REA 证据仅在忽略的 `build/body-analysis/new-controls-evidence.json`。本文保留目标身份、入口、公式与边界,恢复构建不依赖该本地调查目录。
+53
查看文件
@@ -0,0 +1,53 @@
# 瘦身迁移:目标版本核对
核对日期:2026-10-22(Asia/Shanghai)。开发分支:`codex/body-slimming`;源码基线:`13821366a5baee9beea40972118d7fe634b5c735`。
**后续已澄清**:用户通过截图确认记错了,实际需求是迁移新增面板参数。后续以[新版磨皮参数迁移](新版磨皮参数迁移.md)为准,下面保留纠正前的有界调查结论,不再表示当前等待其他插件包。
## 当前结果
用户指定的新目标为 `/Users/dayu/Downloads/MSE18V2.app`。已读取项目交接并检查目标包,**尚未定位到可迁移的新增“瘦身”板块**。当前只完成目标核对与接入点调查,未修改产品源码、模板或正式安装的 1.2.0 APP,未编译或执行目标程序。
接续时先请用户确认瘦身控制的具体名称、面板画面或包含该功能的目标包路径。不能把现有“瘦脸”误当作“瘦身”,也不能自行设计身体变形后称为已迁移原版算法。
## 目标身份
| 项目 | 新下载目标 | 旧安装参考 |
| --- | --- | --- |
| APP 路径 | `/Users/dayu/Downloads/MSE18V2.app` | `/Applications/MSE18V2.app` |
| 外层与插件版本 | `2.4.0` / `20260724150000` | `1.0.20260617-170517` / `20260617170517` |
| 插件 Bundle ID | `com.ms.plugins.mse18v2` | `com.ms.plugins.mse18v2` |
| 插件通用二进制 SHA-256 | `577303e0de72e07feb576c882e82382b3f056b023a7e987d990ffb37f6b16109` | `6c5d74bc844a5c5f745718b48ea10ec6635d08aa08a5b6dc6e62653980849f8a` |
新插件 arm64 切片 SHA-256:`afc71d0d21fd3c1ca95ca745ddafcd729e36ad95f17d8638009f2e45d9b7e8df`。插件二进制位于各 APP 的 `Contents/PlugIns/MSE18V2.pluginkit/Contents/MacOS/MSE18V2`。
## 已观察证据与范围
- 对新旧包的外层和插件、arm64 与 x86_64 切片,静态检查 `__ustring`、`__cstring`、`__objc_methname`、`__objc_classname`。在这些段内未发现“瘦身、瘦腰、瘦腿、身体”及对应 body/slim/waist/slender/stretch/shoushen 功能命名。可读板块仍为磨皮、美白、瘦脸;新包另有“预览设置、肤色范围、非肤色区保护”等文字。这是有界字符串检查,不能排除动态生成或其他未解释数据。
- 新插件 arm64 的 Ghidra 参数注册函数 `MSSuperSkinSmoothingPlugIn::addParametersWithError:`(`0x10001fc10`)注册面板 210、磨皮/肤色/现有脸型参数和三模块开关,所见注册列表没有身体参数。Evidence:`ev_4d3e7e7dc8aa21347adbd0f0847fab13e8b69462bd5e6adf3657cbc0c1998266`。
- 面板值类的方法包括 `faceThin`、`faceNarrow`、`faceChin`、`faceJaw`、`faceSmallHead` 等,以及 skin/tone/face 三个模块开关。过程名称搜索没有返回身体变形入口;不能由名称负结果断言所有匿名函数均不存在身体算法。Evidence:`ev_446e4a969ff46db0600fe15988d0f396f394641aaeac760d6372a0c0509bf177`、`ev_157df22ee7802216f3581c9842a9629c69ee66097db068b825695bdfd99385d1`。
- 所见几何 GPU 管线仍为 `faceThin*`;新旧 metallib 的 12 个命名函数集合相同。文件变大不能证明新增身体算法,也不能由相同函数名断言函数内容相同。
- REA 对提供者已定义字符串对象的搜索只返回无关的 `URLRequest.httpBody`。Ghidra 未在该搜索中解码中文 UTF-16 常量,因此中文检查另使用实际 Mach-O 字节,未把 REA 空结果当作整个包不含中文的证据。Evidence:`ev_015a585ce5565d874f5b55af0c363bed634f09a29088ef660d3ca1c547626c26`。
REA 使用 Ghidra 12.1.4。通用 Mach-O 不支持该提供者直接选架构,故只读提取 arm64 切片分析。会话已关闭;切片、完整证据和快照仅保存在忽略的 `build/body-analysis/`,不作为构建或远端恢复依赖,不上传原版 APP、模型或 metallib。上述地址与 Evidence ID 仅对应本次 SHA,目标改变后需重新核对。
## 已完成与待定事项
| 问题 | 状态 |
| --- | --- |
| 项目交接、Git 基线、现有正式安装身份 | 已核对,产品源码未改 |
| 新下载包身份及与旧包差异 | 已核对;确为不同内容 |
| 新增瘦身控制、默认值、范围、画布操作 | 未定位,需确认正确目标 |
| 身体算法、处理顺序、跟随与蒙版行为 | 未建立证据,未实施 |
| 产品编译、回归、签名、公证、安装 | 本次未执行 |
## 确认目标后的接入提示
现有工程只有人脸几何,新增身体效果应有独立状态与总开关,不能依赖人脸检测成功。具体控制数量、范围、算法和顺序以正确目标的证据为准。
- `PGInspectorState.m` 的描述表同时驱动面板、归档和插值。保留参数 210 及既有 ID;数值字典缺失项会补默认值。新增卡片时,`PGInspectorView.m` 需按 section 识别“更多设置”,不能继续依赖 `index==3`。
- `PGBeautySettings` 当前是 160 字节 v1 裸结构体。若追加字段,应保留旧前缀并明确接受旧版本/长度组合,补齐新默认值;同步修改宿主解码,拒绝截断、超长或未知版本。不要只更改 `sizeof` 检查。
- OSC 必须同步完整面板对象 210,单写隐藏参数会被已编辑的面板状态覆盖。OSC 回调使用宿主已建立的参数上下文,不能套用面板的 `startAction/endAction` 路径;保留原选脸 ID 和 UUID。
- 身体变形需核对与外观处理、四类蒙版及整体混合的先后关系;验证无人脸、非零 extent、原点标签、极端参数、旧归档、撤销、连续拖动与保存重开。
本次分支基线已在 `origin` 和 `github` 读回核验。两端的最新研究记录以当前分支引用为准;尚无瘦身功能交付标签。
+39
查看文件
@@ -0,0 +1,39 @@
# 短脸与下颌骨局部变形
本次将短脸与下颌骨从包围框近似场替换为目标产物中恢复的76点局部场。几何实现在`PGFaceProcessor.m`;`PGBeautyRenderer.m`负责外观,不是这次位置问题的修改点。
证据是目标ARM64二进制的只读CPU汇编、常量字节与已有Apple metal-objdump AIR。未运行原版APP或shader,未操作Motion/FCP。CPU证据见`rea-jaw-short.json`,带原始行号的GPU IR见`short-jaw-air.txt`,推导及来源摘要见`short-jaw-report.json`。
## 确认的规则
两项共用像素尺寸增益:
`gain = clamp(280 / max(|(P75-P59)*imageSize|, 2*|(P67-(P74+P60)/2)*imageSize|, 1), 1, 2.25)`。
距离为UV时,点与采样坐标统一采用全图归一化、Y向下;像素增益另用实际渲染宽高计算。产品内部76点采用Y向上,因此在同一个kernel中统一转换,未改宿主图像方向。
下颌骨按顺序使用六组`(origin, radiusNeighbour, directionAnchor)`:
`(72,71,29), (62,63,29), (71,70,29), (63,64,29), (70,71,29), (64,63,29)`。
半径是前两点的相邻轮廓距离,方向是`P29-origin`。每步令`weight=clamp(1-|q-origin|/radius,0,1)`,再依次更新`q=clamp(q-direction*ratio*weight,0,1)`。`ratio=clamp(jaw,0,1)*0.05*gain`。不能把半径替换为到嘴锚点的距离,也不能将六步合并为在同一原始坐标上求和。
短脸使用`P62...P72`构成的11边闭合下半脸区域。内部权重为1;外部权重按到最近线段的UV距离线性下降,在距离达到`|P46-P48|`时为0。位移轴为`P46-P48`(公开Vision的鼻梁点区域),`ratio=clamp(short,-1,1)*0.25*gain`,采样更新`q=clamp(q-axis*ratio*weight,0,1)`。正值的可见运动沿鼻梁方向收短,负值延长。半径不超过`0.0001`时跳过;线段投影的平方长度门限为`0.000001`。
CPU字节证据ID:`ev_d1b8a49fc62e384710bac234967c3e8cbf7c5127081c9b2c6f6a0bbd80b80967`。`0x10005f9a8`的double值为`0.05`;`0x10005f9e0`为`0.25`,`0x10005f9d0`和`0x10005f9f0`分别是短脸下限`-1`与缩放后下限`-0.25`。汇编ID:`ev_8bc31392c07788d2482546121297c3f177d527282275ef21fd3e5edef9921544`。结构字段`xiaegu`偏移12、`duanlian`偏移24,结合CPU写入与AIR读取顺序确认映射。
## 产品改动及边界
移除旧`jaw*0.20*jawBand`和`-shortFace*0.16*lower`。保留瘦脸17步、下巴3步的点位、系数和数学,新的局部顺序为`jaw6 → chin3 → short polygon`,仍在同一个CIWarpKernel内更新采样坐标,对每张输入图像或蒙版,每张脸仅进行一次重采样。图像、磨皮/肤色/牙齿/眼睛四张蒙版调用同一变形路径。没有完整合法76点时,这四项恢复算法安全直通;旧记录、其他参数和离线归档继续可读。
原版完整顺序为`thin → narrow → V → jaw → cheek → chin → short → small-head → eyes`。产品其余五项仍采用原有近似body/眼睛场:body先于jaw,故组合全链不宣称原版等价。原版CPU另接受共同形变强度;本产品该乘数固定为1,未映射到任何用户参数。`PGAmount`/`s.amount`仅表示磨皮强度,不参与thin/chin/jaw/short比例;四项共用同一像素尺寸gain。用户分别调节各项脸型值,最终`PGMix`由宿主适配器独立混合总输出。没有新增共同形变强度控制,以保持磨皮、美白和脸型卡片各自的含义。这里没有证实或添加3D姿态识别、yaw衰减或五官恢复锁定。
旧算法与原版不同是确定事实;单凭静态代码,不能替某张已安装宿主画面的“太阳穴变化”断言唯一原因。下述位置验证针对真实PNG,宿主适配和原生交互由父任务验收。
## 验证
`scripts/test.sh`:Beauty49、Face116、Slim796,共961项通过。旧394项thin/chin测试保留;新增独立double oracle从上述AIR规则写成,比较实际GPU坐标场,最大UV误差`1.09828022e-05`。覆盖非零extent、横竖画幅、侧脸投影与roll、正负短脸、小脸增益上限、相邻轮廓半径反例、组合顺序、缺失/非法76点和四张蒙版一致性。
ASan专项以NASA公开肖像及本地用户正面/侧脸帧运行:886项通过,无ASan诊断。独立CGImage Vision请求对照了瞳孔、嘴唇、鼻梁和上下轮廓索引,防止与生产CIImage路径共用一次Y翻转假设。实际GPU采样场确认下半脸有响应,处于支持域外的瞳孔和上部轮廓位置不响应。
用户帧、完整坐标和测试构建只留在忽略的`build/`目录,不进入证据文件。上述不代表原版逐像素一致,也未替代新版本Motion/FCP原生验收;本次未构建APP、安装或提交。
+25
查看文件
@@ -0,0 +1,25 @@
# 自定义面板交互连接修复
1.1.0在FCP原生界面复现:卡片能显示,“更多设置”可展开,但全部参数控件禁用,底部显示“等待宿主连接”。这不是整张视图不接收事件。
控制器原先在startAction之前检查FxParameterRetrievalAPI_v6与FxParameterSettingAPI_v5,若宿主仅在action上下文中提供它们,就根本进不了action。1.1.1改为先取得FxCustomParameterActionAPI_v4,以真实PGInspectorView为sender开启操作,再获取读写接口;缺接口时正确结束操作,后续可重试。NSView sender也符合本机官方头文件的sender定义。
实际FCP正式安装版日志确认readBefore=0、writeBefore=0,进入action后readInAction=1、writeInAction=1,viewSender=1、onMain=1。界面控件随即启用,原生重置按钮能把肤色亮度清零;数值输入37并按Return后,滑块与数值显示同步为0.37/37%。因此原先门控条件在实际宿主中确实无法成立。
新增模拟宿主只有在action内才提供参数接口,并要求sender为NSView:修改前141项检查有5项失败,修改后141项全部通过;独立远端恢复的同一测试启用ASan通过。完整1046项回归通过。签名代码节点为53ce88dd15983e9397ab08f5ec9ad608fce5d0b5,正式中间版1.1.1(10)已安装并通过签名、公证和票据。后续用户报告短脸和下颌骨位置错误,继续在合并修复版完成两宿主最终验收,未给中间版建立最终发布标签。
## 原生验收的边界
Mouse/keyboard自动化尝试中有焦点落回时间线及参数在非本次操作时改变的情况,不能据此断言点击坐标一定错位。另一次FCP高CPU与AX超时,调用栈落在大量效果浏览器的辅助功能遍历;插件主线程大多空闲。收起效果浏览器后AX读取从约10秒降到约1秒。这不是已证明的插件死锁。原始截图、用户测试片段和全部窗口树保留本机build/native-111,不上传远程。
原版UI的只读对照显示isFlipped同为YES,原生滑块同样使用super mouseDown;root鼠标以locationInWindow经convertPoint:fromView:nil转换。名字含WidthFix的方法只处理容器高度不足,没有鼠标Y翻转或backing像素重映射。没有证据需要盲改本产品的isFlipped。1.1.2最终Motion/FCP数值、重置、保存重开及画面响应将另行记录。
## 数值失焦与拖动连续预览
原生build11验收发现数值Return后仍保留字段编辑器,失焦通知无条件再次提交旧文本,可能把宿主刚撤销或重置的状态写回。新增独立回归确认旧delegate在失焦时复活旧值;现追踪尚未提交的真实文本改动,Return只提交一次并释放AppKit字段编辑器,失焦仅提交新改动。离屏真实NSWindow/field editor用例已覆盖。
用户另报滑杆只在松手后更新:旧view层在mouseDown之前beginInteraction,整个NSSlider tracking loop结束才endInteraction,虽然continuous为YES,宿主可直到endAction才发布预览。现在gesture depth只阻止定时刷新覆盖拖动显示,每个有效slider action由controller单独开启/结束宿主上下文,仍先在真实NSView sender的action内取得API,完整自定义状态和隐藏镜像一起提交。没有新增手动分析或强制刷新按钮。
在仅于endAction发布预览的模拟宿主中,三个中间步进旧版3项失败,新版155项检查器ASan全部通过,含无变化去重、action配对、每步可读的完整渲染设置。宿主是否合并快速更新以及实际显示帧率由其调度和设备性能决定;不保证每一个鼠标事件均在屏幕独立显示一帧。新版原生复验另记。
远程编辑器补充:Motion build12中数值提交后的重置已经改变实际slider/输出,但仍保留字段编辑器并显示旧文本。最终改为对已提交编辑调用abortEditing,并仅在存在尚未提交的真实输入时阻止宿主刷新/保留文本;单纯残留焦点不再遮蔽撤销或重置。新增两个真实离屏编辑器用例确认无改动焦点可刷新、尚未提交输入仍受保护;检查器ASan现157项通过。
+41
查看文件
@@ -0,0 +1,41 @@
{
"generator": "built-in image_gen",
"type": "generated promotional artwork, not an actual effect-output comparison",
"style": "宋式青绿古风;成年女性面部近景;金色瘦脸轮廓线与内收箭头",
"thumbnail_text": [
"大鱼人像美化",
"自动瘦脸",
"自动跟随",
"自动美颜",
"免费开源"
],
"app_card_text": [
"大鱼人像美化",
"免费开源",
"自动注册 · 无需激活码",
"启动 3 秒后自动退出",
"Final Cut Pro · Motion",
"dayu.media"
],
"files": [
{
"path": "Assets/Artwork/portrait-cover.png",
"sha256": "a346f06e7793b4e5483ccd4b3b86f34c2036bbe6bbddb7ad9cc70c47e7d014ab"
},
{
"path": "beatygril/beatygril/Wrapper Application/Resources/LauncherInfo.png",
"sha256": "239552eeea738a32fafa70922d3cd1d4c115ff75d672574fa4c5acd941381fba"
},
{
"path": "Templates/大鱼人像美化/large.png",
"sha256": "a02ddb255b1ae255c749bb837a759e2dee1c3b8ffb9bdc1167957761bd5a1b97"
},
{
"path": "Templates/大鱼人像美化/small.png",
"sha256": "1552b838dd88f60dee0795e20aaca652f9c558ecefc93500e895fbff77c2a4d5"
}
],
"thumbnail_lock": "uchg on both PNGs only; installer must restore flags",
"template_sha256": "e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15",
"revision": "User feedback: reduce three feature lines by approximately one third and increase negative space."
}
+5
查看文件
@@ -0,0 +1,5 @@
{
"mode": "built-in image_gen",
"cover_prompt": "Use case: ads-marketing. Asset type: final 16:9 wide Chinese classical portrait beautification FxPlug product cover and very small Final Cut Pro effect thumbnail.\nEdit the supplied previous cover. Preserve its original jade-green, ivory and antique-gold Song-dynasty Chinese painting direction and the fictional adult Chinese hanfu woman identity, but redesign the composition for thumbnail legibility.\nPrimary request: CLOSE-UP FACE portrait dominates the RIGHT 52 percent; crop from the ornate updo to just below shoulders, face itself very large (about 65 percent of image height), almost frontal with slight elegant three-quarter angle, both cheeks and jaw clearly visible, natural skin texture and beautiful natural proportion. No fan, no hands, no full-body or waist framing. Gold/jade hairpin and small part of hanfu collar retain classical character. Background quiet dark jade and understated distant misty Chinese mountains; remove busy koi and flowers near lettering.\nDraw precise elegant luminous antique-gold contour curves along BOTH cheeks and jaw (following the skin outline, from below cheekbones toward chin) plus two short inward arrows on each side, unmistakably communicating automatic face slimming. Add a few restrained dotted jade landmark points and four fine rounded face-following corner marks. These overlays are design graphics only and must not distort the portrait. Avoid modern blue sci-fi HUD, grids covering eyes, and competitor likeness.\nLEFT 46 percent: extremely clear bold warm ivory Chinese display lettering, restrained gold border, generous spacing and high contrast. Text verbatim and only:\nTop compact brand line: \"大鱼人像美化\"\nThree equally prominent large feature lines stacked vertically:\n\"自动瘦脸\"\n\"自动跟随\"\n\"自动美颜\"\nSmall vermilion seal: \"免费开源\"\nSmall bottom line: \"Final Cut Pro · Motion\"\nNo tiny explanatory paragraphs and no extra slogans. Main three feature lines must be very large and remain distinguishable after downscaling to 192x108. Keep all key text and facial features inside 6 percent edge-safe margins. Refined classical poster with realistic close-up portrait, contemporary clear Chinese typography integrated into antique jade/gold aesthetics. Output a polished landscape 16:9 master image.\n",
"final_refinement_prompt": "Edit this exact cover, changing ONLY the oversized typography layout. Preserve the classical jade-green/gold Chinese backdrop, the SAME adult hanfu woman's close-up face, all natural facial proportions, gold jaw-slimming contour arrows and tracking marks, 16:9 canvas, portrait placement. User says the feature text is too large.\nReduce the three feature lines \"自动瘦脸\", \"自动跟随\", \"自动美颜\" to approximately 62 percent of their current font height and width. Make the type refined, medium-weight warm ivory/gold rather than massive heavy gold brush blocks. Set them as three compact clean evenly spaced lines centered within the left column, with substantial calm dark-jade negative space above, below and around. Entire feature text group should occupy roughly 26 percent of total canvas width and 35 percent of canvas height, not the current 40 percent width and 57 percent height.\nKeep the product name \"大鱼人像美化\" at the top left but reduce it slightly (about 15 percent), preserving visual hierarchy: product name slightly larger than each feature line. Small red \"免费开源\" seal and small \"Final Cut Pro · Motion\" footer remain at bottom left. Remove the horizontal rules between the three feature lines; keep only subtle fine gold divider beneath product name and near footer. No new text. No giant lettering. Quiet elegant premium classical poster with FACE as the main visual focus. Exact required text retained: 大鱼人像美化 / 自动瘦脸 / 自动跟随 / 自动美颜 / 免费开源 / Final Cut Pro · Motion.\n"
}
@@ -0,0 +1,17 @@
{
"article_id": 15593,
"url": "https://dayu.media/15593/",
"status": "publish",
"github_repository": "https://github.com/FAMEDaYu/FCP-BeatyGril",
"github_release": "https://github.com/FAMEDaYu/FCP-BeatyGril/releases/tag/v1.2.0",
"anonymous_frontend_http": 200,
"both_github_links_present_in_frontend": true,
"code_writing_credit_retained": "代码由 OpenAI + Codex 全程编写,站长仅参与调试和测试。",
"resource_price_download_cover_seo_and_author_preserved": true,
"only_content_requested": true,
"frontend_seo_unique_and_exact": true,
"idempotency_key": "55e60cc5-509a-4ae9-ba96-c0d25b2c575a",
"before_content_sha256": "2701991a543b80114c062cc7ee68b83afff505dd9456cfe82f0b8819ea81b119",
"after_content_sha256": "c66e1ddb374714a938442cd24cf5034482ea4e67d6f8dd79c07d43ba74ad1b1d",
"verified_at_utc": "2026-10-21T19:32:48.060004+00:00"
}
+15
查看文件
@@ -0,0 +1,15 @@
{
"target": "https://github.com/FAMEDaYu/FCP-BeatyGril.git",
"source_commit": "dffa547d92478dd471fb4926579df91084581756",
"all_reachable_blobs_scanned": 406,
"secret_pattern_matches": [],
"package_sha256": "5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"connector_target_push_permission": false,
"local_https_credential_present": false,
"status": "prepared_waiting_for_GitHub_write_authentication",
"github_visibility": "public",
"github_repository_id": "1428817365",
"github_repository_initial_state": "empty",
"origin_retained": "https://dayu.media/git/dayu/paintfcp-fxplug.git",
"github_remote_added": true
}
+19
查看文件
@@ -0,0 +1,19 @@
{
"repository": "https://github.com/FAMEDaYu/FCP-BeatyGril",
"repository_id": 1428817365,
"visibility": "public",
"source_commit": "356683b41af702d6c0143ad7fa5f540d752d6e14",
"local_refs": {
"refs/heads/main": "356683b41af702d6c0143ad7fa5f540d752d6e14",
"refs/tags/baseline-20261021": "4124c350ce288b5fa3cf843ec0e9751e9db19b4c",
"refs/tags/v1.0.4": "302dc20c0a90c0b8934c4341d65c2467d4ed3386",
"refs/tags/v1.0.5": "1008651f6e2111a26d1420021c49f40d6f728b3a",
"refs/tags/v1.0.6": "5793e3de499bfe320b5e9a9db16ef7bc79a5243d",
"refs/tags/v1.1.0": "3bb33818eaa8033b8b1d140eb64e31f38ec3fa75",
"refs/tags/v1.1.2": "e9fddda5e13042f761755762fa39dfe090853c6a",
"refs/tags/v1.2.0": "3c7261c3a861b9f4704cfb36055d7b500c239dab"
},
"github_refs_verified": true,
"main_upstream_retained": "origin",
"auth_storage": "macOS keyring through GitHub CLI; no token included"
}
+14
查看文件
@@ -0,0 +1,14 @@
{
"remote": "https://github.com/FAMEDaYu/FCP-BeatyGril.git",
"anonymous_clone": true,
"credentials_disabled_for_clone": true,
"commit": "356683b41af702d6c0143ad7fa5f540d752d6e14",
"tracked_files_compared": 197,
"all_tag_refs_equal": true,
"tag_count": 7,
"git_fsck_full_strict": true,
"package_sha256": "5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"lfs": false,
"submodules": false,
"temporary_clone_removed": true
}
+18
查看文件
@@ -0,0 +1,18 @@
{
"repository": "FAMEDaYu/FCP-BeatyGril",
"url": "https://github.com/FAMEDaYu/FCP-BeatyGril/releases/tag/v1.2.0",
"release_id": 419972270,
"tag": "v1.2.0",
"draft": false,
"prerelease": false,
"asset": {
"id": 663571667,
"name": "Dayu-Portrait-1.2.0.pkg",
"size": 5011005,
"digest": "sha256:5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"browser_download_url": "https://github.com/FAMEDaYu/FCP-BeatyGril/releases/download/v1.2.0/Dayu-Portrait-1.2.0.pkg"
},
"sha256": "5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"anonymous_asset_download_hash_matches": true,
"downloaded_pkg_signature_and_ticket_valid": true
}
+5
查看文件
@@ -0,0 +1,5 @@
Beauty renderer: 49 checks, 0 failures (Metal).
2026-10-21 23:20:16.950 face-tests[22007:5696503] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
Face processing: 116 checks passed
2026-10-21 23:20:21.817 slim-tests[22045:5696731] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
PASS: 394 slim alignment checks; maximum UV oracle error 1.09828022e-05
+21
查看文件
@@ -0,0 +1,21 @@
2026-10-21 23:20:18.015 host-tests[22024:5696629] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
Default IOSurface maximum byte difference: 0
Alternate destination tag maximum byte difference: 0
Anatomy default 0/0 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 0/1 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 1/0 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 1/1 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy big-eye 0/0 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 0/1 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 1/0 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 1/1 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy chin-positive 0/0 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 0/1 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 1/0 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 1/1 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-negative 0/0 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 0/1 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 1/0 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 1/1 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Legacy fallback upright comparison: max=2 mean=0.0010357
Host adapter: 248 checks, 0 failures
@@ -0,0 +1,6 @@
FAIL: an action-scoped host connects and reads the actual template values
FAIL: custom parameter actions identify their actual inspector NSView
FAIL: action-scoped parameter APIs do not leave the whole native panel disabled
FAIL: a connected native control writes through the action-scoped setting API
FAIL: a later host connection restores controls after a transient API failure
Inspector: 141 checks, 5 failures
@@ -0,0 +1 @@
Inspector: 141 checks, 0 failures
@@ -0,0 +1 @@
Inspector: 141 checks, 0 failures
@@ -0,0 +1,43 @@
{
"status": "failed",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"options": {
"waitForHosts": true,
"userTests": false
},
"nativeEffectQA": {
"status": "pending_operator",
"performedByScript": false
},
"source": {
"commit": "53ce88dd15983e9397ab08f5ec9ad608fce5d0b5",
"trackedWorktreeChanges": []
},
"updatedAt": "2026-10-21T15:40:33.591925+00:00",
"version": "1.1.1",
"build": "10",
"stagingSignature": "Executable=/private/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a\nCandidateCDHashFull sha256=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a3b65e0bd8d653434f77cad3a\nHash choices=sha256\nCMSDigest=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a3b65e0bd8d653434f77cad3a\nCMSDigestType=2\nCDHash=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 21, 2026 at 23:22:09\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"notarization": {
"message": "Processing complete",
"status": "Accepted",
"id": "a6218c05-b08f-417f-9617-c8e39b458a28"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"runningHosts": [],
"installedSignature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a\nCandidateCDHashFull sha256=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a3b65e0bd8d653434f77cad3a\nHash choices=sha256\nCMSDigest=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a3b65e0bd8d653434f77cad3a\nCMSDigestType=2\nCDHash=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 21, 2026 at 23:22:09\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"installedSignatureVerified": true,
"installedStapleValidated": true,
"gatekeeperAccepted": true,
"pluginDiscovery": {
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"formalPath": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"output": " com.dayu.beatygril.fxplug(1.1)\tDDFB35E6-8D3D-4436-B8FA-A8D5372F38E8\t2026-10-21 15:22:36 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)\n"
},
"failure": {
"type": "KeyboardInterrupt",
"message": ""
}
}
@@ -0,0 +1,2 @@
com.dayu.beatygril.fxplug(1.1) DDFB35E6-8D3D-4436-B8FA-A8D5372F38E8 2026-10-21 15:22:36 +0000 /Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit
(1 plug-in)
@@ -0,0 +1,24 @@
Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril
Identifier=com.dayu.beatygril
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a
CandidateCDHashFull sha256=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a3b65e0bd8d653434f77cad3a
Hash choices=sha256
CMSDigest=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a3b65e0bd8d653434f77cad3a
CMSDigestType=2
CDHash=3b65dadb35fe03201c99ce39fb1a41bb3ed6b00a
Signature size=8968
Authority=Developer ID Application: zhong luo (B3W25FX5H5)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Oct 21, 2026 at 23:22:09
Notarization Ticket=stapled
Info.plist entries=22
TeamIdentifier=B3W25FX5H5
Runtime Version=27.0.0
Sealed Resources version=2 rules=13 files=4
Internal requirements count=1 size=180
Total signatures=1
Chosen signature=1
@@ -0,0 +1 @@
{"message":"Processing complete","status":"Accepted","id":"a6218c05-b08f-417f-9617-c8e39b458a28"}
@@ -0,0 +1,11 @@
{
"installedVersionRetained": "1.1.1 (10)",
"reason": "API handshake confirmed native; broader UI and new short/jaw fixes continue in next build; not tagged as final release",
"removedKnownGeneratedPaths": [
"/Users/dayu/Documents/PaintFCP/build/delivery/previous-beatygril.app",
"/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app",
"/tmp/paintfcp-build-20261021",
"/Users/dayu/Documents/PaintFCP/build/delivery/notarization.zip"
],
"UIOperatedByCleanup": false
}
@@ -0,0 +1,8 @@
Timestamp Ty Process[PID:TID]
2026-10-21 23:24:07.867 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
2026-10-21 23:26:03.703 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
2026-10-21 23:29:21.518 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
2026-10-21 23:29:43.237 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
2026-10-21 23:33:38.371 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
2026-10-21 23:37:47.022 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
2026-10-21 23:38:06.329 Df beatygril XPC Service[22755:570e44] PGInspector connection readBefore=0 writeBefore=0 readInAction=1 writeInAction=1 viewSender=1 onMain=1
+21
查看文件
@@ -0,0 +1,21 @@
2026-10-21 23:20:17.783 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.25,0.75) setter=(0.25,0.75) readback=(0.25,0.75) mode=normalized verified=1
2026-10-21 23:20:17.791 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(80,180) surface=320x240 origin=0
2026-10-21 23:20:18.509 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.8,0.3) setter=(1152,-432) readback=(0.8,0.3) mode=centered-pixels verified=1
2026-10-21 23:20:18.509 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.7,0.4) objectBounds=(-1920,-1080,3840,2160) canvas=(152,78) surface=320x240 origin=0
2026-10-21 23:20:18.607 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.8,0.3) setter=(0.8,0.3) readback=(0.12345,0.87654) mode=normalized verified=0
2026-10-21 23:20:18.607 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.75,0.25) setter=(0.75,0.25) readback=(0.75,0.25) mode=normalized verified=1
2026-10-21 23:20:18.607 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.75,0.25) objectBounds=(-100,-50,200,100) canvas=(160,60) surface=320x240 origin=0
2026-10-21 23:20:18.684 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.625,0.375) setter=(0.625,0.375) readback=(0.625,0.375) mode=normalized verified=1
2026-10-21 23:20:18.684 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.625,0.375) objectBounds=(-100,-50,200,100) canvas=(240,60) surface=320x240 origin=0
2026-10-21 23:20:18.765 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.25,0.75) setter=(0.25,0.75) readback=(0.25,0.75) mode=normalized verified=1
2026-10-21 23:20:18.765 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(144,180) surface=320x240 origin=0
2026-10-21 23:20:18.864 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:20:18.864 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0,1) objectBounds=(-100,-50,200,100) canvas=(100,140) surface=320x240 origin=0
2026-10-21 23:20:18.947 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(nan,nan) surface=320x240 origin=0
2026-10-21 23:20:19.044 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:20:19.044 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(inf,nan) surface=320x240 origin=0
2026-10-21 23:20:19.123 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:20:19.123 osc-tests[22026:5696635] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(80,nan) surface=320x240 origin=0
2026-10-21 23:20:19.203 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:20:19.203 osc-tests[22026:5696635] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
OSC adapter: 98 checks, 0 failures
文件差异过大,未显示。 加载差异
@@ -0,0 +1,13 @@
Target: 53ce88dd15983e9397ab08f5ec9ad608fce5d0b5
Remote: https://dayu.media/git/dayu/paintfcp-fxplug.git
Passed: True
Tracked files: 125
All tracked bytes/blob IDs/modes: True
Git fsck --strict --full: 0
LFS/submodules: [] / []
Inspector tests: {'checks': 141, 'failures': 0, 'ASan': True, 'exitCode': 0, 'log': 'inspector-tests-asan.txt'}
Template audit: structure_verified_native_loading_pending
Core 559 tests not repeated; no APP build/host/UI/sign/install.
Temporary clone removed: True
Focused handshake review: PASS. startAction line159 precedes actual availability gate line163; pre-action API queries are diagnostics only. View init assigns its own NSView as actionSender; same sender balances endAction.
Offscreen AppKit controls and action-gated/requires-view host mock covered; native Motion/FCP acceptance remains outside this task.
@@ -0,0 +1,25 @@
{
"version": "1.1.2",
"build": "13",
"total": 1551,
"counts": {
"beauty": 49,
"face": 116,
"thinChinJawShort": 796,
"hostAdapterASan": 335,
"oscASan": 98,
"inspectorASan": 157
},
"allPassed": true,
"extraRealFramesASan": {
"checks": 886,
"includedRepeatedBaseChecks": true,
"addedToTotal": false
},
"originCombinations": 28,
"originTagsExactlyByteIdentical": true,
"maxByteDifferenceVsIndependentUprightReference": 2,
"meanByteDifferenceLimit": 0.005,
"nativeCombinedBuildQA": "pending",
"continuousPreview": "each changed step completes its own host action before mouse-up; mock publishes at endAction"
}
@@ -0,0 +1,4 @@
FAIL: every drag step publishes a completed host snapshot before mouse-up
FAIL: every drag step publishes a completed host snapshot before mouse-up
FAIL: every drag step publishes a completed host snapshot before mouse-up
Inspector: 155 checks, 3 failures
+5
查看文件
@@ -0,0 +1,5 @@
Beauty renderer: 49 checks, 0 failures (Metal).
2026-10-21 23:46:40.676 face-tests[24719:5743987] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
Face processing: 116 checks passed
2026-10-21 23:46:52.402 slim-tests[24738:5744142] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
PASS: 796 slim alignment checks; maximum UV oracle error 1.09828022e-05
@@ -0,0 +1,53 @@
{
"status": "complete",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"options": {
"waitForHosts": true,
"userTests": false
},
"nativeEffectQA": {
"status": "operator_confirmed",
"performedByScript": false,
"scopeDocument": "native-qa.json",
"heldMouseCanvasTiming": "User confirmed continuous visible updates while dragging on 2026-10-22 (Asia/Shanghai); host not specified, no per-event frame timing claim.",
"userConfirmation": {
"date": "2026-10-22",
"timezone": "Asia/Shanghai",
"response": "拖动中已持续更新",
"version": "1.1.2",
"build": "13"
}
},
"source": {
"commit": "a2e33e8e00a99b95dc29d67a819cb0897eda5756",
"trackedWorktreeChanges": []
},
"updatedAt": "2026-10-21T16:31:12.570976+00:00",
"version": "1.1.2",
"build": "13",
"stagingSignature": "Executable=/private/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=78b01963732b743659b501c5beedc96a725f1156\nCandidateCDHashFull sha256=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2\nHash choices=sha256\nCMSDigest=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2\nCMSDigestType=2\nCDHash=78b01963732b743659b501c5beedc96a725f1156\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 00:20:39\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"notarization": {
"message": "Processing complete",
"id": "5f5ce378-8430-467b-ae97-048e6bc81573",
"status": "Accepted"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"runningHosts": [],
"installedSignature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=78b01963732b743659b501c5beedc96a725f1156\nCandidateCDHashFull sha256=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2\nHash choices=sha256\nCMSDigest=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2\nCMSDigestType=2\nCDHash=78b01963732b743659b501c5beedc96a725f1156\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 00:20:39\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"installedSignatureVerified": true,
"installedStapleValidated": true,
"gatekeeperAccepted": true,
"pluginDiscovery": {
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"formalPath": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"output": " com.dayu.beatygril.fxplug(1.1)\t2293B0A5-4D98-4AE9-88F7-7022E3485E14\t2026-10-21 16:21:03 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)\n"
},
"removedGeneratedPaths": [
"/Users/dayu/Documents/PaintFCP/build/delivery/previous-beatygril.app",
"/tmp/paintfcp-build-20261021",
"/Users/dayu/Documents/PaintFCP/build/delivery/notarization.zip"
]
}
@@ -0,0 +1,16 @@
{
"remote": "https://dayu.media/git/dayu/paintfcp-fxplug.git",
"tag": "v1.1.2",
"sourceCommit": "a2e33e8e00a99b95dc29d67a819cb0897eda5756",
"passed": true,
"testsNotRepeated": "Source is byte-identical to the independently recovered and Inspector-ASan-tested signed source node.",
"tagCommit": "e9fddda5e13042f761755762fa39dfe090853c6a",
"productSourceIdenticalToSignedNode": true,
"trackedFiles": 158,
"allBytesBlobsModesMatch": true,
"gitFsck": "",
"lfs": false,
"submodules": false,
"temporaryCloneRemoved": true,
"completedAt": "2026-10-21T16:32:45.814667+00:00"
}
@@ -0,0 +1,33 @@
2026-10-21 23:54:44.774 host-tests[25302:5759794] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
Default IOSurface maximum byte difference: 0
Alternate destination tag maximum byte difference: 0
Anatomy default 0/0 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 0/1 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 1/0 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 1/1 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy big-eye 0/0 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 0/1 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 1/0 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 1/1 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy chin-positive 0/0 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 0/1 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 1/0 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 1/1 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-negative 0/0 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 0/1 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 1/0 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 1/1 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy short-positive 0/0 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-positive 0/1 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-positive 1/0 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-positive 1/1 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-negative 0/0 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy short-negative 0/1 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy short-negative 1/0 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy short-negative 1/1 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy jaw 0/0 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy jaw 0/1 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy jaw 1/0 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy jaw 1/1 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Legacy fallback upright comparison: max=2 mean=0.0010357
Host adapter: 335 checks, 0 failures
@@ -0,0 +1,10 @@
{
"status": "passed",
"productionSourceSHA256": "e4122ca95f7ba41bc925b4cc4bf2bf88a72044ea41880cd66acd9c8278a7daf4",
"review": "Independent read-only review against recovered CPU constants and AIR: jaw six triples/radius/sequence, short polygon/axis/sign/thresholds, one landmark Y conversion, 56 argument layout, missing-topology pass-through. No blocking defect found.",
"extraChecks": {
"AIRProductCrossingCases": 30000,
"axisYConversionIdentities": 1000
},
"scope": "Five remaining approximate shape controls and full combined-chain equivalence remain outside this repair. Sampled anatomical upper-contour/pupil points do not prove every temple pixel under all poses is unchanged. Native combined-build QA pending."
}
@@ -0,0 +1 @@
Inspector: 157 checks, 0 failures
@@ -0,0 +1,2 @@
com.dayu.beatygril.fxplug(1.1) 2293B0A5-4D98-4AE9-88F7-7022E3485E14 2026-10-21 16:21:03 +0000 /Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit
(1 plug-in)
@@ -0,0 +1,24 @@
Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril
Identifier=com.dayu.beatygril
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=78b01963732b743659b501c5beedc96a725f1156
CandidateCDHashFull sha256=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2
Hash choices=sha256
CMSDigest=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2
CMSDigestType=2
CDHash=78b01963732b743659b501c5beedc96a725f1156
Signature size=8968
Authority=Developer ID Application: zhong luo (B3W25FX5H5)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Oct 22, 2026 at 00:20:39
Notarization Ticket=stapled
Info.plist entries=22
TeamIdentifier=B3W25FX5H5
Runtime Version=27.0.0
Sealed Resources version=2 rules=13 files=4
Internal requirements count=1 size=180
Total signatures=1
Chosen signature=1
@@ -0,0 +1,93 @@
{
"version": "1.1.2",
"build": "13",
"date": "2026-10-21T16:31:12.717850+00:00",
"sourceCommit": "a2e33e8e00a99b95dc29d67a819cb0897eda5756",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"codesign": {
"exitCode": 0,
"stdout": "",
"stderr": ""
},
"staple": {
"exitCode": 0,
"stdout": "Processing: /Library/Plug-Ins/FxPlug/beatygril.app\nThe validate action worked!",
"stderr": ""
},
"gatekeeper": {
"exitCode": 0,
"stdout": "",
"stderr": "/Library/Plug-Ins/FxPlug/beatygril.app: accepted\nsource=Notarized Developer ID"
},
"identity": [
{
"path": "/Library/Plug-Ins/FxPlug/beatygril.app",
"bundleIdentifier": "com.dayu.beatygril",
"version": "1.1.2",
"build": "13",
"archs": "x86_64 arm64",
"signature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=78b01963732b743659b501c5beedc96a725f1156\nCandidateCDHashFull sha256=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2\nHash choices=sha256\nCMSDigest=78b01963732b743659b501c5beedc96a725f11560ebafe992a93195b3bae4dc2\nCMSDigestType=2\nCDHash=78b01963732b743659b501c5beedc96a725f1156\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 00:20:39\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1"
},
{
"path": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"version": "1.1.2",
"build": "13",
"archs": "x86_64 arm64",
"signature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit/Contents/MacOS/beatygril XPC Service\nIdentifier=com.dayu.beatygril.fxplug\nFormat=bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=869 flags=0x10000(runtime) hashes=20+3 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=79f2d1c3d638b27b2e5edeccf5d9255f6dd484b3\nCandidateCDHashFull sha256=79f2d1c3d638b27b2e5edeccf5d9255f6dd484b39910fe88ebdb2d09bd42bea4\nHash choices=sha256\nCMSDigest=79f2d1c3d638b27b2e5edeccf5d9255f6dd484b39910fe88ebdb2d09bd42bea4\nCMSDigestType=2\nCDHash=79f2d1c3d638b27b2e5edeccf5d9255f6dd484b3\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 00:20:38\nInfo.plist entries=26\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=188\nTotal signatures=1\nChosen signature=1"
}
],
"template": [
{
"path": "/Users/dayu/Movies/Motion Templates.localized/Effects.localized/大鱼/大鱼人像美化/大鱼人像美化.moef",
"bytes": 23073,
"sha256": "e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15"
},
{
"path": "/Users/dayu/Movies/Motion Templates.localized/Effects.localized/大鱼/大鱼人像美化/Drop Zone.tiff",
"bytes": 420128,
"sha256": "a7f8e3a2a431dbb3ce9e777040bb55e701cfe9ab9632e8cbb10359732bc8692e"
}
],
"discovery": {
"exitCode": 0,
"stdout": "com.dayu.beatygril.fxplug(1.1)\t2293B0A5-4D98-4AE9-88F7-7022E3485E14\t2026-10-21 16:21:03 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)",
"stderr": ""
},
"duplicateInventory": {
"scopes": [
"/Users/dayu/Documents/PaintFCP",
"/Users/dayu/.codex/worktrees",
"/Users/dayu/Library/Developer/Xcode/DerivedData",
"/Users/dayu/Desktop",
"/Users/dayu/Downloads",
"/Applications",
"/Library/Plug-Ins/FxPlug",
"/Users/dayu/Library/Plug-Ins/FxPlug",
"/private/tmp/paintfcp-format-probe.PsxvYQ",
"/private/tmp/paintfcp-y-review.KpPi8T",
"/private/tmp/paintfcp-live-review.ItH4EG",
"/private/tmp/paintfcp-slim-field.6fDdJj",
"/private/tmp/paintfcp-chin-smoke.rfco16hq",
"/private/tmp/paintfcp-rea.b3j9Te",
"/private/tmp/paintfcp-slim-smoke.3ncdDe"
],
"matchingOuterApps": [
{
"path": "/Library/Plug-Ins/FxPlug/beatygril.app",
"bundleIdentifier": "com.dayu.beatygril",
"version": "1.1.2",
"build": "13"
}
],
"errors": [],
"spotlight": {
"exitCode": 0,
"existingProductPaths": [
"/Library/Plug-Ins/FxPlug/beatygril.app"
]
},
"scopeLimit": "Bounded directories and existing indexed product paths; no full-volume completeness claim."
},
"nativeQAScope": "native-qa.json"
}
@@ -0,0 +1,44 @@
{
"status": "failed",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"options": {
"waitForHosts": true,
"userTests": false
},
"nativeEffectQA": {
"status": "pending_operator",
"performedByScript": false
},
"source": {
"commit": "183bf0e4b2227477c4d38cb201ce2c0279eeb740",
"trackedWorktreeChanges": []
},
"updatedAt": "2026-10-21T16:06:51.497292+00:00",
"version": "1.1.2",
"build": "11",
"stagingSignature": "Executable=/private/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=8e50a6a2b99f93880d8a5a8b5978d120a227a6b7\nCandidateCDHashFull sha256=8e50a6a2b99f93880d8a5a8b5978d120a227a6b72d1b6480bef338f2c8f1fbd4\nHash choices=sha256\nCMSDigest=8e50a6a2b99f93880d8a5a8b5978d120a227a6b72d1b6480bef338f2c8f1fbd4\nCMSDigestType=2\nCDHash=8e50a6a2b99f93880d8a5a8b5978d120a227a6b7\nSignature size=8969\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 21, 2026 at 23:57:21\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"notarization": {
"message": "Processing complete",
"id": "a9b454c3-5d30-47bd-b266-f19447f3db7e",
"status": "Accepted"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"runningHosts": [],
"installedSignature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=8e50a6a2b99f93880d8a5a8b5978d120a227a6b7\nCandidateCDHashFull sha256=8e50a6a2b99f93880d8a5a8b5978d120a227a6b72d1b6480bef338f2c8f1fbd4\nHash choices=sha256\nCMSDigest=8e50a6a2b99f93880d8a5a8b5978d120a227a6b72d1b6480bef338f2c8f1fbd4\nCMSDigestType=2\nCDHash=8e50a6a2b99f93880d8a5a8b5978d120a227a6b7\nSignature size=8969\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 21, 2026 at 23:57:21\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"installedSignatureVerified": true,
"installedStapleValidated": true,
"gatekeeperAccepted": true,
"pluginDiscovery": {
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"formalPath": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"output": " com.dayu.beatygril.fxplug(1.1)\tEFA7AB61-D5AA-44BB-B096-FF6BF12E7D02\t2026-10-21 15:57:43 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)\n"
},
"failure": {
"type": "KeyboardInterrupt",
"message": ""
},
"interimReason": "Native testing found number field focus-loss resubmission; combined build11 not accepted as final."
}
@@ -0,0 +1,44 @@
{
"status": "failed",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"options": {
"waitForHosts": true,
"userTests": false
},
"nativeEffectQA": {
"status": "pending_operator",
"performedByScript": false
},
"source": {
"commit": "3f075922cbdd7b80b9609cb0640bc2591ad3240b",
"trackedWorktreeChanges": []
},
"updatedAt": "2026-10-21T16:18:39.997054+00:00",
"version": "1.1.2",
"build": "12",
"stagingSignature": "Executable=/private/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=c50126c3762c66d9fcdc3890d3393ede57f75958\nCandidateCDHashFull sha256=c50126c3762c66d9fcdc3890d3393ede57f75958be276e1a4a83e1c11ed239b3\nHash choices=sha256\nCMSDigest=c50126c3762c66d9fcdc3890d3393ede57f75958be276e1a4a83e1c11ed239b3\nCMSDigestType=2\nCDHash=c50126c3762c66d9fcdc3890d3393ede57f75958\nSignature size=8969\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 00:14:13\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"notarization": {
"message": "Processing complete",
"status": "Accepted",
"id": "dbe3476f-c9d3-419d-9041-5180a37568dd"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"runningHosts": [],
"installedSignature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=c50126c3762c66d9fcdc3890d3393ede57f75958\nCandidateCDHashFull sha256=c50126c3762c66d9fcdc3890d3393ede57f75958be276e1a4a83e1c11ed239b3\nHash choices=sha256\nCMSDigest=c50126c3762c66d9fcdc3890d3393ede57f75958be276e1a4a83e1c11ed239b3\nCMSDigestType=2\nCDHash=c50126c3762c66d9fcdc3890d3393ede57f75958\nSignature size=8969\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 00:14:13\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=4\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"installedSignatureVerified": true,
"installedStapleValidated": true,
"gatekeeperAccepted": true,
"pluginDiscovery": {
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"formalPath": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"output": " com.dayu.beatygril.fxplug(1.1)\t51B2D2BF-2C90-41AA-BC26-50CFC1F824A9\t2026-10-21 16:14:42 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)\n"
},
"failure": {
"type": "KeyboardInterrupt",
"message": ""
},
"interimReason": "Geometry loads and reset changes slider; remote text editor remains focused and shows stale submitted text. Final dirty-aware refresh/abortEditing refinement pending build13."
}
+48
查看文件
@@ -0,0 +1,48 @@
{
"version": "1.1.2",
"build": "13",
"sourceCommit": "a2e33e8e00a99b95dc29d67a819cb0897eda5756",
"date": "2026-10-21T16:31:02.046442+00:00",
"Motion": {
"formalInstalledPluginLoaded": true,
"numberInput": true,
"singleResetUpdatesSliderAndText": true,
"hostUndoUpdatesSliderAndText": true,
"switchingEditedControlPreservesUndoneState": true,
"saveCloseReopen": {
"shortFace": 0.5,
"jaw": 0
},
"earlierSameGeometryBuild11": "Isolated short +1/-1 and jaw +1; same-frame bypass is byte-identical to neutral viewer; profile and tilted-face images inspected. PGFaceProcessor bytes unchanged in final build13."
},
"FCP": {
"formalInstalledPluginLoaded": true,
"nativePanelEnabled": true,
"numberInput": true,
"singleResetUpdatesSliderAndText": true,
"shapeIsolation": "Smoothing/color cards bypassed; other eight shape values cleared; short +1 and jaw +1 separately rendered on the same frame.",
"viewerRespondedToEachIsolatedControl": true,
"qaTimelineOnly": true
},
"continuousPreview": {
"production": "Each changed continuous step finishes its FxPlug host action before mouse-up; repeated equal steps are deduplicated.",
"automated": "Three intermediate snapshots published before gesture end; production view/controller exercised under action-scoped mock.",
"nativePointerObservation": "User confirmed on 2026-10-22 (Asia/Shanghai): 拖动中已持续更新. Native held-drag visual behavior is accepted by the user; the host was not specified and per-event frame timing was not instrumented.",
"userAcceptance": {
"date": "2026-10-22",
"timezone": "Asia/Shanghai",
"version": "1.1.2",
"build": "13",
"response": "拖动中已持续更新",
"passed": true,
"scope": "User-observed continuous preview during held slider drag in at least one native host; does not establish separate held-drag acceptance in both Motion and FCP or a frame for every mouse event."
}
},
"limits": [
"No claim that every mouse event is presented as a separate host frame. Host scheduling and render speed can coalesce rapid updates.",
"Remaining five approximate shape algorithms and full combined-chain pixel equivalence remain outside this repair.",
"Some legacy Motion QA documents retain serialized standard parameter sections; new registration and current FCP template hide them.",
"Native VoiceOver, old independent keyframe-curve migration, and exhaustive multi-face/all-pose testing not performed."
],
"privateEvidence": "User video, native screenshots, full AX and pixel-coordinate comparisons remain in ignored build/native-112; not uploaded."
}
@@ -0,0 +1 @@
{"message":"Processing complete","id":"5f5ce378-8430-467b-ae97-048e6bc81573","status":"Accepted"}
+21
查看文件
@@ -0,0 +1,21 @@
2026-10-21 23:54:43.574 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.25,0.75) setter=(0.25,0.75) readback=(0.25,0.75) mode=normalized verified=1
2026-10-21 23:54:43.583 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(80,180) surface=320x240 origin=0
2026-10-21 23:54:44.244 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.8,0.3) setter=(1152,-432) readback=(0.8,0.3) mode=centered-pixels verified=1
2026-10-21 23:54:44.244 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.7,0.4) objectBounds=(-1920,-1080,3840,2160) canvas=(152,78) surface=320x240 origin=0
2026-10-21 23:54:44.321 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.8,0.3) setter=(0.8,0.3) readback=(0.12345,0.87654) mode=normalized verified=0
2026-10-21 23:54:44.321 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.75,0.25) setter=(0.75,0.25) readback=(0.75,0.25) mode=normalized verified=1
2026-10-21 23:54:44.321 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.75,0.25) objectBounds=(-100,-50,200,100) canvas=(160,60) surface=320x240 origin=0
2026-10-21 23:54:44.402 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.625,0.375) setter=(0.625,0.375) readback=(0.625,0.375) mode=normalized verified=1
2026-10-21 23:54:44.402 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.625,0.375) objectBounds=(-100,-50,200,100) canvas=(240,60) surface=320x240 origin=0
2026-10-21 23:54:44.483 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.25,0.75) setter=(0.25,0.75) readback=(0.25,0.75) mode=normalized verified=1
2026-10-21 23:54:44.483 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(144,180) surface=320x240 origin=0
2026-10-21 23:54:44.561 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:54:44.561 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0,1) objectBounds=(-100,-50,200,100) canvas=(100,140) surface=320x240 origin=0
2026-10-21 23:54:44.646 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(nan,nan) surface=320x240 origin=0
2026-10-21 23:54:44.721 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:54:44.721 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(inf,nan) surface=320x240 origin=0
2026-10-21 23:54:44.806 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:54:44.807 osc-tests[25289:5759689] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(80,nan) surface=320x240 origin=0
2026-10-21 23:54:44.889 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-21 23:54:44.889 osc-tests[25289:5759689] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
OSC adapter: 98 checks, 0 failures
@@ -0,0 +1,2 @@
2026-10-21 23:46:52.888 slim-tests-asan[24731:5744056] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
PASS: 886 slim alignment checks; maximum UV oracle error 1.09828022e-05
文件差异过大,未显示。 加载差异
@@ -0,0 +1,11 @@
Target: a2e33e8e00a99b95dc29d67a819cb0897eda5756
Remote: https://dayu.media/git/dayu/paintfcp-fxplug.git
Passed: True
Tracked files: 149
All tracked bytes/blob IDs/modes: True
Git fsck --strict --full: 0
LFS/submodules: [] / []
Inspector tests: {'checks': 157, 'failures': 0, 'ASan': True, 'exitCode': 0, 'log': 'inspector-tests-asan.txt'}
Template audit: structure_verified_native_loading_pending
Core 961 tests not repeated; no APP build/host/UI/sign/install.
Temporary clone removed: True
@@ -0,0 +1 @@
Inspector: 157 checks, 0 failures
@@ -0,0 +1,36 @@
{
"article_id": 15593,
"url": "https://dayu.media/15593/",
"status": "publish",
"updated_fields": [
"content"
],
"attribution": "代码由 OpenAI + Codex 全程编写,站长仅参与调试和测试。",
"removed_original_authorship_wording": true,
"anonymous_frontend_http": 200,
"frontend_attribution_verified": true,
"unrelated_settings_unchanged": true,
"preserved": [
"title",
"author account (article publisher)",
"excerpt",
"categories",
"tags",
"featured_media",
"resource including all free-download settings and URLs",
"seo",
"fcpx configuration",
"installation instructions and native code block"
],
"automatic_derived_change": {
"field": "fcpx.article_state.checked_at",
"before": "2026-10-22 01:52:41",
"after": "2026-10-22 02:01:36",
"meaning": "Content save hook refreshed check timestamp; sync remains disabled."
},
"frontend_seo_exact_and_unique": true,
"idempotency_key": "66b51f0d-24ed-4ed9-82fd-e61e626cec4b",
"before_content_sha256": "5968a343e8a9116a5adb7885eafd487acb23608be32d422144196454b1434290",
"after_content_sha256": "2701991a543b80114c062cc7ee68b83afff505dd9456cfe82f0b8819ea81b119",
"verification_time_utc": "2026-10-21T18:02:35.974219+00:00"
}
@@ -0,0 +1,44 @@
{
"status": "complete",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"options": {
"waitForHosts": false,
"userTests": false
},
"nativeEffectQA": {
"status": "operator_confirmed",
"performedByScript": false
},
"source": {
"commit": "696d5f39b30404ed5d1d4c25f61d17475c7fc91b",
"trackedWorktreeChanges": []
},
"updatedAt": "2026-10-21T17:39:12.166311+00:00",
"version": "1.2.0",
"build": "14",
"stagingSignature": "Executable=/private/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=c229cfbd5d26e1215ace1dd36e4442a412b52220\nCandidateCDHashFull sha256=c229cfbd5d26e1215ace1dd36e4442a412b52220f48215bd108107e1affb0b97\nHash choices=sha256\nCMSDigest=c229cfbd5d26e1215ace1dd36e4442a412b52220f48215bd108107e1affb0b97\nCMSDigestType=2\nCDHash=c229cfbd5d26e1215ace1dd36e4442a412b52220\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 01:32:31\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=5\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"notarization": {
"status": "Accepted",
"id": "3999fe91-a80e-49d3-9ed0-4003b82f6f54",
"message": "Processing complete"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"runningHosts": [],
"installedSignature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=c229cfbd5d26e1215ace1dd36e4442a412b52220\nCandidateCDHashFull sha256=c229cfbd5d26e1215ace1dd36e4442a412b52220f48215bd108107e1affb0b97\nHash choices=sha256\nCMSDigest=c229cfbd5d26e1215ace1dd36e4442a412b52220f48215bd108107e1affb0b97\nCMSDigestType=2\nCDHash=c229cfbd5d26e1215ace1dd36e4442a412b52220\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 01:32:31\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=5\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"installedSignatureVerified": true,
"installedStapleValidated": true,
"gatekeeperAccepted": true,
"pluginDiscovery": {
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"formalPath": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"output": " com.dayu.beatygril.fxplug(1.1)\tDECE2AF1-8D68-43B9-BE2E-6C97FB9EE96D\t2026-10-21 17:33:00 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)\n"
},
"removedGeneratedPaths": [
"/Users/dayu/Documents/PaintFCP/build/delivery/previous-beatygril.app",
"/tmp/paintfcp-build-20261021",
"/Users/dayu/Documents/PaintFCP/build/delivery/notarization.zip"
]
}
@@ -0,0 +1,17 @@
{
"roots": [
"/Applications",
"/Library/Plug-Ins/FxPlug",
"/Users/dayu/Library/Plug-Ins/FxPlug",
"/Users/dayu/Documents/PaintFCP",
"/tmp/paintfcp-build-20261021"
],
"product_paths": [
"/Library/Plug-Ins/FxPlug/beatygril.app"
],
"errors": [],
"removed": [
"build/pkg-expanded"
],
"scope": "bounded scan; not all mounted volumes"
}
@@ -0,0 +1,13 @@
{
"tag": "v1.2.0",
"commit": "3c7261c3a861b9f4704cfb36055d7b500c239dab",
"files_verified": 183,
"fsck_full_strict": true,
"package_sha256": "5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"recovered_package_signature_and_ticket": true,
"xcode_project_readable": true,
"lfs": false,
"submodules": false,
"authentication": "saved member Git credential; anonymous gateway access remains restricted",
"temporary_clone_removed": true
}
@@ -0,0 +1,22 @@
[
{
"path": "/Users/dayu/Documents/PaintFCP/Templates/大鱼人像美化/large.png",
"uchg": true,
"sha256": "a02ddb255b1ae255c749bb837a759e2dee1c3b8ffb9bdc1167957761bd5a1b97"
},
{
"path": "/Users/dayu/Documents/PaintFCP/Templates/大鱼人像美化/small.png",
"uchg": true,
"sha256": "1552b838dd88f60dee0795e20aaca652f9c558ecefc93500e895fbff77c2a4d5"
},
{
"path": "/Users/dayu/Movies/Motion Templates.localized/Effects.localized/大鱼磨皮瘦脸/大鱼人像美化/large.png",
"uchg": true,
"sha256": "a02ddb255b1ae255c749bb837a759e2dee1c3b8ffb9bdc1167957761bd5a1b97"
},
{
"path": "/Users/dayu/Movies/Motion Templates.localized/Effects.localized/大鱼磨皮瘦脸/大鱼人像美化/small.png",
"uchg": true,
"sha256": "1552b838dd88f60dee0795e20aaca652f9c558ecefc93500e895fbff77c2a4d5"
}
]
@@ -0,0 +1,2 @@
com.dayu.beatygril.fxplug(1.1) DECE2AF1-8D68-43B9-BE2E-6C97FB9EE96D 2026-10-21 17:33:00 +0000 /Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit
(1 plug-in)
@@ -0,0 +1,24 @@
Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril
Identifier=com.dayu.beatygril
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=c229cfbd5d26e1215ace1dd36e4442a412b52220
CandidateCDHashFull sha256=c229cfbd5d26e1215ace1dd36e4442a412b52220f48215bd108107e1affb0b97
Hash choices=sha256
CMSDigest=c229cfbd5d26e1215ace1dd36e4442a412b52220f48215bd108107e1affb0b97
CMSDigestType=2
CDHash=c229cfbd5d26e1215ace1dd36e4442a412b52220
Signature size=8968
Authority=Developer ID Application: zhong luo (B3W25FX5H5)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Oct 22, 2026 at 01:32:31
Notarization Ticket=stapled
Info.plist entries=22
TeamIdentifier=B3W25FX5H5
Runtime Version=27.0.0
Sealed Resources version=2 rules=13 files=5
Internal requirements count=1 size=180
Total signatures=1
Chosen signature=1
@@ -0,0 +1,14 @@
[
{
"elapsed": 13.717,
"running": true,
"processes": [
"33709 /Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril"
]
},
{
"elapsed": 17.944,
"running": false,
"processes": []
}
]
+16
查看文件
@@ -0,0 +1,16 @@
{
"version": "1.2.0",
"build": "14",
"source_commit": "696d5f39b30404ed5d1d4c25f61d17475c7fc91b",
"native_app_card": "Observed correct classical information card, with accessible text",
"exit_timer_seconds_after_window_shown": 3.0,
"observed_process_lifetime_seconds": 4.227,
"process_lifetime_note": "Includes process initialization before didFinishLaunching/window presentation. Not a measurement of timer drift.",
"automatic_registration": "Own bundle registered via LSRegisterURL; installed PluginKit entry remains at unique formal path",
"host_validation": {
"FCP": "Fresh launch, new locked thumbnail visible in 大鱼磨皮瘦脸; applied ours to second clip in existing QA project; panel loaded, brightness set to20%, picture rendered without black output.",
"Motion": "No fresh 1.2.0 UI test; renderer and inspector source unchanged from user-accepted 1.1.2."
},
"screenshots": "Native app and FCP screenshots kept local under ignored build/delivery; user stock imagery not published",
"bounded_duplicate_inventory": "Final cleanup removed known build and backup app paths; final inventory follows in packaging verification."
}
@@ -0,0 +1 @@
{"status":"Accepted","id":"3999fe91-a80e-49d3-9ed0-4003b82f6f54","message":"Processing complete"}
@@ -0,0 +1,6 @@
{
"name": "大鱼人像美化-1.2.0.pkg",
"id": "96a3d1be-a751-4fb8-b062-33a09c01ddf2",
"status": "Accepted",
"createdDate": "2026-10-21T17:39:18.173Z"
}
@@ -0,0 +1,36 @@
{
"package": "releases/1.2.0/大鱼人像美化-1.2.0.pkg",
"bytes": 5011005,
"sha256": "5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"version": "1.2.0",
"build": "14",
"app_files_compared": 34,
"app_byte_and_symlink_equality": true,
"template_files": {
"大鱼人像美化.moef": "e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15",
"Drop Zone.tiff": "a7f8e3a2a431dbb3ce9e777040bb55e701cfe9ab9632e8cbb10359732bc8692e",
"large.png": "a02ddb255b1ae255c749bb837a759e2dee1c3b8ffb9bdc1167957761bd5a1b97",
"small.png": "1552b838dd88f60dee0795e20aaca652f9c558ecefc93500e895fbff77c2a4d5"
},
"locked_relative_paths": [
"大鱼人像美化/large.png",
"大鱼人像美化/small.png"
],
"script_sha256": {
"preinstall": "b0562f7705c84a2f34e31df67a4f0d429e60083bab122dad99f56a4b266c0174",
"postinstall": "eeada4e07a284726d70772591c481f6ae12bfda12ed9ae3035d1089bca0bd59b"
},
"isolated_script_tests": [
"fresh install",
"replace old locked thumbnail",
"partial copy failure restores old bytes and locks"
],
"isolation_changes": [
"Console identity/home redirected to task fixture",
"chown replaced with true",
"FxPlug verification skipped; formal app signature and discovery verified separately"
],
"real_installer_execution": false,
"app_and_template_installed": "APP installed through signed delivery workflow; user thumbnail directory updated separately, not by running this PKG",
"fonts": "No editable third-party font dependency; promotional lettering baked into PNG. No optional font ZIP needed."
}
@@ -0,0 +1,11 @@
{
"checked_commit": "906f770805fdbe8329c9d4ecd3594310e23bca6a",
"reachable_blobs_scanned": 356,
"secret_pattern_matches": [],
"disallowed_extensions": [],
"notes": [
"No original competitor app, metallib, model or user stock video is included.",
"NASA astronaut sample retains its source attribution.",
"Tool-generated promotional art is labeled as illustration."
]
}
@@ -0,0 +1,59 @@
{
"article_id": 15593,
"url": "https://dayu.media/15593/",
"status": "publish",
"anonymous_http": 200,
"category": 3,
"free_for_all": true,
"featured_media": 15595,
"native_code_block_present": true,
"seo_tags": {
"title": [
"大鱼人像美化 1.2.0|FCP / Motion 免费开源自动美颜插件"
],
"description": [
"大鱼人像美化是适用于 Final Cut Pro 和 Motion 的免费开源 FxPlug4 插件,支持磨皮、美白、自动人脸跟随及瘦脸调整。提供 Apple 签名公证 PKG 安装包和源码,安装自动注册,无需激活码,并附具体安装、使用及红色警告排查说明。"
],
"keywords": [
"大鱼人像美化,FCP美颜插件,Motion磨皮,自动瘦脸,自动跟随,FxPlug4,免费开源"
],
"unique_and_exact": true
},
"assets": [
{
"role": "package",
"url": "https://dayu.media/wp-content/uploads/2026/10/1792604749-1ea4dca3cc5a5c3.pkg",
"anonymous_http": 200,
"bytes": 5011005,
"sha256": "5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243",
"matches_local": true
},
{
"role": "source",
"url": "https://dayu.media/wp-content/uploads/2026/10/1792604741-f6e09da5b67c006.zip",
"anonymous_http": 200,
"bytes": 9607987,
"sha256": "a235fb3168c09a1e3a4fc5f347b3957cbd9ee2a1c3848e2af1dda2e64afbb870",
"matches_local": true
},
{
"role": "cover",
"url": "https://dayu.media/wp-content/uploads/2026/10/1792604750-357ca780597c39f.png",
"anonymous_http": 200,
"bytes": 2776027,
"sha256": "a346f06e7793b4e5483ccd4b3b86f34c2036bbe6bbddb7ad9cc70c47e7d014ab",
"matches_local": true
},
{
"role": "card",
"url": "https://dayu.media/wp-content/uploads/2026/10/1792604743-1c99c2ba53c7614.png",
"anonymous_http": 200,
"bytes": 3065968,
"sha256": "239552eeea738a32fafa70922d3cd1d4c115ff75d672574fa4c5acd941381fba",
"matches_local": true
}
],
"source_article_click_anonymous_verified": true,
"fcpx_app_sync_requested": false,
"git_visibility": "Gitea public attribute verified; anonymous gateway access still requires membership as disclosed in article"
}
@@ -0,0 +1,85 @@
{
"article": {
"id": 15593,
"url": "https://dayu.media/15593/",
"edit_url": "https://dayu.media/wp-admin/post.php?post=15593&action=edit",
"status": "publish",
"title": "大鱼人像美化 1.2.0:FCP / Motion 免费开源自动美颜插件",
"content": "<!-- wp:paragraph -->\n<p>大鱼人像美化是一款适用于 Final Cut Pro 与 Motion 的免费开源人像插件,把磨皮、美白和脸型调整放进同一块原生卡片面板。插件会识别当前画面中的人脸并自动跟随,无需先点击分析;你可以按素材需要调整强度,拖动滑杆时持续查看效果。</p>\n<!-- /wp:paragraph -->\n<!-- wp:paragraph -->\n<p><strong>代码由 OpenAI + Codex 全程编写,站长仅参与调试和测试。</strong></p>\n<!-- /wp:paragraph -->\n\n<!-- wp:image {\"sizeSlug\":\"full\"} -->\n<figure class=\"wp-block-image size-full\"><img src=\"https://dayu.media/wp-content/uploads/2026/10/1792604750-357ca780597c39f.png\" alt=\"大鱼人像美化古风宣传封面,展示自动瘦脸、自动跟随与自动美颜\" /><figcaption class=\"wp-element-caption\">古风宣传插画;面部线条用于示意瘦脸与跟随功能。</figcaption></figure>\n<!-- /wp:image -->\n\n<!-- wp:heading -->\n<h2 class=\"wp-block-heading\">可以做什么</h2>\n<!-- /wp:heading -->\n\n<!-- wp:list {\"className\":\"wp-block-list\"} -->\n<ul class=\"wp-block-list\"><!-- wp:list-item -->\n<li>磨皮:局部磨皮、全局磨皮与五官保护,强度分别控制。</li>\n<!-- /wp:list-item -->\n\n<!-- wp:list-item -->\n<li>美白:肤色预设、肤色亮度、皮肤色相和牙齿美白。</li>\n<!-- /wp:list-item -->\n\n<!-- wp:list-item -->\n<li>脸型:瘦脸、大眼、短脸、窄脸、下巴、V 脸、下颌骨、颧骨与小头调整。</li>\n<!-- /wp:list-item -->\n\n<!-- wp:list-item -->\n<li>自动跟随:默认跟随主要人脸,也提供多人模式、防跳脸范围与检测框预览。</li>\n<!-- /wp:list-item -->\n\n<!-- wp:list-item -->\n<li>实时预览:滑杆、数值、单项开关和重置集中在同一面板,便于反复对比。</li>\n<!-- /wp:list-item --></ul>\n<!-- /wp:list -->\n\n<!-- wp:paragraph -->\n<p>自动识别负责定位处理区域,效果强度由你控制。建议先从较小的数值开始;多人交叉、严重遮挡和极端侧脸的结果需要结合具体素材检查。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:heading -->\n<h2 class=\"wp-block-heading\">版本与下载</h2>\n<!-- /wp:heading -->\n\n<!-- wp:paragraph -->\n<p>当前版本 <strong>1.2.0(14)</strong>,支持 macOS 13 或更高版本,包含 Apple Silicon 与 Intel 两种架构。下载包包含 FxPlug4 程序和一个配套 FCP 效果模板。APP 与 PKG 均已完成 Developer ID 正式签名、Apple 公证和票据粘附;安装包为所有用户免费资源。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>本次更新加入古风封面与锁定缩略图、免费开源说明页和主 APP 三秒自动退出。人脸处理与面板交互沿用 1.1.2 已验收实现,不需要重新运行手动分析。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:heading -->\n<h2 class=\"wp-block-heading\">安装</h2>\n<!-- /wp:heading -->\n\n<!-- wp:paragraph -->\n<p>安装前先保存工作并退出 Final Cut Pro 和 Motion,安装期间保持关闭。运行本页提供的 PKG,按安装器提示完成安装;它会把程序安装到 <code>/Library/Plug-Ins/FxPlug/beatygril.app</code>,把配套效果安装到当前登录用户的 Motion Templates 目录,并自动验证和修复系统插件注册。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>本插件免费开源,<strong>无需激活码、付费注册或账号授权</strong>。主 APP 打开时显示说明图,窗口显示三秒后自动退出;宿主中的滤镜由独立服务运行。安装器还会重新锁定两张缩略图,避免被宿主自动替换。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:image {\"sizeSlug\":\"full\"} -->\n<figure class=\"wp-block-image size-full\"><img src=\"https://dayu.media/wp-content/uploads/2026/10/1792604743-1c99c2ba53c7614.png\" alt=\"主程序说明页:免费开源,自动注册,无需激活码,启动三秒后自动退出\" /></figure>\n<!-- /wp:image -->\n\n<!-- wp:heading -->\n<h2 class=\"wp-block-heading\">使用</h2>\n<!-- /wp:heading -->\n\n<!-- wp:paragraph -->\n<p>Final Cut Pro:打开<strong>效果</strong>浏览器,找到<strong>大鱼磨皮瘦脸</strong>分类,将<strong>大鱼人像美化</strong>添加到人像片段。Motion:在原生滤镜资源库的<strong>大鱼</strong>分类中选择<strong>大鱼人像美化</strong>。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>在检查器中按需调节磨皮、美白和脸型。每项左侧的眼睛可暂时停用该项,数值会保留;右侧回转箭头用于重置。人脸会随画面自动更新,开启检测框预览可以检查跟随位置。多人模式建议先用短片段观察稳定性。</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:heading -->\n<h2 class=\"wp-block-heading\">常见问题</h2>\n<!-- /wp:heading -->\n\n<!-- wp:paragraph -->\n<p>如果效果没有出现或显示红色警告,先退出 Final Cut Pro 和 Motion,Line truncated
"excerpt": "磨皮、美白、瘦脸与自动人脸跟随,原生卡片面板实时预览。免费开源,自动注册,无需激活码;提供签名公证安装包和源码。",
"author": 1,
"categories": [
3
],
"tags": [],
"featured_media": 15595,
"resource": {
"cao_status": "1",
"cao_close_novip_pay": "0",
"cao_is_boosvip": "",
"cao_video": "",
"cao_is_video_free": "",
"cao_price": "0",
"cao_vip_rate": "1",
"cao_ref_bonus_rate": "0.25",
"cao_expire_day": "0",
"cao_downurl": "https://dayu.media/wp-content/uploads/2026/10/1792604749-1ea4dca3cc5a5c3.pkg",
"cao_downurl_bak": "",
"cao_demourl": "",
"video_url": "",
"video_poster_url": "",
"cao_pwd": "",
"cao_original_filename": "1792604749-1ea4dca3cc5a5c3.pkg",
"post_style": "sidebar",
"cao_info": [
{
"title": "版本",
"desc": "1.2.0(14)"
},
{
"title": "宿主",
"desc": "Final Cut Pro / Motion"
},
{
"title": "系统",
"desc": "macOS 13 或更高版本"
},
{
"title": "架构",
"desc": "Apple Silicon / Intel"
},
{
"title": "授权",
"desc": "免费开源,无需激活码"
}
]
},
"seo": {
"title": {
"enabled": true,
"value": "大鱼人像美化 1.2.0|FCP / Motion 免费开源自动美颜插件"
},
"description": {
"enabled": true,
"value": "大鱼人像美化是适用于 Final Cut Pro 和 Motion 的免费开源 FxPlug4 插件,支持磨皮、美白、自动人脸跟随及瘦脸调整。提供 Apple 签名公证 PKG 安装包和源码,安装自动注册,无需激活码,并附具体安装、使用及红色警告排查说明。"
},
"keywords": {
"enabled": true,
"value": "大鱼人像美化,FCP美颜插件,Motion磨皮,自动瘦脸,自动跟随,FxPlug4,免费开源"
}
},
"fcpx": {
"enabled": "0",
"kinds": [],
"version": "",
"entry": "",
"article_state": {
"code": "hidden",
"message": "未同步到 APP",
"checked_at": "2026-10-22 03:32:39"
},
"file_check": "",
"product_id": ""
}
}
}
+7
查看文件
@@ -0,0 +1,7 @@
# 1.2.0 / build 14
本次只修改外层启动器、版本和宣传资源;PGFaceProcessor、PGBeautyRenderer、PGInspectorView、PGInspectorState 与 Metal 渲染算法保持 1.1.2 用户验收版本。缩略图以用户指定的生成宣传画为来源,不冒充真实渲染静帧。
安装分类使用当前用户已移动后的 `Effects.localized/大鱼磨皮瘦脸/大鱼人像美化`。本地磁盘 moef 与源码基线 SHA-256 均为 e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15,未覆盖任何最新手改。只为 large.png / small.png 设置 uchg。
待验证:正式 Release 构建、双架构、APP 签名 / 公证 / 票据 / 安装 / 插件发现、启动器三秒退出、PKG 签名公证与有效载荷 / 缩略图锁定脚本、远端发布与文章。
@@ -0,0 +1,8 @@
{
"id": 1,
"name": "Dayu-Portrait-1.2.0.pkg",
"size": 5011005,
"browser_download_url": "https://dayu.media/git/attachments/2d27be42-6380-421c-8475-7524574ec889",
"uuid": "2d27be42-6380-421c-8475-7524574ec889",
"created_at": "2026-10-22T01:48:05+08:00"
}
@@ -0,0 +1,10 @@
{
"id": 128,
"tag_name": "v1.2.0",
"name": "大鱼人像美化 1.2.0",
"html_url": "https://dayu.media/git/dayu/paintfcp-fxplug/releases/tag/v1.2.0",
"url": "https://dayu.media/git/api/v1/repos/dayu/paintfcp-fxplug/releases/128",
"draft": false,
"prerelease": false,
"body": "大鱼人像美化 1.2.0(14)\n\n免费开源。自动跟随、人像磨皮、美白和脸型调整。新增古风宣传封面与缩略图,主 APP 显示免费开源说明并在窗口显示三秒后退出。\n\nAPP 和 PKG 均已正式签名、Apple 公证并粘附票据。\n\n免费安装包与免 Git 登录源码快照:https://dayu.media/15593/\n\n安装包仓库位置:releases/1.2.0/大鱼人像美化-1.2.0.pkg\nSHA-256:5bd77c28b3a7e54f3d4060be1f16bcb145d9bc4d6b9cfb9eb137c01130440243\n\n当前站点 Git 网关仍需登录;仓库公开属性已设为 public,站外读者可通过文章免费下载源码快照。"
}
@@ -0,0 +1,13 @@
{
"patch": "accepted",
"id": 36,
"private": false,
"url": "https://dayu.media/git/dayu/paintfcp-fxplug",
"anonymous_access": {
"html_http": 302,
"api_http": 401,
"git_ls_remote": "credential request denied in anonymous mode",
"reason": "Site-wide WordPress Git membership gateway is evaluated before Gitea public-repository permissions.",
"server_code_changed": false
}
}
@@ -0,0 +1,9 @@
{
"source_click_url": "https://dayu.media?cao_direct_download=1&file_url=https%3A%2F%2Fdayu.media%2Fwp-content%2Fuploads%2F2026%2F10%2F1792604741-f6e09da5b67c006.zip",
"http": 200,
"content_type": "application/octet-stream",
"final_url": "https://dayu.media?cao_direct_download=1&file_url=https%3A%2F%2Fdayu.media%2Fwp-content%2Fuploads%2F2026%2F10%2F1792604741-f6e09da5b67c006.zip",
"bytes": 9607987,
"sha256": "a235fb3168c09a1e3a4fc5f347b3957cbd9ee2a1c3848e2af1dda2e64afbb870",
"click_download_matches_source": true
}
@@ -0,0 +1,8 @@
{
"commit": "788ba0d5514595cf349af33074055d70b0754185",
"files": 182,
"package_excluded": true,
"filename": "Dayu-Portrait-1.2.0-source.zip",
"bytes": 9607987,
"sha256": "a235fb3168c09a1e3a4fc5f347b3957cbd9ee2a1c3848e2af1dda2e64afbb870"
}
@@ -0,0 +1,26 @@
{
"installationCategory": "大鱼磨皮瘦脸",
"template": "大鱼人像美化.moef",
"files": {
"大鱼人像美化.moef": {
"size": 23073,
"sha256": "e9fa97dc14323d0daa7d3d61b06a78ba4000a70ab9f5e67ebffd750d49df1e15",
"locked": false
},
"Drop Zone.tiff": {
"size": 420128,
"sha256": "a7f8e3a2a431dbb3ce9e777040bb55e701cfe9ab9632e8cbb10359732bc8692e",
"locked": false
},
"large.png": {
"size": 454742,
"sha256": "a02ddb255b1ae255c749bb837a759e2dee1c3b8ffb9bdc1167957761bd5a1b97",
"locked": true
},
"small.png": {
"size": 45373,
"sha256": "1552b838dd88f60dee0795e20aaca652f9c558ecefc93500e895fbff77c2a4d5",
"locked": true
}
}
}
@@ -0,0 +1,29 @@
{
"date": "2026-10-22",
"timezone": "Asia/Shanghai",
"version": "1.3.0",
"build": "15",
"status": "passed",
"checks": {
"beauty": 57,
"face": 116,
"geometry": 796,
"host_adapter_asan": 341,
"osc_asan": 98,
"inspector_asan_including_optional_preview": 228
},
"total": 1636,
"commands": [
"./scripts/test.sh",
"PAINTFCP_HOST_ASAN=1 ./scripts/test-host.sh",
"PAINTFCP_OSC_ASAN=1 ./scripts/test-osc.sh",
"PAINTFCP_INSPECTOR_ASAN=1 PAINTFCP_INSPECTOR_PNG=<local-path> ./scripts/test-inspector.sh"
],
"notes": [
"OSC passed before the later standalone beauty fallback and legacy inspector numeric-read fixes; those fixes do not change OSC code.",
"Core, host adapter and inspector rerun after all source fixes.",
"Inspector includes one optional offscreen PNG write assertion.",
"No native Motion/FCP interaction test performed for this version; active user hosts are preserved.",
"Reference interpretation and implementation limitations are in docs/analysis/新版磨皮参数迁移.md."
]
}
@@ -0,0 +1,44 @@
{
"status": "installed_user_qa_pending",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"options": {
"waitForHosts": true,
"userTests": true
},
"nativeEffectQA": {
"status": "pending_user",
"performedByScript": false
},
"source": {
"commit": "2f2c081980dc610ac810f8daf92da8966f310802",
"trackedWorktreeChanges": []
},
"updatedAt": "2026-10-22T07:15:35.383726+00:00",
"version": "1.3.0",
"build": "15",
"stagingSignature": "Executable=/private/tmp/paintfcp-build-20261021/Build/Products/Release/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=93e3245cafc8ced5f2c01b8a72c8e0c3933eee83\nCandidateCDHashFull sha256=93e3245cafc8ced5f2c01b8a72c8e0c3933eee837831a2d779233e4364dded7c\nHash choices=sha256\nCMSDigest=93e3245cafc8ced5f2c01b8a72c8e0c3933eee837831a2d779233e4364dded7c\nCMSDigestType=2\nCDHash=93e3245cafc8ced5f2c01b8a72c8e0c3933eee83\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 15:07:35\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=5\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"notarization": {
"id": "ca96837f-bf33-44fa-8d58-799026ce5c7d",
"message": "Processing complete",
"status": "Accepted"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"runningHosts": [],
"installedSignature": "Executable=/Library/Plug-Ins/FxPlug/beatygril.app/Contents/MacOS/beatygril\nIdentifier=com.dayu.beatygril\nFormat=app bundle with Mach-O universal (x86_64 arm64)\nCodeDirectory v=20500 size=478 flags=0x10000(runtime) hashes=4+7 location=embedded\nHash type=sha256 size=32\nCandidateCDHash sha256=93e3245cafc8ced5f2c01b8a72c8e0c3933eee83\nCandidateCDHashFull sha256=93e3245cafc8ced5f2c01b8a72c8e0c3933eee837831a2d779233e4364dded7c\nHash choices=sha256\nCMSDigest=93e3245cafc8ced5f2c01b8a72c8e0c3933eee837831a2d779233e4364dded7c\nCMSDigestType=2\nCDHash=93e3245cafc8ced5f2c01b8a72c8e0c3933eee83\nSignature size=8968\nAuthority=Developer ID Application: zhong luo (B3W25FX5H5)\nAuthority=Developer ID Certification Authority\nAuthority=Apple Root CA\nTimestamp=Oct 22, 2026 at 15:07:35\nNotarization Ticket=stapled\nInfo.plist entries=22\nTeamIdentifier=B3W25FX5H5\nRuntime Version=27.0.0\nSealed Resources version=2 rules=13 files=5\nInternal requirements count=1 size=180\nTotal signatures=1\nChosen signature=1\n",
"installedSignatureVerified": true,
"installedStapleValidated": true,
"gatekeeperAccepted": true,
"pluginDiscovery": {
"bundleIdentifier": "com.dayu.beatygril.fxplug",
"formalPath": "/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit",
"output": " com.dayu.beatygril.fxplug(1.1)\t97262612-DD61-47F2-B25E-D82B95C893EE\t2026-10-22 07:15:35 +0000\t/Library/Plug-Ins/FxPlug/beatygril.app/Contents/PlugIns/beatygril XPC Service.pluginkit\n (1 plug-in)\n"
},
"removedGeneratedPaths": [
"/Users/dayu/Documents/PaintFCP/build/delivery/previous-beatygril.app",
"/tmp/paintfcp-build-20261021",
"/Users/dayu/Documents/PaintFCP/build/delivery/notarization.zip"
]
}
@@ -0,0 +1,38 @@
{
"status": "verified",
"date": "2026-10-22",
"timezone": "Asia/Shanghai",
"installedProduct": {
"path": "/Library/Plug-Ins/FxPlug/beatygril.app",
"version": "1.3.0",
"build": "15"
},
"signatureAllArchitecturesVerified": true,
"duplicateInventory": {
"scope": "Listed local paths and existing explicit related PaintFCP paths on mounted volumes; Spotlight additionally queried. Not a full scan of every volume.",
"roots": [
"/Applications",
"/Library/Plug-Ins/FxPlug",
"/Users/dayu/Library/Plug-Ins/FxPlug",
"/Users/dayu/Documents/PaintFCP",
"/Users/dayu/Desktop",
"/Users/dayu/Downloads",
"/Users/dayu/Library/Developer/Xcode/DerivedData",
"/tmp/paintfcp-build-20261021"
],
"products": [
{
"path": "/Library/Plug-Ins/FxPlug/beatygril.app",
"version": "1.3.0",
"build": "15"
}
],
"errors": []
},
"temporaryPathsRemoved": [
"/tmp/paintfcp-build-20261021",
"build/delivery/previous-beatygril.app",
"build/delivery/notarization.zip"
],
"nativeEffectQA": "pending_user"
}
@@ -0,0 +1,21 @@
{
"status": "waiting_for_host_exit",
"bundleIdentifier": "com.dayu.beatygril",
"installationPath": "/Library/Plug-Ins/FxPlug/beatygril.app",
"version": "1.3.0",
"build": "15",
"source": {
"commit": "2f2c081980dc610ac810f8daf92da8966f310802",
"trackedWorktreeChanges": []
},
"notarization": {
"id": "ca96837f-bf33-44fa-8d58-799026ce5c7d",
"message": "Processing complete",
"status": "Accepted"
},
"signingVerified": true,
"stapleValidated": true,
"stagingPluginUnregistered": true,
"nativeEffectQA": "pending_user",
"note": "Prepared Release is Accepted and stapled; installation is waiting for existing user hosts to close. The installed product has not been replaced."
}
@@ -0,0 +1,12 @@
{
"status": "verified",
"date": "2026-10-22",
"commit": "2f2c081980dc610ac810f8daf92da8966f310802",
"remote": "https://dayu.media/git/dayu/paintfcp-fxplug.git",
"branch": "codex/new-beauty-controls",
"trackedFilesCompared": 205,
"gitFsckFullStrict": true,
"lfs": false,
"submodules": false,
"resources": "All tracked source, template and artwork bytes match; user QA media/signing credentials are external and not required to compile source."
}
已加载 100/113 个文件。由于本次变更涉及的文件过多,其余文件未显示。 显示更多