Files
EzVibeR/docs/impl/2026-06-12-interaction-fix.md
2026-06-12 17:24:21 +08:00

5.7 KiB
Raw Permalink Blame History

EzVibeR+ 实施记录 — 2026-06-11/12

Tauri v2 升级 + 健康提醒 CRUD + 窗口交互修复 + Live2D 表情动作映射


一、双击变大修复

问题

GNOME/KDE 窗口管理器在透明窗口上双击会将窗口最大化/填充屏幕,导致桌面宠变形和点击失效。

修复

文件 变更
src-tauri/tauri.conf.json 主窗口新增 "maximizable": false"maxWidth": 800"maxHeight": 640
src-tauri/src/main.rs setup 中调用 main_window.set_maximizable(false)show 托盘处理中也设置

二、drag-region 逻辑反转(点击修复)

问题

data-tauri-drag-region="true" 默认设在 canvas 上,导致 GNOME 窗口管理器将所有 pointer 事件截获用于拖窗PIXI 交互系统完全收不到点击。

修复(src/live2d/index.vue

  • 默认canvas 不设 drag-region → 点击正常到达 DOM → 手动桥接到模型
  • 移动模式工具栏定位按钮canvas 启用 drag-region → 窗口可拖
  • onFocusChanged 不再恢复 drag-region

DOM→模型桥接

由于 PIXI v6 在 Tauri 透明窗口下交互系统失效,改为直接在 canvas 的 pointerdown 事件中:

  1. 计算点击坐标相对模型的位置
  2. 上级 35% 为头部 → 切换表情
  3. 其余为身体 → 播放动作 + 通知后端情绪引擎
canvas.addEventListener("pointerdown", async (e) => {
  const px = (e.clientX - rect.left) * scaleX;
  const py = (e.clientY - rect.top) * scaleY;
  const isHead = (py - model.y) < model.height * 0.35;
  // ...
});

三、健康提醒 CRUD 面板

架构设计

单一数据源:所有提醒行为统一存储在 AppConf.behaviors 中,不再区分"内置"与"自定义"。

新增文件

文件 用途
health.html 入口页面
src/health/App.ts Vue 入口
src/components/HealthReminders.vue CRUD 表格 + 模态表单

后端改动

文件 变更
src-tauri/src/app/config.rs 新增 BehaviorDef 结构体 + default_behaviors() + ensure_default_behaviors() + write_behaviors() 安全写入
src-tauri/src/modules/scheduler.rs 移除硬编码 register_builtin(),新增 reload_all_behaviors() 全量替换
src-tauri/src/app/commands.rs 新增 list_behaviors, add_behavior, update_behavior, delete_behavior
src-tauri/src/main.rs 启动时 ensure_default_behaviors() + reload_all_behaviors();托盘新增 "健康提醒" 菜单项

安全写入

write_behaviors() 只修改 behaviors 字段,不影响 LLM 等配置:

pub fn write_behaviors(behaviors: Vec<BehaviorDef>) {
    let conf = Self::read();
    let mut json = serde_json::to_value(&conf).unwrap();
    json["behaviors"] = serde_json::to_value(&behaviors).unwrap();
    std::fs::write(Self::file_path(), serde_json::to_string_pretty(&json).unwrap());
}

用户使用

右键托盘 → 健康提醒 → 打开管理面板。支持增删改查实时同步到后端调度器。


四、情绪引擎 → Live2D 动作/表情映射

架构

后端 emotion.rs                 前端 index.vue
┌─────────────────┐           ┌──────────────────────────┐
│ EmotionEngine    │──心跳→    │ ezvibe:emotion/heartbeat │
│ Idle/Happy/...   │           │          ↓               │
└─────────────────┘           │ applyEmotion(state)      │
                              │   ├─ motion 动作        │
                              │   └─ expression 表情     │
                              └──────────────────────────┘

关键实现

功能 位置 说明
模型能力发现 discoverModelCapabilities() 从 model3.json 读取表达式列表和动作组
情绪→表情映射 applyEmotion() 关键词匹配Happy→星星/比耶, Annoyed→黑脸等
动作匹配 fuzzyMatch() 精确/包含/反向三种策略
事件监听 onMounted 监听 ezvibe:emotion + ezvibe:heartbeat

表达式文件路径修复

March 7th 模型的表达式文件在 exp/ 子目录,但 model3.json 引用路径不含子目录前缀。pixi-live2d-display v0.4.0 无法正确加载,导致 model.expression() 静默失败。

修复:用 fetch 直接从 exp/{n}.exp3.json 加载表达式文件,调用 coreModel.setParameterValueById() 直接操作 Cubism 4 参数。

表达式重置

每个表达式只改 1 个参数(如 Param27切换时需先清除上一个表达式的参数

上一个表达式 → setParameterValueById(Param27, 0)  // 清掉
resetExpression()                                   // 原生重置
新表达式     → setParameterValueById(Param28, 0.5)  // 应用

记录 lastExpressionParamIds 数组,每次切前先清掉所有上一个涉及的参数 ID。


五、前景遮罩修复

tryAddFrame() 中的前景 Sprite 使用 stage.addChildAt(foreground, 0) 添加到 index 0最底层确保模型始终在上方接收事件。


六、配置窗口重建

托盘 "配置中心" / "健康提醒" 点击时先关闭旧窗口再重建,确保 Vue 组件重新挂载并从后端重新读取配置。


七、新增 Tauri 命令

命令 功能
list_behaviors 列出所有提醒行为
add_behavior 添加提醒行为
update_behavior 更新提醒行为(支持改名)
delete_behavior 删除提醒行为
debug_log 前端日志透传到终端 stderr