@lemoncat7/dsh-theme-xiaohei 0.3.0-alpha.23 → 0.3.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 (222) hide show
  1. package/README.md +39 -17
  2. package/THIRD_PARTY_NOTICES.md +41 -0
  3. package/lib/appearance.js +26 -10
  4. package/lib/blink.js +3 -3
  5. package/lib/bloub-heixiu/ambient.d.ts +3 -0
  6. package/lib/bloub-heixiu/ambient.js +12 -0
  7. package/lib/bloub-heixiu/character.d.ts +33 -0
  8. package/lib/bloub-heixiu/character.js +124 -0
  9. package/lib/bloub-heixiu/effects.d.ts +4 -0
  10. package/lib/bloub-heixiu/effects.js +91 -0
  11. package/lib/bloub-heixiu/flight.d.ts +15 -0
  12. package/lib/bloub-heixiu/flight.js +66 -0
  13. package/lib/bloub-heixiu/follow.d.ts +13 -0
  14. package/lib/bloub-heixiu/follow.js +23 -0
  15. package/lib/bloub-heixiu/layout.d.ts +18 -0
  16. package/lib/bloub-heixiu/layout.js +12 -0
  17. package/lib/bloub-heixiu/renderer.d.ts +16 -0
  18. package/lib/bloub-heixiu/renderer.js +94 -0
  19. package/lib/bloub-heixiu/runtime.d.ts +6 -0
  20. package/lib/bloub-heixiu/runtime.js +395 -0
  21. package/lib/bloub-heixiu/signals.d.ts +17 -0
  22. package/lib/bloub-heixiu/signals.js +53 -0
  23. package/lib/bloub-heixiu/styles.d.ts +2 -0
  24. package/lib/bloub-heixiu/styles.js +98 -0
  25. package/lib/chrome/accessibility.d.ts +1 -1
  26. package/lib/chrome/accessibility.js +5 -13
  27. package/lib/chrome/composer-avatar.d.ts +10 -0
  28. package/lib/chrome/composer-avatar.js +599 -0
  29. package/lib/chrome/composer-send-heixiu.d.ts +3 -0
  30. package/lib/chrome/composer-send-heixiu.js +143 -0
  31. package/lib/chrome/composer.d.ts +2 -2
  32. package/lib/chrome/composer.js +84 -95
  33. package/lib/chrome/controls.d.ts +8 -0
  34. package/lib/chrome/controls.js +348 -0
  35. package/lib/chrome/conversation-messages.d.ts +1 -1
  36. package/lib/chrome/conversation-messages.js +207 -9
  37. package/lib/chrome/conversation.d.ts +1 -1
  38. package/lib/chrome/conversation.js +6 -0
  39. package/lib/chrome/identity.js +4 -18
  40. package/lib/chrome/portal.d.ts +1 -1
  41. package/lib/chrome/portal.js +1 -1
  42. package/lib/chrome/sidebar.d.ts +1 -1
  43. package/lib/chrome/sidebar.js +134 -153
  44. package/lib/chrome/tokens.d.ts +1 -1
  45. package/lib/chrome/tokens.js +121 -68
  46. package/lib/chrome/workspace.d.ts +2 -2
  47. package/lib/chrome/workspace.js +35 -254
  48. package/lib/chrome.js +4 -0
  49. package/lib/client.d.ts +5 -12
  50. package/lib/client.js +6262 -4455
  51. package/lib/composer-avatar.d.ts +18 -0
  52. package/lib/composer-avatar.js +441 -0
  53. package/lib/composer-send-heixiu.d.ts +8 -0
  54. package/lib/composer-send-heixiu.js +133 -0
  55. package/lib/gaze.js +3 -3
  56. package/lib/generated-backgrounds.d.ts +14 -0
  57. package/lib/generated-backgrounds.js +14 -0
  58. package/lib/generated-character-motion.d.ts +4 -0
  59. package/lib/generated-character-motion.js +2 -0
  60. package/lib/generated-identity.d.ts +1 -0
  61. package/lib/generated-identity.js +1 -0
  62. package/lib/generated-keyart.d.ts +18 -3
  63. package/lib/generated-keyart.js +18 -3
  64. package/lib/host-contract.d.ts +9 -0
  65. package/lib/host-contract.js +13 -0
  66. package/lib/host-dom.d.ts +11 -0
  67. package/lib/host-dom.js +60 -0
  68. package/lib/loading-heixiu.js +3 -3
  69. package/lib/metallic-brand-mark.d.ts +10 -0
  70. package/lib/metallic-brand-mark.js +323 -0
  71. package/lib/plugin.d.ts +1 -1
  72. package/lib/plugin.js +31 -16
  73. package/lib/portal.js +11 -10
  74. package/lib/reactions.js +3 -3
  75. package/lib/scene/avatar-model.d.ts +6 -0
  76. package/lib/scene/avatar-model.js +646 -0
  77. package/lib/scene/avatar-motion.d.ts +3 -0
  78. package/lib/scene/avatar-motion.js +799 -0
  79. package/lib/scene/character-idle.d.ts +17 -0
  80. package/lib/scene/character-idle.js +65 -0
  81. package/lib/scene/character-layout.d.ts +24 -0
  82. package/lib/scene/character-layout.js +51 -0
  83. package/lib/scene/character-motion-clock.d.ts +18 -0
  84. package/lib/scene/character-motion-clock.js +57 -0
  85. package/lib/scene/character-motion-types.d.ts +12 -0
  86. package/lib/scene/character-motion-types.js +2 -0
  87. package/lib/scene/character-motion.d.ts +6 -0
  88. package/lib/scene/character-motion.js +126 -0
  89. package/lib/scene/character-poses.d.ts +26 -0
  90. package/lib/scene/character-poses.js +11 -0
  91. package/lib/scene/character-rig-renderer.d.ts +4 -0
  92. package/lib/scene/character-rig-renderer.js +85 -0
  93. package/lib/scene/character-rig.d.ts +20 -0
  94. package/lib/scene/character-rig.js +53 -0
  95. package/lib/scene/heixiu-feedback.d.ts +1 -1
  96. package/lib/scene/heixiu-feedback.js +0 -17
  97. package/lib/scene/pointer-bridge.d.ts +21 -0
  98. package/lib/scene/pointer-bridge.js +155 -0
  99. package/lib/scene/runtime.d.ts +12 -0
  100. package/lib/scene/runtime.js +87 -0
  101. package/lib/scene/styles.d.ts +7 -0
  102. package/lib/scene/styles.js +75 -0
  103. package/lib/scene/sylva-performance.d.ts +11 -0
  104. package/lib/scene/sylva-performance.js +58 -0
  105. package/lib/scene/wallpaper-character-styles.d.ts +3 -0
  106. package/lib/scene/wallpaper-character-styles.js +53 -0
  107. package/lib/scene/wallpaper-character.d.ts +4 -0
  108. package/lib/scene/wallpaper-character.js +213 -0
  109. package/lib/scene.d.ts +7 -13
  110. package/lib/scene.js +7 -1023
  111. package/lib/sidebar-glass.js +99 -36
  112. package/lib/sidebar-heixiu-roaming.js +5 -5
  113. package/lib/sidebar-reveal.d.ts +8 -0
  114. package/lib/sidebar-reveal.js +51 -0
  115. package/lib/state.d.ts +14 -2
  116. package/lib/state.js +12 -4
  117. package/lib/theme.js +2 -2
  118. package/lib/vendor/bloub/decor.d.ts +114 -0
  119. package/lib/vendor/bloub/decor.js +198 -0
  120. package/lib/vendor/bloub/engine.d.ts +213 -0
  121. package/lib/vendor/bloub/engine.js +452 -0
  122. package/lib/vendor/bloub/expressions.d.ts +35 -0
  123. package/lib/vendor/bloub/expressions.js +143 -0
  124. package/lib/vendor/bloub/eyefit.d.ts +75 -0
  125. package/lib/vendor/bloub/eyefit.js +393 -0
  126. package/lib/vendor/bloub/face.d.ts +63 -0
  127. package/lib/vendor/bloub/face.js +106 -0
  128. package/lib/vendor/bloub/math.d.ts +22 -0
  129. package/lib/vendor/bloub/math.js +36 -0
  130. package/lib/vendor/bloub/profiles.d.ts +8 -0
  131. package/lib/vendor/bloub/profiles.js +20 -0
  132. package/lib/vendor/bloub/repere.d.ts +30 -0
  133. package/lib/vendor/bloub/repere.js +32 -0
  134. package/lib/vendor/bloub/shape.d.ts +80 -0
  135. package/lib/vendor/bloub/shape.js +268 -0
  136. package/lib/vendor/bloub/skins.d.ts +36 -0
  137. package/lib/vendor/bloub/skins.js +74 -0
  138. package/lib/vendor/bloub/states.d.ts +87 -0
  139. package/lib/vendor/bloub/states.js +468 -0
  140. package/package.json +23 -6
  141. package/lib/appearance.d.ts.map +0 -1
  142. package/lib/appearance.js.map +0 -1
  143. package/lib/blink.d.ts.map +0 -1
  144. package/lib/blink.js.map +0 -1
  145. package/lib/boot-appearance.d.ts.map +0 -1
  146. package/lib/boot-appearance.js.map +0 -1
  147. package/lib/boot-loader.d.ts.map +0 -1
  148. package/lib/boot-loader.js.map +0 -1
  149. package/lib/chrome/accessibility.d.ts.map +0 -1
  150. package/lib/chrome/accessibility.js.map +0 -1
  151. package/lib/chrome/blink.d.ts.map +0 -1
  152. package/lib/chrome/blink.js.map +0 -1
  153. package/lib/chrome/composer.d.ts.map +0 -1
  154. package/lib/chrome/composer.js.map +0 -1
  155. package/lib/chrome/conversation-messages.d.ts.map +0 -1
  156. package/lib/chrome/conversation-messages.js.map +0 -1
  157. package/lib/chrome/conversation.d.ts.map +0 -1
  158. package/lib/chrome/conversation.js.map +0 -1
  159. package/lib/chrome/frames.d.ts.map +0 -1
  160. package/lib/chrome/frames.js.map +0 -1
  161. package/lib/chrome/gaze.d.ts.map +0 -1
  162. package/lib/chrome/gaze.js.map +0 -1
  163. package/lib/chrome/identity.d.ts.map +0 -1
  164. package/lib/chrome/identity.js.map +0 -1
  165. package/lib/chrome/overlays.d.ts.map +0 -1
  166. package/lib/chrome/overlays.js.map +0 -1
  167. package/lib/chrome/portal.d.ts.map +0 -1
  168. package/lib/chrome/portal.js.map +0 -1
  169. package/lib/chrome/reactions.d.ts.map +0 -1
  170. package/lib/chrome/reactions.js.map +0 -1
  171. package/lib/chrome/sidebar.d.ts.map +0 -1
  172. package/lib/chrome/sidebar.js.map +0 -1
  173. package/lib/chrome/tokens.d.ts.map +0 -1
  174. package/lib/chrome/tokens.js.map +0 -1
  175. package/lib/chrome/workspace.d.ts.map +0 -1
  176. package/lib/chrome/workspace.js.map +0 -1
  177. package/lib/chrome.d.ts.map +0 -1
  178. package/lib/chrome.js.map +0 -1
  179. package/lib/client.d.ts.map +0 -1
  180. package/lib/client.js.map +0 -7
  181. package/lib/gaze.d.ts.map +0 -1
  182. package/lib/gaze.js.map +0 -1
  183. package/lib/generated-identity.d.ts.map +0 -1
  184. package/lib/generated-identity.js.map +0 -1
  185. package/lib/generated-keyart.d.ts.map +0 -1
  186. package/lib/generated-keyart.js.map +0 -1
  187. package/lib/generated-loading-assets.d.ts.map +0 -1
  188. package/lib/generated-loading-assets.js.map +0 -1
  189. package/lib/generated-sidebar-assets.d.ts +0 -4
  190. package/lib/generated-sidebar-assets.d.ts.map +0 -1
  191. package/lib/generated-sidebar-assets.js +0 -4
  192. package/lib/generated-sidebar-assets.js.map +0 -1
  193. package/lib/heixiu-interactions.d.ts.map +0 -1
  194. package/lib/heixiu-interactions.js.map +0 -1
  195. package/lib/index.d.ts.map +0 -1
  196. package/lib/index.js.map +0 -1
  197. package/lib/loading-heixiu.d.ts.map +0 -1
  198. package/lib/loading-heixiu.js.map +0 -1
  199. package/lib/plugin.d.ts.map +0 -1
  200. package/lib/plugin.js.map +0 -1
  201. package/lib/portal.d.ts.map +0 -1
  202. package/lib/portal.js.map +0 -1
  203. package/lib/reactions.d.ts.map +0 -1
  204. package/lib/reactions.js.map +0 -1
  205. package/lib/scene/heixiu-feedback.d.ts.map +0 -1
  206. package/lib/scene/heixiu-feedback.js.map +0 -1
  207. package/lib/scene/heixiu-interactions.d.ts.map +0 -1
  208. package/lib/scene/heixiu-interactions.js.map +0 -1
  209. package/lib/scene/state-transitions.d.ts.map +0 -1
  210. package/lib/scene/state-transitions.js.map +0 -1
  211. package/lib/scene.d.ts.map +0 -1
  212. package/lib/scene.js.map +0 -1
  213. package/lib/sidebar-glass.d.ts.map +0 -1
  214. package/lib/sidebar-glass.js.map +0 -1
  215. package/lib/sidebar-heixiu-escape.d.ts.map +0 -1
  216. package/lib/sidebar-heixiu-escape.js.map +0 -1
  217. package/lib/sidebar-heixiu-roaming.d.ts.map +0 -1
  218. package/lib/sidebar-heixiu-roaming.js.map +0 -1
  219. package/lib/state.d.ts.map +0 -1
  220. package/lib/state.js.map +0 -1
  221. package/lib/theme.d.ts.map +0 -1
  222. package/lib/theme.js.map +0 -1
