diff --git a/assets/desktop_pet/classic_pet.js b/assets/desktop_pet/classic_pet.js index fbeb6f8a..78024bf1 100644 --- a/assets/desktop_pet/classic_pet.js +++ b/assets/desktop_pet/classic_pet.js @@ -139,6 +139,10 @@ const sway = (1 - Math.cos(now / 1900)) * peekStyle().hidden / 3; peekLean += ((hovered ? 12 : base === 'waiting' ? 9 : 0) - peekLean) * 0.12; o.dx = (docked === 'right' ? -1 : 1) * Math.min(peekStyle().hidden, sway + peekLean); + // Pixel art drawn without smoothing only changes once the offset crosses a pixel edge, so near + // the sway's turning points it would stand still for about two seconds; a small vertical bob a + // quarter period apart keeps it moving (the two never slow down together). + if (!peekStyle().smooth) o.dy = Math.sin(now / 1900) * 1.5; const since = now - peekBounceAt; if (peekBounce === 'happy' && since < 900) o.dy = -Math.abs(Math.sin(since / 90)) * 6 * (1 - since / 900); else if (peekBounce === 'shake' && since < 700) o.dx += Math.sin(since / 28) * 3 * (1 - since / 700); diff --git a/docs/desktop-agent-office.md b/docs/desktop-agent-office.md index df984832..d68d0fe2 100644 --- a/docs/desktop-agent-office.md +++ b/docs/desktop-agent-office.md @@ -16,7 +16,7 @@ Windows 与 macOS Desktop 可开启透明桌面宠物,默认关闭。设置 - **悬停**:鼠标移到宠物身上跳一下(Codex jumping,3 秒内不重复),悬停期间整个宠物框可点,避免跳动改变轮廓导致悬停闪烁。 - **单击**:做一个回应动作(回形针挥手、rover 被点、鲸鱼娘挥手);双击的第二下不会重复回应。 - **双击**:陪伴宠物双击把 ACECode 主窗口叫到前台(Codex Mini 也是直接打开主窗口),具体会话从卡片打开。虚拟办公室双击选中的人物打开其会话,双击空地打开当前会话,没有会话时也把主窗口叫到前台。Windows 由宠物窗口短暂挂接前台线程输入队列后激活主窗口(点击落在 WebView2 浏览器进程的子窗口里,本进程不一定有前台权限),macOS 走与通知点击相同的 `mac_bring_window_foreground`。 -- **趴边偷看(三只陪伴宠物都有)**:拖到屏幕左 / 右边缘附近松手(窗口中心离边缘不超过窗口宽度的 1/4,约等于身体碰到屏幕边),窗口贴到那条边,宠物换成从屏幕边探出半个身子偷看的样子(贴左边时镜像):鲸鱼娘双手扒着边,回形针把上半截钢丝和两只大眼睛探进来,rover 探出脑袋、两只前爪扒着边。缓慢地探进探出,每 2–5 秒眨一次眼、偶尔连眨两下;悬停时探得更靠里并开心地眯眼,有会话等你处理时也会多探出来一点,新完成的会话让它开心眯眼、失败时抖一下;双击照常打开 ACECode,再拖起来就恢复全身。缩放和恢复默认大小时保持贴边,「回到右下角」取消吸附;贴着边在右键菜单里换宠物,新宠物接着从同一条边偷看(页面记住窗口所在的边,素材还在解码时收到的贴边消息也不会丢)。画面都是用 Codex 按各自原有帧的画风画的两帧(睁眼 / 闭眼),来源与处理见 `assets/desktop_pet/whale/README.md` 与 `assets/desktop_pet/classic/README.md`。头的大小与其它姿势一致:鲸鱼娘的偷看原画比精灵帧大约 1.8 倍(眼睛高度、发箍到嘴的距离都量过),按常规帧缩放 ÷ 1.8 平滑绘制,曾经固定画成 170 像素高、头大了将近一倍;回形针与 rover 的偷看图直接做成精灵分辨率(眼睛大小与原帧一致),和原帧一样不平滑放大,像素颗粒一致。每只宠物藏在屏幕外的宽度(鲸鱼娘 9、像素宠物 4 个画布像素)与是否平滑在 `classic_pet.js` 的 `PEEK` 表,探进探出的幅度按藏边宽度缩放,不会顶到上限停住。吸附判定与贴边位置是 `desktop_pet_layout` 里的纯函数(`desktop_pet_has_edge_peek` / `desktop_pet_dock_side` / `dock_desktop_pet`),原生在拖动结束时判定并发 `{type:'pet-dock', side:'left'|'right'|''}`。 +- **趴边偷看(三只陪伴宠物都有)**:拖到屏幕左 / 右边缘附近松手(窗口中心离边缘不超过窗口宽度的 1/4,约等于身体碰到屏幕边),窗口贴到那条边,宠物换成从屏幕边探出半个身子偷看的样子(贴左边时镜像):鲸鱼娘双手扒着边,回形针把上半截钢丝和两只大眼睛探进来,rover 探出脑袋、两只前爪扒着边。缓慢地探进探出,每 2–5 秒眨一次眼、偶尔连眨两下;悬停时探得更靠里并开心地眯眼,有会话等你处理时也会多探出来一点,新完成的会话让它开心眯眼、失败时抖一下;双击照常打开 ACECode,再拖起来就恢复全身。缩放和恢复默认大小时保持贴边,「回到右下角」取消吸附;贴着边在右键菜单里换宠物,新宠物接着从同一条边偷看(页面记住窗口所在的边,素材还在解码时收到的贴边消息也不会丢)。画面都是用 Codex 按各自原有帧的画风画的两帧(睁眼 / 闭眼),来源与处理见 `assets/desktop_pet/whale/README.md` 与 `assets/desktop_pet/classic/README.md`。头的大小与其它姿势一致:鲸鱼娘的偷看原画比精灵帧大约 1.8 倍(眼睛高度、发箍到嘴的距离都量过),按常规帧缩放 ÷ 1.8 平滑绘制,曾经固定画成 170 像素高、头大了将近一倍;回形针与 rover 的偷看图直接做成精灵分辨率(眼睛大小与原帧一致),和原帧一样不平滑放大,像素颗粒一致。每只宠物藏在屏幕外的宽度(鲸鱼娘 9、像素宠物 4 个画布像素)与是否平滑在 `classic_pet.js` 的 `PEEK` 表,探进探出的幅度按藏边宽度缩放,不会顶到上限停住;像素宠物不平滑绘制,偏移要跨过像素边界画面才变,左右摇摆在两端放慢时会停住约 2 秒,所以再加一个错开四分之一周期、1.5 像素的上下浮动,两者不会同时停。吸附判定与贴边位置是 `desktop_pet_layout` 里的纯函数(`desktop_pet_has_edge_peek` / `desktop_pet_dock_side` / `dock_desktop_pet`),原生在拖动结束时判定并发 `{type:'pet-dock', side:'left'|'right'|''}`。 - **拖动**:原生拖动循环按窗口横向位移向页面发 `{type:'pet-drag', phase:'start'|'move'|'end', direction}`(`DesktopPetDragTracker` 累计 4 像素才报方向)。鲸鱼娘整个拖动过程都是被一只手拎起来的姿势(drag 帧)并以手为支点轻轻摆动;回形针朝拖动方向看;rover 先吃惊再朝拖动方向看,停住 0.45 秒转回正面。松开后继续原来的状态。松手时没有吸附,窗口又有一部分在屏幕外,就整窗收回工作区(`keep_desktop_pet_in_work_area`,所有宠物都适用)。吸附要窗口伸出屏幕约 1/4 宽,只是蹭到边上松手,正好会停在半出屏的位置,头顶的会话卡片会被屏幕边截掉。 虚拟办公室继续显示主/子 Agent 的完整协作场景。单会话有一个主角色 Maestro,多 agent 任务按真实子会话入座;无需启动额外模型,也没有演示任务循环。美术与拖动缩放来自原有 Claude 桌宠,旧的 `design-prototypes/agent-office` 事务所原型已移除。 @@ -37,7 +37,7 @@ Windows 与 macOS Desktop 可开启透明桌面宠物,默认关闭。设置 - 子 agent 出现时门先打开,人从门槛淡入走进来,先到派活的人桌前领「任务」信封再回工位,坐下后跳一跳、冒星星、说「报到!」;完成后走到派活的人桌前递「回报」信封(派活的人显示「收到…的结果」),说「再见」后快步出门、在门槛淡出;失败或停止的成员直接道别出门。网状协作中 agent 间消息以带「消息 / 新任务 / 回报」标签的信封在工位间飞过。系统开启「减少动态效果」时不走路,交接信封、「报到!」和原地「再见」仍然显示。 - 等待授权、等待回答、重试、压缩、失败和取消有各自状态。超过七个子角色时点击 `+N` 查看成员并打开对应会话;列表随状态更新,Escape 收起。选中房间人物后双击可打开其会话;双击空地打开当前会话,没有会话时也会把 ACECode 主窗口叫到前台。 - 文件堆随当前上下文占用增长,压缩后依据实际新统计变薄。工具符号与聊天工具行共用 SVG 来源。 -- 拖动房间空地移动窗口;滚轮、房间左上角的缩放三角形和右键菜单可缩放(陪伴宠物的三角形贴在宠物可见轮廓的左上角,随动作和贴边移动,经 overlay 的 `grip` 上报给原生命中)。三角形平时隐藏,鼠标移到它上面才显示,隐藏时照样能拖。窗口不抢主界面焦点,透明角落可穿透点击;尺寸按原实现保存。 +- 拖动房间空地移动窗口;滚轮、房间左上角的缩放三角形和右键菜单可缩放(陪伴宠物的三角形贴在宠物可见轮廓的左上角,随动作和贴边移动,经 overlay 的 `grip` 上报给原生命中;鼠标停在上面时它不再跟着动作移动,否则抓不住;有会话卡片时它放在收拢卡片区域的下沿之下,因为卡片区域连同阴影留白会盖住它、吞掉鼠标,macOS 也把那片区域当前景)。三角形平时隐藏,鼠标移到它上面才显示,隐藏时照样能拖。窗口不抢主界面焦点,透明角落可穿透点击;尺寸按原实现保存。 ## 构建与数据流 diff --git a/web/scripts/test-classic-desktop-pets.mjs b/web/scripts/test-classic-desktop-pets.mjs index 1fb29016..d21c6a75 100644 --- a/web/scripts/test-classic-desktop-pets.mjs +++ b/web/scripts/test-classic-desktop-pets.mjs @@ -326,6 +326,11 @@ try { await page.mouse.move(gripBox.x + 8, gripBox.y + 8); } assert.ok(await onGrip(), 'pointer reaches the resize handle'); + // 场景:有会话卡片时缩放。bug 表现:三角形落在卡片区域(含阴影留白)下面,鼠标到不了,macOS 也把它当卡片。 + // 期望:三角形始终在收拢的卡片区域下沿之下。 + assert.ok(await page.evaluate(() => { const stackBox = document.getElementById('stack'); + return stackBox.hidden || document.getElementById('grip').getBoundingClientRect().top >= stackBox.getBoundingClientRect().bottom - 0.5; }), + 'the resize handle stays below the card stack'); await page.waitForFunction(() => Number(getComputedStyle(document.getElementById('grip')).opacity) === 1); await page.waitForTimeout(1200); assert.ok(await onGrip(), 'the resize handle holds still under the pointer while the pet keeps moving');