dsh-pet 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +100 -0
- package/README.md +101 -97
- package/assets/thumb//344/270/234/345/274/240/350/245/277/346/234/233.webm +0 -0
- package/assets/thumb//344/270/255/347/247/213/350/265/217/346/234/210/345/220/203/346/234/210/351/245/274.webm +0 -0
- package/assets/thumb//344/274/230/351/233/205/345/245/263/344/273/206/350/210/236.webm +0 -0
- package/assets/thumb//345/201/267/345/220/203/351/233/266/351/243/237/350/242/253/346/212/223/344/275/217.webm +0 -0
- package/assets/thumb//345/206/231/344/273/243/347/240/201.webm +0 -0
- package/assets/thumb//345/212/250/347/211/251/347/216/257/347/273/225.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/344/270/223/345/277/203/347/216/251/351/255/224/346/226/271.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/345/260/217/346/206/251/346/262/211/347/234/240.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/345/267/246/350/275/254/345/245/224/350/267/221.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/346/225/262/345/207/273/346/241/214/351/235/242/344/272/222/345/212/250.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/346/274/202/346/265/256/350/270/217/346/255/245.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/350/267/263/350/267/203/346/212/223/347/242/216/345/244/264/351/241/266/347/211/251/345/223/201.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/350/271/262/344/270/213/347/216/251/347/216/251/345/205/267/346/261/275/350/275/246.webm +0 -0
- package/assets/thumb//345/216/237/345/234/260/351/207/215/345/212/233/344/270/213/350/271/262/345/216/213/347/274/251.webm +0 -0
- package/assets/thumb//345/217/257/347/210/261/345/256/205/350/210/236.webm +0 -0
- package/assets/thumb//345/220/203Token.webm +0 -0
- package/assets/thumb//345/220/203/345/206/260/346/267/207/346/267/213/350/236/215/345/214/226.webm +0 -0
- package/assets/thumb//345/220/203/345/215/210/351/244/220.webm +0 -0
- package/assets/thumb//345/220/203/346/227/251/351/244/220.webm +0 -0
- package/assets/thumb//345/220/203/346/231/232/351/244/220.webm +0 -0
- package/assets/thumb//345/220/203/347/231/275/351/245/255.webm +0 -0
- package/assets/thumb//345/220/271/346/260/224/347/220/203.webm +0 -0
- package/assets/thumb//345/223/210/346/254/240/350/277/236/345/244/251.webm +0 -0
- package/assets/thumb//345/240/206/351/233/252/344/272/272.webm +0 -0
- package/assets/thumb//345/244/247/345/217/243/345/220/203/351/233/266/351/243/237.webm +0 -0
- package/assets/thumb//345/245/263/344/273/206/345/261/210/350/206/235/347/244/274/344/273/252.webm +0 -0
- package/assets/thumb//345/260/217/345/271/205/345/272/246/345/216/237/345/234/260 360 /345/272/246/346/227/213/350/275/254/345/261/225/347/244/272.webm +0 -0
- package/assets/thumb//345/260/217/346/217/220/347/220/264/346/274/224/345/245/217.webm +0 -0
- package/assets/thumb//345/276/205/346/234/272/345/221/274/345/220/270/344/274/221/351/227/262.webm +0 -0
- package/assets/thumb//346/202/240/351/227/262/345/223/274/346/255/214.webm +0 -0
- package/assets/thumb//346/211/223/347/236/214/347/235/241/350/242/253/346/203/212/351/206/222.webm +0 -0
- package/assets/thumb//346/221/207/346/211/207/347/272/263/345/207/211.webm +0 -0
- package/assets/thumb//346/224/276/351/243/216/347/255/235.webm +0 -0
- package/assets/thumb//346/225/264/344/275/223/346/215/242/350/243/205/350/257/225/350/211/262.webm +0 -0
- package/assets/thumb//346/267/261/345/272/246/346/200/235/350/200/203/347/242/216/347/242/216/345/277/265.webm +0 -0
- package/assets/thumb//347/202/271/345/207/273/345/233/236/345/272/224 - /345/202/262/345/250/207/347/224/237/346/260/224/357/274/210/344/276/247/350/272/253/345/261/225/347/244/272/357/274/211.webm +0 -0
- package/assets/thumb//347/202/271/345/207/273/345/233/236/345/272/224 - /345/256/263/347/276/236/346/203/212/350/256/266.webm +0 -0
- package/assets/thumb//347/202/271/345/207/273/345/233/236/345/272/224 - /345/274/200/345/277/203/350/267/203/345/212/250.webm +0 -0
- package/assets/thumb//347/205/247/351/225/234/345/255/220.webm +0 -0
- package/assets/thumb//347/216/251/346/260/264/346/236/252.webm +0 -0
- package/assets/thumb//347/216/251/346/270/270/346/210/217/346/260/224/346/200/245/350/264/245/345/235/217.webm +0 -0
- package/assets/thumb//347/224/250/351/262/270/351/261/274/345/260/276/345/267/264/346/213/215/346/211/223/345/234/260/351/235/242.webm +0 -0
- package/assets/thumb//350/223/235/351/262/270/347/216/260/344/270/226.webm +0 -0
- package/assets/thumb//350/236/203/350/237/271/350/265/260/350/267/257.webm +0 -0
- package/assets/thumb//350/242/253/345/220/223/344/270/200/350/267/263/357/274/210/347/202/270/346/257/233/357/274/211.webm +0 -0
- package/assets/thumb//350/242/253/350/220/275/345/217/266/346/267/271/346/262/241.webm +0 -0
- package/assets/thumb//350/242/253/351/274/240/346/240/207/346/213/226/346/213/275/346/202/254/347/251/272/345/217/215/351/246/210.webm +0 -0
- package/assets/thumb//350/266/205/345/244/247/344/274/270/346/207/222/350/205/260.webm +0 -0
- package/assets/thumb//350/275/273/345/277/253/346/221/207/346/221/206/350/210/236.webm +0 -0
- package/assets/thumb//350/275/273/345/277/253/350/256/260/345/275/225.webm +0 -0
- package/assets/thumb//351/262/270/351/261/274/345/220/220/346/263/241/346/263/241/347/211/271/346/225/210.webm +0 -0
- package/lib/client.js +121 -37
- package/package.json +1 -1
- package/README.zh.md +0 -97
package/README.en.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# dsh-pet 🐾
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-pet?label=npm&color=blue"></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm monthly downloads" src="https://img.shields.io/npm/dm/dsh-pet?label=monthly&color=brightgreen"></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="total downloads" src="https://img.shields.io/npm/dt/dsh-pet?label=total&color=success"></a>
|
|
7
|
+
<a href="https://github.com/PC2005-cloud/dsh-pet"><img alt="stars" src="https://img.shields.io/github/stars/PC2005-cloud/dsh-pet?style=social"></a>
|
|
8
|
+
<a href="https://github.com/PC2005-cloud/dsh-pet/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/github/license/PC2005-cloud/dsh-pet?color=orange"></a>
|
|
9
|
+
<a href="https://awesome-dsh-plugin.com"><img alt="awesome dsh plugin" src="https://awesome-dsh-plugin.com/badge.svg"></a>
|
|
10
|
+
<img alt="platform" src="https://img.shields.io/badge/platform-DeepSeek%20Harness%20Web-8A2BE2">
|
|
11
|
+
<img alt="assets" src="https://img.shields.io/badge/assets-51%20animations-ff69b4">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
> A floating desktop pet for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web UI: idle breathing, random actions (including dozing off), occasional turns, screen wandering, click reactions, and draggable.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🚀 Quick Start (Install the Plugin)
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
dsh plugin --profile web add dsh-pet
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Restart `dsh web` and the pet appears in the bottom-right corner — 51 transparent animations, ready to use out of the box, no generation pipeline required.
|
|
25
|
+
|
|
26
|
+
> 💡 Want to craft your own one-of-a-kind pet? Clone [PC2005-cloud/dsh-pet](https://github.com/PC2005-cloud/dsh-pet) and use the bundled asset pipeline (AI prompts → green-screen video → transparent animation, generated with Doubao) to generate one from scratch — fully reproducible.
|
|
27
|
+
|
|
28
|
+
## ✨ Features
|
|
29
|
+
|
|
30
|
+
- **A pure pet, nothing else**: no business features — no weather, no monitoring, no agent-state sensing; just a companion. Zero core changes, zero model cost (no LLM/API calls at runtime)
|
|
31
|
+
- **51 hand-drawn style transparent animations**: idle breathing, dozing off, playing with a Rubik's cube, humming, hair-raising, blowing bubbles, playing with a water gun, playing violin, the whale emerging, eating rice, looking in the mirror, three dances, writing code, seasonal actions (kite flying, snowman building, ice cream eating, fireworks…) — all seamlessly chained
|
|
32
|
+
- **Never-ending animation chain**: when each animation finishes, the next one is picked instantly by probability (30% idle / 10% turn / 40% action / 20% move)
|
|
33
|
+
- **Screen wandering**: walks toward its facing direction, checks the space ahead and never walks off screen
|
|
34
|
+
- **Click / drag**: click triggers a random reaction animation (happy / shy / tsundere); drag it anywhere
|
|
35
|
+
- **Left/right facing**: all animations are CSS-mirrored, the pet can face left or right
|
|
36
|
+
- **Ground alignment**: animations share a unified foot line, the pet always stands on the "ground"
|
|
37
|
+
- **Smooth transitions**: double-buffered video cross-fade, zero blank frames between switches
|
|
38
|
+
- **Accessibility-friendly**: supports `prefers-reduced-motion`
|
|
39
|
+
|
|
40
|
+
## ⚙️ Configuration
|
|
41
|
+
|
|
42
|
+
| Key | Description | Current status |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `size` | Stage width (px); pet height ≈ width×9/16×74% | Default 462 (≈260px tall), **not yet delivered to the browser** (DSH client config pipeline limitation; falls back to code default) |
|
|
45
|
+
| `position` | Default corner position | Defaults to bottom-right, same as above (not yet delivered) |
|
|
46
|
+
| `fullRoot` | Original 2160×1215 master asset directory | Defaults to `$DSH_HOME/pet-assets`; takes effect after manually downloading the master assets |
|
|
47
|
+
|
|
48
|
+
> Note: the plugin works out of the box; all config above is optional. Browser-side configuration of `size`/`position` is planned.
|
|
49
|
+
|
|
50
|
+
## 🗑️ Uninstall
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
dsh plugin --profile web remove dsh-pet
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 🖥️ Running Screenshots
|
|
57
|
+
|
|
58
|
+
What the pet looks like running inside the DSH Web UI:
|
|
59
|
+
|
|
60
|
+
<p>
|
|
61
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/assets/screenshots/dsh-pet-running-1.png" width="380" alt="dsh-pet running in DSH Web UI 1" title="dsh-pet running in DSH Web UI 1">
|
|
62
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/assets/screenshots/dsh-pet-running-2.png" width="380" alt="dsh-pet running in DSH Web UI 2" title="dsh-pet running in DSH Web UI 2">
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
## 🎬 Animation Previews
|
|
66
|
+
|
|
67
|
+
> The animations have transparent backgrounds; in these GIF previews the transparent areas show the page background color, while the actual playback (webm) is transparent.
|
|
68
|
+
|
|
69
|
+
<p>
|
|
70
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%BE%85%E6%9C%BA%E5%91%BC%E5%90%B8%E4%BC%91%E9%97%B2.gif" width="160" alt="Idle breathing & chill" title="Idle breathing & chill">
|
|
71
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E4%B8%9C%E5%BC%A0%E8%A5%BF%E6%9C%9B.gif" width="160" alt="Looking around" title="Looking around">
|
|
72
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%8E%9F%E5%9C%B0%E6%BC%82%E6%B5%AE%E8%B8%8F%E6%AD%A5.gif" width="160" alt="Floating in place" title="Floating in place">
|
|
73
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%8E%9F%E5%9C%B0%E5%B0%8F%E6%86%A9%E6%B2%89%E7%9C%A0.gif" width="160" alt="Napping" title="Napping">
|
|
74
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E7%82%B9%E5%87%BB%E5%9B%9E%E5%BA%94%20-%20%E5%BC%80%E5%BF%83%E8%B7%83%E5%8A%A8.gif" width="160" alt="Click response - happy bounce" title="Click response - happy bounce">
|
|
75
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E8%A2%AB%E9%BC%A0%E6%A0%87%E6%8B%96%E6%8B%BD%E6%82%AC%E7%A9%BA%E5%8F%8D%E9%A6%88.gif" width="160" alt="Dragged by the mouse" title="Dragged by the mouse">
|
|
76
|
+
</p>
|
|
77
|
+
|
|
78
|
+
All 51 animations live in the repo under `dsh-pet/assets/thumb/`.
|
|
79
|
+
|
|
80
|
+
## 📚 A Complete Project (More Than a Plugin)
|
|
81
|
+
|
|
82
|
+
This is a **complete three-piece project** — anyone can clone the repo and generate their own desktop pet from scratch:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
① Prompts (recipe) → ② Asset pipeline (engine) → ③ Plugin (product)
|
|
86
|
+
AI animation prompts source video → transparent the pet running in DSH
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- Repository: [PC2005-cloud/dsh-pet](https://github.com/PC2005-cloud/dsh-pet)
|
|
90
|
+
- Design & implementation docs: [DESIGN.md](https://github.com/PC2005-cloud/dsh-pet/blob/master/DESIGN.md)
|
|
91
|
+
|
|
92
|
+
## 🔎 Discover More DSH Plugins
|
|
93
|
+
|
|
94
|
+
- Community plugin catalog: [awesome-dsh-plugin.com](https://awesome-dsh-plugin.com)
|
|
95
|
+
- DSH official repository: [deepseek-ai/DeepSeek-Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
96
|
+
|
|
97
|
+
## 📄 License
|
|
98
|
+
|
|
99
|
+
- Code: MIT
|
|
100
|
+
- Assets (animations/prompts): see the repository notes
|
package/README.md
CHANGED
|
@@ -1,97 +1,101 @@
|
|
|
1
|
-
# dsh-pet 🐾
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-pet?label=npm&color=blue"></a>
|
|
5
|
-
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm downloads" src="https://img.shields.io/npm/dm/dsh-pet?color=brightgreen"></a>
|
|
6
|
-
<a href="https://
|
|
7
|
-
<a href="https://github.com/PC2005-cloud/dsh-pet
|
|
8
|
-
<a href="https://
|
|
9
|
-
<img alt="
|
|
10
|
-
<img alt="
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
##
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%
|
|
72
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
|
|
1
|
+
# dsh-pet 🐾
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-pet?label=npm&color=blue"></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm monthly downloads" src="https://img.shields.io/npm/dm/dsh-pet?label=%E6%9C%88%E4%B8%8B%E8%BD%BD&color=brightgreen"></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="total downloads" src="https://img.shields.io/npm/dt/dsh-pet?label=%E6%80%BB%E4%B8%8B%E8%BD%BD&color=success"></a>
|
|
7
|
+
<a href="https://github.com/PC2005-cloud/dsh-pet"><img alt="stars" src="https://img.shields.io/github/stars/PC2005-cloud/dsh-pet?style=social"></a>
|
|
8
|
+
<a href="https://github.com/PC2005-cloud/dsh-pet/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/github/license/PC2005-cloud/dsh-pet?color=orange"></a>
|
|
9
|
+
<a href="https://awesome-dsh-plugin.com"><img alt="awesome dsh plugin" src="https://awesome-dsh-plugin.com/badge.svg"></a>
|
|
10
|
+
<img alt="platform" src="https://img.shields.io/badge/platform-DeepSeek%20Harness%20Web-8A2BE2">
|
|
11
|
+
<img alt="assets" src="https://img.shields.io/badge/assets-51%20animations-ff69b4">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
> A floating desktop pet for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web UI.
|
|
15
|
+
> 一只住在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web 界面里的桌面宠物:待机呼吸、随机动作(含打瞌睡)、偶尔转向、屏幕漫游、点击反应、可拖拽。
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🚀 快速开始(安装插件)
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
dsh plugin --profile web add dsh-pet
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
重启 `dsh web`,宠物出现在界面右下角——51 个透明动画开箱即用,无需任何生成流程。
|
|
26
|
+
|
|
27
|
+
> 💡 想自己造一只专属宠物?克隆 [PC2005-cloud/dsh-pet](https://github.com/PC2005-cloud/dsh-pet) 仓库,用内置素材链(AI 提示词 → 绿幕视频 → 透明动画,素材由豆包生成)从零生成,全流程可复现。
|
|
28
|
+
|
|
29
|
+
## ✨ 功能特性
|
|
30
|
+
|
|
31
|
+
- **纯粹的桌宠**:不掺业务功能——没有天气查询、系统监控、Agent 状态感知,就一件事:陪你。零核心改动、零模型成本(运行时零 LLM/API 调用)
|
|
32
|
+
- **51 个手绘风透明动画**:待机呼吸、打瞌睡、玩魔方、哼歌、炸毛、吐泡泡、玩水枪、小提琴演奏、蓝鲸现世、吃白饭、照镜子、三支舞、写代码、四季动作(放风筝、堆雪人、吃冰淇淋、放烟花……)全部无缝衔接
|
|
33
|
+
- **永不停止的动画链**:每段动画播完立即按概率选下一个(30% 待机 / 10% 转向 / 40% 动作 / 20% 移动)
|
|
34
|
+
- **屏幕漫游**:朝 facing 方向行走,自动检查空间、不走出屏幕
|
|
35
|
+
- **点击 / 拖拽**:点击有随机回应动画(开心 / 害羞 / 傲娇),可拖到任意位置
|
|
36
|
+
- **左右朝向**:所有动画 CSS 镜像,人物可朝左 / 朝右
|
|
37
|
+
- **落地对齐**:动画统一脚底线,宠物始终站在"地面"上
|
|
38
|
+
- **流畅切换**:双缓冲 video 交叉淡入,切换零空白帧
|
|
39
|
+
- **无障碍友好**:支持 `prefers-reduced-motion`
|
|
40
|
+
|
|
41
|
+
## ⚙️ 配置
|
|
42
|
+
|
|
43
|
+
| 配置项 | 说明 | 当前状态 |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `size` | 舞台宽度(px),宠物高度 = 宽度×9/16×74% | 默认 462(≈高度 260px),**暂未下发到浏览器**(DSH 客户端配置管线限制,走代码默认值) |
|
|
46
|
+
| `position` | 默认角落位置 | 默认右下角,同上暂未下发 |
|
|
47
|
+
| `fullRoot` | 原始 2160×1215 母版资源目录 | 默认 `$DSH_HOME/pet-assets`,需手动下载母版后生效 |
|
|
48
|
+
|
|
49
|
+
> 说明:插件安装即用,上述配置均为可选;`size`/`position` 的浏览器侧配置化正在规划中。
|
|
50
|
+
|
|
51
|
+
## 🗑️ 卸载
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
dsh plugin --profile web remove dsh-pet
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 🖥️ 运行效果
|
|
58
|
+
|
|
59
|
+
宠物实际运行在 DSH Web 界面中的样子:
|
|
60
|
+
|
|
61
|
+
<p>
|
|
62
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/assets/screenshots/dsh-pet-running-1.png" width="380" alt="dsh-pet running in DSH Web UI 1" title="dsh-pet running in DSH Web UI 1">
|
|
63
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/assets/screenshots/dsh-pet-running-2.png" width="380" alt="dsh-pet running in DSH Web UI 2" title="dsh-pet running in DSH Web UI 2">
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
## 🎬 效果预览
|
|
67
|
+
|
|
68
|
+
> 动画为透明背景;GIF 预览中透明部分显示为页面底色,实际播放为透明。
|
|
69
|
+
|
|
70
|
+
<p>
|
|
71
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%BE%85%E6%9C%BA%E5%91%BC%E5%90%B8%E4%BC%91%E9%97%B2.gif" width="160" alt="待机呼吸休闲" title="待机呼吸休闲">
|
|
72
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E4%B8%9C%E5%BC%A0%E8%A5%BF%E6%9C%9B.gif" width="160" alt="东张西望" title="东张西望">
|
|
73
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%8E%9F%E5%9C%B0%E6%BC%82%E6%B5%AE%E8%B8%8F%E6%AD%A5.gif" width="160" alt="原地漂浮踏步" title="原地漂浮踏步">
|
|
74
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%8E%9F%E5%9C%B0%E5%B0%8F%E6%86%A9%E6%B2%89%E7%9C%A0.gif" width="160" alt="原地小憩沉眠" title="原地小憩沉眠">
|
|
75
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E7%82%B9%E5%87%BB%E5%9B%9E%E5%BA%94%20-%20%E5%BC%80%E5%BF%83%E8%B7%83%E5%8A%A8.gif" width="160" alt="点击回应 - 开心跃动" title="点击回应 - 开心跃动">
|
|
76
|
+
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E8%A2%AB%E9%BC%A0%E6%A0%87%E6%8B%96%E6%8B%BD%E6%82%AC%E7%A9%BA%E5%8F%8D%E9%A6%88.gif" width="160" alt="被鼠标拖拽悬空反馈" title="被鼠标拖拽悬空反馈">
|
|
77
|
+
</p>
|
|
78
|
+
|
|
79
|
+
全部 51 个动画见仓库:`dsh-pet/assets/thumb/`。
|
|
80
|
+
|
|
81
|
+
## 📚 完整项目(不止是插件)
|
|
82
|
+
|
|
83
|
+
这是**完整的三件套项目**,任何人 clone 仓库都可以从零生成自己的桌面宠物:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
① 提示词(配方) → ② 素材生成链(引擎) → ③ 插件(成品)
|
|
87
|
+
AI 生成动画的配方 源视频 → 透明动画的管线 运行在 DSH 里的宠物
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- 仓库:[PC2005-cloud/dsh-pet](https://github.com/PC2005-cloud/dsh-pet)
|
|
91
|
+
- 设计与实现文档:[DESIGN.md](https://github.com/PC2005-cloud/dsh-pet/blob/master/DESIGN.md)
|
|
92
|
+
|
|
93
|
+
## 🔎 发现更多 DSH 插件
|
|
94
|
+
|
|
95
|
+
- 社区插件目录:[awesome-dsh-plugin.com](https://awesome-dsh-plugin.com)
|
|
96
|
+
- DSH 官方仓库:[deepseek-ai/DeepSeek-Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
97
|
+
|
|
98
|
+
## 📄 许可
|
|
99
|
+
|
|
100
|
+
- 代码:MIT
|
|
101
|
+
- 素材(动画/提示词):见仓库说明
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/assets/thumb//345/216/237/345/234/260/345/260/217/346/206/251/346/262/211/347/234/240.webm
CHANGED
|
Binary file
|
package/assets/thumb//345/216/237/345/234/260/345/267/246/350/275/254/345/245/224/350/267/221.webm
CHANGED
|
Binary file
|
|
Binary file
|
package/assets/thumb//345/216/237/345/234/260/346/274/202/346/265/256/350/270/217/346/255/245.webm
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/assets/thumb//345/220/203/345/206/260/346/267/207/346/267/213/350/236/215/345/214/226.webm
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/assets/thumb//345/245/263/344/273/206/345/261/210/350/206/235/347/244/274/344/273/252.webm
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/assets/thumb//345/276/205/346/234/272/345/221/274/345/220/270/344/274/221/351/227/262.webm
CHANGED
|
Binary file
|
|
Binary file
|
package/assets/thumb//346/211/223/347/236/214/347/235/241/350/242/253/346/203/212/351/206/222.webm
CHANGED
|
Binary file
|
|
Binary file
|
package/assets/thumb//346/225/264/344/275/223/346/215/242/350/243/205/350/257/225/350/211/262.webm
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -54,15 +54,16 @@ window.__ModuleLoader__.load({
|
|
|
54
54
|
'.dsh-pet-root[data-corner="bottom-right"]{right:24px;bottom:0}',
|
|
55
55
|
// 左下角位置
|
|
56
56
|
'.dsh-pet-root[data-corner="bottom-left"]{left:24px;bottom:0}',
|
|
57
|
-
//
|
|
58
|
-
'.dsh-pet-stage{position:relative;width:var(--dsh-pet-size,
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
'.dsh-pet-video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;pointer-events:
|
|
57
|
+
// 舞台:16:9(--dsh-pet-size 为宽度,默认 462px=高度260;高度自动 = 宽度×9/16),本身不响应鼠标
|
|
58
|
+
'.dsh-pet-stage{position:relative;width:var(--dsh-pet-size,462px);height:calc(var(--dsh-pet-size,462px)*9/16);pointer-events:none}',
|
|
59
|
+
// 视频:铺满舞台、保持比例,**pointer-events:none 完全穿透**——
|
|
60
|
+
// 交互统一由覆盖 HIT_BOX 区域的 .dsh-pet-hit 层负责,透明区域点击直达下层 UI。
|
|
61
|
+
'.dsh-pet-video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;pointer-events:none;opacity:0;transition:opacity .18s ease;transform-origin:center}',
|
|
62
62
|
// 显示中的视频(is-front 类)
|
|
63
63
|
'.dsh-pet-video.is-front{opacity:1}',
|
|
64
|
-
//
|
|
65
|
-
'.dsh-pet-
|
|
64
|
+
// 命中层:覆盖人物区域(HIT_BOX),是唯一可交互区域;光标跟随 + 拖拽抓取
|
|
65
|
+
'.dsh-pet-hit{position:absolute;pointer-events:auto;cursor:default;z-index:1}',
|
|
66
|
+
'.dsh-pet-hit.dragging{cursor:grabbing}',
|
|
66
67
|
// 朝向镜像说明:不用 CSS 全局规则(data-facing)控制镜像——facing 翻转会
|
|
67
68
|
// 同步镜像所有 video(含仍在显示的旧视频),造成"旧帧被镜像"的闪烁。
|
|
68
69
|
// 镜像改为在 switchTo 的 onReady 里按实际朝向给每个 video 设置 inline
|
|
@@ -84,12 +85,19 @@ window.__ModuleLoader__.load({
|
|
|
84
85
|
// ============================================================================
|
|
85
86
|
// 动画目录(animation catalog)—— 所有动画名和参数的"事实来源"
|
|
86
87
|
// ============================================================================
|
|
87
|
-
// 对齐说明:thumb 视频是
|
|
88
|
-
// (360-330)/360 = 30/360 = 0.0833,与
|
|
88
|
+
// 对齐说明:thumb 视频是 640×360(16:9)画布,人物的"脚底"在 y=330 处。
|
|
89
|
+
// (360-330)/360 = 30/360 = 0.0833,与 2160x1215 母版 (1215-1115)/1215 比例一致,
|
|
89
90
|
// 所以用这个比例做落地对齐,缩放后依然准确。
|
|
90
91
|
const CANVAS_H = 360; // thumb 画布高度
|
|
91
92
|
const FEET_Y = 330; // thumb 画布上"脚底"的 y 坐标(人物站在 y=330 线上)
|
|
92
93
|
|
|
94
|
+
// ---- 点击/拖拽命中矩形(thumb 640×360 像素坐标)----
|
|
95
|
+
// normalize 已把全部动画的人物统一缩放居中。41 个动画站立帧 bbox 并集
|
|
96
|
+
// 为 x:138~461, y:42~339,但并集被少数伸左手的动画撑宽,视觉上左边
|
|
97
|
+
// 多出很多、右边多 ~25px。多数动画实际约 x:214~425(中心≈320),
|
|
98
|
+
// 取对称整数范围 x:200~440(中心 320),y:50~335 贴近头顶/脚底。
|
|
99
|
+
const HIT_BOX = { x0: 200, y0: 50, x1: 440, y1: 335 };
|
|
100
|
+
|
|
93
101
|
// 主体待机动画(唯一常驻、循环播放)
|
|
94
102
|
const IDLE = '待机呼吸休闲';
|
|
95
103
|
// 转向动画(东张西望本身内容就是"从偏左看到偏右",播完翻转 facing)
|
|
@@ -117,6 +125,29 @@ window.__ModuleLoader__.load({
|
|
|
117
125
|
'打瞌睡被惊醒', // 原独立闲置动画,已并入
|
|
118
126
|
'玩水枪',
|
|
119
127
|
'小提琴演奏',
|
|
128
|
+
'蓝鲸现世',
|
|
129
|
+
'吃白饭',
|
|
130
|
+
'照镜子',
|
|
131
|
+
'优雅女仆舞',
|
|
132
|
+
'轻快摇摆舞',
|
|
133
|
+
'可爱宅舞',
|
|
134
|
+
'整体换装试色',
|
|
135
|
+
'大口吃零食',
|
|
136
|
+
'吹气球',
|
|
137
|
+
'动物环绕',
|
|
138
|
+
'深度思考碎碎念',
|
|
139
|
+
'轻快记录',
|
|
140
|
+
'写代码',
|
|
141
|
+
'吃Token',
|
|
142
|
+
'吃早餐',
|
|
143
|
+
'吃午餐',
|
|
144
|
+
'吃晚餐',
|
|
145
|
+
'放风筝',
|
|
146
|
+
'摇扇纳凉',
|
|
147
|
+
'吃冰淇淋融化',
|
|
148
|
+
'被落叶淹没',
|
|
149
|
+
'中秋赏月吃月饼',
|
|
150
|
+
'堆雪人',
|
|
120
151
|
];
|
|
121
152
|
// 点击回应动画池(3 选 1)
|
|
122
153
|
const CLICKS = ['点击回应 - 开心跃动', '点击回应 - 害羞惊讶', '点击回应 - 傲娇生气(侧身展示)'];
|
|
@@ -153,8 +184,11 @@ window.__ModuleLoader__.load({
|
|
|
153
184
|
*/
|
|
154
185
|
function Pet({ config }) {
|
|
155
186
|
// ---- 从 config 读取参数(当前走默认值) ----
|
|
156
|
-
const size = (config && config.size) ||
|
|
187
|
+
const size = (config && config.size) || 462; // 显示尺寸(px,宽度;默认=高度260)
|
|
157
188
|
const corner = (config && config.position) || 'bottom-right'; // 默认角落
|
|
189
|
+
// 舞台 16:9:宽=size、高=size×9/16;中心偏移(定位/拖拽共用)
|
|
190
|
+
const halfW = size / 2;
|
|
191
|
+
const halfH = size * 9 / 16 / 2;
|
|
158
192
|
|
|
159
193
|
// ---- React 状态 ----
|
|
160
194
|
const [anim, setAnim] = useState(IDLE); // 当前动画名
|
|
@@ -273,21 +307,36 @@ window.__ModuleLoader__.load({
|
|
|
273
307
|
// 点击/拖拽打断的动画播完后先回待机(作为缓冲),待机播完再进随机链。
|
|
274
308
|
const pickNext = () => {
|
|
275
309
|
const roll = Math.random();
|
|
310
|
+
let kind = '';
|
|
311
|
+
let next = '';
|
|
276
312
|
if (roll < 0.3) {
|
|
277
313
|
// 30% 待机:待机呼吸休闲(也是一次性,播完再选)
|
|
314
|
+
kind = 'IDLE';
|
|
315
|
+
next = IDLE;
|
|
278
316
|
setAnim(IDLE);
|
|
279
317
|
} else if (roll < 0.4) {
|
|
280
318
|
// 10% 转向:东张西望,播完 handleEnded 里翻转 facing
|
|
319
|
+
kind = 'TURN';
|
|
320
|
+
next = TURN;
|
|
281
321
|
setAnim(TURN);
|
|
282
322
|
} else if (roll < 0.8) {
|
|
283
323
|
// 40% 随机动作(等概率 + 去重)
|
|
284
|
-
|
|
324
|
+
kind = 'ACTS';
|
|
325
|
+
next = pick(ACTS, animRef.current);
|
|
326
|
+
setAnim(next);
|
|
285
327
|
} else {
|
|
286
328
|
// 20% 尝试移动:tryMove 先检查空间,不够就回退随机动作
|
|
287
329
|
if (!tryMove()) {
|
|
288
|
-
|
|
330
|
+
kind = 'ACTS';
|
|
331
|
+
next = pick(ACTS, animRef.current);
|
|
332
|
+
setAnim(next);
|
|
333
|
+
} else {
|
|
334
|
+
kind = 'MOVES';
|
|
335
|
+
next = '移动(池内随机)';
|
|
289
336
|
}
|
|
290
337
|
}
|
|
338
|
+
// 【测试用】打印随机数 + 动画种类 + 选中动画,方便核对概率分布;正式版可删除
|
|
339
|
+
console.log('[dsh-pet] roll=' + roll.toFixed(4) + ' → [' + kind + '] ' + next);
|
|
291
340
|
setOnce(true); // 链式模型全部一次性
|
|
292
341
|
setSeq((s) => s + 1); // 保证即使 anim 没变也重新播放
|
|
293
342
|
};
|
|
@@ -327,16 +376,16 @@ window.__ModuleLoader__.load({
|
|
|
327
376
|
const cp = customPosRef.current;
|
|
328
377
|
if (cp) return cp.rx * window.innerWidth;
|
|
329
378
|
const rootEl = rootRef.current;
|
|
330
|
-
if (rootEl) return rootEl.getBoundingClientRect().left +
|
|
331
|
-
return window.innerWidth - 24 -
|
|
379
|
+
if (rootEl) return rootEl.getBoundingClientRect().left + halfW;
|
|
380
|
+
return window.innerWidth - 24 - halfW;
|
|
332
381
|
};
|
|
333
382
|
// 当前宠物中心 y(视口坐标)
|
|
334
383
|
const currentCenterY = () => {
|
|
335
384
|
const cp = customPosRef.current;
|
|
336
385
|
if (cp) return cp.ry * window.innerHeight;
|
|
337
386
|
const rootEl = rootRef.current;
|
|
338
|
-
if (rootEl) return rootEl.getBoundingClientRect().top +
|
|
339
|
-
return window.innerHeight - 20 -
|
|
387
|
+
if (rootEl) return rootEl.getBoundingClientRect().top + halfH;
|
|
388
|
+
return window.innerHeight - 20 - halfH;
|
|
340
389
|
};
|
|
341
390
|
|
|
342
391
|
/**
|
|
@@ -381,8 +430,8 @@ window.__ModuleLoader__.load({
|
|
|
381
430
|
const px = ratioX * W;
|
|
382
431
|
const py = startYRatio * H;
|
|
383
432
|
// 直接改 DOM style(不触发 React 重渲染,保证 60fps 平滑)
|
|
384
|
-
rootEl.style.left = (px -
|
|
385
|
-
rootEl.style.top = (py -
|
|
433
|
+
rootEl.style.left = (px - halfW) + 'px';
|
|
434
|
+
rootEl.style.top = (py - halfH) + 'px';
|
|
386
435
|
rootEl.style.right = 'auto';
|
|
387
436
|
rootEl.style.bottom = 'auto';
|
|
388
437
|
}
|
|
@@ -414,8 +463,8 @@ window.__ModuleLoader__.load({
|
|
|
414
463
|
const distance = randomBetween(MOVE_MIN_PX, MOVE_MAX_PX);
|
|
415
464
|
const target = cx + dir * distance;
|
|
416
465
|
// 【播放前检查一次距离】目标点必须在屏幕安全边距内,否则不移动
|
|
417
|
-
const leftBound = MOVE_MARGIN +
|
|
418
|
-
const rightBound = W - MOVE_MARGIN -
|
|
466
|
+
const leftBound = MOVE_MARGIN + halfW;
|
|
467
|
+
const rightBound = W - MOVE_MARGIN - halfW;
|
|
419
468
|
if (target < leftBound || target > rightBound) return false; // 空间不够
|
|
420
469
|
// 记录计划(存"比例"而非绝对坐标,resize 后仍正确):
|
|
421
470
|
// 起点比例、目标比例、Y 比例、方向、总距离比例
|
|
@@ -453,11 +502,25 @@ window.__ModuleLoader__.load({
|
|
|
453
502
|
// (播放拖拽动画并跟手);松手时若没拖过,click 事件正常触发点击回应。
|
|
454
503
|
const DRAG_THRESHOLD = 5; // 拖拽判定阈值(px)
|
|
455
504
|
|
|
505
|
+
// ---- 命中层(.dsh-pet-hit)覆盖 HIT_BOX 区域 ----
|
|
506
|
+
// 交互范围由 CSS 命中层限定:视频 pointer-events:none(完全穿透),
|
|
507
|
+
// 命中层 pointer-events:auto 只覆盖人物区域。所以这里的事件天然都在
|
|
508
|
+
// 人物范围内,无需再做坐标命中检查;命中层之外点击直达下层 UI。
|
|
456
509
|
// 按下:只记录,不立即切动画
|
|
457
510
|
const handlePointerDown = (e) => {
|
|
511
|
+
e.currentTarget.classList.add('dragging'); // 拖拽中抓取光标
|
|
458
512
|
stopMove(); // 用户交互打断正在进行的移动
|
|
459
513
|
e.currentTarget.setPointerCapture(e.pointerId); // 捕获指针(拖出元素也能收到 move)
|
|
460
|
-
|
|
514
|
+
// 记录"鼠标点相对舞台中心的偏移"(舞台宽 size、高 size×9/16):
|
|
515
|
+
// 拖动时保持该偏移,从人物任意位置抓起都不会瞬移到鼠标下。
|
|
516
|
+
const rootEl = rootRef.current;
|
|
517
|
+
let offX = 0, offY = 0;
|
|
518
|
+
if (rootEl) {
|
|
519
|
+
const rr = rootEl.getBoundingClientRect();
|
|
520
|
+
offX = e.clientX - (rr.left + rr.width / 2);
|
|
521
|
+
offY = e.clientY - (rr.top + rr.height / 2);
|
|
522
|
+
}
|
|
523
|
+
dragRef.current = { active: true, dragging: false, sx: e.clientX, sy: e.clientY, offX, offY };
|
|
461
524
|
};
|
|
462
525
|
// 移动:超过阈值才进入拖拽模式
|
|
463
526
|
const handlePointerMove = (e) => {
|
|
@@ -475,10 +538,14 @@ window.__ModuleLoader__.load({
|
|
|
475
538
|
setAnim(DRAG);
|
|
476
539
|
}
|
|
477
540
|
// 跟手:直接改 root 的 style(不触发 React 重渲染 → 60fps 平滑)
|
|
541
|
+
// 舞台中心 = 鼠标点 - 按下时记录的偏移;left/top 是 root 左上角,
|
|
542
|
+
// 舞台宽 size、高 size×9/16,所以中心再减一半尺寸。
|
|
478
543
|
const rootEl = rootRef.current;
|
|
479
544
|
if (rootEl) {
|
|
480
|
-
|
|
481
|
-
|
|
545
|
+
const halfW = size / 2;
|
|
546
|
+
const halfH = size * 9 / 16 / 2;
|
|
547
|
+
rootEl.style.left = (e.clientX - d.offX - halfW) + 'px';
|
|
548
|
+
rootEl.style.top = (e.clientY - d.offY - halfH) + 'px';
|
|
482
549
|
rootEl.style.right = 'auto';
|
|
483
550
|
rootEl.style.bottom = 'auto';
|
|
484
551
|
}
|
|
@@ -491,15 +558,18 @@ window.__ModuleLoader__.load({
|
|
|
491
558
|
const wasDragging = d.dragging;
|
|
492
559
|
d.active = false;
|
|
493
560
|
d.dragging = false;
|
|
561
|
+
e.currentTarget.classList.remove('dragging'); // 结束抓取光标
|
|
494
562
|
if (wasDragging) {
|
|
495
563
|
// 抑制拖拽结束后的"幽灵点击"(浏览器在拖完也会发 click)
|
|
496
564
|
justDraggedRef.current = true;
|
|
497
565
|
setTimeout(() => { justDraggedRef.current = false; }, 100);
|
|
498
566
|
setDragging(false);
|
|
499
|
-
//
|
|
567
|
+
// 停在松手处(以舞台中心为基准,而非鼠标点——从角落抓起时
|
|
568
|
+
// 松手也保持偏移,宠物不会跳回鼠标位置);存相对窗口比例,
|
|
569
|
+
// 窗口变化时位置跟随。
|
|
500
570
|
setCustomPos({
|
|
501
|
-
rx: e.clientX / window.innerWidth,
|
|
502
|
-
ry: e.clientY / window.innerHeight,
|
|
571
|
+
rx: (e.clientX - d.offX) / window.innerWidth,
|
|
572
|
+
ry: (e.clientY - d.offY) / window.innerHeight,
|
|
503
573
|
});
|
|
504
574
|
const stageEl = stageRef.current;
|
|
505
575
|
if (stageEl) stageEl.style.transform = 'translateY(' + bottomPad + 'px)'; // 恢复落地对齐
|
|
@@ -510,7 +580,7 @@ window.__ModuleLoader__.load({
|
|
|
510
580
|
};
|
|
511
581
|
|
|
512
582
|
// ---- 点击回应(仅真点击触发,拖拽后的 click 被忽略) ----
|
|
513
|
-
const handleClick = () => {
|
|
583
|
+
const handleClick = (e) => {
|
|
514
584
|
const d = dragRef.current;
|
|
515
585
|
if (d.active || d.dragging || justDraggedRef.current) return; // 拖拽中/刚拖完:忽略
|
|
516
586
|
if (once && animRef.current !== IDLE) return; // 正在播一次性动画:不打断
|
|
@@ -522,10 +592,10 @@ window.__ModuleLoader__.load({
|
|
|
522
592
|
// ============================================================================
|
|
523
593
|
// 渲染
|
|
524
594
|
// ============================================================================
|
|
525
|
-
// 落地对齐:视频是 360 画布、脚在 y=330,脚底距画布底 30px
|
|
526
|
-
//
|
|
527
|
-
//
|
|
528
|
-
const bottomPad = (size * (CANVAS_H - FEET_Y)) / CANVAS_H;
|
|
595
|
+
// 落地对齐:视频是 640×360 画布、脚在 y=330,脚底距画布底 30px(8.33%)。
|
|
596
|
+
// 舞台是 16:9(高 = size×9/16),脚底距舞台底 = 舞台高 × 8.33%;
|
|
597
|
+
// bottomPad 就是把这个距离下移,让"脚"正好落在视口底线上。
|
|
598
|
+
const bottomPad = (size * 9 / 16 * (CANVAS_H - FEET_Y)) / CANVAS_H;
|
|
529
599
|
// 舞台样式:拖拽中无偏移;平时 translateY(bottomPad) 落地
|
|
530
600
|
const stageStyle = dragging
|
|
531
601
|
? { transform: 'none' }
|
|
@@ -537,20 +607,33 @@ window.__ModuleLoader__.load({
|
|
|
537
607
|
// 同时钳制到窗口内,防止窗口缩小到宠物放不下时跑出屏幕。
|
|
538
608
|
const rootStyle = customPos
|
|
539
609
|
? (() => {
|
|
540
|
-
const half = size / 2;
|
|
541
610
|
const rx = customPos.rx;
|
|
542
611
|
const ry = customPos.ry;
|
|
543
|
-
const left = Math.min(Math.max(rx * window.innerWidth -
|
|
544
|
-
const top = Math.min(Math.max(ry * window.innerHeight -
|
|
612
|
+
const left = Math.min(Math.max(rx * window.innerWidth - halfW, 0), window.innerWidth - size);
|
|
613
|
+
const top = Math.min(Math.max(ry * window.innerHeight - halfH, 0), window.innerHeight - size * 9 / 16);
|
|
545
614
|
return { left: left + 'px', top: top + 'px', right: 'auto', bottom: 'auto' };
|
|
546
615
|
})()
|
|
547
616
|
: {};
|
|
548
617
|
|
|
549
|
-
// 两个 video 共用的 props
|
|
618
|
+
// 两个 video 共用的 props(纯播放属性,交互交给命中层)
|
|
550
619
|
const commonVideoProps = {
|
|
551
620
|
muted: true,
|
|
552
621
|
playsInline: true,
|
|
553
622
|
autoPlay: true,
|
|
623
|
+
title: 'dsh-pet',
|
|
624
|
+
};
|
|
625
|
+
// 命中层 props:覆盖 HIT_BOX 区域,承载全部交互事件与抓取光标。
|
|
626
|
+
// 命中层内必然命中人物,光标固定 grab(拖拽中 .dragging 类显示 grabbing)。
|
|
627
|
+
const hitProps = {
|
|
628
|
+
className: 'dsh-pet-hit',
|
|
629
|
+
style: {
|
|
630
|
+
left: (HIT_BOX.x0 / 640 * 100) + '%',
|
|
631
|
+
top: (HIT_BOX.y0 / 360 * 100) + '%',
|
|
632
|
+
width: ((HIT_BOX.x1 - HIT_BOX.x0) / 640 * 100) + '%',
|
|
633
|
+
height: ((HIT_BOX.y1 - HIT_BOX.y0) / 360 * 100) + '%',
|
|
634
|
+
},
|
|
635
|
+
onMouseEnter: (e) => { if (!dragRef.current.active) e.currentTarget.style.cursor = 'grab'; },
|
|
636
|
+
onMouseLeave: (e) => { if (!dragRef.current.active) e.currentTarget.style.cursor = 'default'; },
|
|
554
637
|
onClick: handleClick,
|
|
555
638
|
onPointerDown: handlePointerDown,
|
|
556
639
|
onPointerMove: handlePointerMove,
|
|
@@ -559,8 +642,8 @@ window.__ModuleLoader__.load({
|
|
|
559
642
|
title: 'dsh-pet',
|
|
560
643
|
};
|
|
561
644
|
|
|
562
|
-
// 渲染树:root > stage > [video A, video B]
|
|
563
|
-
// A 初始带 is-front(显示),B
|
|
645
|
+
// 渲染树:root > stage > [video A, video B, 命中层]
|
|
646
|
+
// A 初始带 is-front(显示),B 隐藏待命;命中层在最上层承载交互
|
|
564
647
|
return h('div', {
|
|
565
648
|
ref: rootRef,
|
|
566
649
|
className: 'dsh-pet-root',
|
|
@@ -574,6 +657,7 @@ window.__ModuleLoader__.load({
|
|
|
574
657
|
children: [
|
|
575
658
|
h('video', Object.assign({}, commonVideoProps, { ref: videoARef, className: 'dsh-pet-video is-front' })),
|
|
576
659
|
h('video', Object.assign({}, commonVideoProps, { ref: videoBRef, className: 'dsh-pet-video' })),
|
|
660
|
+
h('div', hitProps),
|
|
577
661
|
],
|
|
578
662
|
}),
|
|
579
663
|
});
|
package/package.json
CHANGED
package/README.zh.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# dsh-pet 🐾
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-pet?label=npm&color=blue"></a>
|
|
5
|
-
<a href="https://www.npmjs.com/package/dsh-pet"><img alt="npm downloads" src="https://img.shields.io/npm/dm/dsh-pet?color=brightgreen"></a>
|
|
6
|
-
<a href="https://github.com/PC2005-cloud/dsh-pet"><img alt="stars" src="https://img.shields.io/github/stars/PC2005-cloud/dsh-pet?style=social"></a>
|
|
7
|
-
<a href="https://github.com/PC2005-cloud/dsh-pet/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/github/license/PC2005-cloud/dsh-pet?color=orange"></a>
|
|
8
|
-
<a href="https://awesome-dsh-plugin.com"><img alt="awesome dsh plugin" src="https://awesome-dsh-plugin.com/badge.svg"></a>
|
|
9
|
-
<img alt="platform" src="https://img.shields.io/badge/platform-DeepSeek%20Harness%20Web-8A2BE2">
|
|
10
|
-
<img alt="assets" src="https://img.shields.io/badge/assets-25%20animations-ff69b4">
|
|
11
|
-
</p>
|
|
12
|
-
|
|
13
|
-
> 一只住在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web 界面里的桌面宠物:待机呼吸、随机动作、屏幕漫游、点击反应、可拖拽。
|
|
14
|
-
> A floating desktop pet for the DeepSeek Harness Web UI.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## ✨ 功能特性
|
|
19
|
-
|
|
20
|
-
- **28 个手绘风透明动画**:待机呼吸、打瞌睡、玩魔方、哼歌、炸毛、吐泡泡、玩水枪、小提琴演奏……全部无缝衔接
|
|
21
|
-
- **永不停止的动画链**:每段动画播完立即按概率选下一个(30% 待机 / 10% 转向 / 40% 动作 / 20% 移动)
|
|
22
|
-
- **屏幕漫游**:朝 facing 方向行走,自动检查空间、不走出屏幕
|
|
23
|
-
- **点击 / 拖拽**:点击有随机回应动画(开心 / 害羞 / 傲娇),可拖到任意位置
|
|
24
|
-
- **左右朝向**:所有动画 CSS 镜像,人物可朝左 / 朝右
|
|
25
|
-
- **落地对齐**:动画统一脚底线,宠物始终站在"地面"上
|
|
26
|
-
- **流畅切换**:双缓冲 video 交叉淡入,切换零空白帧
|
|
27
|
-
- **无障碍友好**:支持 `prefers-reduced-motion`
|
|
28
|
-
|
|
29
|
-
## 📦 安装
|
|
30
|
-
|
|
31
|
-
```sh
|
|
32
|
-
dsh plugin --profile web add dsh-pet
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
重启 `dsh web`,宠物出现在界面右下角。
|
|
36
|
-
|
|
37
|
-
## ⚙️ 配置
|
|
38
|
-
|
|
39
|
-
| 配置项 | 说明 | 当前状态 |
|
|
40
|
-
|---|---|---|
|
|
41
|
-
| `size` | 宠物显示高度(px) | 默认 260,**暂未下发到浏览器**(DSH 客户端配置管线限制,走代码默认值) |
|
|
42
|
-
| `position` | 默认角落位置 | 默认右下角,同上暂未下发 |
|
|
43
|
-
| `fullRoot` | 原始 1200×1200 母版资源目录 | 默认 `$DSH_HOME/pet-assets`,需手动下载母版后生效 |
|
|
44
|
-
|
|
45
|
-
> 说明:插件安装即用,上述配置均为可选;`size`/`position` 的浏览器侧配置化正在规划中。
|
|
46
|
-
|
|
47
|
-
## 🗑️ 卸载
|
|
48
|
-
|
|
49
|
-
```sh
|
|
50
|
-
dsh plugin --profile web remove dsh-pet
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## 🖥️ 运行效果
|
|
54
|
-
|
|
55
|
-
宠物实际运行在 DSH Web 界面中的样子:
|
|
56
|
-
|
|
57
|
-
<p>
|
|
58
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/assets/screenshots/dsh-pet-running-1.png" width="380" alt="dsh-pet 运行效果 1" title="dsh-pet 运行效果 1">
|
|
59
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/assets/screenshots/dsh-pet-running-2.png" width="380" alt="dsh-pet 运行效果 2" title="dsh-pet 运行效果 2">
|
|
60
|
-
</p>
|
|
61
|
-
|
|
62
|
-
## 🎬 效果预览
|
|
63
|
-
|
|
64
|
-
> 动画为透明背景;GIF 预览中透明部分显示为页面底色,实际播放为透明。
|
|
65
|
-
|
|
66
|
-
<p>
|
|
67
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%BE%85%E6%9C%BA%E5%91%BC%E5%90%B8%E4%BC%91%E9%97%B2.gif" width="160" alt="待机呼吸休闲" title="待机呼吸休闲">
|
|
68
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E4%B8%9C%E5%BC%A0%E8%A5%BF%E6%9C%9B.gif" width="160" alt="东张西望" title="东张西望">
|
|
69
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%8E%9F%E5%9C%B0%E6%BC%82%E6%B5%AE%E8%B8%8F%E6%AD%A5.gif" width="160" alt="原地漂浮踏步" title="原地漂浮踏步">
|
|
70
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E5%8E%9F%E5%9C%B0%E5%B0%8F%E6%86%A9%E6%B2%89%E7%9C%A0.gif" width="160" alt="原地小憩沉眠" title="原地小憩沉眠">
|
|
71
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E7%82%B9%E5%87%BB%E5%9B%9E%E5%BA%94%20-%20%E5%BC%80%E5%BF%83%E8%B7%83%E5%8A%A8.gif" width="160" alt="点击回应 - 开心跃动" title="点击回应 - 开心跃动">
|
|
72
|
-
<img src="https://raw.githubusercontent.com/PC2005-cloud/dsh-pet/main/dsh-pet/assets/preview/%E8%A2%AB%E9%BC%A0%E6%A0%87%E6%8B%96%E6%8B%BD%E6%82%AC%E7%A9%BA%E5%8F%8D%E9%A6%88.gif" width="160" alt="被鼠标拖拽悬空反馈" title="被鼠标拖拽悬空反馈">
|
|
73
|
-
</p>
|
|
74
|
-
|
|
75
|
-
全部 28 个动画见仓库:`dsh-pet/assets/thumb/`。
|
|
76
|
-
|
|
77
|
-
## 📚 完整项目(不止是插件)
|
|
78
|
-
|
|
79
|
-
这是**完整的三件套项目**,任何人 clone 仓库都可以从零生成自己的桌面宠物:
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
① 提示词(配方) → ② 素材生成链(引擎) → ③ 插件(成品)
|
|
83
|
-
AI 生成动画的配方 源视频 → 透明动画的管线 运行在 DSH 里的宠物
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
- 仓库:[PC2005-cloud/dsh-pet](https://github.com/PC2005-cloud/dsh-pet)
|
|
87
|
-
- 设计与实现文档:[DESIGN.md](https://github.com/PC2005-cloud/dsh-pet/blob/master/DESIGN.md)
|
|
88
|
-
|
|
89
|
-
## 🔎 发现更多 DSH 插件
|
|
90
|
-
|
|
91
|
-
- 社区插件目录:[awesome-dsh-plugin.com](https://awesome-dsh-plugin.com)
|
|
92
|
-
- DSH 官方仓库:[deepseek-ai/DeepSeek-Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
93
|
-
|
|
94
|
-
## 📄 许可
|
|
95
|
-
|
|
96
|
-
- 代码:MIT
|
|
97
|
-
- 素材(动画/提示词):见仓库说明
|