@@ -0,0 +1,646 @@
1
+ import { XIAOHEI_AVATAR_2D_BLINK, XIAOHEI_AVATAR_2D_FRONT, } from '../generated-keyart.js';
2
+ export const XIAOHEI_SYLVA_AVATAR_MARKER = 'data-xiaohei-avatar-model';
3
+ /**
4
+ * A camera-facing 2.5D character that lives inside ThreeUI's renderer. The
5
+ * authored root world still owns depth and contact, while complete-frame art
6
+ * keeps Xiaohei's proportions and face faithful to the reviewed illustration.
7
+ */
8
+ const AVATAR_ADAPTER = `
9
+ /* ${XIAOHEI_SYLVA_AVATAR_MARKER}="true" */
10
+ var xiaoheiAvatarArt = {
11
+ base: ${JSON.stringify(XIAOHEI_AVATAR_2D_FRONT)},
12
+ blink: ${JSON.stringify(XIAOHEI_AVATAR_2D_BLINK)}
13
+ };
14
+ var xiaoheiAvatar = null;
15
+ var xiaoheiAvatarHostGroup = null;
16
+ var xiaoheiAvatarHostLimbs = null;
17
+ var xiaoheiAvatarPoint = new THREE.Vector3();
18
+ var xiaoheiAvatarCameraLocal = new THREE.Vector3();
19
+ var xiaoheiAvatarRay = new THREE.Raycaster();
20
+ var xiaoheiAvatarHover = 0;
21
+
22
+ function xiaoheiAvatarSmoothstep(value) {
23
+ var t = Math.max(0, Math.min(1, value));
24
+ return t * t * (3 - 2 * t);
25
+ }
26
+
27
+ function xiaoheiAvatarConfigureTexture(texture, columns) {
28
+ texture.encoding = THREE.sRGBEncoding;
29
+ texture.wrapS = THREE.RepeatWrapping;
30
+ texture.wrapT = THREE.ClampToEdgeWrapping;
31
+ texture.minFilter = THREE.LinearMipmapLinearFilter;
32
+ texture.magFilter = THREE.LinearFilter;
33
+ texture.generateMipmaps = true;
34
+ texture.repeat.set(1 / columns, 1);
35
+ texture.offset.set(0, 0);
36
+ texture.needsUpdate = true;
37
+ return texture;
38
+ }
39
+
40
+ function xiaoheiAvatarLoadTexture(source, columns, ready) {
41
+ return new THREE.TextureLoader().load(
42
+ source,
43
+ function (texture) {
44
+ xiaoheiAvatarConfigureTexture(texture, columns);
45
+ if (ready) ready(texture);
46
+ renderFrame();
47
+ },
48
+ undefined,
49
+ function () {
50
+ document.documentElement.dataset.xiaoheiAvatarTexture = 'load-failed';
51
+ }
52
+ );
53
+ }
54
+
55
+ function xiaoheiAvatarUseFrame(avatar, texture, columns, frame) {
56
+ if (!texture || !texture.image) return;
57
+ var safeFrame = Math.max(0, Math.min(columns - 1, frame | 0));
58
+ texture.repeat.x = 1 / columns;
59
+ texture.offset.x = safeFrame / columns;
60
+ if (avatar.headMaterial.map !== texture) {
61
+ avatar.headMaterial.map = texture;
62
+ avatar.headMaterial.needsUpdate = true;
63
+ }
64
+ }
65
+
66
+ function xiaoheiAvatarUseBaseTexture(avatar, texture) {
67
+ avatar.materials.forEach(function (material) {
68
+ material.map = texture;
69
+ material.needsUpdate = true;
70
+ });
71
+ }
72
+
73
+ function xiaoheiAvatarBuildIllustratedRig() {
74
+ var bones = {
75
+ root: new THREE.Bone(),
76
+ torso: new THREE.Bone(),
77
+ head: new THREE.Bone(),
78
+ upperArmLeft: new THREE.Bone(),
79
+ foreArmLeft: new THREE.Bone(),
80
+ handLeft: new THREE.Bone(),
81
+ upperArmRight: new THREE.Bone(),
82
+ foreArmRight: new THREE.Bone(),
83
+ handRight: new THREE.Bone(),
84
+ pelvis: new THREE.Bone(),
85
+ upperLegLeft: new THREE.Bone(),
86
+ lowerLegLeft: new THREE.Bone(),
87
+ footLeft: new THREE.Bone(),
88
+ upperLegRight: new THREE.Bone(),
89
+ lowerLegRight: new THREE.Bone(),
90
+ footRight: new THREE.Bone()
91
+ };
92
+ var ordered = [
93
+ bones.root,
94
+ bones.torso,
95
+ bones.head,
96
+ bones.upperArmLeft,
97
+ bones.foreArmLeft,
98
+ bones.handLeft,
99
+ bones.upperArmRight,
100
+ bones.foreArmRight,
101
+ bones.handRight,
102
+ bones.pelvis,
103
+ bones.upperLegLeft,
104
+ bones.lowerLegLeft,
105
+ bones.footLeft,
106
+ bones.upperLegRight,
107
+ bones.lowerLegRight,
108
+ bones.footRight
109
+ ];
110
+ ordered.forEach(function (bone, index) {
111
+ bone.name = 'xiaohei-2d-bone-' + index;
112
+ });
113
+
114
+ bones.root.add(bones.pelvis);
115
+ bones.pelvis.position.set(0, 0.285, 0);
116
+ bones.pelvis.add(bones.torso, bones.upperLegLeft, bones.upperLegRight);
117
+ bones.torso.position.set(0, 0.155, 0);
118
+ bones.torso.add(bones.head, bones.upperArmLeft, bones.upperArmRight);
119
+ bones.head.position.set(0, 0.13, 0);
120
+ bones.upperArmLeft.position.set(-0.125, 0.105, 0);
121
+ bones.upperArmRight.position.set(0.125, 0.105, 0);
122
+ bones.upperArmLeft.add(bones.foreArmLeft);
123
+ bones.foreArmLeft.position.set(-0.12, -0.02, 0);
124
+ bones.foreArmLeft.add(bones.handLeft);
125
+ bones.handLeft.position.set(-0.09, -0.015, 0);
126
+ bones.upperArmRight.add(bones.foreArmRight);
127
+ bones.foreArmRight.position.set(0.12, -0.02, 0);
128
+ bones.foreArmRight.add(bones.handRight);
129
+ bones.handRight.position.set(0.09, -0.015, 0);
130
+ bones.upperLegLeft.position.set(-0.065, -0.015, 0);
131
+ bones.upperLegRight.position.set(0.065, -0.015, 0);
132
+ bones.upperLegLeft.add(bones.lowerLegLeft);
133
+ bones.lowerLegLeft.position.set(0, -0.115, 0);
134
+ bones.lowerLegLeft.add(bones.footLeft);
135
+ bones.footLeft.position.set(0, -0.105, 0);
136
+ bones.upperLegRight.add(bones.lowerLegRight);
137
+ bones.lowerLegRight.position.set(0, -0.115, 0);
138
+ bones.lowerLegRight.add(bones.footRight);
139
+ bones.footRight.position.set(0, -0.105, 0);
140
+
141
+ return {
142
+ root: bones.root,
143
+ bones: bones,
144
+ skeleton: new THREE.Skeleton(ordered),
145
+ rest: {
146
+ torsoY: bones.torso.position.y,
147
+ headY: bones.head.position.y,
148
+ pelvisY: bones.pelvis.position.y
149
+ }
150
+ };
151
+ }
152
+
153
+ function xiaoheiAvatarBuildPartGeometry(bounds, pivot, segmentsX, segmentsY) {
154
+ var width = bounds[1] - bounds[0];
155
+ var height = bounds[3] - bounds[2];
156
+ var geometry = new THREE.PlaneGeometry(
157
+ width,
158
+ height,
159
+ segmentsX || 1,
160
+ segmentsY || 1
161
+ );
162
+ geometry.translate(
163
+ (bounds[0] + bounds[1]) * 0.5 - pivot[0],
164
+ (bounds[2] + bounds[3]) * 0.5 - pivot[1],
165
+ 0
166
+ );
167
+ var uv = geometry.getAttribute('uv');
168
+ for (var vertex = 0; vertex < uv.count; vertex += 1) {
169
+ uv.setXY(
170
+ vertex,
171
+ bounds[0] + 0.5 + uv.getX(vertex) * width,
172
+ bounds[2] + uv.getY(vertex) * height
173
+ );
174
+ }
175
+ uv.needsUpdate = true;
176
+ return geometry;
177
+ }
178
+
179
+ function xiaoheiAvatarBuildPart(bone, definition, materials, hitMeshes) {
180
+ var material = new THREE.MeshBasicMaterial({
181
+ color: 0xffffff,
182
+ transparent: true,
183
+ opacity: 0,
184
+ alphaTest: 0.026,
185
+ depthTest: true,
186
+ depthWrite: false,
187
+ side: THREE.DoubleSide
188
+ });
189
+ material.toneMapped = false;
190
+ var geometry = xiaoheiAvatarBuildPartGeometry(
191
+ definition.bounds,
192
+ definition.pivot,
193
+ definition.segmentsX,
194
+ definition.segmentsY
195
+ );
196
+ var mesh = new THREE.Mesh(geometry, material);
197
+ mesh.name = 'xiaohei-avatar-part-' + definition.name;
198
+ mesh.position.z = definition.depth || 0;
199
+ mesh.renderOrder = definition.order;
200
+ mesh.frustumCulled = false;
201
+ bone.add(mesh);
202
+ materials.push(material);
203
+ hitMeshes.push(mesh);
204
+ return mesh;
205
+ }
206
+
207
+ function xiaoheiAvatarBuildSkinnedPart(model, rig, definition, materials, hitMeshes) {
208
+ var material = new THREE.MeshBasicMaterial({
209
+ color: 0xffffff,
210
+ transparent: true,
211
+ opacity: 0,
212
+ alphaTest: 0.026,
213
+ depthTest: true,
214
+ depthWrite: false,
215
+ side: THREE.DoubleSide
216
+ });
217
+ material.toneMapped = false;
218
+ var geometry = xiaoheiAvatarBuildPartGeometry(
219
+ definition.bounds,
220
+ [0, 0],
221
+ definition.segmentsX,
222
+ definition.segmentsY
223
+ );
224
+ var position = geometry.getAttribute('position');
225
+ var skinIndex = new Uint16Array(position.count * 4);
226
+ var skinWeight = new Float32Array(position.count * 4);
227
+ for (var vertex = 0; vertex < position.count; vertex += 1) {
228
+ var along = definition.axis === 'x'
229
+ ? (position.getX(vertex) - definition.origin) * definition.direction
230
+ : (definition.origin - position.getY(vertex));
231
+ var first = definition.chain[0];
232
+ var second = first;
233
+ var firstWeight = 1;
234
+ if (along > definition.joints[1] - definition.blend) {
235
+ first = definition.chain[2];
236
+ second = definition.chain[1];
237
+ firstWeight = xiaoheiAvatarSmoothstep(
238
+ (along - definition.joints[1] + definition.blend) / (definition.blend * 2)
239
+ );
240
+ } else if (along > definition.joints[0] - definition.blend) {
241
+ first = definition.chain[1];
242
+ second = definition.chain[0];
243
+ firstWeight = xiaoheiAvatarSmoothstep(
244
+ (along - definition.joints[0] + definition.blend) / (definition.blend * 2)
245
+ );
246
+ }
247
+ var offset = vertex * 4;
248
+ skinIndex[offset] = first;
249
+ skinIndex[offset + 1] = second;
250
+ skinWeight[offset] = firstWeight;
251
+ skinWeight[offset + 1] = 1 - firstWeight;
252
+ }
253
+ geometry.setAttribute('skinIndex', new THREE.Uint16BufferAttribute(skinIndex, 4));
254
+ geometry.setAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeight, 4));
255
+ var mesh = new THREE.SkinnedMesh(geometry, material);
256
+ mesh.name = 'xiaohei-avatar-part-' + definition.name;
257
+ mesh.position.z = definition.depth || 0;
258
+ mesh.renderOrder = definition.order;
259
+ mesh.frustumCulled = false;
260
+ mesh.bind(rig.skeleton);
261
+ model.add(mesh);
262
+ materials.push(material);
263
+ hitMeshes.push(mesh);
264
+ return mesh;
265
+ }
266
+
267
+ function xiaoheiAvatarUpdateRig(avatar, now) {
268
+ var bones = avatar.rig.bones;
269
+ var rest = avatar.rig.rest;
270
+ var seconds = (now - avatar.motionStarted) * 0.001;
271
+ var breath = REDUCED ? 0 : Math.sin(seconds * 1.72);
272
+ var slow = REDUCED ? 0 : Math.sin(seconds * 0.63 + 0.8);
273
+ var delayed = REDUCED ? 0 : Math.sin(seconds * 1.72 - 0.34);
274
+
275
+ /* The source illustration is a T pose. Rotate the complete painted sleeve,
276
+ cuff and hand regions as one articulated chain so clothing never floats
277
+ away from the limb it belongs to. */
278
+ bones.root.rotation.set(0, 0, 0);
279
+ bones.root.position.set(0, 0, 0);
280
+ bones.torso.position.y = rest.torsoY + breath * 0.0022;
281
+ bones.torso.rotation.set(0, 0, slow * 0.008);
282
+ bones.torso.scale.set(1, 1 + breath * 0.0035, 1);
283
+ bones.head.position.y = rest.headY;
284
+ bones.head.rotation.set(0, 0, -slow * 0.014 + delayed * 0.004);
285
+
286
+ bones.upperArmLeft.rotation.set(0, 0, 1.39 + breath * 0.012 + slow * 0.008);
287
+ bones.foreArmLeft.rotation.set(0, 0, -0.075 + delayed * 0.009);
288
+ bones.handLeft.rotation.set(0, 0, 0.035 - delayed * 0.012);
289
+ bones.upperArmRight.rotation.set(0, 0, -1.39 - breath * 0.012 + slow * 0.008);
290
+ bones.foreArmRight.rotation.set(0, 0, 0.075 - delayed * 0.009);
291
+ bones.handRight.rotation.set(0, 0, -0.035 + delayed * 0.012);
292
+
293
+ bones.pelvis.position.y = rest.pelvisY;
294
+ bones.pelvis.rotation.set(0, 0, -slow * 0.004);
295
+ bones.upperLegLeft.rotation.set(0, 0, slow * 0.006);
296
+ bones.lowerLegLeft.rotation.set(0, 0, -slow * 0.004);
297
+ bones.footLeft.rotation.set(0, 0, -slow * 0.002);
298
+ bones.upperLegRight.rotation.set(0, 0, slow * 0.006);
299
+ bones.lowerLegRight.rotation.set(0, 0, -slow * 0.004);
300
+ bones.footRight.rotation.set(0, 0, -slow * 0.002);
301
+ bones.root.updateMatrixWorld(true);
302
+ }
303
+
304
+ function xiaoheiAvatarBuildModel() {
305
+ var root = new THREE.Group();
306
+ root.name = 'xiaohei-avatar-2-5d-root-v1';
307
+ var model = new THREE.Group();
308
+ model.name = 'xiaohei-avatar-2-5d-model-v1';
309
+ root.add(model);
310
+
311
+ var rig = xiaoheiAvatarBuildIllustratedRig();
312
+ var materials = [];
313
+ var hitMeshes = [];
314
+ model.add(rig.root);
315
+ rig.root.updateMatrixWorld(true);
316
+
317
+ var parts = {};
318
+ parts.armLeft = xiaoheiAvatarBuildSkinnedPart(model, rig, {
319
+ name: 'arm-left-with-sleeve', bounds: [-0.42, -0.105, 0.425, 0.62],
320
+ axis: 'x', origin: -0.125, direction: -1, chain: [3, 4, 5],
321
+ joints: [0.12, 0.21], blend: 0.025,
322
+ order: 4, segmentsX: 24, segmentsY: 8
323
+ }, materials, hitMeshes);
324
+ parts.armRight = xiaoheiAvatarBuildSkinnedPart(model, rig, {
325
+ name: 'arm-right-with-sleeve', bounds: [0.105, 0.42, 0.425, 0.62],
326
+ axis: 'x', origin: 0.125, direction: 1, chain: [6, 7, 8],
327
+ joints: [0.12, 0.21], blend: 0.025,
328
+ order: 4, segmentsX: 24, segmentsY: 8
329
+ }, materials, hitMeshes);
330
+ parts.legLeft = xiaoheiAvatarBuildSkinnedPart(model, rig, {
331
+ name: 'leg-left-with-shoe', bounds: [-0.175, -0.005, 0.0, 0.32],
332
+ axis: 'y', origin: 0.27, direction: 1, chain: [10, 11, 12],
333
+ joints: [0.115, 0.22], blend: 0.022,
334
+ order: 3, segmentsX: 8, segmentsY: 24
335
+ }, materials, hitMeshes);
336
+ parts.legRight = xiaoheiAvatarBuildSkinnedPart(model, rig, {
337
+ name: 'leg-right-with-shoe', bounds: [0.005, 0.175, 0.0, 0.32],
338
+ axis: 'y', origin: 0.27, direction: 1, chain: [13, 14, 15],
339
+ joints: [0.115, 0.22], blend: 0.022,
340
+ order: 3, segmentsX: 8, segmentsY: 24
341
+ }, materials, hitMeshes);
342
+ parts.torso = xiaoheiAvatarBuildPart(rig.bones.torso, {
343
+ name: 'torso-clothing', bounds: [-0.19, 0.19, 0.225, 0.65],
344
+ pivot: [0, 0.44], order: 6
345
+ }, materials, hitMeshes);
346
+ parts.head = xiaoheiAvatarBuildPart(rig.bones.head, {
347
+ name: 'head', bounds: [-0.265, 0.265, 0.555, 1.0],
348
+ pivot: [0, 0.57], order: 8, segmentsX: 24, segmentsY: 24, depth: 0.006
349
+ }, materials, hitMeshes);
350
+ var basePositions = parts.head.geometry.getAttribute('position').array.slice();
351
+
352
+ var scanMaterial = new THREE.MeshBasicMaterial({
353
+ color: 0x9bf1c9,
354
+ transparent: true,
355
+ opacity: 0,
356
+ depthTest: true,
357
+ depthWrite: false,
358
+ blending: THREE.AdditiveBlending,
359
+ side: THREE.DoubleSide
360
+ });
361
+ scanMaterial.toneMapped = false;
362
+ var scanLine = new THREE.Mesh(new THREE.PlaneGeometry(0.72, 0.012), scanMaterial);
363
+ scanLine.name = 'xiaohei-avatar-scan-line-v1';
364
+ scanLine.position.set(-0.02, 0.02, 0.024);
365
+ scanLine.renderOrder = 10;
366
+ model.add(scanLine);
367
+
368
+ var avatar = {
369
+ root: root,
370
+ model: model,
371
+ rig: rig,
372
+ parts: parts,
373
+ headMesh: parts.head,
374
+ headMaterial: parts.head.material,
375
+ materials: materials,
376
+ hitMeshes: hitMeshes,
377
+ basePositions: basePositions,
378
+ scanLine: scanLine,
379
+ scanMaterial: scanMaterial,
380
+ textures: {},
381
+ ready: false,
382
+ builtAt: performance.now(),
383
+ motionStarted: performance.now(),
384
+ anchorT: 0.38,
385
+ reaction: '',
386
+ reactionStarted: 0,
387
+ reactionUntil: 0,
388
+ hoverEar: '',
389
+ earLeftAmount: 0,
390
+ earRightAmount: 0,
391
+ nextBlink: performance.now() + 3200 + Math.random() * 2600,
392
+ blinkUntil: 0,
393
+ nextEar: performance.now() + 8000 + Math.random() * 9000
394
+ };
395
+
396
+ avatar.textures.base = xiaoheiAvatarLoadTexture(xiaoheiAvatarArt.base, 1, function (texture) {
397
+ avatar.ready = true;
398
+ avatar.builtAt = performance.now();
399
+ xiaoheiAvatarUseBaseTexture(avatar, texture);
400
+ xiaoheiAvatarUseFrame(avatar, texture, 1, 0);
401
+ document.documentElement.dataset.xiaoheiAvatarTexture = 'illustrated-2-5d-v1';
402
+ document.documentElement.dataset.xiaoheiAvatarScan = REDUCED ? 'skipped' : 'active';
403
+ });
404
+ avatar.textures.blink = xiaoheiAvatarLoadTexture(xiaoheiAvatarArt.blink, 1);
405
+ return avatar;
406
+ }
407
+
408
+ function xiaoheiAvatarSampleAt(t, target) {
409
+ if (!xiaoheiAvatarHostLimbs || !xiaoheiAvatarHostLimbs[0]) return false;
410
+ var limb = xiaoheiAvatarHostLimbs[0];
411
+ if (limb.grid && limb.S && limb.R) {
412
+ var row = Math.max(0, Math.min(limb.S, t * limb.S));
413
+ var row0 = Math.min(limb.S - 1, Math.floor(row));
414
+ var row1 = Math.min(limb.S, row0 + 1);
415
+ var blend = row - row0;
416
+ var stride = limb.R + 1;
417
+ var highestY = -Infinity;
418
+ for (var ringIndex = 0; ringIndex < limb.R; ringIndex += 1) {
419
+ var offset0 = (row0 * stride + ringIndex) * 3;
420
+ var offset1 = (row1 * stride + ringIndex) * 3;
421
+ var surfaceY = limb.grid[offset0 + 1]
422
+ + (limb.grid[offset1 + 1] - limb.grid[offset0 + 1]) * blend;
423
+ if (surfaceY <= highestY) continue;
424
+ highestY = surfaceY;
425
+ target.set(
426
+ limb.grid[offset0] + (limb.grid[offset1] - limb.grid[offset0]) * blend,
427
+ surfaceY + 0.018,
428
+ limb.grid[offset0 + 2]
429
+ + (limb.grid[offset1 + 2] - limb.grid[offset0 + 2]) * blend
430
+ );
431
+ }
432
+ return highestY > -Infinity;
433
+ }
434
+ target.copy(limb.curve.getPointAt(t));
435
+ var moss = limb.moss ? limb.moss(t) : 0;
436
+ var radius = limb.rw(t) + moss * 0.52;
437
+ if (limb.sink) target.y -= moss * limb.sink;
438
+ target.y += radius + 0.02;
439
+ return true;
440
+ }
441
+
442
+ function xiaoheiAvatarBeginReaction(avatar, reaction, now, duration) {
443
+ if (avatar.reaction && now < avatar.reactionUntil) return;
444
+ avatar.reaction = reaction;
445
+ avatar.reactionStarted = now;
446
+ avatar.reactionUntil = now + duration;
447
+ document.documentElement.dataset.xiaoheiAvatarAction = reaction + '-2-5d';
448
+ }
449
+
450
+ function xiaoheiAvatarUpdatePointer(avatar, now) {
451
+ var hit = null;
452
+ if (avatar.ready && ndc.x >= -1.2 && ndc.x <= 1.2 && ndc.y >= -1.2 && ndc.y <= 1.2) {
453
+ xiaoheiAvatarRay.setFromCamera(ndc, camera);
454
+ var intersections = xiaoheiAvatarRay.intersectObjects(avatar.hitMeshes, false);
455
+ if (intersections.length) hit = intersections[0];
456
+ }
457
+ xiaoheiAvatarHover += ((hit ? 1 : 0) - xiaoheiAvatarHover) * (hit ? 0.16 : 0.08);
458
+ var ear = '';
459
+ if (hit && hit.uv) {
460
+ var leftDistance = Math.hypot(
461
+ (hit.uv.x - 0.35) / 0.11,
462
+ (hit.uv.y - 0.85) / 0.16
463
+ );
464
+ var rightDistance = Math.hypot(
465
+ (hit.uv.x - 0.64) / 0.11,
466
+ (hit.uv.y - 0.84) / 0.16
467
+ );
468
+ if (leftDistance <= 1 || rightDistance <= 1) {
469
+ ear = leftDistance <= rightDistance ? 'ear-left' : 'ear-right';
470
+ }
471
+ }
472
+ if (ear && ear !== avatar.hoverEar && now >= avatar.reactionUntil) {
473
+ xiaoheiAvatarBeginReaction(avatar, ear, now, 560);
474
+ }
475
+ avatar.hoverEar = ear;
476
+ document.documentElement.dataset.xiaoheiAvatarHover = xiaoheiAvatarHover > 0.08 ? 'true' : 'false';
477
+ }
478
+
479
+ function xiaoheiAvatarDeformEar(avatar, centerU, centerV, pivotU, pivotV, amount) {
480
+ if (Math.abs(amount) < 0.0001) return;
481
+ var position = avatar.headMesh.geometry.getAttribute('position');
482
+ var uv = avatar.headMesh.geometry.getAttribute('uv');
483
+ for (var vertex = 0; vertex < position.count; vertex += 1) {
484
+ var du = (uv.getX(vertex) - centerU) / 0.13;
485
+ var dv = (uv.getY(vertex) - centerV) / 0.18;
486
+ var distance = Math.hypot(du, dv);
487
+ if (distance >= 1) continue;
488
+ var influence = xiaoheiAvatarSmoothstep(1 - distance);
489
+ var angle = amount * influence;
490
+ var x = position.getX(vertex) - (pivotU - 0.5);
491
+ var localPivotY = pivotV - 0.57;
492
+ var y = position.getY(vertex) - localPivotY;
493
+ var cosine = Math.cos(angle);
494
+ var sine = Math.sin(angle);
495
+ position.setXY(
496
+ vertex,
497
+ x * cosine - y * sine + pivotU - 0.5,
498
+ x * sine + y * cosine + localPivotY
499
+ );
500
+ }
501
+ }
502
+
503
+ function xiaoheiAvatarUpdateEars(avatar) {
504
+ var position = avatar.headMesh.geometry.getAttribute('position');
505
+ position.array.set(avatar.basePositions);
506
+ xiaoheiAvatarDeformEar(avatar, 0.35, 0.85, 0.39, 0.73, avatar.earLeftAmount * 0.12);
507
+ xiaoheiAvatarDeformEar(avatar, 0.64, 0.84, 0.60, 0.73, avatar.earRightAmount * -0.12);
508
+ position.needsUpdate = true;
509
+ }
510
+
511
+ function xiaoheiAvatarUpdateVisual(avatar, now) {
512
+ var blinking = now < avatar.blinkUntil;
513
+ if (!REDUCED && !avatar.reaction && now >= avatar.nextBlink) {
514
+ avatar.blinkUntil = now + 135;
515
+ avatar.nextBlink = now + 3800 + Math.random() * 3600;
516
+ blinking = true;
517
+ }
518
+ if (!REDUCED && !avatar.reaction && now >= avatar.nextEar) {
519
+ xiaoheiAvatarBeginReaction(
520
+ avatar,
521
+ Math.random() < 0.5 ? 'ear-left' : 'ear-right',
522
+ now,
523
+ 620
524
+ );
525
+ avatar.nextEar = now + 8000 + Math.random() * 9000;
526
+ }
527
+
528
+ if (avatar.reaction && now >= avatar.reactionUntil) {
529
+ avatar.reaction = '';
530
+ document.documentElement.dataset.xiaoheiAvatarAction = 'idle-2-5d';
531
+ }
532
+
533
+ avatar.earLeftAmount = 0;
534
+ avatar.earRightAmount = 0;
535
+ if (avatar.reaction) {
536
+ var reactionProgress = Math.max(0, Math.min(0.999,
537
+ (now - avatar.reactionStarted) / (avatar.reactionUntil - avatar.reactionStarted)
538
+ ));
539
+ var earPulse = Math.sin(reactionProgress * Math.PI)
540
+ * Math.sin(reactionProgress * Math.PI * 2.5);
541
+ if (avatar.reaction === 'ear-left') {
542
+ avatar.earLeftAmount = earPulse;
543
+ } else if (avatar.reaction === 'ear-right') {
544
+ avatar.earRightAmount = earPulse;
545
+ }
546
+ }
547
+ if (blinking) {
548
+ xiaoheiAvatarUseFrame(avatar, avatar.textures.blink, 1, 0);
549
+ } else {
550
+ xiaoheiAvatarUseFrame(avatar, avatar.textures.base, 1, 0);
551
+ }
552
+ xiaoheiAvatarUpdateEars(avatar);
553
+ }
554
+
555
+ function xiaoheiAvatarBuild() {
556
+ if (!xiaoheiAvatarHostGroup || !xiaoheiAvatarHostLimbs || xiaoheiAvatar) return;
557
+ xiaoheiAvatar = xiaoheiAvatarBuildModel();
558
+ xiaoheiAvatarHostGroup.add(xiaoheiAvatar.root);
559
+ xiaoheiAvatarSampleAt(xiaoheiAvatar.anchorT, xiaoheiAvatarPoint);
560
+ xiaoheiAvatar.root.position.copy(xiaoheiAvatarPoint);
561
+ document.documentElement.dataset.xiaoheiAvatarReady = 'true';
562
+ document.documentElement.dataset.xiaoheiAvatarMotion = 'illustrated-2-5d-v1';
563
+ document.documentElement.dataset.xiaoheiAvatarAction = 'idle-2-5d';
564
+ document.documentElement.dataset.xiaoheiAvatarPose = 'idle';
565
+ renderFrame();
566
+ }
567
+
568
+ function xiaoheiAvatarUpdate() {
569
+ if (!xiaoheiAvatar || !camera || !xiaoheiAvatarHostGroup) return;
570
+ var avatar = xiaoheiAvatar;
571
+ var now = performance.now();
572
+ xiaoheiAvatarSampleAt(avatar.anchorT, xiaoheiAvatarPoint);
573
+ avatar.root.position.copy(xiaoheiAvatarPoint);
574
+ var displayHeight = NARROW.matches ? 2.08 : 1.72;
575
+ avatar.model.scale.setScalar(displayHeight);
576
+ avatar.model.position.y = 0;
577
+
578
+ xiaoheiAvatarCameraLocal.copy(camera.position);
579
+ xiaoheiAvatarHostGroup.worldToLocal(xiaoheiAvatarCameraLocal);
580
+ var cameraDx = xiaoheiAvatarCameraLocal.x - xiaoheiAvatarPoint.x;
581
+ var cameraDz = xiaoheiAvatarCameraLocal.z - xiaoheiAvatarPoint.z;
582
+ avatar.model.rotation.y = Math.atan2(cameraDx, cameraDz);
583
+
584
+ if (avatar.ready) {
585
+ var reveal = REDUCED ? 1 : xiaoheiAvatarSmoothstep((now - avatar.builtAt) / 860);
586
+ avatar.materials.forEach(function (material) {
587
+ material.opacity = reveal;
588
+ });
589
+ avatar.scanLine.visible = reveal < 0.995 && !REDUCED;
590
+ avatar.scanLine.position.y = 0.04 + reveal * 0.80;
591
+ avatar.scanMaterial.opacity = Math.sin(reveal * Math.PI) * 0.42;
592
+ if (reveal >= 0.995 && document.documentElement.dataset.xiaoheiAvatarScan !== 'complete') {
593
+ document.documentElement.dataset.xiaoheiAvatarScan = 'complete';
594
+ }
595
+ xiaoheiAvatarUpdatePointer(avatar, now);
596
+ xiaoheiAvatarUpdateVisual(avatar, now);
597
+ xiaoheiAvatarUpdateRig(avatar, now);
598
+ }
599
+ }
600
+
601
+ var xiaoheiAvatarOriginalAssembleRoot = assembleRoot;
602
+ assembleRoot = function (limbs, options) {
603
+ var group = xiaoheiAvatarOriginalAssembleRoot(limbs, options);
604
+ if (options && options.order === 0) {
605
+ xiaoheiAvatarHostLimbs = limbs;
606
+ xiaoheiAvatarHostGroup = group;
607
+ }
608
+ return group;
609
+ };
610
+
611
+ var xiaoheiAvatarOriginalRenderFrame = renderFrame;
612
+ renderFrame = function () {
613
+ xiaoheiAvatarUpdate();
614
+ xiaoheiAvatarOriginalRenderFrame();
615
+ };
616
+
617
+ var xiaoheiAvatarOriginalBuild = build;
618
+ build = function () {
619
+ xiaoheiAvatarOriginalBuild();
620
+ xiaoheiAvatarBuild();
621
+ };
622
+ `;
623
+ /** Inject the renderer-sharing 2.5D avatar without editing registered ThreeUI files. */
624
+ export function injectXiaoheiSylvaAvatarModel(source) {
625
+ if (source.includes(`${XIAOHEI_SYLVA_AVATAR_MARKER}="true"`))
626
+ return source;
627
+ const runtimeEnd = source.lastIndexOf('\n})();\n</script>');
628
+ if (runtimeEnd < 0)
629
+ return source;
630
+ return `${source.slice(0, runtimeEnd)}${AVATAR_ADAPTER}${source.slice(runtimeEnd)}`;
631
+ }
632
+ /** Prepare the detached iframe so the avatar exists on its first WebGL boot. */
633
+ export function prepareXiaoheiSylvaAvatarFrame(frame) {
634
+ const source = frame.getAttribute('srcdoc');
635
+ if (source === null)
636
+ return false;
637
+ const modeledSource = injectXiaoheiSylvaAvatarModel(source);
638
+ if (modeledSource === source && !source.includes(`${XIAOHEI_SYLVA_AVATAR_MARKER}="true"`)) {
639
+ return false;
640
+ }
641
+ frame.dataset.xiaoheiAvatarModel = 'true';
642
+ if (modeledSource !== source)
643
+ frame.setAttribute('srcdoc', modeledSource);
644
+ return true;
645
+ }
646
+ //# sourceMappingURL=avatar-model.js.map