dsh-pet-live2d 3.2.0 → 3.3.1
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/CHANGELOG.md +20 -0
- package/README.md +14 -1
- package/icon.png +0 -0
- package/lib/client.js +125 -7
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## 3.3.1(2026-10-09)
|
|
4
|
+
|
|
5
|
+
### 修:插件卡片上的图标换成她本人
|
|
6
|
+
|
|
7
|
+
3.3.0 那张卡片上的图标是手画的抽象图形,不好看。现在直接用桌面端托盘那套美术:从待机画面
|
|
8
|
+
裁一版脸的特写(256×256,带透明底),「插件」页与「设置 → 内置插件」两处都换成它。
|
|
9
|
+
|
|
10
|
+
图标与模型同属 **CC BY-NC-SA 4.0**(由截屏裁切缩放而来,属于改编),署名见
|
|
11
|
+
[`../NOTICE.md`](../NOTICE.md)。
|
|
12
|
+
|
|
13
|
+
## 3.3.0(2026-10-09)
|
|
14
|
+
|
|
15
|
+
### 新:官方「插件」页里有自己的图标和常用设置
|
|
16
|
+
|
|
17
|
+
侧栏「插件」页上这张卡片以前是默认插画加包名,现在有自己的图标、中文与英文标题/描述
|
|
18
|
+
(「设置 → 内置插件」那份列表同样受益)。点进详情页多了一节配置区:常用开关(气泡 /
|
|
19
|
+
提示音 / 摸头 / 摸尾巴 / 转圈 / 记住装扮)、四根手感滑杆(注视满偏、收回倍数、摸鱼静置、
|
|
20
|
+
提示音音量)和「显示位置」。它写的是与 **设置 → 桌宠** 同一份配置,改哪边都一样;
|
|
21
|
+
相位台词、池子编辑器、装扮与文案仍在设置页里改。
|
|
22
|
+
|
|
3
23
|
## 3.2.0(2026-10-09)
|
|
4
24
|
|
|
5
25
|
### 新:会话状态提示音
|
package/README.md
CHANGED
|
@@ -68,10 +68,22 @@ dsh plugin --profile web add "link:./dsh-pet-live2d/dsh-live2d-pet"
|
|
|
68
68
|
|
|
69
69
|
- **右键点宠物** 呼出面板:「动作」「装扮」两个页签,底部是大小滑杆和「归位」。
|
|
70
70
|
平时画面上没有常驻 UI。
|
|
71
|
-
- **改配置**
|
|
71
|
+
- **改配置** 两个入口:**DSH 设置页 → 桌宠**(完整设置),或**侧栏「插件」→ 本插件**(常用开关)。
|
|
72
72
|
|
|
73
73
|
## 设置说明
|
|
74
74
|
|
|
75
|
+
### 官方「插件」页上的那一节
|
|
76
|
+
|
|
77
|
+
侧栏点「插件」,「已安装」里那张带图标的卡片就是本插件。点进详情,描述与插件行之间是它
|
|
78
|
+
自己的配置区:
|
|
79
|
+
|
|
80
|
+
- **常用开关**:气泡、会话提示音、摸头 / 摸尾巴 / 转圈、跨启动记住装扮;
|
|
81
|
+
- **四根滑杆**:注视满偏、收回倍数、静置多久开始摸鱼、提示音音量;
|
|
82
|
+
- **显示位置**:自动 / 页面内 / 桌面。
|
|
83
|
+
|
|
84
|
+
改的是与设置页**同一份**配置(`%DSH_HOME%\pet-settings.json`),两边随时一致。相位台词、
|
|
85
|
+
池子编辑器、装扮与台词文案仍在 **设置 → 桌宠** 里改 —— 那里才是完整设置。
|
|
86
|
+
|
|
75
87
|
### 摸鱼:每个槽位一张条目表
|
|
76
88
|
|
|
77
89
|
摸鱼 = 静置一会儿之后,宠物自己换个样子。**每个槽位各掷一次骰子**(不是"这次只动一两个"),
|
|
@@ -366,6 +378,7 @@ cd ../../tools/browser-test && npm install && npm run suite
|
|
|
366
378
|
- Cubism Core:Live2D 专有,**不随包分发**;缺失时由宿主半区从 Live2D 官方 CDN 取一份并缓存到本地
|
|
367
379
|
- DS鲸鱼娘模型:**CC BY-NC-SA 4.0**(署名 · **非商业** · 相同方式共享),见
|
|
368
380
|
[`pets/ds-whale-girl/LICENSE`](pets/ds-whale-girl/LICENSE)。
|
|
381
|
+
**插件图标 `icon.png` 同属这一许可**(由模型待机画面裁切缩放而来,属于改编)。
|
|
369
382
|
|
|
370
383
|
版权链:**上善无形**(鲸鱼娘角色原作,原创 OC「溟月」)→ **ZipZipPipe**(DeepSeek 女仆二创)
|
|
371
384
|
→ **氵六青**(本模型)。氵六青已授权本项目转载开源,但该授权**不解除基础版权**,
|
package/icon.png
ADDED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -26,6 +26,15 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
26
26
|
const { useCallback, useEffect, useRef, useState } = react;
|
|
27
27
|
|
|
28
28
|
const name = "live2d-pet";
|
|
29
|
+
/**
|
|
30
|
+
* 本包的 npm 包名。
|
|
31
|
+
*
|
|
32
|
+
* 官方「插件」页按**包名**派发组合包的配置区(`plugins.bundle.config` 的 key 就是
|
|
33
|
+
* 组合包的包名,见 `dsh-client-ui-plugin-manager` 的 `configLedgerSource`),所以这个
|
|
34
|
+
* 字符串必须与 `package.json` 的 `name` 逐字相同 —— 写错的表现是"注册没报错、
|
|
35
|
+
* 页面上什么都没多出来"(页面按包名查不到这个键就不渲染那一节)。
|
|
36
|
+
*/
|
|
37
|
+
const PACKAGE_NAME = "dsh-pet-live2d";
|
|
29
38
|
// "slots" 是 DSH 客户端界面给插件的扩展点(设置页就是这么挂进去的)。
|
|
30
39
|
const inject = ["slots"];
|
|
31
40
|
|
|
@@ -3550,7 +3559,20 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
3550
3559
|
+ SETTINGS_SEL + " [data-setting=phases]{grid-template-columns:minmax(0,1fr)}",
|
|
3551
3560
|
"}",
|
|
3552
3561
|
];
|
|
3553
|
-
|
|
3562
|
+
/**
|
|
3563
|
+
* 官方「插件」页那一节的微调(作用域 = 两个属性同时在的那个根节点)。
|
|
3564
|
+
*
|
|
3565
|
+
* 只有两条,都是有理由的:
|
|
3566
|
+
* * 状态行("她现在在哪")本来借的是 `[data-note]` 的灰度 —— 那是给补充说明用的,
|
|
3567
|
+
* 而这一行是这一节**最先要回答**的问题,按 55% 透明度画就太虚了;
|
|
3568
|
+
* * 插件页是窄栏,卡片间距收一档,四张卡不至于要滚半天。
|
|
3569
|
+
*/
|
|
3570
|
+
const PLUGIN_PAGE_CSS = [
|
|
3571
|
+
SETTINGS_SEL + "[data-pet-plugin-page]>[data-plugin-status]{font-size:11px;opacity:.85;padding:0 0 9px}",
|
|
3572
|
+
SETTINGS_SEL + "[data-pet-plugin-page] [data-card]{margin-bottom:8px}",
|
|
3573
|
+
];
|
|
3574
|
+
const STYLE_TEXT = CSS + "\n" + SETTINGS_CSS.join("\n") + "\n" + PLUGIN_PAGE_CSS.join("\n")
|
|
3575
|
+
+ "\n" + PAGE_PHASE_CSS.join("\n");
|
|
3554
3576
|
|
|
3555
3577
|
function ensureStyle() {
|
|
3556
3578
|
if (document.getElementById(STYLE_ID) !== null) return;
|
|
@@ -4752,8 +4774,13 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
4752
4774
|
function TuningControls(props) {
|
|
4753
4775
|
useSettings();
|
|
4754
4776
|
const only = props?.group;
|
|
4755
|
-
|
|
4756
|
-
|
|
4777
|
+
// 也能按**具体键**挑几根滑杆(官方插件页那一节只放最常用的四项,
|
|
4778
|
+
// 不想把八根手感滑杆整套搬过去)。给了 keys 就按 keys 过滤,忽略 group。
|
|
4779
|
+
const keys = Array.isArray(props?.keys) ? props.keys : null;
|
|
4780
|
+
const fields = TUNING_FIELDS.filter((field) => keys === null
|
|
4781
|
+
? (only === undefined || tuningGroupOf(field) === only)
|
|
4782
|
+
: keys.includes(field.key));
|
|
4783
|
+
return h("div", { "data-settings": "", "data-setting": only ?? (keys === null ? "all" : "subset") },
|
|
4757
4784
|
fields.map((field) => h("label", {
|
|
4758
4785
|
key: field.key,
|
|
4759
4786
|
"data-field": field.key,
|
|
@@ -4773,13 +4800,14 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
4773
4800
|
h("code", { "data-value": field.key }, String(TUNING[field.key])),
|
|
4774
4801
|
)),
|
|
4775
4802
|
// 恢复默认单独一行:它是"这一组"的动作,混在滑杆行里会看着像又一个控件。
|
|
4803
|
+
// 只挑了四项时按钮说"全部" —— 它恢复的确实是整份 TUNING,不含糊。
|
|
4776
4804
|
only === undefined || only === "feel"
|
|
4777
4805
|
? h("div", { "data-add-row": "" },
|
|
4778
4806
|
h("button", {
|
|
4779
4807
|
type: "button",
|
|
4780
4808
|
"data-reset": "tuning",
|
|
4781
4809
|
onClick: () => applyTuning(Object.assign({}, TUNING_DEFAULTS)),
|
|
4782
|
-
}, "恢复默认"))
|
|
4810
|
+
}, keys === null ? "恢复默认" : "全部恢复默认"))
|
|
4783
4811
|
: null,
|
|
4784
4812
|
);
|
|
4785
4813
|
}
|
|
@@ -8621,15 +8649,25 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
8621
8649
|
);
|
|
8622
8650
|
}
|
|
8623
8651
|
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8652
|
+
/**
|
|
8653
|
+
* 一张设置卡片:标题条(+ 右上角提示)+ 内容区。
|
|
8654
|
+
*
|
|
8655
|
+
* 提到模块作用域是因为现在**两个地方**要画同一种卡片:DSH 设置页那一节,和官方
|
|
8656
|
+
* 「插件」页上这一组合包的配置区。各写一份的下场是两边慢慢长得不一样。
|
|
8657
|
+
*/
|
|
8658
|
+
function settingsCard(key, title, hint, body) {
|
|
8659
|
+
return h("div", { key, "data-card": key },
|
|
8627
8660
|
h("div", { "data-card-head": "" },
|
|
8628
8661
|
h("span", { "data-card-title": "" }, title),
|
|
8629
8662
|
hint === null || hint === undefined ? null : h("span", { "data-card-hint": "" }, hint),
|
|
8630
8663
|
),
|
|
8631
8664
|
h("div", { "data-card-body": "" }, body),
|
|
8632
8665
|
);
|
|
8666
|
+
}
|
|
8667
|
+
|
|
8668
|
+
function PetSettingsBody({ compact = false } = {}) {
|
|
8669
|
+
useSettings();
|
|
8670
|
+
const card = settingsCard;
|
|
8633
8671
|
return [
|
|
8634
8672
|
...TUNING_GROUPS.filter((group) => !TUNING_GROUPS_INLINE.includes(group.id)).map((group) => card(
|
|
8635
8673
|
"tune-" + group.id, group.label, group.hint, h(TuningControls, { group: group.id }))),
|
|
@@ -8680,6 +8718,61 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
8680
8718
|
return h("div", { "data-pet-settings": "" }, h(PetSettingsBody, null));
|
|
8681
8719
|
}
|
|
8682
8720
|
|
|
8721
|
+
/**
|
|
8722
|
+
* 侧栏「插件」页上这一组合包的配置区(`plugins.bundle.config`,键 = 包名)。
|
|
8723
|
+
*
|
|
8724
|
+
* 为什么要有它:官方插件页把"插件自带配置"渲染在**组合包详情页**的描述与行之间
|
|
8725
|
+
* (`dsh-client-ui-plugin-manager`;页面只在有人注册了这个键时才画那一节)。我们的
|
|
8726
|
+
* 组合包只有一行(`live2d-pet`),所以"这一行的配置"就是"这只宠物的配置"。
|
|
8727
|
+
*
|
|
8728
|
+
* 它**不是**设置正文的第二个家:相位台词、池子编辑器、装扮与文案仍然只在
|
|
8729
|
+
* 「设置 → 桌宠」里改(正文只写一份,这条是 2.0.0 定下来的)。这里是插件页上最常用的
|
|
8730
|
+
* 那几项 —— 开关、四根滑杆、显示位置 —— 写进去的还是**同一份共享设置**
|
|
8731
|
+
* (`persistShared` → `%DSH_HOME%\pet-settings.json`),所以两个界面永远一致。
|
|
8732
|
+
*
|
|
8733
|
+
* 样式直接复用设置正文那一套(`[data-pet-settings]` 作用域):卡片、行、滑杆、药丸
|
|
8734
|
+
* 按钮的观感与设置页逐字相同,不需要新写一份 CSS。
|
|
8735
|
+
*/
|
|
8736
|
+
function PetPluginConfig() {
|
|
8737
|
+
useSettings();
|
|
8738
|
+
const layer = useLayerState();
|
|
8739
|
+
const pet = MANIFEST.current ?? {};
|
|
8740
|
+
const petLabel = typeof pet.label === "string" && pet.label !== ""
|
|
8741
|
+
? pet.label
|
|
8742
|
+
: (typeof pet.id === "string" && pet.id !== "" ? pet.id : "还没加载");
|
|
8743
|
+
const modeLabel = layer.mode === "inline" ? "页面内" : (layer.mode === "desktop" ? "桌面" : "自动");
|
|
8744
|
+
const ownerLabel = layer.owner === "desktop" ? "现在在桌面上" : "现在在页面里";
|
|
8745
|
+
const flagRow = (key, label, note) => h("label", { key, "data-flag-row": key },
|
|
8746
|
+
h("input", {
|
|
8747
|
+
type: "checkbox",
|
|
8748
|
+
checked: FLAGS[key] === true,
|
|
8749
|
+
"data-flag": key,
|
|
8750
|
+
onChange: (event) => applyFlag(key, event.target.checked),
|
|
8751
|
+
}),
|
|
8752
|
+
h("span", { "data-row-label": "" }, label),
|
|
8753
|
+
note === undefined ? null : h("span", { "data-note-inline": "" }, note),
|
|
8754
|
+
);
|
|
8755
|
+
return h("div", { "data-pet-settings": "", "data-pet-plugin-page": "" },
|
|
8756
|
+
// 第一行先说"这只宠物现在在哪":它比任何开关都更该先回答,
|
|
8757
|
+
// 而且换过显示位置的人回来第一眼就是找这一句。
|
|
8758
|
+
h("div", { "data-plugin-status": "" },
|
|
8759
|
+
"当前宠物:" + petLabel + " · 显示位置:" + modeLabel + "(" + ownerLabel + ")"),
|
|
8760
|
+
settingsCard("plugin-flags", "常用开关", "点一下立刻生效", [
|
|
8761
|
+
flagRow("bubbleEnabled", "显示气泡", FLAGS.bubbleEnabled ? undefined : "已关:任何台词都不弹"),
|
|
8762
|
+
flagRow("soundEnabled", "会话提示音", FLAGS.soundEnabled ? undefined : "默认静音"),
|
|
8763
|
+
flagRow("patEnabled", "摸头有反应", undefined),
|
|
8764
|
+
flagRow("tailEnabled", "摸尾巴有反应", undefined),
|
|
8765
|
+
flagRow("spinEnabled", "鼠标绕着转圈会晕", undefined),
|
|
8766
|
+
flagRow("outfitArchive", "跨启动记住装扮", FLAGS.outfitArchive ? undefined : "已关:也不再记录"),
|
|
8767
|
+
]),
|
|
8768
|
+
settingsCard("plugin-tuning", "手感", "注视范围 · 摸鱼节奏 · 音量",
|
|
8769
|
+
h(TuningControls, { keys: ["gazeRangePx", "gazeWatchingRatio", "fidgetQuietMs", "soundVolume"] })),
|
|
8770
|
+
settingsCard("plugin-layer", "显示位置", "页面内 / 桌面上", h(LayerControls, null)),
|
|
8771
|
+
h("div", { "data-note": "" },
|
|
8772
|
+
"相位台词、池子编辑器、装扮与台词文案在「设置 → 桌宠」里改。"),
|
|
8773
|
+
);
|
|
8774
|
+
}
|
|
8775
|
+
|
|
8683
8776
|
function applySettings(ctx) {
|
|
8684
8777
|
if (ctx === null || ctx === undefined) return;
|
|
8685
8778
|
const slots = ctx.slots;
|
|
@@ -8696,6 +8789,30 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
8696
8789
|
}
|
|
8697
8790
|
}
|
|
8698
8791
|
|
|
8792
|
+
/**
|
|
8793
|
+
* 侧栏「插件」页里的配置区。
|
|
8794
|
+
*
|
|
8795
|
+
* 两个容易踩的点:
|
|
8796
|
+
*
|
|
8797
|
+
* * **键必须写包名**(`PACKAGE_NAME`)—— 页面按组合包的包名派发这一格,写错的表现是
|
|
8798
|
+
* "注册成功、页面什么都不多"。
|
|
8799
|
+
* * **`slots.inject` 而不是"现在就注册"**:插件页是懒挂载的面板,它的子 slot 在页面
|
|
8800
|
+
* 注册时才声明;`inject` 会等到那一刻再跑(页面重开/销毁也跟着走)。
|
|
8801
|
+
*/
|
|
8802
|
+
function applyPluginPage(ctx) {
|
|
8803
|
+
if (ctx === null || ctx === undefined) return;
|
|
8804
|
+
const slots = ctx.slots;
|
|
8805
|
+
if (slots === undefined || slots === null) return;
|
|
8806
|
+
try {
|
|
8807
|
+
slots.inject("plugins.bundle.config", () => slots.register({
|
|
8808
|
+
name: "plugins.bundle.config",
|
|
8809
|
+
key: PACKAGE_NAME,
|
|
8810
|
+
}, () => h(PetPluginConfig, null)));
|
|
8811
|
+
} catch {
|
|
8812
|
+
/* 老版本 DSH 没有这条 slot:设置页那一节还在,不影响使用 */
|
|
8813
|
+
}
|
|
8814
|
+
}
|
|
8815
|
+
|
|
8699
8816
|
function apply(ctx) {
|
|
8700
8817
|
ensureStyle();
|
|
8701
8818
|
// 先按本地存档起来(宿主不在时这就是全部)。
|
|
@@ -8742,6 +8859,7 @@ window.__ModuleLoader__.load({ id: "dsh-pet-live2d", factory: (require) => {
|
|
|
8742
8859
|
}, SHARED_POLL_MS);
|
|
8743
8860
|
}
|
|
8744
8861
|
applySettings(ctx);
|
|
8862
|
+
applyPluginPage(ctx);
|
|
8745
8863
|
// Takeover: an earlier instance — a hot reload, or one left behind by a
|
|
8746
8864
|
// crashed reload — must not leave a second floating pet on the page.
|
|
8747
8865
|
teardown();
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-pet-live2d",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"description": "Live2D 桌宠插件:为 DSH Web GUI 挂一只可拖动、会跟随鼠标、能换动作与表情的 Live2D 宠物。",
|
|
5
|
+
"icon": "./icon.png",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "lib/index.js",
|
|
7
8
|
"license": "MIT",
|
|
@@ -18,6 +19,8 @@
|
|
|
18
19
|
"src",
|
|
19
20
|
"docs",
|
|
20
21
|
"pets",
|
|
22
|
+
"locale",
|
|
23
|
+
"icon.png",
|
|
21
24
|
"cordis.patch.yml",
|
|
22
25
|
"screenshots.json",
|
|
23
26
|
"README.md",
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
"./client": "./lib/client.js",
|
|
32
35
|
"./desktop": "./lib/desktop.js",
|
|
33
36
|
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
37
|
+
"./locale/*.json": "./locale/*.json",
|
|
34
38
|
"./package.json": "./package.json"
|
|
35
39
|
},
|
|
36
40
|
"scripts": {
|
|
@@ -49,8 +53,8 @@
|
|
|
49
53
|
}
|
|
50
54
|
},
|
|
51
55
|
"optionalDependencies": {
|
|
52
|
-
"dsh-pet-live2d-desktop-darwin-arm64": "3.
|
|
53
|
-
"dsh-pet-live2d-desktop-win32-x64": "3.
|
|
56
|
+
"dsh-pet-live2d-desktop-darwin-arm64": "3.3.1",
|
|
57
|
+
"dsh-pet-live2d-desktop-win32-x64": "3.3.1"
|
|
54
58
|
},
|
|
55
59
|
"devDependencies": {
|
|
56
60
|
"esbuild": "^0.25.10",
|