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

160 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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. 其余为身体 → 播放动作 + 通知后端情绪引擎
```typescript
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 等配置:
```rust
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 |