Ewwii 的物理卡片宿主。它是一块全屏、透明、位于 X11 桌面层的画布,把登记的"卡片插件"变成 rapier2d 物理体,并负责一切与卡片无关的通用能力:物理、拖拽、菜单、设置弹窗、点击穿透、克隆、持久化。
卡片插件本身不含物理——所有物理都在这里(
physics_desktop+ewwii_physics_engine)。
| 能力 | 说明 |
|---|---|
| 画布 + 物理 | 全屏 rapier2d 世界(2560×1600 起),刚体/碰撞/重力/边界墙;卡片可拖拽、有惯性、会碰撞、可固定 |
| 卡片登记 | 监听 sig::REGISTER,按 CardDef(kind + collider + 初始位置 + default_physics)spawn 物理体 |
| 内容协议(宿主侧) | 卡片把"画什么"以纯数据发来(IMAGE_SPEC/PUZZLE_SPEC/CALENDAR_SPEC/WEATHER_SPEC/WIDGET_OPTIONS),按 card_id 存,绘制时用 ewwii_cards::render_card_full 画 |
| 右键菜单 | 卡片通过 MENU_REGISTER 声明菜单;宿主渲染并在点击时发 MENU_ACTION。克隆体走 source_card_id 向上溯源找到菜单 |
| 设置弹窗 | Ctrl + 右键打开宿主的物理设置窗(质量/重量/固定/物理开关/穿透/忽略交互/角度/位置/大小),应用 → apply_config + save_card_config 写 physics.toml |
| 点击穿透 | passthrough 卡片用 XShape 从窗口输入区"打洞",事件直达桌面/下层窗口 |
| 克隆(duplicate) | 克隆体为 <源id>.<n>;宿主拷贝源快照 + 发 CARD_SPAWN;持久化到 clones.json,重启恢复 |
| 持久化 | 每 3s 轮询把每个 body 的 CardConfig 写 cards/<id>/physics.toml;并广播 PERSIST_TICK 让卡片插件自查自存 |
| 渲染缓存 | 每张卡的静态内容渲染成 cairo surface 缓存一次,每帧只 blit(位置/角度作变换);每帧变化的卡(钟表/日历/GIF/拼图动画)跳过缓存 |
cargo build --release # 产出 target/release/libphysics_desktop.so部署到某个 ewwii 场景的插件目录(命名必须是 physics_desktop.so,不能是 libphysics_desktop.so——双宿主会导致 daemon 卡死):
cp target/release/libphysics_desktop.so <scene>/plugins/physics_desktop.so
rm -f <scene>/plugins/libphysics_desktop.so # 有则删ewwii_cards(渲染 + 协议 +config_paths)、ewwii_physics_engine(rapier2d 封装)、ewwii_plugin_api(总线/API)- 这三个在主仓库
../Ewwii-plugin/crates/下,以 path 依赖引入。 gtk4/gdk4-x11/x11rb(XShape 点击穿透)。
src/lib.rs:全部宿主逻辑(2400+ 行)。含Shared状态、spawn_card/spawn_clone/clone_card、拖拽/物理线程、set_draw_func(渲染缓存 + 点击穿透)、MENU_ACTION/REGISTER/COMMAND/IMAGE_SPEC… 各总线处理器、设置弹窗。
主仓库 技术文档/插件开发文档.md(协议、语义、FAQ)与 技术文档/03-接手指南-代码地图与现状.md。
