160 lines
5.7 KiB
Markdown
160 lines
5.7 KiB
Markdown
# 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 |
|