dsh-pet-live2d-viola 1.1.1 → 1.1.2

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.
Files changed (2) hide show
  1. package/lib/client.js +87 -22
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -100,22 +100,36 @@ window.__ModuleLoader__.load({
100
100
  * @see aspect
101
101
  */
102
102
  const SURFACE_ASPECT_SCALE = {
103
- yuno: { default: 1.15, full: 1, threeQuarter: 1.1, bust: 1.28 },
104
- yuno_virtual: { default: 1.15, full: 1, threeQuarter: 1.1, bust: 1.28 }
103
+ /*
104
+ * The shared entry: every model falls back to `default`, so a character only needs its own line to differ.
105
+ *
106
+ * `full` is named explicitly because `default` also covers crops with no entry — a bare `default: 0.9` would
107
+ * narrow EVERY crop, which is not the same thing.
108
+ */
109
+ default: { default: 1, full: 0.7, threeQuarter: 0.85 },
110
+ yuno: { default: 1.15, full: 0.7, threeQuarter: 1.1, bust: 1.28 },
111
+ yuno_virtual: { default: 1.15, full: 0.7, threeQuarter: 1.1, bust: 1.28 }
105
112
  };
106
113
  /**
107
114
  * The framing-box width multiplier for a character and crop.
108
115
  *
116
+ * Resolution order: the character's own entry, then the shared `default` entry, then 1. Within an entry, a crop
117
+ * missing from it falls back to that entry's `default`, so a character can widen one crop without listing the
118
+ * others.
119
+ *
109
120
  * @param character - the active model id.
110
121
  * @param crop - the framing preset key.
111
122
  * @returns the multiplier on the surface width; 1 when nothing is configured.
112
123
  */
113
124
  function aspectScaleFor(character, crop) {
114
- const entry = SURFACE_ASPECT_SCALE[character];
115
- if (entry === undefined) return 1;
116
- // A plain number applies to every crop; an object may override per crop with `default` as the fallback.
117
- const value = typeof entry === "number" ? entry : (entry[crop] ?? entry.default);
118
- return typeof value === "number" && value > 0 ? value : 1;
125
+ const resolve = (entry) => {
126
+ if (entry === undefined) return undefined;
127
+ if (typeof entry === "number") return entry;
128
+ const value = entry[crop] ?? entry.default;
129
+ return typeof value === "number" ? value : undefined;
130
+ };
131
+ const value = resolve(SURFACE_ASPECT_SCALE[character]) ?? resolve(SURFACE_ASPECT_SCALE.default) ?? 1;
132
+ return value > 0 ? value : 1;
119
133
  }
120
134
  /**
121
135
  * Vertical position adjustment for a widened box, as a fraction of the box HEIGHT.
@@ -135,21 +149,36 @@ window.__ModuleLoader__.load({
135
149
  * line. Change a number here; nothing else has to move.
136
150
  */
137
151
  const SURFACE_Y_ADJUST = {
138
- yuno: { default: 0.12, full: 0, threeQuarter: 0.08, bust: 0.3 },
139
- yuno_virtual: { default: 0.12, full: 0, threeQuarter: 0.08, bust: 0.3 }
152
+ /*
153
+ * The shared entry, like the one on `SURFACE_ASPECT_SCALE`: every model falls back to it, so a value meant for
154
+ * everyone is written once. Per character only where it has to differ.
155
+ *
156
+ * `full` begins at 0 — the un-widened box's own framing, which is the right starting point for a crop that has
157
+ * not needed adjustment.
158
+ */
159
+ default: { default: 0, full: -0.18, threeQuarter: -0.14 },
160
+ yuno: { default: 0.12, full: -0.18, threeQuarter: 0.08, bust: 0.3 },
161
+ yuno_virtual: { default: 0.12, full: -0.18, threeQuarter: 0.08, bust: 0.3 }
140
162
  };
141
163
  /**
142
164
  * The vertical adjustment for a character and crop.
143
165
  *
166
+ * Resolution order mirrors `aspectScaleFor`: the character's own entry, then the shared `default` entry, then 0.
167
+ * Within an entry, a crop missing from it falls back to that entry's `default`.
168
+ *
144
169
  * @param character - the active model id.
145
170
  * @param crop - the framing preset key.
146
171
  * @returns the fraction of box height to shift by; 0 when nothing is configured.
147
172
  */
148
173
  function yAdjustFor(character, crop) {
149
- const perChar = SURFACE_Y_ADJUST[character];
150
- if (perChar === undefined) return 0;
151
- const value = perChar[crop] ?? perChar.default;
152
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
174
+ const resolve = (entry) => {
175
+ if (entry === undefined) return undefined;
176
+ if (typeof entry === "number") return entry;
177
+ const value = entry[crop] ?? entry.default;
178
+ return typeof value === "number" ? value : undefined;
179
+ };
180
+ const value = resolve(SURFACE_Y_ADJUST[character]) ?? resolve(SURFACE_Y_ADJUST.default) ?? 0;
181
+ return Number.isFinite(value) ? value : 0;
153
182
  }
154
183
 
155
184
  /**
@@ -163,15 +192,33 @@ window.__ModuleLoader__.load({
163
192
  * preset's zoom, so a tighter crop shifts further.
164
193
  */
165
194
  const SURFACE_X_ADJUST = {
166
- yuno: { default: 0, bust: 0 },
167
- yuno_virtual: { default: 0, bust: 0 }
195
+ /*
196
+ * The shared entry, mirroring `SURFACE_Y_ADJUST`: every model falls back to it, so a value meant for everyone
197
+ * is written once. Without it, a request to move "everyone" would silently apply to 由乃 alone.
198
+ */
199
+ default: { default: 0, full: 0.07, threeQuarter: -0.02 },
200
+ yuno: { default: 0, full: 0.07, bust: 0 },
201
+ yuno_virtual: { default: 0, full: 0.07, bust: 0 }
168
202
  };
169
- /** The horizontal adjustment for a character and crop. @see SURFACE_X_ADJUST */
203
+ /**
204
+ * The horizontal adjustment for a character and crop.
205
+ *
206
+ * Resolution order mirrors `aspectScaleFor` / `yAdjustFor`: the character's own entry, then the shared `default`
207
+ * entry, then 0. Reading only the character's own entry is what made an "everyone" change apply to 由乃 alone.
208
+ *
209
+ * @param character - the active model id.
210
+ * @param crop - the framing preset key.
211
+ * @returns the fraction of box width to shift by; 0 when nothing is configured.
212
+ */
170
213
  function xAdjustFor(character, crop) {
171
- const perChar = SURFACE_X_ADJUST[character];
172
- if (perChar === undefined) return 0;
173
- const value = perChar[crop] ?? perChar.default;
174
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
214
+ const resolve = (entry) => {
215
+ if (entry === undefined) return undefined;
216
+ if (typeof entry === "number") return entry;
217
+ const value = entry[crop] ?? entry.default;
218
+ return typeof value === "number" ? value : undefined;
219
+ };
220
+ const value = resolve(SURFACE_X_ADJUST[character]) ?? resolve(SURFACE_X_ADJUST.default) ?? 0;
221
+ return Number.isFinite(value) ? value : 0;
175
222
  }
176
223
  /**
177
224
  * Extra surface height, as a multiple of the base height, added BELOW the character.
@@ -2387,8 +2434,26 @@ window.__ModuleLoader__.load({
2387
2434
  bottom: calc(100% - var(--bubble-offset, 10px) * var(--bubble-scale, 1));
2388
2435
  top: auto;
2389
2436
  transform: translateX(-50%);
2390
- max-width: min(94%, 400px);
2391
- min-width: 84px;
2437
+ /*
2438
+ * An EXPLICIT width, because the percentage offset would otherwise decide it.
2439
+ *
2440
+ * The element is absolutely positioned with left:50%, and for those the shrink-to-fit width has the offset
2441
+ * subtracted from the containing block: in a 246 px frame the available width is only 246 - 123 = 123 px. That is why
2442
+ * raising max-width had no effect — measured, the rendered width stayed at exactly half the frame (123 / 246), and
2443
+ * removing max-width, zeroing min-width and clearing the transform ALL also left it at 123.
2444
+ *
2445
+ * Setting the width outright takes it out of that calculation, so the caption is sized by the text and by how big the
2446
+ * pet is, not by how far the frame has been cropped. Measured after the change: 400 px in every crop.
2447
+ *
2448
+ * All three numbers are independent of the frame:
2449
+ * 351px * --bubble-scale tracks the pet's own size, so a bigger pet gets a bigger caption
2450
+ * 400px the ceiling, unchanged from before
2451
+ * 84px * --bubble-scale the floor, so a two-word line is not a sliver
2452
+ * max-content hugs the text rather than filling the width
2453
+ */
2454
+ width: max-content;
2455
+ max-width: min(calc(351px * var(--bubble-scale, 1)), 400px);
2456
+ min-width: calc(84px * var(--bubble-scale, 1));
2392
2457
  /*
2393
2458
  * Sized from --bubble-scale, which the layout sets to the model's own scale.
2394
2459
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-pet-live2d-viola",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Live2D desktop pet for the DeepSeek Harness web GUI. One pet, three characters: 都子 (miyako_014_casual_spring_01_marukun), 薇欧拉 in casual or school uniform, and 由乃 in casual clothes or her virtual-avatar outfit — each with its own motions, expressions, voice lines, captions, idle drift, click reactions and goodbye.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",